@snowcone-app/ui 0.1.43 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +18 -4
- package/package.json +9 -5
- package/src/components/CanvasIsolationBoundary.tsx +202 -0
- package/src/components/LoadingOverlayPrism.tsx +251 -0
- package/src/composed/AddToCart.tsx +229 -0
- package/src/composed/ArtAlignment.tsx +703 -0
- package/src/composed/ArtSelector.tsx +290 -0
- package/src/composed/ArtworkCustomizer.tsx +212 -0
- package/src/composed/CanvasEditor.tsx +79 -0
- package/src/composed/ColorPicker.tsx +111 -0
- package/src/composed/CurrentSelectionDisplay.tsx +86 -0
- package/src/composed/HeroProductImage.tsx +1071 -0
- package/src/composed/Lightbox.index.ts +2 -0
- package/src/composed/Lightbox.tsx +230 -0
- package/src/composed/PlacementClipShapeSelector.tsx +88 -0
- package/src/composed/PlacementTabs.tsx +179 -0
- package/src/composed/ProductCard.tsx +298 -0
- package/src/composed/ProductGallery.tsx +54 -0
- package/src/composed/ProductImage.tsx +129 -0
- package/src/composed/ProductList.tsx +147 -0
- package/src/composed/ProductOptions.tsx +305 -0
- package/src/composed/RealtimeMockup.tsx +121 -0
- package/src/composed/TileCount.tsx +348 -0
- package/src/composed/carousels/HeroCarousel.tsx +240 -0
- package/src/composed/carousels/MobileProductCarousel.tsx +1002 -0
- package/src/composed/carousels/index.ts +11 -0
- package/src/composed/carousels/types.ts +58 -0
- package/src/composed/grids/MasonryGrid.tsx +238 -0
- package/src/composed/grids/index.ts +9 -0
- package/src/composed/search/CurrentRefinements.tsx +80 -0
- package/src/composed/search/Filters.tsx +49 -0
- package/src/composed/search/FiltersButton.tsx +57 -0
- package/src/composed/search/FiltersDrawer.tsx +375 -0
- package/src/composed/search/ProductGrid.tsx +118 -0
- package/src/composed/search/ProductHit.tsx +56 -0
- package/src/composed/search/SearchBox.tsx +109 -0
- package/src/composed/search/SearchProvider.tsx +136 -0
- package/src/composed/search/facetConfig.ts +16 -0
- package/src/composed/search/index.ts +22 -0
- package/src/composed/search/meilisearchAdapter.ts +20 -0
- package/src/composed/search/types.ts +22 -0
- package/src/composed/zoom/EnhancedImageViewer.tsx +505 -0
- package/src/composed/zoom/ResponsiveZoom.tsx +134 -0
- package/src/composed/zoom/ZoomOverlay.tsx +194 -0
- package/src/composed/zoom/index.ts +12 -0
- package/src/composed/zoom/types.ts +12 -0
- package/src/design-system/ColorPalette.tsx +126 -0
- package/src/design-system/ColorSwatch.tsx +49 -0
- package/src/design-system/DesignSystemPage.tsx +130 -0
- package/src/design-system/ThemeSwitcher.tsx +181 -0
- package/src/design-system/TypographyScale.tsx +106 -0
- package/src/design-system/index.ts +5 -0
- package/src/ecommerce/stories/HeroProductImage.stories.tsx +66 -0
- package/src/ecommerce/stories/PDPHeroGallery.stories.tsx +105 -0
- package/src/ecommerce/stories/PDPInfoPanel.stories.tsx +472 -0
- package/src/ecommerce/stories/PDPLayout.stories.tsx +365 -0
- package/src/hooks/useBrand.ts +41 -0
- package/src/hooks/useCanvasContext.ts +127 -0
- package/src/hooks/useDeviceDetection.ts +64 -0
- package/src/hooks/useFocusTrap.ts +70 -0
- package/src/hooks/useImagePreloader.ts +268 -0
- package/src/hooks/useImageTransition.ts +608 -0
- package/src/hooks/usePlacementsProcessor.ts +74 -0
- package/src/hooks/useProductGallery.ts +193 -0
- package/src/hooks/useProductPage.ts +467 -0
- package/src/hooks/useRenderGuard.ts +96 -0
- package/src/hooks/useScrollDirection.ts +196 -0
- package/src/hooks/viewport/index.ts +25 -0
- package/src/hooks/viewport/useContainerWidth.ts +59 -0
- package/src/hooks/viewport/useMediaQuery.ts +52 -0
- package/src/hooks/viewport/useResponsiveImageCap.ts +149 -0
- package/src/hooks/viewport/useViewportDimensions.ts +135 -0
- package/src/hooks/viewport/useWideMonitorMode.ts +150 -0
- package/src/hooks/visibility/index.ts +15 -0
- package/src/hooks/visibility/observerPool.ts +150 -0
- package/src/index.ts +240 -0
- package/src/layouts/hero-zoom/HeroShrinkLayout.tsx +209 -0
- package/src/layouts/hero-zoom/HeroZoomLayout.tsx +351 -0
- package/src/layouts/hero-zoom/index.ts +30 -0
- package/src/layouts/hero-zoom/stories/HeroZoomLayout.stories.tsx +350 -0
- package/src/layouts/hero-zoom/types.ts +113 -0
- package/src/layouts/hero-zoom/useHeroZoomScales.ts +156 -0
- package/src/layouts/index.ts +9 -0
- package/src/layouts/pdp/EdgeBlurBox.tsx +210 -0
- package/src/layouts/pdp/ImageBlurExtension.tsx +215 -0
- package/src/layouts/pdp/ImageEdgeBlur.tsx +215 -0
- package/src/layouts/pdp/PDPLayout.tsx +246 -0
- package/src/layouts/pdp/SimpleImageBlur.tsx +140 -0
- package/src/layouts/pdp/index.ts +40 -0
- package/src/lib/env.ts +15 -0
- package/src/lib/locale.ts +167 -0
- package/src/lib/router.tsx +46 -0
- package/src/lib/utils.ts +6 -0
- package/src/lightbox/README.md +77 -0
- package/src/next/index.tsx +26 -0
- package/src/patterns/MockupPriorityProvider.tsx +1014 -0
- package/src/patterns/Product.tsx +850 -0
- package/src/patterns/ProductPageProvider.tsx +224 -0
- package/src/patterns/RealtimeProvider.tsx +1162 -0
- package/src/patterns/ShopProvider.tsx +603 -0
- package/src/personalization/PersonalizationBridge.tsx +235 -0
- package/src/personalization/PersonalizationContext.ts +29 -0
- package/src/personalization/PersonalizationInputs.tsx +110 -0
- package/src/personalization/PersonalizationProvider.tsx +407 -0
- package/src/personalization/canvas-stub.d.ts +22 -0
- package/src/personalization/index.ts +43 -0
- package/src/personalization/types.ts +48 -0
- package/src/personalization/usePersonalization.ts +32 -0
- package/src/personalization/usePersonalizationShimmer.ts +159 -0
- package/src/personalization/utils.ts +59 -0
- package/src/primitives/BrandLogo.tsx +65 -0
- package/src/primitives/BrandName.tsx +51 -0
- package/src/primitives/Button.tsx +123 -0
- package/src/primitives/ColorSwatch.tsx +221 -0
- package/src/primitives/DragHintAnimation.tsx +190 -0
- package/src/primitives/EdgeSwipeGuards.tsx +60 -0
- package/src/primitives/FloatingActionGroup.tsx +176 -0
- package/src/primitives/ProductPrice.tsx +171 -0
- package/src/primitives/ProgressiveBlur.tsx +295 -0
- package/src/primitives/ThemeToggle.tsx +125 -0
- package/src/primitives/__tests__/story-coverage.test.ts +98 -0
- package/src/primitives/accordion.tsx +280 -0
- package/src/primitives/badge.tsx +137 -0
- package/src/primitives/card.tsx +61 -0
- package/src/primitives/checkbox.tsx +56 -0
- package/src/primitives/collapsible.tsx +51 -0
- package/src/primitives/drawer.tsx +828 -0
- package/src/primitives/dropdown-menu.tsx +197 -0
- package/src/primitives/fieldset.tsx +73 -0
- package/src/primitives/index.ts +138 -0
- package/src/primitives/input.tsx +91 -0
- package/src/primitives/kbd.tsx +130 -0
- package/src/primitives/label.tsx +20 -0
- package/src/primitives/link.tsx +182 -0
- package/src/primitives/popover.tsx +80 -0
- package/src/primitives/radio-group.tsx +79 -0
- package/src/primitives/scroll-fade.tsx +159 -0
- package/src/primitives/select.tsx +170 -0
- package/src/primitives/separator.tsx +25 -0
- package/src/primitives/slider.tsx +221 -0
- package/src/primitives/spinner.tsx +72 -0
- package/src/primitives/stories/Accordion.stories.tsx +121 -0
- package/src/primitives/stories/Badge.stories.tsx +221 -0
- package/src/primitives/stories/Button.stories.tsx +185 -0
- package/src/primitives/stories/Card.stories.tsx +171 -0
- package/src/primitives/stories/Checkbox.stories.tsx +214 -0
- package/src/primitives/stories/Collapsible.stories.tsx +230 -0
- package/src/primitives/stories/Drawer.stories.tsx +378 -0
- package/src/primitives/stories/DropdownMenu.stories.tsx +182 -0
- package/src/primitives/stories/Fieldset.stories.tsx +212 -0
- package/src/primitives/stories/Input.stories.tsx +172 -0
- package/src/primitives/stories/Kbd.stories.tsx +183 -0
- package/src/primitives/stories/Label.stories.tsx +98 -0
- package/src/primitives/stories/Link.stories.tsx +260 -0
- package/src/primitives/stories/Popover.stories.tsx +178 -0
- package/src/primitives/stories/RadioGroup.stories.tsx +205 -0
- package/src/primitives/stories/Select.stories.tsx +222 -0
- package/src/primitives/stories/Separator.stories.tsx +134 -0
- package/src/primitives/stories/Slider.stories.tsx +203 -0
- package/src/primitives/stories/Spinner.stories.tsx +142 -0
- package/src/primitives/stories/Surface.stories.tsx +257 -0
- package/src/primitives/stories/Switch.stories.tsx +131 -0
- package/src/primitives/stories/Tabs.stories.tsx +275 -0
- package/src/primitives/stories/TextField.stories.tsx +139 -0
- package/src/primitives/stories/Textarea.stories.tsx +148 -0
- package/src/primitives/stories/Tooltip.stories.tsx +119 -0
- package/src/primitives/surface.tsx +86 -0
- package/src/primitives/switch.tsx +35 -0
- package/src/primitives/tabs.tsx +206 -0
- package/src/primitives/text-field.tsx +84 -0
- package/src/primitives/textarea.tsx +50 -0
- package/src/primitives/tooltip.tsx +58 -0
- package/src/services/CanvasExportService.ts +518 -0
- package/src/styles/base.css +380 -0
- package/src/styles/defaults.css +280 -0
- package/src/styles/globals.css +1242 -0
- package/src/styles/index.css +17 -0
- package/src/styles/ne-themes.css +4740 -0
- package/src/styles/tailwind.css +11 -0
- package/src/styles/tokens.css +117 -0
- package/src/styles/utilities.css +188 -0
- package/src/themes/apply-theme.ts +449 -0
- package/src/themes/getThemeStyles.ts +454 -0
- package/src/themes/index.ts +48 -0
- package/src/themes/oklch-theme.ts +283 -0
- package/src/themes/presets.ts +989 -0
- package/src/themes/types.ts +386 -0
- package/src/themes/useTheme.tsx +450 -0
- package/src/utils/dev-warnings.ts +161 -0
- package/src/utils/devWarnings.ts +153 -0
- package/dist/styles.css +0 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* OKLCH THEME SYSTEM - Quick Reference
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* This module generates all theme colors from a hue + chroma definition.
|
|
7
|
+
* Colors are computed algorithmically for consistent contrast and readability.
|
|
8
|
+
*
|
|
9
|
+
* ┌─────────────────────────────────────────────────────────────────────────┐
|
|
10
|
+
* │ SEMANTIC VARIABLES │
|
|
11
|
+
* ├─────────────────────────────────────────────────────────────────────────┤
|
|
12
|
+
* │ │
|
|
13
|
+
* │ SURFACES (neutral backgrounds) │
|
|
14
|
+
* │ ────────────────────────────── │
|
|
15
|
+
* │ --color-background Page background (darkest in dark mode) │
|
|
16
|
+
* │ --color-surface Cards, panels, modals │
|
|
17
|
+
* │ --color-surface-raised Popovers, dropdowns (on top of surface) │
|
|
18
|
+
* │ --color-muted Muted areas, switch/slider tracks │
|
|
19
|
+
* │ │
|
|
20
|
+
* │ FIELDS (form inputs - context-aware) │
|
|
21
|
+
* │ ──────────────────────────────────── │
|
|
22
|
+
* │ --color-field Field on page/transparent bg │
|
|
23
|
+
* │ --color-field-on-surface Field inside Surface/Card (auto-detected) │
|
|
24
|
+
* │ │
|
|
25
|
+
* │ TEXT (always neutral - no color tint) │
|
|
26
|
+
* │ ───────────────────────────────────── │
|
|
27
|
+
* │ --color-foreground Primary text │
|
|
28
|
+
* │ --color-muted-foreground Secondary/muted text │
|
|
29
|
+
* │ │
|
|
30
|
+
* │ ACCENTS (uses theme hue + chroma) │
|
|
31
|
+
* │ ──────────────────────────────── │
|
|
32
|
+
* │ --color-primary Brand accent color │
|
|
33
|
+
* │ --color-secondary Secondary accent │
|
|
34
|
+
* │ --color-border Dividers and borders │
|
|
35
|
+
* │ │
|
|
36
|
+
* └─────────────────────────────────────────────────────────────────────────┘
|
|
37
|
+
*
|
|
38
|
+
* USAGE IN COMPONENTS:
|
|
39
|
+
* - Use `bg-surface` for Card/Surface backgrounds
|
|
40
|
+
* - Use `bg-muted` for hover states, tracks, muted areas
|
|
41
|
+
* - Use `bg-[var(--color-field-on-surface)]` for fields inside surfaces
|
|
42
|
+
* - Use `useSurface()` hook to detect surface context automatically
|
|
43
|
+
*
|
|
44
|
+
* DO NOT USE: content1, content2, content3, content4 (legacy, removed)
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
import type { OklchThemeConfig } from './types';
|
|
48
|
+
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// SEMANTIC LIGHTNESS VALUES
|
|
51
|
+
// =============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Lightness values with semantic names.
|
|
55
|
+
* Each value describes WHAT it's for, not an abstract "level".
|
|
56
|
+
*/
|
|
57
|
+
export const LIGHTNESS = {
|
|
58
|
+
dark: {
|
|
59
|
+
// Page & Surfaces
|
|
60
|
+
background: 0.12, // Page background (darkest)
|
|
61
|
+
surface: 0.16, // Cards, panels (~#18181b)
|
|
62
|
+
surfaceRaised: 0.25, // Popovers, dropdowns, muted backgrounds
|
|
63
|
+
surfaceHover: 0.25, // Hover state for surfaces
|
|
64
|
+
|
|
65
|
+
// Form Fields
|
|
66
|
+
field: 0.16, // Field bg on transparent/page (same as surface)
|
|
67
|
+
fieldOnSurface: 0.20, // Field bg inside Surface/Card (~#252528)
|
|
68
|
+
|
|
69
|
+
// Text
|
|
70
|
+
foreground: 0.96, // Primary text (near white)
|
|
71
|
+
foregroundMuted: 0.65, // Secondary text
|
|
72
|
+
|
|
73
|
+
// Accents
|
|
74
|
+
primary: 0.70, // Primary brand color
|
|
75
|
+
primaryHover: 0.75, // Primary hover state
|
|
76
|
+
secondary: 0.68, // Secondary accent
|
|
77
|
+
|
|
78
|
+
// Borders
|
|
79
|
+
border: 0.25, // Dividers, borders
|
|
80
|
+
},
|
|
81
|
+
light: {
|
|
82
|
+
// Page & Surfaces
|
|
83
|
+
background: 0.97, // Page background (near white)
|
|
84
|
+
surface: 1.0, // Cards, panels (pure white)
|
|
85
|
+
surfaceRaised: 0.94, // Popovers, dropdowns, muted backgrounds
|
|
86
|
+
surfaceHover: 0.94, // Hover state
|
|
87
|
+
|
|
88
|
+
// Form Fields
|
|
89
|
+
field: 1.0, // Field bg on transparent/page (white)
|
|
90
|
+
fieldOnSurface: 0.96, // Field bg inside Surface/Card (subtle gray)
|
|
91
|
+
|
|
92
|
+
// Text
|
|
93
|
+
foreground: 0.15, // Primary text (near black)
|
|
94
|
+
foregroundMuted: 0.45, // Secondary text
|
|
95
|
+
|
|
96
|
+
// Accents
|
|
97
|
+
primary: 0.55, // Primary brand color
|
|
98
|
+
primaryHover: 0.50, // Primary hover (darker)
|
|
99
|
+
secondary: 0.45, // Secondary accent
|
|
100
|
+
|
|
101
|
+
// Borders
|
|
102
|
+
border: 0.85, // Dividers, borders
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Chroma values - how much color tint to add
|
|
108
|
+
*
|
|
109
|
+
* DESIGN PRINCIPLE: Text is always neutral, theme color is for accents only.
|
|
110
|
+
* - Text (foreground, heading, muted) = 0 chroma (pure grayscale)
|
|
111
|
+
* - Backgrounds/surfaces = 0 chroma (neutral)
|
|
112
|
+
* - Accents (primary, icons, links) = full theme chroma
|
|
113
|
+
*/
|
|
114
|
+
export const CHROMA = {
|
|
115
|
+
neutral: 0, // For all non-accent colors (text, surfaces, borders)
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// =============================================================================
|
|
119
|
+
// COLOR GENERATION FUNCTIONS
|
|
120
|
+
// =============================================================================
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Generate an OKLCH color string
|
|
124
|
+
*/
|
|
125
|
+
export function oklch(lightness: number, chroma: number, hue: number): string {
|
|
126
|
+
const l = Math.max(0, Math.min(1, lightness));
|
|
127
|
+
const c = Math.max(0, Math.min(0.4, chroma));
|
|
128
|
+
const h = ((hue % 360) + 360) % 360;
|
|
129
|
+
return `oklch(${(l * 100).toFixed(1)}% ${c.toFixed(4)} ${h.toFixed(1)})`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Generate all CSS color variables for a theme
|
|
134
|
+
*
|
|
135
|
+
* Variable naming convention:
|
|
136
|
+
* - `--color-{name}` is the canonical form
|
|
137
|
+
* - `--{name}` is an alias for convenience
|
|
138
|
+
*/
|
|
139
|
+
export function generateThemeVariables(config: OklchThemeConfig): Record<string, string> {
|
|
140
|
+
const { hue, isDark, chroma: primaryChroma = 0.18, primaryLightness } = config;
|
|
141
|
+
const L = isDark ? LIGHTNESS.dark : LIGHTNESS.light;
|
|
142
|
+
|
|
143
|
+
// Allow per-theme override of primary lightness
|
|
144
|
+
const effectivePrimaryL = primaryLightness ?? L.primary;
|
|
145
|
+
|
|
146
|
+
// Calculate primary foreground based on primary lightness
|
|
147
|
+
const primaryFgLightness = effectivePrimaryL > 0.6 ? 0.12 : 0.96;
|
|
148
|
+
|
|
149
|
+
const vars: Record<string, string> = {
|
|
150
|
+
// =========================================================================
|
|
151
|
+
// BACKGROUND - Page level
|
|
152
|
+
// =========================================================================
|
|
153
|
+
'--color-background': oklch(L.background, CHROMA.neutral, hue),
|
|
154
|
+
'--background': oklch(L.background, CHROMA.neutral, hue),
|
|
155
|
+
|
|
156
|
+
// =========================================================================
|
|
157
|
+
// SURFACE - Cards, panels, modals
|
|
158
|
+
// =========================================================================
|
|
159
|
+
'--color-surface': oklch(L.surface, CHROMA.neutral, hue),
|
|
160
|
+
'--color-card': oklch(L.surface, CHROMA.neutral, hue),
|
|
161
|
+
'--surface': oklch(L.surface, CHROMA.neutral, hue),
|
|
162
|
+
|
|
163
|
+
// Raised surface (popovers, dropdowns on top of surface)
|
|
164
|
+
'--color-surface-raised': oklch(L.surfaceRaised, CHROMA.neutral, hue),
|
|
165
|
+
'--color-popover': oklch(L.surfaceRaised, CHROMA.neutral, hue),
|
|
166
|
+
|
|
167
|
+
// =========================================================================
|
|
168
|
+
// FIELDS - Form inputs
|
|
169
|
+
// =========================================================================
|
|
170
|
+
// Field on transparent/page background
|
|
171
|
+
'--color-field': oklch(L.field, CHROMA.neutral, hue),
|
|
172
|
+
|
|
173
|
+
// Field inside Surface/Card (needs contrast with surface)
|
|
174
|
+
'--color-field-on-surface': oklch(L.fieldOnSurface, CHROMA.neutral, hue),
|
|
175
|
+
|
|
176
|
+
// =========================================================================
|
|
177
|
+
// FOREGROUND - Text colors
|
|
178
|
+
// =========================================================================
|
|
179
|
+
'--color-foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
180
|
+
'--foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
181
|
+
'--color-heading': oklch(L.foreground, CHROMA.neutral, hue),
|
|
182
|
+
'--color-card-foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
183
|
+
'--color-popover-foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
184
|
+
|
|
185
|
+
// Muted text
|
|
186
|
+
'--color-muted-foreground': oklch(L.foregroundMuted, CHROMA.neutral, hue),
|
|
187
|
+
'--muted-foreground': oklch(L.foregroundMuted, CHROMA.neutral, hue),
|
|
188
|
+
|
|
189
|
+
// =========================================================================
|
|
190
|
+
// PRIMARY - Brand accent
|
|
191
|
+
// =========================================================================
|
|
192
|
+
'--color-primary': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
193
|
+
'--primary': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
194
|
+
'--color-accent': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
195
|
+
'--accent': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
196
|
+
'--color-ring': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
197
|
+
'--focus': oklch(effectivePrimaryL, primaryChroma, hue),
|
|
198
|
+
|
|
199
|
+
// Primary foreground (text on primary bg)
|
|
200
|
+
'--color-primary-foreground': oklch(primaryFgLightness, CHROMA.neutral, hue),
|
|
201
|
+
'--primary-foreground': oklch(primaryFgLightness, CHROMA.neutral, hue),
|
|
202
|
+
'--color-accent-foreground': oklch(primaryFgLightness, CHROMA.neutral, hue),
|
|
203
|
+
|
|
204
|
+
// =========================================================================
|
|
205
|
+
// SECONDARY - Secondary accent
|
|
206
|
+
// =========================================================================
|
|
207
|
+
'--color-secondary': oklch(L.secondary, primaryChroma * 0.8, hue),
|
|
208
|
+
'--secondary': oklch(L.secondary, primaryChroma * 0.8, hue),
|
|
209
|
+
'--color-secondary-foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
210
|
+
'--secondary-foreground': oklch(L.foreground, CHROMA.neutral, hue),
|
|
211
|
+
|
|
212
|
+
// =========================================================================
|
|
213
|
+
// BORDER - Dividers, borders
|
|
214
|
+
// =========================================================================
|
|
215
|
+
'--color-border': oklch(L.border, CHROMA.neutral, hue),
|
|
216
|
+
'--border': oklch(L.border, CHROMA.neutral, hue),
|
|
217
|
+
'--color-divider': oklch(L.border, CHROMA.neutral, hue),
|
|
218
|
+
'--divider': oklch(L.border, CHROMA.neutral, hue),
|
|
219
|
+
|
|
220
|
+
// =========================================================================
|
|
221
|
+
// MUTED - Muted backgrounds
|
|
222
|
+
// =========================================================================
|
|
223
|
+
'--color-muted': oklch(L.surfaceRaised, CHROMA.neutral, hue),
|
|
224
|
+
'--muted': oklch(L.surfaceRaised, CHROMA.neutral, hue),
|
|
225
|
+
|
|
226
|
+
// =========================================================================
|
|
227
|
+
// ICON - Icon colors (uses primary with reduced chroma)
|
|
228
|
+
// =========================================================================
|
|
229
|
+
'--color-icon': oklch(isDark ? 0.75 : 0.55, primaryChroma * 0.7, hue),
|
|
230
|
+
|
|
231
|
+
// =========================================================================
|
|
232
|
+
// ACCENT TEXT - For overlays and labels
|
|
233
|
+
// =========================================================================
|
|
234
|
+
'--color-accent-text-overlay': oklch(isDark ? 0.75 : 0.45, primaryChroma * 0.5, hue),
|
|
235
|
+
'--color-accent-text-page': oklch(isDark ? 0.60 : 0.50, primaryChroma * 0.5, hue),
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
return vars;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Apply OKLCH theme to DOM
|
|
243
|
+
*/
|
|
244
|
+
export function applyOklchTheme(
|
|
245
|
+
config: OklchThemeConfig,
|
|
246
|
+
root: HTMLElement = document.documentElement
|
|
247
|
+
): void {
|
|
248
|
+
const vars = generateThemeVariables(config);
|
|
249
|
+
|
|
250
|
+
// Apply all CSS variables
|
|
251
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
252
|
+
root.style.setProperty(key, value);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Apply dark mode class and color scheme
|
|
256
|
+
if (config.isDark) {
|
|
257
|
+
root.classList.add('dark');
|
|
258
|
+
root.classList.remove('light');
|
|
259
|
+
root.style.colorScheme = 'dark';
|
|
260
|
+
} else {
|
|
261
|
+
root.classList.remove('dark');
|
|
262
|
+
root.classList.add('light');
|
|
263
|
+
root.style.colorScheme = 'light';
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Set data-theme attribute for CSS selectors
|
|
267
|
+
const themeId = `ne-${config.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
|
|
268
|
+
root.setAttribute('data-theme', themeId);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get theme styles as an object (for SSR/React style prop)
|
|
273
|
+
*/
|
|
274
|
+
export function getOklchThemeStyles(config: OklchThemeConfig): Record<string, string> {
|
|
275
|
+
const vars = generateThemeVariables(config);
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
...vars,
|
|
279
|
+
colorScheme: config.isDark ? 'dark' : 'light',
|
|
280
|
+
backgroundColor: vars['--background'],
|
|
281
|
+
color: vars['--foreground'],
|
|
282
|
+
};
|
|
283
|
+
}
|