@hilum/ui 3.8.6 → 3.10.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/README.md +32 -1
- package/dist/{chunk-RI6QJR2L.js → chunk-R576DV2A.js} +120 -14
- package/dist/chunk-R576DV2A.js.map +1 -0
- package/dist/create-theme.js +2 -1
- package/dist/create-theme.js.map +1 -1
- package/dist/index.d.ts +733 -68
- package/dist/index.js +3097 -1619
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +163 -19
- package/dist/tokens.d.ts +69 -5
- package/dist/tokens.js +1 -1
- package/llms.txt +11 -4
- package/package.json +11 -10
- package/src/components/accordion.tsx +2 -2
- package/src/components/account-menu.tsx +1 -1
- package/src/components/alert-dialog.tsx +107 -0
- package/src/components/ask-user-questions.tsx +24 -18
- package/src/components/badge.tsx +36 -3
- package/src/components/breadcrumb.tsx +4 -2
- package/src/components/button-group.tsx +1 -1
- package/src/components/button.tsx +31 -23
- package/src/components/calendar.tsx +1 -1
- package/src/components/card.tsx +4 -2
- package/src/components/checkbox-card.tsx +1 -1
- package/src/components/checkbox-group.tsx +2 -1
- package/src/components/code-block.tsx +99 -0
- package/src/components/color-input.tsx +9 -6
- package/src/components/color-picker.tsx +38 -26
- package/src/components/combobox.tsx +59 -12
- package/src/components/command-palette.tsx +150 -42
- package/src/components/command.tsx +5 -3
- package/src/components/context-menu.tsx +18 -15
- package/src/components/contextual-save-bar.tsx +156 -0
- package/src/components/data-table.tsx +34 -5
- package/src/components/date-picker.tsx +275 -28
- package/src/components/date-text.tsx +90 -0
- package/src/components/dropdown-menu.tsx +11 -8
- package/src/components/dropdown.tsx +6 -3
- package/src/components/empty-state.tsx +85 -20
- package/src/components/file-dropzone.tsx +2 -1
- package/src/components/file-thumbnail.tsx +84 -20
- package/src/components/filter-bar.tsx +91 -0
- package/src/components/grid-list.tsx +2 -2
- package/src/components/help-tooltip.tsx +1 -1
- package/src/components/input-copy.tsx +1 -1
- package/src/components/input-group.tsx +1 -1
- package/src/components/input-message.tsx +5 -4
- package/src/components/input-number.tsx +103 -11
- package/src/components/input.tsx +5 -3
- package/src/components/label.tsx +1 -0
- package/src/components/media-asset-card.tsx +1 -1
- package/src/components/menu-item.tsx +37 -3
- package/src/components/menubar.tsx +21 -18
- package/src/components/native-select.tsx +1 -1
- package/src/components/navigation-menu.tsx +2 -2
- package/src/components/notification.tsx +1 -1
- package/src/components/pagination.tsx +97 -3
- package/src/components/popover.tsx +2 -0
- package/src/components/property-row.tsx +7 -4
- package/src/components/radio-card.tsx +1 -1
- package/src/components/radio-group.tsx +2 -1
- package/src/components/rating.tsx +136 -0
- package/src/components/resizable.tsx +1 -1
- package/src/components/resource-item.tsx +133 -0
- package/src/components/rich-text-editor.tsx +1 -0
- package/src/components/search-input.tsx +98 -0
- package/src/components/searchable-table.tsx +10 -11
- package/src/components/select.tsx +28 -9
- package/src/components/sidebar.tsx +4 -4
- package/src/components/slider.tsx +78 -36
- package/src/components/sonner.tsx +18 -4
- package/src/components/stat-card.tsx +121 -37
- package/src/components/status-badge.tsx +142 -47
- package/src/components/status-tile.tsx +9 -0
- package/src/components/switch.tsx +6 -5
- package/src/components/tabs-subtle.tsx +10 -2
- package/src/components/tabs.tsx +23 -3
- package/src/components/textarea.tsx +2 -3
- package/src/components/thinking-steps.tsx +3 -3
- package/src/components/toggle.tsx +14 -13
- package/src/components/tooltip.tsx +11 -8
- package/src/components/url-redirect-prompt.tsx +0 -1
- package/src/index.ts +15 -0
- package/src/lib/density-context.tsx +65 -0
- package/src/lib/format.tsx +301 -0
- package/src/lib/interaction.ts +12 -4
- package/src/lib/scroll-fade.tsx +39 -0
- package/src/tokens/tokens.test.ts +77 -0
- package/src/tokens/tokens.ts +114 -5
- package/dist/chunk-RI6QJR2L.js.map +0 -1
package/README.md
CHANGED
|
@@ -18,7 +18,27 @@ In your app's `globals.css`:
|
|
|
18
18
|
@import "@hilum/ui/fonts.css";
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
These imports provide the palette, typography, fonts, light/dark theming and the surface elevation ladder (`bg-surface-1…8`, `shadow-surface-1…8`).
|
|
22
|
+
|
|
23
|
+
### Tailwind class scanning (`@source`)
|
|
24
|
+
|
|
25
|
+
Tailwind v4 only generates utilities for class names it finds in scanned files, and it doesn't scan `node_modules` by default.
|
|
26
|
+
|
|
27
|
+
- **`@hilum/ui`**: `tokens.css` contains `@source "../src";`, resolved relative to the file itself (`node_modules/@hilum/ui/dist/tokens.css` → `node_modules/@hilum/ui/src`, which ships in the package). This only works when your Tailwind build resolves `@import "@hilum/ui/tokens.css"` to the real file, which `@tailwindcss/vite`, `@tailwindcss/postcss` and the CLI all do. If components come out unstyled, add the path yourself (relative to your CSS file):
|
|
28
|
+
|
|
29
|
+
```css
|
|
30
|
+
@source "../node_modules/@hilum/ui/src";
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- **`@hilum/app-shell`, `@hilum/designer`, `@hilum/designer-canvas`**: these don't ship `src`, and `tokens.css` doesn't cover them. Add an `@source` for each one you use, pointing at its `dist`:
|
|
34
|
+
|
|
35
|
+
```css
|
|
36
|
+
@source "../node_modules/@hilum/app-shell/dist";
|
|
37
|
+
@source "../node_modules/@hilum/designer/dist";
|
|
38
|
+
@source "../node_modules/@hilum/designer-canvas/dist";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
In a monorepo with hoisted dependencies, adjust the relative path (for example `../../../node_modules/...`).
|
|
22
42
|
|
|
23
43
|
## Usage
|
|
24
44
|
|
|
@@ -48,6 +68,17 @@ tokens.brand.secondary; // "#FFF5BF"
|
|
|
48
68
|
tokens.ground[500]; // "#737373"
|
|
49
69
|
```
|
|
50
70
|
|
|
71
|
+
## PDF previews (`FileThumbnail`)
|
|
72
|
+
|
|
73
|
+
PDF thumbnails use pdf.js, which needs a worker script. By default it loads from jsDelivr (matching the installed `pdfjs-dist` version). To self-host (strict CSP, offline apps), set it once at startup, or per component with the `pdfWorkerSrc` prop:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { setPdfWorkerSrc } from "@hilum/ui";
|
|
77
|
+
import workerSrc from "pdfjs-dist/build/pdf.worker.min.mjs?url"; // Vite
|
|
78
|
+
|
|
79
|
+
setPdfWorkerSrc(workerSrc);
|
|
80
|
+
```
|
|
81
|
+
|
|
51
82
|
## Theming
|
|
52
83
|
|
|
53
84
|
Light/dark mode works automatically via `prefers-color-scheme`. Override explicitly:
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
// src/tokens/tokens.ts
|
|
2
|
+
var surfaceShadowRamp = (ring, drop) => {
|
|
3
|
+
const layers = [
|
|
4
|
+
`0 0 0 1px ${ring}`,
|
|
5
|
+
`0 1px 1px -0.5px ${drop(0.06)}, 0 3px 3px -1.5px ${drop(0.06)}`,
|
|
6
|
+
`0 6px 6px -3px ${drop(0.06)}`,
|
|
7
|
+
`0 12px 12px -6px ${drop(0.04)}`,
|
|
8
|
+
`0 24px 24px -12px ${drop(0.04)}`,
|
|
9
|
+
`0 24px 24px 2px ${drop(0.08)}`,
|
|
10
|
+
`0 32px 40px 4px ${drop(0.1)}`,
|
|
11
|
+
`0 48px 56px 8px ${drop(0.12)}`
|
|
12
|
+
];
|
|
13
|
+
return [1, 2, 3, 4, 5, 6, 7, 8].map((level) => layers.slice(0, level).join(", "));
|
|
14
|
+
};
|
|
2
15
|
var tokens = {
|
|
3
16
|
/* ============================================================== *
|
|
4
17
|
* PALETTE — concrete colors *
|
|
@@ -67,9 +80,14 @@ var tokens = {
|
|
|
67
80
|
// ground-50
|
|
68
81
|
surfaceForeground: "#262626",
|
|
69
82
|
// ground-800
|
|
70
|
-
|
|
71
|
-
//
|
|
72
|
-
|
|
83
|
+
// ground-200 on white ≈ 1.26:1 — the same hairline weight Figma/Linear use
|
|
84
|
+
// for panel and field edges (#f5f5f5 was ~1.09:1 and read as invisible).
|
|
85
|
+
border: "#e5e5e5",
|
|
86
|
+
// ground-200
|
|
87
|
+
borderStrong: "#d4d4d4",
|
|
88
|
+
// ground-300 — hover / emphasised edges
|
|
89
|
+
input: "#e5e5e5",
|
|
90
|
+
// input edge (border-input) — matches border
|
|
73
91
|
muted: "#fafafa",
|
|
74
92
|
mutedForeground: "#737373",
|
|
75
93
|
// ground-500
|
|
@@ -77,6 +95,10 @@ var tokens = {
|
|
|
77
95
|
// purple-50
|
|
78
96
|
accentForeground: "#740092",
|
|
79
97
|
// purple-700
|
|
98
|
+
// Neutral interaction washes behind `bg-hover` / `bg-active` (tabs,
|
|
99
|
+
// accordions, radio/checkbox groups, ghost + outline buttons).
|
|
100
|
+
hover: "rgba(23, 23, 23, 0.05)",
|
|
101
|
+
active: "rgba(23, 23, 23, 0.08)",
|
|
80
102
|
primary: "#c100f1",
|
|
81
103
|
// purple-500 = brand.primary
|
|
82
104
|
primaryForeground: "#ffffff",
|
|
@@ -93,8 +115,15 @@ var tokens = {
|
|
|
93
115
|
// butter-200 = brand.secondary
|
|
94
116
|
warningForeground: "#171717",
|
|
95
117
|
// ground-900
|
|
96
|
-
ring: "#c100f1"
|
|
118
|
+
ring: "#c100f1",
|
|
97
119
|
// purple-500 = brand.primary
|
|
120
|
+
// Transparency checkerboard (colour picker alpha track, swatches).
|
|
121
|
+
checkerA: "#ffffff",
|
|
122
|
+
checkerB: "#e5e5e5",
|
|
123
|
+
// Editor workspace behind floating chrome (Figma-style grey canvas),
|
|
124
|
+
// one step below panels so they read as raised in every theme.
|
|
125
|
+
canvas: "#f5f5f5"
|
|
126
|
+
// ground-100
|
|
98
127
|
},
|
|
99
128
|
// Mid — a neutral medium-gray theme (from the Pappery designer "mid" palette,
|
|
100
129
|
// mapped onto the ground scale). Sits between light and dark.
|
|
@@ -111,8 +140,10 @@ var tokens = {
|
|
|
111
140
|
surfaceForeground: "#fafafa",
|
|
112
141
|
border: "#a3a3a3",
|
|
113
142
|
// ground-400 (designer border — lighter so it reads on the gray)
|
|
114
|
-
|
|
115
|
-
//
|
|
143
|
+
borderStrong: "#bdbdbd",
|
|
144
|
+
// hover / emphasised edges
|
|
145
|
+
input: "#a3a3a3",
|
|
146
|
+
// input edge (border-input) — matches border
|
|
116
147
|
muted: "#525252",
|
|
117
148
|
// ground-600
|
|
118
149
|
mutedForeground: "#e5e5e5",
|
|
@@ -120,6 +151,8 @@ var tokens = {
|
|
|
120
151
|
accent: "#404040",
|
|
121
152
|
// ground-700 (designer item-hover-bg)
|
|
122
153
|
accentForeground: "#fafafa",
|
|
154
|
+
hover: "rgba(255, 255, 255, 0.08)",
|
|
155
|
+
active: "rgba(255, 255, 255, 0.13)",
|
|
123
156
|
primary: "#c100f1",
|
|
124
157
|
// brand stays consistent across themes
|
|
125
158
|
primaryForeground: "#ffffff",
|
|
@@ -135,7 +168,10 @@ var tokens = {
|
|
|
135
168
|
warning: "#fff5bf",
|
|
136
169
|
// butter-200
|
|
137
170
|
warningForeground: "#171717",
|
|
138
|
-
ring: "#c100f1"
|
|
171
|
+
ring: "#c100f1",
|
|
172
|
+
checkerA: "#8a8a8a",
|
|
173
|
+
checkerB: "#6b6b6b",
|
|
174
|
+
canvas: "#636363"
|
|
139
175
|
},
|
|
140
176
|
dark: {
|
|
141
177
|
background: "#171717",
|
|
@@ -148,10 +184,13 @@ var tokens = {
|
|
|
148
184
|
surface: "#1a1a1a",
|
|
149
185
|
// designer item-hover depth
|
|
150
186
|
surfaceForeground: "#f5f5f5",
|
|
151
|
-
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
187
|
+
// ≈2:1 against the page background and ~1.7:1 against card panels;
|
|
188
|
+
// #404040 (1.73:1 vs bg) blended into panels at small sizes.
|
|
189
|
+
border: "#4a4a4a",
|
|
190
|
+
borderStrong: "#5c5c5c",
|
|
191
|
+
// hover / emphasised edges
|
|
192
|
+
input: "#4a4a4a",
|
|
193
|
+
// input edge (border-input) — matches border
|
|
155
194
|
muted: "#262626",
|
|
156
195
|
// ground-800
|
|
157
196
|
mutedForeground: "#a3a3a3",
|
|
@@ -159,6 +198,8 @@ var tokens = {
|
|
|
159
198
|
accent: "#404040",
|
|
160
199
|
// ground-700 — neutral elevated/hover (designer item-hover)
|
|
161
200
|
accentForeground: "#fafafa",
|
|
201
|
+
hover: "rgba(250, 250, 250, 0.06)",
|
|
202
|
+
active: "rgba(250, 250, 250, 0.1)",
|
|
162
203
|
primary: "#c100f1",
|
|
163
204
|
// purple-500 — brand stays consistent (D8)
|
|
164
205
|
primaryForeground: "#ffffff",
|
|
@@ -175,8 +216,39 @@ var tokens = {
|
|
|
175
216
|
// butter-950 surface
|
|
176
217
|
warningForeground: "#fffad0",
|
|
177
218
|
// butter-100
|
|
178
|
-
ring: "#c100f1"
|
|
219
|
+
ring: "#c100f1",
|
|
179
220
|
// purple-500 = brand.primary
|
|
221
|
+
checkerA: "#4a4a4a",
|
|
222
|
+
checkerB: "#333333",
|
|
223
|
+
canvas: "#1c1c1c"
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
/* ============================================================== *
|
|
227
|
+
* SURFACES — elevation ladder (levels 1–8) *
|
|
228
|
+
* ============================================================== *
|
|
229
|
+
* Consumed via surfaceClasses() / <Elevated> / SurfaceProvider:
|
|
230
|
+
* `bg-surface-N`, `shadow-surface-N`, and the raw `var(--surface-N)`
|
|
231
|
+
* (scroll-fade gradients). Level 1 is the page substrate; each nested
|
|
232
|
+
* layer (popover +2, dialog +4, …) walks up the ladder. Index 0 = level 1.
|
|
233
|
+
*
|
|
234
|
+
* Light: surfaces stay white (matching card/popover) and elevation is
|
|
235
|
+
* carried by the shadow ramp, the house style.
|
|
236
|
+
* Mid/Dark: surfaces step lighter/darker per level so nested layers stay
|
|
237
|
+
* distinguishable where drop shadows barely read. */
|
|
238
|
+
surfaces: {
|
|
239
|
+
light: {
|
|
240
|
+
bg: ["#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff"],
|
|
241
|
+
shadow: surfaceShadowRamp("rgba(0, 0, 0, 0.06)", (a) => `rgba(0, 0, 0, ${a})`)
|
|
242
|
+
},
|
|
243
|
+
mid: {
|
|
244
|
+
// background (#737373) → card (#525252) → ground-700 (#404040)
|
|
245
|
+
bg: ["#737373", "#6b6b6b", "#636363", "#5b5b5b", "#525252", "#4d4d4d", "#474747", "#404040"],
|
|
246
|
+
shadow: surfaceShadowRamp("rgba(0, 0, 0, 0.14)", (a) => `rgba(0, 0, 0, ${Math.min(a * 2.5, 0.3)})`)
|
|
247
|
+
},
|
|
248
|
+
dark: {
|
|
249
|
+
// background (#171717) → card (#262626) → accent (#404040)
|
|
250
|
+
bg: ["#171717", "#1f1f1f", "#262626", "#2b2b2b", "#303030", "#353535", "#3a3a3a", "#404040"],
|
|
251
|
+
shadow: surfaceShadowRamp("rgba(255, 255, 255, 0.08)", (a) => `rgba(0, 0, 0, ${Math.min(a * 4, 0.4)})`)
|
|
180
252
|
}
|
|
181
253
|
},
|
|
182
254
|
/* ============================================================== *
|
|
@@ -252,6 +324,9 @@ var tokens = {
|
|
|
252
324
|
lineHeight: "1.625",
|
|
253
325
|
textWrap: "pretty"
|
|
254
326
|
},
|
|
327
|
+
/** 11px — dense metadata (table sub-lines, chips, editor hints). Use instead of text-[11px]. */
|
|
328
|
+
"caption-sm": { family: "sans", size: "0.6875rem", weight: 400, lineHeight: "1.5" },
|
|
329
|
+
/** 10px — the floor. Use instead of text-[10px]; keep to non-essential metadata. */
|
|
255
330
|
"caption-xs": { family: "sans", size: "0.625rem", weight: 400, lineHeight: "1.625" },
|
|
256
331
|
/* --- "Eyebrow" family — uppercase tracked label used above headlines, --- *
|
|
257
332
|
* on badges, and on section markers. `eyebrow` is the canonical name; *
|
|
@@ -311,6 +386,37 @@ var tokens = {
|
|
|
311
386
|
xl: "calc(0.5rem + 4px)",
|
|
312
387
|
full: "9999px"
|
|
313
388
|
},
|
|
389
|
+
/* ============================================================== *
|
|
390
|
+
* DENSITY — control sizing tiers *
|
|
391
|
+
* ============================================================== *
|
|
392
|
+
* Emitted as `--density-*` custom properties: `:root` carries the
|
|
393
|
+
* default tier, `[data-density="compact"]` the editor-chrome tier.
|
|
394
|
+
* Components switch via the `compact:` Tailwind variant (same
|
|
395
|
+
* attribute); consumers can read the vars for bespoke controls. */
|
|
396
|
+
density: {
|
|
397
|
+
default: {
|
|
398
|
+
controlHeight: "32px",
|
|
399
|
+
inputHeight: "40px",
|
|
400
|
+
rowHeight: "36px",
|
|
401
|
+
text: "14px",
|
|
402
|
+
label: "12px",
|
|
403
|
+
menuItemHeight: "40px",
|
|
404
|
+
menuText: "14px",
|
|
405
|
+
paddingX: "12px",
|
|
406
|
+
radius: "8px"
|
|
407
|
+
},
|
|
408
|
+
compact: {
|
|
409
|
+
controlHeight: "24px",
|
|
410
|
+
inputHeight: "24px",
|
|
411
|
+
rowHeight: "28px",
|
|
412
|
+
text: "12px",
|
|
413
|
+
label: "11px",
|
|
414
|
+
menuItemHeight: "28px",
|
|
415
|
+
menuText: "13px",
|
|
416
|
+
paddingX: "8px",
|
|
417
|
+
radius: "5px"
|
|
418
|
+
}
|
|
419
|
+
},
|
|
314
420
|
/* ============================================================== *
|
|
315
421
|
* Z-INDEX — semantic layering scale *
|
|
316
422
|
* ============================================================== */
|
|
@@ -340,5 +446,5 @@ var tokens = {
|
|
|
340
446
|
};
|
|
341
447
|
|
|
342
448
|
export { tokens };
|
|
343
|
-
//# sourceMappingURL=chunk-
|
|
344
|
-
//# sourceMappingURL=chunk-
|
|
449
|
+
//# sourceMappingURL=chunk-R576DV2A.js.map
|
|
450
|
+
//# sourceMappingURL=chunk-R576DV2A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tokens/tokens.ts"],"names":[],"mappings":"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","file":"chunk-R576DV2A.js","sourcesContent":["// @hilum/ui/tokens — JS-first design tokens (D6).\n//\n// This module is the single source of truth for the Hilum visual identity.\n// A build step (scripts/build-tokens.mjs) reads the compiled output of this\n// file and emits dist/tokens.css for consumers to `@import`.\n//\n// Brand model: D8 — base palette is fixed here. Per-product overrides are\n// applied at runtime via createTheme() in @hilum/ui/create-theme.\n// Color modes: D7 — light + dark, both auto (`prefers-color-scheme`) and\n// explicit via `[data-theme]`.\n//\n// Core brand colors:\n// brand.primary #C100F1 — vivid purple — purple-500 on the scale below\n// brand.secondary #FFF5BF — pale lemon — butter-200 on the scale below\n//\n// ground — neutral spine for text, borders, and structure (values: Tailwind neutral)\n\n// Surface elevation ladder helper. Level 1 is a hairline ring only; every\n// step above adds one more (progressively softer, larger) drop layer, so\n// shadow weight grows monotonically with the surface level. `ring` is the\n// hairline edge colour, `drop` the drop-shadow colour at a given alpha.\nconst surfaceShadowRamp = (ring: string, drop: (alpha: number) => string) => {\n const layers = [\n `0 0 0 1px ${ring}`,\n `0 1px 1px -0.5px ${drop(0.06)}, 0 3px 3px -1.5px ${drop(0.06)}`,\n `0 6px 6px -3px ${drop(0.06)}`,\n `0 12px 12px -6px ${drop(0.04)}`,\n `0 24px 24px -12px ${drop(0.04)}`,\n `0 24px 24px 2px ${drop(0.08)}`,\n `0 32px 40px 4px ${drop(0.1)}`,\n `0 48px 56px 8px ${drop(0.12)}`,\n ];\n return [1, 2, 3, 4, 5, 6, 7, 8].map((level) => layers.slice(0, level).join(\", \"));\n};\n\nexport const tokens = {\n /* ============================================================== *\n * PALETTE — concrete colors *\n * ============================================================== */\n\n ground: {\n 50: \"#fafafa\",\n 100: \"#f5f5f5\",\n 200: \"#e5e5e5\",\n 300: \"#d4d4d4\",\n 400: \"#a3a3a3\",\n 500: \"#737373\",\n 600: \"#525252\",\n 700: \"#404040\",\n 800: \"#262626\",\n 900: \"#171717\",\n 950: \"#0a0a0a\",\n },\n\n // Pale lemon — anchor: butter-200 = #FFF5BF\n butter: {\n 50: \"#ffffe8\",\n 100: \"#fffad0\",\n 200: \"#fff5bf\",\n 300: \"#fde870\",\n 400: \"#f6d42a\",\n 500: \"#dab010\",\n 600: \"#a88008\",\n 700: \"#7c5c04\",\n 800: \"#543e02\",\n 900: \"#382801\",\n 950: \"#221600\",\n },\n\n // Vivid purple — anchor: purple-500 = #C100F1 (brand.primary)\n purple: {\n 50: \"#fdf0ff\",\n 100: \"#f5d6ff\",\n 200: \"#e8a8ff\",\n 300: \"#d870f9\",\n 400: \"#c840f6\",\n 500: \"#c100f1\",\n 600: \"#9c00c0\",\n 700: \"#740092\",\n 800: \"#4e0062\",\n 900: \"#330040\",\n 950: \"#200028\",\n },\n\n // Legacy functional colors — used by components not yet migrated to the new palette.\n brand: {\n primary: \"#C100F1\", // purple-500\n secondary: \"#FFF5BF\", // butter-200\n },\n\n destructive: \"#dc2626\", // red-600\n\n /* ============================================================== *\n * SEMANTIC — what components reference *\n * ============================================================== */\n\n semantic: {\n light: {\n background: \"#ffffff\",\n foreground: \"#171717\", // ground-900\n card: \"#ffffff\",\n cardForeground: \"#171717\",\n surface: \"#fafafa\", // ground-50\n surfaceForeground: \"#262626\", // ground-800\n // ground-200 on white ≈ 1.26:1 — the same hairline weight Figma/Linear use\n // for panel and field edges (#f5f5f5 was ~1.09:1 and read as invisible).\n border: \"#e5e5e5\", // ground-200\n borderStrong: \"#d4d4d4\", // ground-300 — hover / emphasised edges\n input: \"#e5e5e5\", // input edge (border-input) — matches border\n muted: \"#fafafa\",\n mutedForeground: \"#737373\", // ground-500\n accent: \"#fdf0ff\", // purple-50\n accentForeground: \"#740092\", // purple-700\n // Neutral interaction washes behind `bg-hover` / `bg-active` (tabs,\n // accordions, radio/checkbox groups, ghost + outline buttons).\n hover: \"rgba(23, 23, 23, 0.05)\",\n active: \"rgba(23, 23, 23, 0.08)\",\n primary: \"#c100f1\", // purple-500 = brand.primary\n primaryForeground: \"#ffffff\",\n secondary: \"#fafafa\", // ground-50\n secondaryForeground: \"#404040\", // ground-700\n destructive: \"#dc2626\",\n destructiveForeground: \"#ffffff\",\n success: \"#CDEA19\", // lime — functional semantic only\n successForeground: \"#171717\",\n warning: \"#fff5bf\", // butter-200 = brand.secondary\n warningForeground: \"#171717\", // ground-900\n ring: \"#c100f1\", // purple-500 = brand.primary\n // Transparency checkerboard (colour picker alpha track, swatches).\n checkerA: \"#ffffff\",\n checkerB: \"#e5e5e5\",\n // Editor workspace behind floating chrome (Figma-style grey canvas),\n // one step below panels so they read as raised in every theme.\n canvas: \"#f5f5f5\", // ground-100\n },\n // Mid — a neutral medium-gray theme (from the Pappery designer \"mid\" palette,\n // mapped onto the ground scale). Sits between light and dark.\n mid: {\n background: \"#737373\", // ground-500 — main surface (designer panel)\n foreground: \"#fafafa\", // ground-50\n card: \"#525252\", // ground-600 — elevated items (designer item-bg)\n cardForeground: \"#fafafa\",\n surface: \"#525252\", // ground-600 (designer canvas/pane)\n surfaceForeground: \"#fafafa\",\n border: \"#a3a3a3\", // ground-400 (designer border — lighter so it reads on the gray)\n borderStrong: \"#bdbdbd\", // hover / emphasised edges\n input: \"#a3a3a3\", // input edge (border-input) — matches border\n muted: \"#525252\", // ground-600\n mutedForeground: \"#e5e5e5\", // ground-200 (designer text-secondary)\n accent: \"#404040\", // ground-700 (designer item-hover-bg)\n accentForeground: \"#fafafa\",\n hover: \"rgba(255, 255, 255, 0.08)\",\n active: \"rgba(255, 255, 255, 0.13)\",\n primary: \"#c100f1\", // brand stays consistent across themes\n primaryForeground: \"#ffffff\",\n secondary: \"#525252\", // ground-600\n secondaryForeground: \"#fafafa\",\n destructive: \"#ef4444\", // red-500\n destructiveForeground: \"#ffffff\",\n success: \"#CDEA19\", // lime — functional semantic only\n successForeground: \"#171717\",\n warning: \"#fff5bf\", // butter-200\n warningForeground: \"#171717\",\n ring: \"#c100f1\",\n checkerA: \"#8a8a8a\",\n checkerB: \"#6b6b6b\",\n canvas: \"#636363\",\n },\n dark: {\n background: \"#171717\", // ground-900 — designer canvas (deepest)\n foreground: \"#fafafa\", // ground-50\n card: \"#262626\", // ground-800 — designer panel-bg (elevated over bg)\n cardForeground: \"#fafafa\",\n surface: \"#1a1a1a\", // designer item-hover depth\n surfaceForeground: \"#f5f5f5\",\n // ≈2:1 against the page background and ~1.7:1 against card panels;\n // #404040 (1.73:1 vs bg) blended into panels at small sizes.\n border: \"#4a4a4a\",\n borderStrong: \"#5c5c5c\", // hover / emphasised edges\n input: \"#4a4a4a\", // input edge (border-input) — matches border\n muted: \"#262626\", // ground-800\n mutedForeground: \"#a3a3a3\", // ground-400\n accent: \"#404040\", // ground-700 — neutral elevated/hover (designer item-hover)\n accentForeground: \"#fafafa\",\n hover: \"rgba(250, 250, 250, 0.06)\",\n active: \"rgba(250, 250, 250, 0.1)\",\n primary: \"#c100f1\", // purple-500 — brand stays consistent (D8)\n primaryForeground: \"#ffffff\",\n secondary: \"#262626\", // ground-800\n secondaryForeground: \"#f5f5f5\",\n destructive: \"#ef4444\", // red-500 (slightly lighter for dark)\n destructiveForeground: \"#ffffff\",\n success: \"#CDEA19\", // lime — functional semantic only\n successForeground: \"#0a0a0a\",\n warning: \"#221600\", // butter-950 surface\n warningForeground: \"#fffad0\", // butter-100\n ring: \"#c100f1\", // purple-500 = brand.primary\n checkerA: \"#4a4a4a\",\n checkerB: \"#333333\",\n canvas: \"#1c1c1c\",\n },\n },\n\n /* ============================================================== *\n * SURFACES — elevation ladder (levels 1–8) *\n * ============================================================== *\n * Consumed via surfaceClasses() / <Elevated> / SurfaceProvider:\n * `bg-surface-N`, `shadow-surface-N`, and the raw `var(--surface-N)`\n * (scroll-fade gradients). Level 1 is the page substrate; each nested\n * layer (popover +2, dialog +4, …) walks up the ladder. Index 0 = level 1.\n *\n * Light: surfaces stay white (matching card/popover) and elevation is\n * carried by the shadow ramp, the house style.\n * Mid/Dark: surfaces step lighter/darker per level so nested layers stay\n * distinguishable where drop shadows barely read. */\n surfaces: {\n light: {\n bg: [\"#ffffff\", \"#ffffff\", \"#ffffff\", \"#ffffff\", \"#ffffff\", \"#ffffff\", \"#ffffff\", \"#ffffff\"],\n shadow: surfaceShadowRamp(\"rgba(0, 0, 0, 0.06)\", (a) => `rgba(0, 0, 0, ${a})`),\n },\n mid: {\n // background (#737373) → card (#525252) → ground-700 (#404040)\n bg: [\"#737373\", \"#6b6b6b\", \"#636363\", \"#5b5b5b\", \"#525252\", \"#4d4d4d\", \"#474747\", \"#404040\"],\n shadow: surfaceShadowRamp(\"rgba(0, 0, 0, 0.14)\", (a) => `rgba(0, 0, 0, ${Math.min(a * 2.5, 0.3)})`),\n },\n dark: {\n // background (#171717) → card (#262626) → accent (#404040)\n bg: [\"#171717\", \"#1f1f1f\", \"#262626\", \"#2b2b2b\", \"#303030\", \"#353535\", \"#3a3a3a\", \"#404040\"],\n shadow: surfaceShadowRamp(\"rgba(255, 255, 255, 0.08)\", (a) => `rgba(0, 0, 0, ${Math.min(a * 4, 0.4)})`),\n },\n },\n\n /* ============================================================== *\n * TYPOGRAPHY *\n * ============================================================== */\n\n fontFamily: {\n sans: 'Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n display:\n 'Gabarito, Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n mono: 'ui-monospace, \"SFMono-Regular\", \"Menlo\", \"Consolas\", monospace',\n },\n\n /** Type scale utilities — emitted as Tailwind v4 `@utility` blocks. */\n typeScale: {\n \"display-xl\": {\n family: \"display\",\n size: \"3rem\",\n weight: 400,\n lineHeight: \"1.15\",\n textWrap: \"balance\",\n },\n display: {\n family: \"display\",\n size: \"2.25rem\",\n weight: 400,\n lineHeight: \"1.15\",\n textWrap: \"balance\",\n },\n \"heading-xl\": {\n family: \"display\",\n size: \"1.875rem\",\n weight: 400,\n lineHeight: \"1.2\",\n textWrap: \"balance\",\n },\n heading: {\n family: \"display\",\n size: \"1.5rem\",\n weight: 400,\n lineHeight: \"1.2\",\n textWrap: \"balance\",\n },\n subheading: {\n family: \"display\",\n size: \"1.25rem\",\n weight: 400,\n lineHeight: \"1.4\",\n textWrap: \"balance\",\n },\n \"body-lg\": {\n family: \"sans\",\n size: \"1rem\",\n weight: 400,\n lineHeight: \"1.625\",\n textWrap: \"pretty\",\n },\n body: {\n family: \"sans\",\n size: \"0.875rem\",\n weight: 400,\n lineHeight: \"1.625\",\n textWrap: \"pretty\",\n },\n \"body-sm\": {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 500,\n lineHeight: \"1.625\",\n textWrap: \"pretty\",\n },\n caption: {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 400,\n lineHeight: \"1.625\",\n textWrap: \"pretty\",\n },\n /** 11px — dense metadata (table sub-lines, chips, editor hints). Use instead of text-[11px]. */\n \"caption-sm\": { family: \"sans\", size: \"0.6875rem\", weight: 400, lineHeight: \"1.5\" },\n /** 10px — the floor. Use instead of text-[10px]; keep to non-essential metadata. */\n \"caption-xs\": { family: \"sans\", size: \"0.625rem\", weight: 400, lineHeight: \"1.625\" },\n\n /* --- \"Eyebrow\" family — uppercase tracked label used above headlines, --- *\n * on badges, and on section markers. `eyebrow` is the canonical name; *\n * `overline` (Material parlance), `kicker` (editorial parlance) and *\n * `label` (legacy) are aliases of the same scale so consumers can pick *\n * whichever vocabulary reads best in their context. `eyebrow-sm` is *\n * the compact variant for badge-sized chips and tiny status pills. */\n eyebrow: {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 600,\n lineHeight: \"1\",\n letterSpacing: \"0.1em\",\n textTransform: \"uppercase\" as const,\n },\n \"eyebrow-sm\": {\n family: \"sans\",\n size: \"0.625rem\",\n weight: 600,\n lineHeight: \"1\",\n letterSpacing: \"0.1em\",\n textTransform: \"uppercase\" as const,\n },\n overline: {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 600,\n lineHeight: \"1\",\n letterSpacing: \"0.1em\",\n textTransform: \"uppercase\" as const,\n },\n kicker: {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 600,\n lineHeight: \"1\",\n letterSpacing: \"0.1em\",\n textTransform: \"uppercase\" as const,\n },\n label: {\n family: \"sans\",\n size: \"0.75rem\",\n weight: 600,\n lineHeight: \"1\",\n letterSpacing: \"0.1em\",\n textTransform: \"uppercase\" as const,\n },\n },\n\n /* ============================================================== *\n * GEOMETRY *\n * ============================================================== */\n\n radius: {\n base: \"0.5rem\",\n sm: \"calc(0.5rem - 4px)\",\n md: \"calc(0.5rem - 2px)\",\n lg: \"calc(0.5rem + 2px)\",\n xl: \"calc(0.5rem + 4px)\",\n full: \"9999px\",\n },\n\n /* ============================================================== *\n * DENSITY — control sizing tiers *\n * ============================================================== *\n * Emitted as `--density-*` custom properties: `:root` carries the\n * default tier, `[data-density=\"compact\"]` the editor-chrome tier.\n * Components switch via the `compact:` Tailwind variant (same\n * attribute); consumers can read the vars for bespoke controls. */\n density: {\n default: {\n controlHeight: \"32px\",\n inputHeight: \"40px\",\n rowHeight: \"36px\",\n text: \"14px\",\n label: \"12px\",\n menuItemHeight: \"40px\",\n menuText: \"14px\",\n paddingX: \"12px\",\n radius: \"8px\",\n },\n compact: {\n controlHeight: \"24px\",\n inputHeight: \"24px\",\n rowHeight: \"28px\",\n text: \"12px\",\n label: \"11px\",\n menuItemHeight: \"28px\",\n menuText: \"13px\",\n paddingX: \"8px\",\n radius: \"5px\",\n },\n },\n\n /* ============================================================== *\n * Z-INDEX — semantic layering scale *\n * ============================================================== */\n\n zIndex: {\n dropdown: 40,\n sticky: 50,\n fixed: 60,\n modal: 100,\n popover: 110,\n tooltip: 120,\n },\n\n shadow: {\n natural:\n \"0 0px 0px 1px rgba(0, 0, 0, 0.06), 0 1px 1px -0.5px rgba(0, 0, 0, 0.06), 0 3px 3px -1.5px rgba(0, 0, 0, 0.06)\",\n elevated:\n \"0 0px 0px 1px rgba(0, 0, 0, 0.06), 0 1px 1px -0.5px rgba(0, 0, 0, 0.06), 0 3px 3px -1.5px rgba(0, 0, 0, 0.06), 0 6px 6px -3px rgba(0, 0, 0, 0.06), 0 12px 12px -6px rgba(0, 0, 0, 0.04), 0 24px 24px -12px rgba(0, 0, 0, 0.04), 0 24px 24px 2px rgba(0, 0, 0, 0.1)\",\n },\n\n /* ============================================================== *\n * ANIMATION *\n * ============================================================== */\n\n animation: {\n \"accordion-down\": \"accordion-down 0.2s ease-out\",\n \"accordion-up\": \"accordion-up 0.2s ease-out\",\n \"caret-blink\": \"caret-blink 1.25s ease-out infinite\",\n \"hilum-orbit\": \"hilum-orbit 1.4s ease-in-out infinite\",\n \"hilum-spring-in\": \"hilum-spring-in 180ms cubic-bezier(0.2, 0.9, 0.2, 1.15)\",\n \"hilum-thinking\": \"hilum-thinking 1.1s ease-in-out infinite\",\n },\n} as const;\n\nexport type Tokens = typeof tokens;\nexport type SemanticTokens = typeof tokens.semantic.light;\n"]}
|
package/dist/create-theme.js
CHANGED
|
@@ -50,7 +50,8 @@ function oklchToHex(L, C, H) {
|
|
|
50
50
|
let hi = C;
|
|
51
51
|
for (let i = 0; i < 20; i++) {
|
|
52
52
|
const mid = (lo + hi) / 2;
|
|
53
|
-
inSrgbGamut(...oklchToLinearRgb(L, mid, H))
|
|
53
|
+
if (inSrgbGamut(...oklchToLinearRgb(L, mid, H))) lo = mid;
|
|
54
|
+
else hi = mid;
|
|
54
55
|
}
|
|
55
56
|
C = lo;
|
|
56
57
|
}
|
package/dist/create-theme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tokens/create-theme.tsx"],"names":[],"mappings":"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","file":"create-theme.js","sourcesContent":["// @hilum/ui — createTheme: per-product color theming API.\n//\n// Generates a full 11-shade OKLCH palette from primary and secondary hex anchors,\n// then emits a CSS override string that products inject after tokens.css.\n//\n// No external dependencies — OKLCH math is inlined (~100 lines).\n// createTheme() is pure and works in Node (build scripts) and browser.\n// applyTheme() and ThemeProvider require a browser / Electron environment.\n\nimport * as React from \"react\";\n\nexport interface ThemeConfig {\n /** Hex color used as the 500-level anchor for the primary palette. */\n primary: string;\n /** Hex color used as the 500-level anchor for the secondary palette. */\n secondary: string;\n}\n\nexport interface ThemeResult {\n /** Complete CSS override string. Inject via <style> or write to a .css file. */\n css: string;\n /** Generated palette shades for programmatic access. */\n palette: {\n primary: Record<string, string>;\n secondary: Record<string, string>;\n };\n}\n\n/* ------------------------------------------------------------------ *\n * OKLCH math (Björn Ottosson — no external deps) *\n * ------------------------------------------------------------------ */\n\nfunction toLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nfunction toGamma(c: number): number {\n return c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;\n}\n\nfunction hexToOklch(hex: string): [number, number, number] {\n const r = toLinear(parseInt(hex.slice(1, 3), 16) / 255);\n const g = toLinear(parseInt(hex.slice(3, 5), 16) / 255);\n const b = toLinear(parseInt(hex.slice(5, 7), 16) / 255);\n\n // linear sRGB → XYZ D65\n const X = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b;\n const Y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;\n const Z = 0.0193339 * r + 0.1191920 * g + 0.9503041 * b;\n\n // XYZ → OKLab\n const l_ = Math.cbrt(0.8189330101 * X + 0.3618667424 * Y - 0.1288597137 * Z);\n const m_ = Math.cbrt(0.0329845436 * X + 0.9293118715 * Y + 0.0361456387 * Z);\n const s_ = Math.cbrt(0.0482003018 * X + 0.2643662691 * Y + 0.6338517070 * Z);\n\n const L = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_;\n const a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_;\n const bv = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_;\n\n const C = Math.sqrt(a * a + bv * bv);\n let H = (Math.atan2(bv, a) * 180) / Math.PI;\n if (H < 0) H += 360;\n return [L, C, H];\n}\n\nfunction oklchToLinearRgb(L: number, C: number, H: number): [number, number, number] {\n const hRad = (H * Math.PI) / 180;\n const a = C * Math.cos(hRad);\n const bv = C * Math.sin(hRad);\n\n // OKLab → XYZ\n const l_ = L + 0.3963377774 * a + 0.2158037573 * bv;\n const m_ = L - 0.1055613458 * a - 0.0638541728 * bv;\n const s_ = L - 0.0894841775 * a - 1.2914855480 * bv;\n\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n // XYZ → linear sRGB\n const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;\n const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;\n const b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s;\n return [r, g, b];\n}\n\nfunction inSrgbGamut(r: number, g: number, b: number): boolean {\n return r >= -1e-6 && r <= 1 + 1e-6 && g >= -1e-6 && g <= 1 + 1e-6 && b >= -1e-6 && b <= 1 + 1e-6;\n}\n\nfunction oklchToHex(L: number, C: number, H: number): string {\n // Reduce chroma via binary search until in sRGB gamut.\n if (!inSrgbGamut(...oklchToLinearRgb(L, C, H))) {\n let lo = 0;\n let hi = C;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n inSrgbGamut(...oklchToLinearRgb(L, mid, H)) ? (lo = mid) : (hi = mid);\n }\n C = lo;\n }\n const [r, g, b] = oklchToLinearRgb(L, C, H);\n const ch = (c: number) =>\n Math.round(Math.max(0, Math.min(1, toGamma(c))) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${ch(r)}${ch(g)}${ch(b)}`;\n}\n\n/* ------------------------------------------------------------------ *\n * Palette generation *\n * ------------------------------------------------------------------ */\n\nconst SHADE_KEYS = [\"50\", \"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"950\"];\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nfunction generatePalette(hex: string): Record<string, string> {\n const [L0, C0, H] = hexToOklch(hex);\n const palette: Record<string, string> = {};\n\n SHADE_KEYS.forEach((key, i) => {\n if (i === 5) {\n palette[key] = hex.toLowerCase();\n return;\n }\n let L: number, C: number;\n if (i < 5) {\n // Lighter shades: interpolate toward 0.975, fade chroma\n const t = (5 - i) / 5;\n L = lerp(L0, 0.975, t);\n C = C0 * (1 - t * 0.8);\n } else {\n // Darker shades: interpolate toward 0.145, fade chroma slightly\n const t = (i - 5) / 5;\n L = lerp(L0, 0.145, t);\n C = C0 * (1 - t * 0.4);\n }\n palette[key] = oklchToHex(L, C, H);\n });\n\n return palette;\n}\n\n/* ------------------------------------------------------------------ *\n * Foreground auto-detection *\n * ------------------------------------------------------------------ */\n\nconst TAUPE_900 = \"#26181a\";\n\n// WCAG relative luminance Y (XYZ). Threshold ≈ 0.179 gives equal contrast\n// with black and white: use dark text above, white text at or below.\nfunction relativeLuminance(hex: string): number {\n const r = toLinear(parseInt(hex.slice(1, 3), 16) / 255);\n const g = toLinear(parseInt(hex.slice(3, 5), 16) / 255);\n const b = toLinear(parseInt(hex.slice(5, 7), 16) / 255);\n return 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;\n}\n\nfunction autoFg(hex: string): string {\n return relativeLuminance(hex) > 0.179 ? TAUPE_900 : \"#ffffff\";\n}\n\n/* ------------------------------------------------------------------ *\n * CSS emission *\n * ------------------------------------------------------------------ */\n\nfunction buildCss(\n p: Record<string, string>,\n s: Record<string, string>,\n primaryHex: string,\n secondaryHex: string,\n): string {\n const pfg = autoFg(primaryHex);\n\n const lightBlock = [\n ` --color-brand-primary: ${primaryHex};`,\n ` --color-brand-secondary: ${secondaryHex};`,\n ` --primary: ${primaryHex};`,\n ` --primary-foreground: ${pfg};`,\n ` --accent: ${p[\"50\"]};`,\n ` --accent-foreground: ${p[\"700\"]};`,\n ` --ring: ${primaryHex};`,\n ` --warning: ${s[\"200\"]};`,\n ` --warning-foreground: ${TAUPE_900};`,\n // Palette vars for product CSS use (not registered as Tailwind utilities)\n ...SHADE_KEYS.map((k) => ` --color-primary-${k}: ${p[k]};`),\n ...SHADE_KEYS.map((k) => ` --color-secondary-${k}: ${s[k]};`),\n ].join(\"\\n\");\n\n const darkBlock = [\n ` --color-brand-primary: ${primaryHex};`,\n ` --color-brand-secondary: ${secondaryHex};`,\n ` --primary: ${primaryHex};`,\n ` --primary-foreground: #ffffff;`,\n ` --accent: ${p[\"900\"]};`,\n ` --accent-foreground: ${p[\"100\"]};`,\n ` --ring: ${primaryHex};`,\n ` --warning: ${s[\"900\"]};`,\n ` --warning-foreground: ${s[\"100\"]};`,\n ].join(\"\\n\");\n\n const darkMediaBlock = darkBlock\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\");\n\n return `/* @hilum/ui theme override — generated by createTheme() */\n:root {\n${lightBlock}\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n${darkMediaBlock}\n }\n}\n\n[data-theme=\"dark\"] {\n${darkBlock}\n}\n`;\n}\n\n/* ------------------------------------------------------------------ *\n * Public API *\n * ------------------------------------------------------------------ */\n\nexport function createTheme(config: ThemeConfig): ThemeResult {\n const primary = config.primary.trim().toLowerCase();\n const secondary = config.secondary.trim().toLowerCase();\n const p = generatePalette(primary);\n const s = generatePalette(secondary);\n return { css: buildCss(p, s, primary, secondary), palette: { primary: p, secondary: s } };\n}\n\n/** Injects the theme CSS into `document.head`. Returns a cleanup function. */\nexport function applyTheme(config: ThemeConfig): () => void {\n if (typeof document === \"undefined\") return () => {};\n // Remove any stale theme override from a prior call.\n document.querySelectorAll(\"style[data-hilum-theme]\").forEach((el) => el.remove());\n const { css } = createTheme(config);\n const style = document.createElement(\"style\");\n style.dataset.hilumTheme = \"\";\n style.textContent = css;\n document.head.appendChild(style);\n return () => {\n if (style.parentNode) style.parentNode.removeChild(style);\n };\n}\n\n/** React component that applies the theme on mount and cleans up on unmount. */\nexport function ThemeProvider({\n primary,\n secondary,\n children,\n}: ThemeConfig & { children: React.ReactNode }) {\n React.useEffect(() => applyTheme({ primary, secondary }), [primary, secondary]);\n return <>{children}</>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/tokens/create-theme.tsx"],"names":[],"mappings":"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","file":"create-theme.js","sourcesContent":["// @hilum/ui — createTheme: per-product color theming API.\n//\n// Generates a full 11-shade OKLCH palette from primary and secondary hex anchors,\n// then emits a CSS override string that products inject after tokens.css.\n//\n// No external dependencies — OKLCH math is inlined (~100 lines).\n// createTheme() is pure and works in Node (build scripts) and browser.\n// applyTheme() and ThemeProvider require a browser / Electron environment.\n\nimport * as React from \"react\";\n\nexport interface ThemeConfig {\n /** Hex color used as the 500-level anchor for the primary palette. */\n primary: string;\n /** Hex color used as the 500-level anchor for the secondary palette. */\n secondary: string;\n}\n\nexport interface ThemeResult {\n /** Complete CSS override string. Inject via <style> or write to a .css file. */\n css: string;\n /** Generated palette shades for programmatic access. */\n palette: {\n primary: Record<string, string>;\n secondary: Record<string, string>;\n };\n}\n\n/* ------------------------------------------------------------------ *\n * OKLCH math (Björn Ottosson — no external deps) *\n * ------------------------------------------------------------------ */\n\nfunction toLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nfunction toGamma(c: number): number {\n return c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;\n}\n\nfunction hexToOklch(hex: string): [number, number, number] {\n const r = toLinear(parseInt(hex.slice(1, 3), 16) / 255);\n const g = toLinear(parseInt(hex.slice(3, 5), 16) / 255);\n const b = toLinear(parseInt(hex.slice(5, 7), 16) / 255);\n\n // linear sRGB → XYZ D65\n const X = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b;\n const Y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;\n const Z = 0.0193339 * r + 0.1191920 * g + 0.9503041 * b;\n\n // XYZ → OKLab\n const l_ = Math.cbrt(0.8189330101 * X + 0.3618667424 * Y - 0.1288597137 * Z);\n const m_ = Math.cbrt(0.0329845436 * X + 0.9293118715 * Y + 0.0361456387 * Z);\n const s_ = Math.cbrt(0.0482003018 * X + 0.2643662691 * Y + 0.6338517070 * Z);\n\n const L = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_;\n const a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_;\n const bv = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_;\n\n const C = Math.sqrt(a * a + bv * bv);\n let H = (Math.atan2(bv, a) * 180) / Math.PI;\n if (H < 0) H += 360;\n return [L, C, H];\n}\n\nfunction oklchToLinearRgb(L: number, C: number, H: number): [number, number, number] {\n const hRad = (H * Math.PI) / 180;\n const a = C * Math.cos(hRad);\n const bv = C * Math.sin(hRad);\n\n // OKLab → XYZ\n const l_ = L + 0.3963377774 * a + 0.2158037573 * bv;\n const m_ = L - 0.1055613458 * a - 0.0638541728 * bv;\n const s_ = L - 0.0894841775 * a - 1.2914855480 * bv;\n\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n // XYZ → linear sRGB\n const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;\n const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;\n const b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s;\n return [r, g, b];\n}\n\nfunction inSrgbGamut(r: number, g: number, b: number): boolean {\n return r >= -1e-6 && r <= 1 + 1e-6 && g >= -1e-6 && g <= 1 + 1e-6 && b >= -1e-6 && b <= 1 + 1e-6;\n}\n\nfunction oklchToHex(L: number, C: number, H: number): string {\n // Reduce chroma via binary search until in sRGB gamut.\n if (!inSrgbGamut(...oklchToLinearRgb(L, C, H))) {\n let lo = 0;\n let hi = C;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n if (inSrgbGamut(...oklchToLinearRgb(L, mid, H))) lo = mid;\n else hi = mid;\n }\n C = lo;\n }\n const [r, g, b] = oklchToLinearRgb(L, C, H);\n const ch = (c: number) =>\n Math.round(Math.max(0, Math.min(1, toGamma(c))) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${ch(r)}${ch(g)}${ch(b)}`;\n}\n\n/* ------------------------------------------------------------------ *\n * Palette generation *\n * ------------------------------------------------------------------ */\n\nconst SHADE_KEYS = [\"50\", \"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"950\"];\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nfunction generatePalette(hex: string): Record<string, string> {\n const [L0, C0, H] = hexToOklch(hex);\n const palette: Record<string, string> = {};\n\n SHADE_KEYS.forEach((key, i) => {\n if (i === 5) {\n palette[key] = hex.toLowerCase();\n return;\n }\n let L: number, C: number;\n if (i < 5) {\n // Lighter shades: interpolate toward 0.975, fade chroma\n const t = (5 - i) / 5;\n L = lerp(L0, 0.975, t);\n C = C0 * (1 - t * 0.8);\n } else {\n // Darker shades: interpolate toward 0.145, fade chroma slightly\n const t = (i - 5) / 5;\n L = lerp(L0, 0.145, t);\n C = C0 * (1 - t * 0.4);\n }\n palette[key] = oklchToHex(L, C, H);\n });\n\n return palette;\n}\n\n/* ------------------------------------------------------------------ *\n * Foreground auto-detection *\n * ------------------------------------------------------------------ */\n\nconst TAUPE_900 = \"#26181a\";\n\n// WCAG relative luminance Y (XYZ). Threshold ≈ 0.179 gives equal contrast\n// with black and white: use dark text above, white text at or below.\nfunction relativeLuminance(hex: string): number {\n const r = toLinear(parseInt(hex.slice(1, 3), 16) / 255);\n const g = toLinear(parseInt(hex.slice(3, 5), 16) / 255);\n const b = toLinear(parseInt(hex.slice(5, 7), 16) / 255);\n return 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;\n}\n\nfunction autoFg(hex: string): string {\n return relativeLuminance(hex) > 0.179 ? TAUPE_900 : \"#ffffff\";\n}\n\n/* ------------------------------------------------------------------ *\n * CSS emission *\n * ------------------------------------------------------------------ */\n\nfunction buildCss(\n p: Record<string, string>,\n s: Record<string, string>,\n primaryHex: string,\n secondaryHex: string,\n): string {\n const pfg = autoFg(primaryHex);\n\n const lightBlock = [\n ` --color-brand-primary: ${primaryHex};`,\n ` --color-brand-secondary: ${secondaryHex};`,\n ` --primary: ${primaryHex};`,\n ` --primary-foreground: ${pfg};`,\n ` --accent: ${p[\"50\"]};`,\n ` --accent-foreground: ${p[\"700\"]};`,\n ` --ring: ${primaryHex};`,\n ` --warning: ${s[\"200\"]};`,\n ` --warning-foreground: ${TAUPE_900};`,\n // Palette vars for product CSS use (not registered as Tailwind utilities)\n ...SHADE_KEYS.map((k) => ` --color-primary-${k}: ${p[k]};`),\n ...SHADE_KEYS.map((k) => ` --color-secondary-${k}: ${s[k]};`),\n ].join(\"\\n\");\n\n const darkBlock = [\n ` --color-brand-primary: ${primaryHex};`,\n ` --color-brand-secondary: ${secondaryHex};`,\n ` --primary: ${primaryHex};`,\n ` --primary-foreground: #ffffff;`,\n ` --accent: ${p[\"900\"]};`,\n ` --accent-foreground: ${p[\"100\"]};`,\n ` --ring: ${primaryHex};`,\n ` --warning: ${s[\"900\"]};`,\n ` --warning-foreground: ${s[\"100\"]};`,\n ].join(\"\\n\");\n\n const darkMediaBlock = darkBlock\n .split(\"\\n\")\n .map((l) => ` ${l}`)\n .join(\"\\n\");\n\n return `/* @hilum/ui theme override — generated by createTheme() */\n:root {\n${lightBlock}\n}\n\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n${darkMediaBlock}\n }\n}\n\n[data-theme=\"dark\"] {\n${darkBlock}\n}\n`;\n}\n\n/* ------------------------------------------------------------------ *\n * Public API *\n * ------------------------------------------------------------------ */\n\nexport function createTheme(config: ThemeConfig): ThemeResult {\n const primary = config.primary.trim().toLowerCase();\n const secondary = config.secondary.trim().toLowerCase();\n const p = generatePalette(primary);\n const s = generatePalette(secondary);\n return { css: buildCss(p, s, primary, secondary), palette: { primary: p, secondary: s } };\n}\n\n/** Injects the theme CSS into `document.head`. Returns a cleanup function. */\nexport function applyTheme(config: ThemeConfig): () => void {\n if (typeof document === \"undefined\") return () => {};\n // Remove any stale theme override from a prior call.\n document.querySelectorAll(\"style[data-hilum-theme]\").forEach((el) => el.remove());\n const { css } = createTheme(config);\n const style = document.createElement(\"style\");\n style.dataset.hilumTheme = \"\";\n style.textContent = css;\n document.head.appendChild(style);\n return () => {\n if (style.parentNode) style.parentNode.removeChild(style);\n };\n}\n\n/** React component that applies the theme on mount and cleans up on unmount. */\nexport function ThemeProvider({\n primary,\n secondary,\n children,\n}: ThemeConfig & { children: React.ReactNode }) {\n React.useEffect(() => applyTheme({ primary, secondary }), [primary, secondary]);\n return <>{children}</>;\n}\n"]}
|