Skip to content

platform integration modernization (v1.3)#3

Merged
2dubu merged 8 commits intomainfrom
feature/v1.3-platform-modernize
May 2, 2026
Merged

platform integration modernization (v1.3)#3
2dubu merged 8 commits intomainfrom
feature/v1.3-platform-modernize

Conversation

@2dubu
Copy link
Copy Markdown
Owner

@2dubu 2dubu commented May 2, 2026

Summary

  • PaletteColor now conforms to SwiftUI's ShapeStyle (iOS 17+) so it can be passed directly to .fill, .foregroundStyle, .background, .tint, .border, etc. without an adapter call. resolve(in:) produces a Color.Resolved tagged sRGB.
  • UIKit gets a UIColor(_ paletteColor:) convenience initializer (mirrors Apple's UIColor.init(_ color: Color) pattern) and a direct paletteColor.cgColor accessor for CALayer / CGContext drawing — no UIColor round-trip.
  • README + DocC Options.md + GettingStarted.md reorganized with platform-tabbed ### SwiftUI and ### UIKit examples so users find their pattern at a glance.
  • Library structure tidy: MetalContext.swift moved from Support/ to Metal/ (groups with Histogram.metal shader source). Bumps paletteKitVersion to 1.3.0.

What's changed

Library (Sources/PaletteKit/)

  • New: Model/PaletteColor+ShapeStyle.swiftextension PaletteColor: ShapeStyle returning Color.Resolved(colorSpace: .sRGB, ...). Apple handles the sRGB → linear conversion internally.
  • New: Model/PaletteColor+UIKit.swiftUIColor(_ paletteColor:) convenience init and paletteColor.cgColor direct accessor (uses CGColor(srgbRed:...), no UIColor hop).
  • Renamed: Support/MetalContext.swiftMetal/MetalContext.swift. Support/ is now just Logging.swift (its actual purpose).
  • Removed: Model/PaletteColor+SwiftUI.swift — both legacy adapter properties (.swiftUI and .uiColor).
  • paletteKitVersion = "1.3.0".

Demo app (Examples/PaletteKitDemo/)

  • DominantColorView, PaletteGrid, SwatchesView use PaletteColor directly (no .swiftUI adapter call). SwatchCard wraps optional swatch fallbacks in AnyShapeStyle-typed computed properties since ?? cannot unify PaletteColor and Color directly.

Docs

  • README.md: Quick Start split into ### SwiftUI / ### UIKit sub-sections. Features bullet mentions ShapeStyle conformance. New ## What's new in 1.3 section after the Install snippet calls out the BREAKING adapter removals with migration paths. Install snippet bumped to from: "1.3.0". Roadmap refreshed (v1.3 ✅ shipped, v1.4 / v2.0 next).
  • PaletteKit.docc/Tutorials/GettingStarted.md: New ## Using the result section with ### SwiftUI and ### UIKit subsections. Two stale .uiColor references in the existing "Get semantic swatches" example fixed (replaced with UIColor(...) init pattern).
  • PaletteKit.docc/Tutorials/Options.md: New ### SwiftUI integration and ### UIKit integration sections describing the new conformance and accessors.

Audit notes

Color.Resolved is iOS 17+ (Apple's "concrete RGBA value" type stored in linear sRGB extended range). PaletteKit targets iOS 17+ unconditionally so the conformance has no @available guards. Apple's init(colorSpace: .sRGB, red:green:blue:opacity:) lets us pass our 8-bit sRGB-encoded values directly — gamma decode happens inside SwiftUI's pipeline.

For UIKit, UIColor.init(_ color: Color) (iOS 14+) is Apple's idiomatic SwiftUI/value-type → UIKit conversion pattern; UIColor(_ paletteColor:) mirrors it. CGColor(srgbRed:green:blue:alpha:) (iOS 13+) bypasses UIColor entirely so paletteColor.cgColor is a single allocation.

Display P3 fidelity is intentionally unchanged in this release (stays sRGB) — that's earmarked for v1.4 alongside PaletteKitCard graphics where wide-gamut rendering matters.

Breaking changes

  • PaletteColor.swiftUI removed. Replacement: pass PaletteColor directly to any ShapeStyle-accepting modifier.
  • PaletteColor.uiColor removed. Replacement: UIColor(paletteColor) (init) or paletteColor.cgColor (Core Graphics).

Test plan

  • swift test — 35/35 pass (was 31/31; +4 ShapeStyle boundary tests, +5 UIKit tests guarded by #if canImport(UIKit)).
  • make demo-app regenerates the Xcode project; iOS Simulator build succeeds (iPhone 17 Pro).
  • DocC xcodebuild docbuild succeeds.
  • Demo runtime: tap-to-copy still works on palette chips / swatch tiles / dominant card; option sheet still opens; result order (Swatches → Palette → Dominant → Timings) intact.
  • No .swiftUI / .uiColor references remain anywhere in Sources/, Tests/, Examples/, PaletteKit.docc/, README.md (verified by grep).

2dubu added 8 commits May 1, 2026 20:34
PaletteColor now resolves to Color.Resolved (iOS 17+) via
init(colorSpace: .sRGB, red:green:blue:opacity:), so it can be passed
directly to .fill, .foregroundStyle, .background, .border, .tint, and
any other ShapeStyle accepting modifier without an adapter call.

Apple handles the sRGB → linear sRGB extended range conversion
internally. Tests cover boundary RGB values plus a sample linear
gamma decode.
PaletteColor conforms to ShapeStyle now, so the .swiftUI Color
adapter is redundant. The demo views use PaletteColor directly with
.fill / .foregroundStyle. Optional swatch fallbacks are wrapped in
AnyShapeStyle so the existing Color.gray / Color.primary placeholders
still work for nil swatches.

BREAKING: PaletteColor.swiftUI is removed. Use PaletteColor directly
with any ShapeStyle-accepting modifier.
Mirrors Apple's UIColor.init(_ color: Color) conversion pattern. The
init is sRGB-tagged with alpha = 1; chain .withAlphaComponent(_:) for
non-opaque variants.
Direct CGColor without a UIColor hop. Uses CGColor(srgbRed:...) so the
result is sRGB-tagged. Useful for CALayer.backgroundColor, CGContext
fills, and other Core Graphics APIs.
PaletteKit now offers a UIColor(_ paletteColor:) convenience init and
a direct PaletteColor.cgColor accessor (added in the previous two
commits). The legacy .uiColor property is redundant.

BREAKING: PaletteColor.uiColor is removed. Use UIColor(paletteColor)
or paletteColor.cgColor instead.
Groups MetalContext.swift with the Histogram.metal shader source it
pairs with. Support/ now contains only Logging.swift, which is its
true purpose — shared infrastructure utilities.

Package.swift exclusion path "Metal/Histogram.metal" is unchanged
(already correct relative to the source root).
GettingStarted gets a new "Using the result" section with separate
SwiftUI and UIKit subsections so users can find their platform's
pattern at a glance. Options gains "SwiftUI integration" and "UIKit
integration" sections describing the new conformance and accessors.

README:
- Quick start split into SwiftUI / UIKit sub-sections.
- Features bullet mentions ShapeStyle conformance.
- New "What's new in 1.3" section above the install snippet calls
  out the breaking adapter removals.
- Install snippet bumped to from: "1.3.0".
- Roadmap refreshed with v1.3 shipped and v1.4 / v2.0 next.

Also fixes two stale .uiColor references in GettingStarted that
broke after the adapter was removed.
@2dubu 2dubu self-assigned this May 2, 2026
@2dubu 2dubu merged commit 2fa88fd into main May 2, 2026
1 check passed
@2dubu 2dubu deleted the feature/v1.3-platform-modernize branch May 2, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant