Move Compound Inspector into the project.

This commit is contained in:
Doug
2025-09-28 15:37:59 +01:00
committed by Doug
parent 90eeabf9de
commit c6b6c13533
33 changed files with 1828 additions and 0 deletions
@@ -0,0 +1,66 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Compound
import SwiftUI
protocol AllValues {
associatedtype ValueType
var allValues: [(name: String, value: ValueType)] { get }
}
extension AllValues {
var allValues: [(name: String, value: ValueType)] {
var values: [(name: String, value: ValueType)] = []
let mirror = Mirror(reflecting: self)
for property in mirror.children {
if let label = property.label, let value = property.value as? ValueType {
values.append((label, value))
}
}
return values
}
}
extension CompoundColors: AllValues { typealias ValueType = Color }
extension CompoundColorTokens: AllValues { typealias ValueType = Color }
extension CompoundGradients: AllValues { typealias ValueType = Gradient }
extension CompoundFonts: AllValues { typealias ValueType = Font }
extension CompoundIcons: AllValues { typealias ValueType = Image }
extension CompoundColors {
var allColors: [(name: String, value: Color)] {
CompoundColorTokens().allValues + allValues
}
}
extension CompoundIcons {
var allKeyPaths: [(name: String, value: KeyPath<CompoundIcons, Image>)] {
var icons: [(name: String, value: KeyPath<CompoundIcons, Image>)] = []
let mirror = Mirror(reflecting: self)
for property in mirror.children {
if let label = property.label {
let keyPath = \CompoundIcons.[checkedMirrorDescendant: label] as PartialKeyPath
if let imageKeyPath = keyPath as? KeyPath<CompoundIcons, Image> {
icons.append((label, imageKeyPath))
} else {
print("Nope")
}
}
}
return icons
}
private subscript(checkedMirrorDescendant key: String) -> Any {
return Mirror(reflecting: self).descendant(key)!
}
}
@@ -0,0 +1,85 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import SwiftUI
import Compound
struct ColorsScreen: View {
var body: some View {
ScreenContent(navigationTitle: "Colors") {
ForEach(Color.compound.allColors, id: \.name) { color in
ColorItem(color: color.value, name: color.name)
}
}
}
}
struct ColorItem: View {
let color: Color
let name: String
var body: some View {
HStack {
swatch
VStack(alignment: .leading) {
Text(name)
.font(.compound.bodyLG)
.foregroundColor(.compound.textPrimary)
Text(color.hexValue())
.font(.compound.bodySM.monospaced())
.foregroundColor(.compound.textSecondary)
}
}
}
var swatch: some View {
swatchShape
.foregroundColor(color)
.frame(height: 40)
.aspectRatio(1, contentMode: .fit)
.overlay {
swatchShape
.strokeBorder(Color.compound.iconPrimary, lineWidth: 1.5)
.opacity(0.2)
}
}
var swatchShape: some InsettableShape {
RoundedRectangle(cornerRadius: 12, style: .continuous)
}
}
private extension Color {
func hexValue() -> String {
let uiColor = UIColor(self)
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return "#\(red.asHex)\(green.asHex)\(blue.asHex)"
}
}
private extension CGFloat {
var asHex: String {
String(format:"%02X", Int((self * 255).rounded()))
}
}
struct ColorsScreen_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
ColorsScreen()
}
.previewLayout(.fixed(width: 375, height: 700))
}
}
@@ -0,0 +1,40 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import SwiftUI
import Compound
struct FontsScreen: View {
var body: some View {
ScreenContent(navigationTitle: "Fonts") {
ForEach(Font.compound.allValues, id: \.name) { font in
FontItem(font: font.value, name: font.name)
}
}
}
}
struct FontItem: View {
let font: Font
let name: String
var body: some View {
Text(name)
.font(font)
.foregroundColor(.compound.textPrimary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
struct FontsScreen_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
FontsScreen()
}
.previewLayout(.fixed(width: 375, height: 750))
}
}
@@ -0,0 +1,61 @@
//
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import SwiftUI
import Compound
struct GradientsScreen: View {
var body: some View {
ScreenContent(navigationTitle: "Colors") {
ForEach(Gradient.compound.allValues, id: \.name) { gradient in
GradientItem(gradient: gradient.value, name: gradient.name)
}
}
}
}
struct GradientItem: View {
let gradient: Gradient
let name: String
var body: some View {
HStack {
swatch
VStack(alignment: .leading) {
Text(name)
.font(.compound.bodyLG)
.foregroundColor(.compound.textPrimary)
}
}
}
var swatch: some View {
swatchShape
.foregroundStyle(gradient)
.frame(height: 40)
.aspectRatio(1, contentMode: .fit)
.overlay {
swatchShape
.strokeBorder(Color.compound.iconPrimary, lineWidth: 1.5)
.opacity(0.2)
}
}
var swatchShape: some InsettableShape {
RoundedRectangle(cornerRadius: 12, style: .continuous)
}
}
struct GradientsScreen_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
ColorsScreen()
}
.previewLayout(.fixed(width: 375, height: 700))
}
}
@@ -0,0 +1,47 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import SwiftUI
import Compound
struct IconsScreen: View {
let icons = Image.compound.allValues.sorted(by: { $0.name < $1.name })
var body: some View {
ScreenContent(navigationTitle: "Icons") {
ForEach(icons, id: \.name) { icon in
IconItem(icon: icon.value, name: icon.name)
}
}
}
}
struct IconItem: View {
let icon: Image
let name: String
var body: some View {
Label {
Text(name)
.foregroundColor(.compound.textPrimary)
} icon: {
CompoundIcon(customImage: icon)
.foregroundColor(.compound.iconSecondary)
}
.font(.compound.bodyLG)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
struct IconsScreen_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
IconsScreen()
}
.previewLayout(.fixed(width: 375, height: 750))
}
}