diff --git a/.gitignore b/.gitignore index a927c61..bd69837 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /*.xcodeproj xcuserdata/ AGENTS.md +Demo.swiftpm/.build +.claude diff --git a/Demo.swiftpm/.swiftpm/configuration/AppInfo.json b/Demo.swiftpm/.swiftpm/configuration/AppInfo.json new file mode 100644 index 0000000..289ade8 --- /dev/null +++ b/Demo.swiftpm/.swiftpm/configuration/AppInfo.json @@ -0,0 +1,4 @@ +{ + "bundleIdentifierPrefix": "org.bitcoinui", + "displayName": "BitcoinUI Demo" +} diff --git a/Demo.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/Demo.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Demo.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Demo.swiftpm/Demo.xcodeproj/project.pbxproj b/Demo.swiftpm/Demo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b61c86c --- /dev/null +++ b/Demo.swiftpm/Demo.xcodeproj/project.pbxproj @@ -0,0 +1,365 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 35C47B2B2E19EFD8F23EF916 /* BitcoinUI in Frameworks */ = {isa = PBXBuildFile; productRef = 6B11C3BFDEC3F38F6907EA34 /* BitcoinUI */; }; + 3DC2973F6A461014810F7551 /* SeedPhrasesDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C4991E001B4261AC706DB2E /* SeedPhrasesDemoView.swift */; }; + 3F9F15AC7DBBED6446811312 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6376510D5BA52EBE4C0667E6 /* ContentView.swift */; }; + 6675346D138D75E5B5E27A86 /* AddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD999E918A6CEAE408D93B08 /* AddressView.swift */; }; + 86CB226A25B435ACACED4AA4 /* TextStylesDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34F1DA4859C42192A67E246 /* TextStylesDemoView.swift */; }; + 87E4587B2DE439C6339E9ECC /* DemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DF36C68B50A12726B1B9B3D /* DemoApp.swift */; }; + ADC1660ECBBF6A93FD3410CD /* ButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13435783C64ADBBEB45E94F5 /* ButtonsView.swift */; }; + C91C03C35ADD039051A92075 /* ComponentSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5726AAFF07141D681B449458 /* ComponentSection.swift */; }; + E23FC183965794AB6C809F48 /* ColorsDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11933D15AFE190BCA80E253F /* ColorsDemoView.swift */; }; + EFBC04A282D1E523BAAB5ACE /* ImagesDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B47143E8CC564DCC5F15A293 /* ImagesDemoView.swift */; }; + FA6F016DE424AEFA2599C42D /* QRCodeDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64E307BC3F87902D5663118 /* QRCodeDemoView.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 11933D15AFE190BCA80E253F /* ColorsDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorsDemoView.swift; sourceTree = ""; }; + 13435783C64ADBBEB45E94F5 /* ButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonsView.swift; sourceTree = ""; }; + 20F4AF675AD6F7A10AB46782 /* BitcoinUI */ = {isa = PBXFileReference; lastKnownFileType = folder; name = BitcoinUI; path = ..; sourceTree = SOURCE_ROOT; }; + 3C4991E001B4261AC706DB2E /* SeedPhrasesDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedPhrasesDemoView.swift; sourceTree = ""; }; + 5726AAFF07141D681B449458 /* ComponentSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentSection.swift; sourceTree = ""; }; + 6376510D5BA52EBE4C0667E6 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 6DF36C68B50A12726B1B9B3D /* DemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoApp.swift; sourceTree = ""; }; + B47143E8CC564DCC5F15A293 /* ImagesDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesDemoView.swift; sourceTree = ""; }; + B64E307BC3F87902D5663118 /* QRCodeDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeDemoView.swift; sourceTree = ""; }; + BD999E918A6CEAE408D93B08 /* AddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressView.swift; sourceTree = ""; }; + E158E1D8DDD5F3DC89B171A3 /* Demo.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F34F1DA4859C42192A67E246 /* TextStylesDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextStylesDemoView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + F85CE95CC7B9E76D63880B75 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 35C47B2B2E19EFD8F23EF916 /* BitcoinUI in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 18C0F436F671F250CAEFD15D /* Packages */ = { + isa = PBXGroup; + children = ( + 20F4AF675AD6F7A10AB46782 /* BitcoinUI */, + ); + name = Packages; + sourceTree = ""; + }; + 20D12AFFC5038BCC5E0ECDCF /* Components */ = { + isa = PBXGroup; + children = ( + BD999E918A6CEAE408D93B08 /* AddressView.swift */, + 13435783C64ADBBEB45E94F5 /* ButtonsView.swift */, + 11933D15AFE190BCA80E253F /* ColorsDemoView.swift */, + 5726AAFF07141D681B449458 /* ComponentSection.swift */, + B47143E8CC564DCC5F15A293 /* ImagesDemoView.swift */, + B64E307BC3F87902D5663118 /* QRCodeDemoView.swift */, + 3C4991E001B4261AC706DB2E /* SeedPhrasesDemoView.swift */, + F34F1DA4859C42192A67E246 /* TextStylesDemoView.swift */, + ); + path = Components; + sourceTree = ""; + }; + 89EED0D913153940931D2FE8 /* Products */ = { + isa = PBXGroup; + children = ( + E158E1D8DDD5F3DC89B171A3 /* Demo.app */, + ); + name = Products; + sourceTree = ""; + }; + ACE36DE3FB2F24706FD66339 /* Sources */ = { + isa = PBXGroup; + children = ( + 6376510D5BA52EBE4C0667E6 /* ContentView.swift */, + 6DF36C68B50A12726B1B9B3D /* DemoApp.swift */, + 20D12AFFC5038BCC5E0ECDCF /* Components */, + ); + path = Sources; + sourceTree = ""; + }; + E5BB6DC2E977B912CC1AF702 = { + isa = PBXGroup; + children = ( + 18C0F436F671F250CAEFD15D /* Packages */, + ACE36DE3FB2F24706FD66339 /* Sources */, + 89EED0D913153940931D2FE8 /* Products */, + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 22478BC664898A9B8DD4D258 /* Demo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 67F59FA59F734371A2570797 /* Build configuration list for PBXNativeTarget "Demo" */; + buildPhases = ( + A1DCA12CEE65932D9EECDBA4 /* Sources */, + F85CE95CC7B9E76D63880B75 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Demo; + packageProductDependencies = ( + 6B11C3BFDEC3F38F6907EA34 /* BitcoinUI */, + ); + productName = Demo; + productReference = E158E1D8DDD5F3DC89B171A3 /* Demo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5533C1BE5094A04FCE853B33 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1600; + }; + buildConfigurationList = 388F02421550F69BF7947B85 /* Build configuration list for PBXProject "Demo" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = E5BB6DC2E977B912CC1AF702; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + D282B09AE8FB5CC0A51A1597 /* XCLocalSwiftPackageReference "..//" */, + ); + preferredProjectObjectVersion = 77; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 22478BC664898A9B8DD4D258 /* Demo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + A1DCA12CEE65932D9EECDBA4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6675346D138D75E5B5E27A86 /* AddressView.swift in Sources */, + ADC1660ECBBF6A93FD3410CD /* ButtonsView.swift in Sources */, + E23FC183965794AB6C809F48 /* ColorsDemoView.swift in Sources */, + C91C03C35ADD039051A92075 /* ComponentSection.swift in Sources */, + 3F9F15AC7DBBED6446811312 /* ContentView.swift in Sources */, + 87E4587B2DE439C6339E9ECC /* DemoApp.swift in Sources */, + EFBC04A282D1E523BAAB5ACE /* ImagesDemoView.swift in Sources */, + FA6F016DE424AEFA2599C42D /* QRCodeDemoView.swift in Sources */, + 3DC2973F6A461014810F7551 /* SeedPhrasesDemoView.swift in Sources */, + 86CB226A25B435ACACED4AA4 /* TextStylesDemoView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1E0D38BE0A23451ACF3D4625 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.bitcoinui.demo; + SDKROOT = iphoneos; + SWIFT_VERSION = 5; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 431C1D0126FDE809DBCC1F6E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 553BCFF4DF4A314DE3D572F3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.bitcoinui.demo; + SDKROOT = iphoneos; + SWIFT_VERSION = 5; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 76F22F9F8EFF9E558750A9FE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 388F02421550F69BF7947B85 /* Build configuration list for PBXProject "Demo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 76F22F9F8EFF9E558750A9FE /* Debug */, + 431C1D0126FDE809DBCC1F6E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 67F59FA59F734371A2570797 /* Build configuration list for PBXNativeTarget "Demo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 553BCFF4DF4A314DE3D572F3 /* Debug */, + 1E0D38BE0A23451ACF3D4625 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + D282B09AE8FB5CC0A51A1597 /* XCLocalSwiftPackageReference "..//" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "..//"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 6B11C3BFDEC3F38F6907EA34 /* BitcoinUI */ = { + isa = XCSwiftPackageProductDependency; + productName = BitcoinUI; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 5533C1BE5094A04FCE853B33 /* Project object */; +} diff --git a/Demo.swiftpm/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demo.swiftpm/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Demo.swiftpm/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Demo.swiftpm/Info.plist b/Demo.swiftpm/Info.plist new file mode 100644 index 0000000..b2b42b1 --- /dev/null +++ b/Demo.swiftpm/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleIdentifier + org.bitcoinui.demo + CFBundleName + Demo + CFBundleDisplayName + BitcoinUI Demo + CFBundleVersion + 1 + CFBundleShortVersionString + 1.0 + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundlePackageType + APPL + UILaunchScreen + + + diff --git a/Demo.swiftpm/Package.swift b/Demo.swiftpm/Package.swift new file mode 100644 index 0000000..d5f8ef4 --- /dev/null +++ b/Demo.swiftpm/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version: 5.10 +import PackageDescription + +let package = Package( + name: "Demo", + platforms: [ + .iOS(.v16), + .macOS(.v13) + ], + dependencies: [ + .package(name: "BitcoinUI", path: "../") + ], + targets: [ + .executableTarget( + name: "Demo", + dependencies: [ + .product(name: "BitcoinUI", package: "BitcoinUI") + ], + path: "Sources" + ) + ] +) diff --git a/Demo.swiftpm/Sources/Components/AddressView.swift b/Demo.swiftpm/Sources/Components/AddressView.swift new file mode 100644 index 0000000..365bd2a --- /dev/null +++ b/Demo.swiftpm/Sources/Components/AddressView.swift @@ -0,0 +1,33 @@ +import SwiftUI +import BitcoinUI + +struct AddressView: View { + let address = "tb1pw6y0vtmsn46epvz0j8ddc46ketmp28t82p22hcrrkch3a0jhu40qe267dl" + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("3 Columns (default)") { + AddressFormattedView(address: address) + } + + ComponentSection("4 Columns") { + AddressFormattedView(address: address, columns: 4) + } + + ComponentSection("2 Columns") { + AddressFormattedView(address: address, columns: 2) + } + } + .padding() + } + .navigationTitle("Address") + } +} + +#Preview { + NavigationStack { + AddressView() + } +} diff --git a/Demo.swiftpm/Sources/Components/ButtonsView.swift b/Demo.swiftpm/Sources/Components/ButtonsView.swift new file mode 100644 index 0000000..a7ae75c --- /dev/null +++ b/Demo.swiftpm/Sources/Components/ButtonsView.swift @@ -0,0 +1,47 @@ +import SwiftUI +import BitcoinUI + +struct ButtonsView: View { + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("Filled") { + Button("BitcoinFilled") {} + .buttonStyle(BitcoinFilled()) + Button("BitcoinFilled (Capsule)") {} + .buttonStyle(BitcoinFilled(isCapsule: true)) + Button("Disabled") {} + .buttonStyle(BitcoinFilled()) + .disabled(true) + } + + ComponentSection("Outlined") { + Button("BitcoinOutlined") {} + .buttonStyle(BitcoinOutlined()) + Button("BitcoinOutlined (Capsule)") {} + .buttonStyle(BitcoinOutlined(isCapsule: true)) + Button("Disabled") {} + .buttonStyle(BitcoinOutlined()) + .disabled(true) + } + + ComponentSection("Plain") { + Button("BitcoinPlain") {} + .buttonStyle(BitcoinPlain()) + Button("Disabled") {} + .buttonStyle(BitcoinPlain()) + .disabled(true) + } + } + .padding() + } + .navigationTitle("Buttons") + } +} + +#Preview { + NavigationStack { + ButtonsView() + } +} diff --git a/Demo.swiftpm/Sources/Components/ColorsDemoView.swift b/Demo.swiftpm/Sources/Components/ColorsDemoView.swift new file mode 100644 index 0000000..5b16762 --- /dev/null +++ b/Demo.swiftpm/Sources/Components/ColorsDemoView.swift @@ -0,0 +1,70 @@ +import SwiftUI +import BitcoinUI + +struct ColorsDemoView: View { + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("Brand") { + colorRow([ + ("Orange", .bitcoinOrange), + ("Red", .bitcoinRed), + ("Green", .bitcoinGreen), + ("Blue", .bitcoinBlue), + ("Purple", .bitcoinPurple), + ]) + } + + ComponentSection("Neutral") { + colorRow([ + ("White", .bitcoinWhite), + ("N1", .bitcoinNeutral1), + ("N2", .bitcoinNeutral2), + ("N3", .bitcoinNeutral3), + ("N4", .bitcoinNeutral4), + ]) + colorRow([ + ("N5", .bitcoinNeutral5), + ("N6", .bitcoinNeutral6), + ("N7", .bitcoinNeutral7), + ("N8", .bitcoinNeutral8), + ("Black", .bitcoinBlack), + ]) + } + + ComponentSection("Special") { + colorRow([ + ("MyMattress", .bitcoinMyMattress), + ]) + } + } + .padding() + } + .navigationTitle("Colors") + } + + private func colorRow(_ items: [(String, Color)]) -> some View { + HStack(spacing: 12) { + ForEach(items, id: \.0) { label, color in + VStack(spacing: 4) { + Circle() + .fill(color) + .frame(width: 44, height: 44) + .overlay(Circle().stroke(Color.secondary.opacity(0.2), lineWidth: 1)) + Text(label) + .font(.caption2) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + } + .frame(maxWidth: .infinity) + } + } + } +} + +#Preview { + NavigationStack { + ColorsDemoView() + } +} diff --git a/Demo.swiftpm/Sources/Components/ComponentSection.swift b/Demo.swiftpm/Sources/Components/ComponentSection.swift new file mode 100644 index 0000000..fc27178 --- /dev/null +++ b/Demo.swiftpm/Sources/Components/ComponentSection.swift @@ -0,0 +1,20 @@ +import SwiftUI + +struct ComponentSection: View { + let title: String + let content: Content + + init(_ title: String, @ViewBuilder content: () -> Content) { + self.title = title + self.content = content() + } + + var body: some View { + VStack(alignment: .leading, spacing: 12) { + Text(title) + .font(.headline) + .foregroundStyle(.secondary) + content + } + } +} diff --git a/Demo.swiftpm/Sources/Components/ImagesDemoView.swift b/Demo.swiftpm/Sources/Components/ImagesDemoView.swift new file mode 100644 index 0000000..b80bac5 --- /dev/null +++ b/Demo.swiftpm/Sources/Components/ImagesDemoView.swift @@ -0,0 +1,48 @@ +import SwiftUI +import BitcoinUI + +struct ImagesDemoView: View { + private let icons = [ + "bitbox", "blockstream-jade", "cobo-vault", "coldcard", + "foundation-passport", "generic-hardware-wallet", "keepkey", + "ledger-nano", "opendime", "satoshi-v2", "seedplate", + "trezor-model-t", "trezor-one", + ] + + private let columns = [ + GridItem(.adaptive(minimum: 80), spacing: 16), + ] + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + ComponentSection("Hardware Wallets") { + LazyVGrid(columns: columns, spacing: 16) { + ForEach(icons, id: \.self) { name in + VStack(spacing: 6) { + BitcoinImage(named: name) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 48, height: 48) + Text(name) + .font(.caption2) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + .lineLimit(2) + } + .frame(maxWidth: .infinity) + } + } + } + } + .padding() + } + .navigationTitle("Images") + } +} + +#Preview { + NavigationStack { + ImagesDemoView() + } +} diff --git a/Demo.swiftpm/Sources/Components/QRCodeDemoView.swift b/Demo.swiftpm/Sources/Components/QRCodeDemoView.swift new file mode 100644 index 0000000..0244cdf --- /dev/null +++ b/Demo.swiftpm/Sources/Components/QRCodeDemoView.swift @@ -0,0 +1,62 @@ +import SwiftUI +import BitcoinUI + +struct QRCodeDemoView: View { + private let address = "tb1q05g8l05sgqsnzuc2mrmq0chlq7ktxtce4js5dj" + private let invoice = "lntbs1234560u1pnf4qfudq4f4hkuerp0ys9wctvd3jhgnp4q235egp5u2nec2ddcza8eykpd3gl3g0es0m7gncarzeuwuw6xhpqq" + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("Bitcoin") { + QRCodeView(qrCodeType: .bitcoin(address)) + .frame(maxWidth: 240) + .frame(maxWidth: .infinity) + } + + ComponentSection("Bitcoin (Rounded)") { + QRCodeView(qrCodeType: .bitcoin(address), cornerRadius: 20) + .frame(maxWidth: 240) + .frame(maxWidth: .infinity) + } + + ComponentSection("Lightning") { + QRCodeView(qrCodeType: .lightning(invoice)) + .frame(maxWidth: 240) + .frame(maxWidth: .infinity) + } + + ComponentSection("BIP21") { + QRCodeView( + qrCodeType: .bip21( + "bitcoin:\(address)?amount=0.001&label=Demo" + ), + cornerRadius: 12 + ) + .frame(maxWidth: 240) + .frame(maxWidth: .infinity) + } + + ComponentSection("Custom Colors") { + QRCodeView( + qrCodeType: .bitcoin(address), + cornerRadius: 16, + foregroundColor: .bitcoinOrange, + backgroundColor: .black + ) + .frame(maxWidth: 240) + .frame(maxWidth: .infinity) + } + } + .padding() + } + .navigationTitle("QR Code") + } +} + +#Preview { + NavigationStack { + QRCodeDemoView() + } +} diff --git a/Demo.swiftpm/Sources/Components/SeedPhrasesDemoView.swift b/Demo.swiftpm/Sources/Components/SeedPhrasesDemoView.swift new file mode 100644 index 0000000..25810ac --- /dev/null +++ b/Demo.swiftpm/Sources/Components/SeedPhrasesDemoView.swift @@ -0,0 +1,56 @@ +import SwiftUI +import BitcoinUI + +struct SeedPhrasesDemoView: View { + private let words12 = [ + "paddle", "train", "boil", "catch", "trim", "plastic", + "wolf", "hazard", "govern", "oval", "drama", "gun", + ] + private let words24 = [ + "paddle", "train", "boil", "catch", "trim", "plastic", + "wolf", "hazard", "govern", "oval", "drama", "gun", + "swim", "accuse", "degree", "teach", "game", "penalty", + "social", "hard", "crush", "media", "radar", "click", + ] + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("12 Words (2 per row)") { + SeedPhraseView(words: words12, preferredWordsPerRow: 2) + } + + ComponentSection("12 Words (3 per row)") { + SeedPhraseView(words: words12, preferredWordsPerRow: 3) + } + + ComponentSection("24 Words with Paging") { + SeedPhraseView( + words: words24, + preferredWordsPerRow: 2, + usePaging: true, + wordsPerPage: 6 + ) + .frame(height: 200) + } + + ComponentSection("Privacy Sensitive") { + SeedPhraseView( + words: words12, + preferredWordsPerRow: 2, + privacySensitive: true + ) + } + } + .padding() + } + .navigationTitle("Seed Phrase") + } +} + +#Preview { + NavigationStack { + SeedPhrasesDemoView() + } +} diff --git a/Demo.swiftpm/Sources/Components/TextStylesDemoView.swift b/Demo.swiftpm/Sources/Components/TextStylesDemoView.swift new file mode 100644 index 0000000..b12c241 --- /dev/null +++ b/Demo.swiftpm/Sources/Components/TextStylesDemoView.swift @@ -0,0 +1,39 @@ +import SwiftUI +import BitcoinUI + +struct TextStylesDemoView: View { + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 24) { + + ComponentSection("Titles") { + VStack(alignment: .leading, spacing: 8) { + Text("BitcoinTitle1").textStyle(BitcoinTitle1()) + Text("BitcoinTitle2").textStyle(BitcoinTitle2()) + Text("BitcoinTitle3").textStyle(BitcoinTitle3()) + Text("BitcoinTitle4").textStyle(BitcoinTitle4()) + Text("BitcoinTitle5").textStyle(BitcoinTitle5()) + } + } + + ComponentSection("Body") { + VStack(alignment: .leading, spacing: 8) { + Text("BitcoinBody1").textStyle(BitcoinBody1()) + Text("BitcoinBody2").textStyle(BitcoinBody2()) + Text("BitcoinBody3").textStyle(BitcoinBody3()) + Text("BitcoinBody4").textStyle(BitcoinBody4()) + Text("BitcoinBody5").textStyle(BitcoinBody5()) + } + } + } + .padding() + } + .navigationTitle("Text Styles") + } +} + +#Preview { + NavigationStack { + TextStylesDemoView() + } +} diff --git a/Demo.swiftpm/Sources/ContentView.swift b/Demo.swiftpm/Sources/ContentView.swift new file mode 100644 index 0000000..fb8f943 --- /dev/null +++ b/Demo.swiftpm/Sources/ContentView.swift @@ -0,0 +1,26 @@ +import SwiftUI + +struct ContentView: View { + var body: some View { + NavigationStack { + List { + Section("Components") { + NavigationLink("Buttons", destination: ButtonsView()) + NavigationLink("Address", destination: AddressView()) + NavigationLink("QR Code", destination: QRCodeDemoView()) + NavigationLink("Seed Phrase", destination: SeedPhrasesDemoView()) + } + Section("Foundations") { + NavigationLink("Text Styles", destination: TextStylesDemoView()) + NavigationLink("Colors", destination: ColorsDemoView()) + NavigationLink("Images", destination: ImagesDemoView()) + } + } + .navigationTitle("BitcoinUI") + } + } +} + +#Preview { + ContentView() +} diff --git a/Demo.swiftpm/Sources/DemoApp.swift b/Demo.swiftpm/Sources/DemoApp.swift new file mode 100644 index 0000000..470184c --- /dev/null +++ b/Demo.swiftpm/Sources/DemoApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct DemoApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Demo.swiftpm/project.yml b/Demo.swiftpm/project.yml new file mode 100644 index 0000000..8a187f3 --- /dev/null +++ b/Demo.swiftpm/project.yml @@ -0,0 +1,22 @@ +name: Demo +options: + bundleIdPrefix: org.bitcoinui + deploymentTarget: + iOS: "16.0" + xcodeVersion: "16" +packages: + BitcoinUI: + path: ../ +targets: + Demo: + type: application + platform: iOS + sources: Sources + settings: + base: + SWIFT_VERSION: "5" + PRODUCT_BUNDLE_IDENTIFIER: org.bitcoinui.demo + INFOPLIST_FILE: Info.plist + dependencies: + - package: BitcoinUI + product: BitcoinUI diff --git a/README.md b/README.md index 4132f8b..4630791 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Bitcoin UI components and review for native iOS apps. [Swift Package](#swift-package)
+[Demo App](#demo-app)
[Design Review](#design-review)
## Swift Package @@ -28,6 +29,12 @@ Text("Bitcoin Orange") .multilineTextAlignment(.center) ``` +## Demo App + +Open `Demo.swiftpm/Demo.xcodeproj` in Xcode, select an iOS Simulator, and press Run (⌘R). + + + ## Design Review Install `bitcoinui` in your AI coding tool. diff --git a/SnapshotsDemo/01.png b/SnapshotsDemo/01.png new file mode 100644 index 0000000..f91d07c Binary files /dev/null and b/SnapshotsDemo/01.png differ diff --git a/SnapshotsDemo/02.png b/SnapshotsDemo/02.png new file mode 100644 index 0000000..5bf74d9 Binary files /dev/null and b/SnapshotsDemo/02.png differ diff --git a/SnapshotsDemo/03.png b/SnapshotsDemo/03.png new file mode 100644 index 0000000..673e4fd Binary files /dev/null and b/SnapshotsDemo/03.png differ diff --git a/SnapshotsDemo/04.png b/SnapshotsDemo/04.png new file mode 100644 index 0000000..ee8cc7f Binary files /dev/null and b/SnapshotsDemo/04.png differ diff --git a/SnapshotsDemo/05.png b/SnapshotsDemo/05.png new file mode 100644 index 0000000..d3e4c77 Binary files /dev/null and b/SnapshotsDemo/05.png differ diff --git a/SnapshotsDemo/06.png b/SnapshotsDemo/06.png new file mode 100644 index 0000000..d2ea376 Binary files /dev/null and b/SnapshotsDemo/06.png differ diff --git a/SnapshotsDemo/07.png b/SnapshotsDemo/07.png new file mode 100644 index 0000000..19cd7bb Binary files /dev/null and b/SnapshotsDemo/07.png differ diff --git a/SnapshotsDemo/08.png b/SnapshotsDemo/08.png new file mode 100644 index 0000000..da4dda1 Binary files /dev/null and b/SnapshotsDemo/08.png differ