nuvox 0.1.1 → 0.1.3

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.
@@ -265,6 +265,14 @@ active*, not a portal, not a value being typed. Usually no portal at
265
265
  all.
266
266
 
267
267
  **What to keep:**
268
+ - **Same `value` + `onChange` (controlled) / `defaultValue`
269
+ (uncontrolled) convention as Category B, applied to "which item is
270
+ active" instead of "what's typed."** Not `onValueChange` — there is
271
+ exactly one controlled-state prop name across this entire library,
272
+ regardless of category, and it's `onChange`. (This had to be fixed
273
+ once already — Tabs and Accordion shipped with `onValueChange` in
274
+ 0.1.0/0.1.1 because this line didn't exist yet. See `tests/no-on-value-change.test.ts`,
275
+ which now fails the build if this drifts again.)
268
276
  - Roving `tabIndex` pattern for keyboard nav within the group (Tabs,
269
277
  Accordion) — only the active tab is in the natural tab order; arrow
270
278
  keys move between siblings. This is the same class of "accessibility
package/CHANGELOG.md ADDED
@@ -0,0 +1,133 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ Format loosely follows [Keep a Changelog](https://keepachangelog.com/).
5
+
6
+ ## [0.1.3]
7
+
8
+ ### Fixed
9
+ - `neobrutalism`'s `warning.light` token (`#fef3c7`) was byte-identical
10
+ to the theme's own `background` — every warning `Alert`, and anything
11
+ else drawing from that token, rendered invisibly against the page.
12
+ Now `#fde68a`, one step further into the same warm-amber family.
13
+ - `neobrutalism`'s `Rating` stars had no visible outline once filled:
14
+ the star icon's stroke and fill both come from `color`, so a filled
15
+ star's outline was purple-on-purple, not the black border every
16
+ other surface in this theme gets. Scoped override forces a black
17
+ stroke on all three star states (`neobrutalism` only).
18
+ - `gradient`'s `text`/`textMuted` were still `light` theme's values,
19
+ measured at 2.79:1 and a barely-there 1.32:1 against the theme's own
20
+ background gradient's darker stop — anything rendered directly on
21
+ the page background (as `Timeline`/`Pagination`/`Tabs` are, per this
22
+ library's own docs examples, with no wrapping surface assumed) was
23
+ close to unreadable. Darkened both — see the measured before/after
24
+ in the new `tests/theme-text-contrast.test.ts`. `textMuted` still
25
+ can't clear full AA (4.5:1) against the gradient's darkest point
26
+ with a single flat color; this is the best available compromise,
27
+ not a complete fix.
28
+ - `glass`'s `border` (`rgba(255,255,255,0.35)`) composited to literal
29
+ `#ffffff` against a plain white backdrop — a 1.0:1 ratio, i.e.
30
+ actually invisible (reported as `Progress`'s track outline
31
+ vanishing). Retinted to a neutral slate that stays visible against
32
+ both a plain white and a plain black fallback backdrop, since most
33
+ consumers won't add the "rich background" this theme's own
34
+ description says it needs.
35
+ - `Slider`'s value-label bubble (`showValueLabel`) had no space
36
+ reserved for it above the track and could overflow into the field's
37
+ own `label` text above it — most visible with a thumb near 0%.
38
+ `getRootClasses` (internal, not part of the public API surface) now
39
+ takes `showValueLabel` and adds a modifier class that reserves the
40
+ room the bubble actually needs.
41
+ - Nesting one dismissible overlay inside another (e.g. a `DropdownMenu`
42
+ inside a `Popover`) broke: every overlay portals its content to
43
+ `document.body` via `ThemedPortal`, as a DOM sibling of wherever it
44
+ was rendered rather than a descendant, so a click inside the nested
45
+ one registered as "outside" the outer one's own refs and closed it
46
+ before the click could register. `useClickOutside` now ignores
47
+ clicks inside any `[data-nuvox-portal]` node, fixing every
48
+ `Popover`/`DropdownMenu`/`Select`/`Combobox`/`ContextMenu`/
49
+ `CommandPalette` pairing at once instead of one at a time. See
50
+ `tests/nested-overlays.test.tsx`.
51
+ - `Carousel`'s `CarouselPrevious`/`CarouselNext` centered against the
52
+ whole `.nx-carousel` box (viewport + indicators + anything else
53
+ below it), not the viewport alone — correct only by coincidence when
54
+ the viewport was tall relative to everything else in the box.
55
+ `.nx-carousel` is now a CSS grid with the viewport pinned to its own
56
+ grid cell, which becomes the containing block for a same-cell
57
+ absolutely-positioned item (CSS Grid §10.1). This holds regardless
58
+ of `CarouselIndicators`' height or the viewport's own height, so an
59
+ explicit height is no longer required for correct centering (still
60
+ good practice for layout stability, just not load-bearing anymore).
61
+ Wrapping the buttons in your own `<div>` is still unsupported, for a
62
+ different reason than before: a plain wrapper isn't a positioning
63
+ context, so the buttons fall through to `.nx-carousel` regardless of
64
+ the grid fix.
65
+ - `docs-site`'s live "Controlled" `Carousel` demo and `carousel.mdx`'s
66
+ guidance both still reflected the pre-fix structure/requirements;
67
+ updated to match the fix above.
68
+
69
+ ### Added
70
+ - `tests/nested-overlays.test.tsx` — regression coverage for the
71
+ overlay-nesting fix above: fails against the old `useClickOutside`,
72
+ passes against the new one.
73
+ - `tests/theme-text-contrast.test.ts` — checks `text`/`textMuted`
74
+ against `background` for every theme, including gradient stops
75
+ extracted from non-solid backgrounds. `outline-text-contrast.test.ts`
76
+ only ever checked the outline-button `color-mix()` blend and
77
+ explicitly skipped non-solid backgrounds — a real coverage gap; this
78
+ is what would have caught the `gradient` regression above before it
79
+ shipped.
80
+
81
+ ## [0.1.2]
82
+
83
+ ### Fixed
84
+ - `Select` now has a real `label` prop (previously only `aria-label`/
85
+ `aria-labelledby` — every other form field had `label`, this was the
86
+ one gap).
87
+ - `Slider`'s `onChange` no longer forces the `number | readonly [number,
88
+ number]` union in single-thumb mode. It's now generic, so a plain
89
+ `<Slider value={n} onChange={setN} />` infers `(value: number) =>
90
+ void` with no cast needed; range mode still infers the tuple.
91
+ - `nuvox/react` now re-exports ~20 prop-relevant types that previously
92
+ only lived in `"nuvox"` (`SliderValue`, `SelectOptionItem`,
93
+ `CommandItem`/`CommandGroup`, `TableCoreProps`, `DrawerSide`/
94
+ `DrawerSize`, `ModalSize`, `ProgressVariant`, and others) — a
95
+ consumer typing a handler no longer needs to import from both
96
+ entry points for one component.
97
+
98
+ ### Changed
99
+ - **Breaking:** `Accordion`, `Combobox`, `Select`, and `Tabs` renamed
100
+ `onValueChange` → `onChange`, unifying every controlled component in
101
+ the library on one convention (`onChange` was already the majority —
102
+ 9 of 13 controlled components used it before this). No deprecated
103
+ alias was kept; see `CONTRACT.md` Rule 10 for why this was allowed
104
+ as a one-time pre-1.0 exception.
105
+
106
+ ### Added
107
+ - `docs-site/content/docs/css-variables.mdx` — a real reference page
108
+ for the theme system's CSS custom properties (`--color-background`,
109
+ `--color-text`, `--color-border`, etc.), previously only discoverable
110
+ incidentally inside `card.mdx`.
111
+ - `tests/no-on-value-change.test.ts` — fails the build if
112
+ `onValueChange` is ever reintroduced as a real prop anywhere in
113
+ `src/react/`. Added after an external review caught the drift above;
114
+ this is the enforcement so it can't silently happen again.
115
+ - `BUILDING-COMPONENTS.md`'s Category E section now explicitly states
116
+ the `value`/`onChange` convention applies there too — it previously
117
+ had no documented prop-naming rule at all for Tabs/Accordion's
118
+ controlled state, which is how they drifted differently from
119
+ Select/Combobox (Category D, which *did* already have this rule and
120
+ violated it).
121
+
122
+ ## [0.1.1]
123
+
124
+ Published, but no record was kept of what changed from 0.1.0.
125
+ If you're reading this after the fact: fill this in from `git log` /
126
+ `npm diff nuvox@0.1.0 nuvox@0.1.1` before it's forgotten for good.
127
+
128
+ ## [0.1.0]
129
+
130
+ Initial public release. Single consolidated `nuvox` package (core +
131
+ React bindings, previously split across 7 scoped `@nuvox/*` packages —
132
+ all deprecated/unpublished as part of this release) with a
133
+ framework-agnostic core, 40+ components, 11 themes, 490+ icons.
package/CONTRACT.md CHANGED
@@ -210,6 +210,12 @@ other rules were — Nuvox v1 never shipped a public version — but it's
210
210
  the rule that protects everything else in this document from being
211
211
  undermined the moment real consumers exist.
212
212
 
213
+ **Documented exception:** 0.1.2 broke this rule on purpose —
214
+ `Accordion`/`Combobox`/`Select`/`Tabs`' `onValueChange` was renamed to
215
+ `onChange` with no alias, as a straight break. Justified only because
216
+ the library had zero real consumers at the time; see CHANGELOG.md.
217
+ This is not a precedent for doing it again once real users exist.
218
+
213
219
  ## 11. Every overlay component meets the same accessibility baseline
214
220
  Any component that opens/closes, floats, or portals (Modal, Drawer,
215
221
  Popover, Dropdown, Select, Combobox, ContextMenu, Tour, Toast,
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Nuvox
2
2
 
3
3
  A framework-agnostic React component library with a themeable,
4
- token-driven design system. 41 components, 11 visual themes, 9 named
5
- accent colors (plus support for any raw CSS color), and 492 icons —
4
+ token-driven design system. 40+ components, 10+ visual themes, named
5
+ accent colors (plus support for any raw CSS color), and 500+ icons —
6
6
  fully typed, accessible, and built on zero runtime dependencies.
7
7
 
8
8
  ## The core idea: theme is shape, color is color
@@ -50,16 +50,16 @@ variables, `styles.css` reads them into visible styles.
50
50
 
51
51
  ## What's in the box
52
52
 
53
- - **41 components** across forms (Input, Select, Checkbox, Slider...),
53
+ - **40+ components** across forms (Input, Select, Checkbox, Slider...),
54
54
  overlays (Modal, Popover, Dropdown, Drawer...), composite widgets
55
55
  (Combobox, DatePicker, CommandPalette...), and navigation
56
56
  (Tabs, Accordion, Breadcrumb, Pagination...)
57
- - **11 themes** (light, dark, glass, dark-glass, minimalism,
57
+ - **10+ themes** (light, dark, glass, dark-glass, minimalism,
58
58
  brutalism, neobrutalism, cyberpunk, gradient, material,
59
59
  skeuomorphism) — switchable at runtime with no re-render logic
60
- - **9 named accent colors**, or drop in any raw CSS color with zero
60
+ - **Named accent colors**, or drop in any raw CSS color with zero
61
61
  registration
62
- - **492 icons**, tree-shakeable, each accepting `size` and `color`
62
+ - **500+ icons**, tree-shakeable, each accepting `size` and `color`
63
63
  - Full TypeScript support out of the box — no separate `@types`
64
64
  package needed
65
65
  - Accessible by default: every overlay component handles focus
@@ -91,7 +91,7 @@ npm run docs:dev # → http://localhost:3000
91
91
  - `/docs` — installation and setup
92
92
  - `/docs/components` — every component, with live previews
93
93
  - `/docs/themes` — the full theme/accent catalog, try them live
94
- - `/docs/icons` — browse and search all 492 icons
94
+ - `/docs/icons` — browse and search all 500+ icons
95
95
 
96
96
 
97
97
  ## License
@@ -270,7 +270,17 @@ var glass = defineTheme({
270
270
  background: "transparent",
271
271
  surface: "rgba(255,255,255,0.55)",
272
272
  surfaceRaised: "rgba(255,255,255,0.75)",
273
- border: "rgba(255,255,255,0.35)",
273
+ // Was rgba(255,255,255,0.35) — translucent WHITE. Composited on
274
+ // a plain white page (the theme's own meta.description admits it
275
+ // "needs a rich background behind it," but most consumers won't
276
+ // add one), that resolves to literal #ffffff — a 1.0:1 contrast
277
+ // ratio, i.e. actually invisible, which is the reported vanished
278
+ // Progress-track border. A neutral slate tint stays visible
279
+ // against both a plain white AND a plain black fallback backdrop
280
+ // (measured ~2.1-2.3:1 either way) — short of full 3:1 UI-contrast
281
+ // on both extremes at once, but a large improvement over 1.0, and
282
+ // still reads as a soft glass edge over an actual rich backdrop.
283
+ border: "rgba(100,116,139,0.6)",
274
284
  borderFocus: "#9ca3af",
275
285
  text: "#111827",
276
286
  textMuted: "rgba(17,24,39,0.65)",
@@ -404,7 +414,13 @@ var neobrutalism = defineTheme({
404
414
  surface: "#ffffff",
405
415
  surfaceRaised: "#ffffff",
406
416
  border: "#000000",
407
- borderFocus: "#000000"
417
+ borderFocus: "#000000",
418
+ // light.color.warning.light (#fef3c7) is identical to this
419
+ // theme's own background — every warning Alert/Badge/etc. was
420
+ // rendering invisibly on the page. Bumped to the next step in
421
+ // the same warm-amber family (matches light.color.warning.subtle)
422
+ // so it stays on-theme but is actually visible against the page.
423
+ warning: { ...light.color.warning, light: "#fde68a" }
408
424
  },
409
425
  radius: { sm: "4px", md: "6px", lg: "8px", xl: "10px", "2xl": "12px", full: "9999px" },
410
426
  shadow: {
@@ -468,7 +484,24 @@ var gradient = defineTheme({
468
484
  surface: "linear-gradient(135deg, rgba(255,255,255,0.92), rgba(255,255,255,0.75))",
469
485
  surfaceRaised: "#ffffff",
470
486
  border: "rgba(118,75,162,0.25)",
471
- borderFocus: "#764ba2"
487
+ borderFocus: "#764ba2",
488
+ // text/textMuted were still light theme's values (#111827 /
489
+ // #6b7280) — fine on the near-white `surface`, but components
490
+ // that render straight on `background` (Timeline, Pagination,
491
+ // Tabs — all used with no wrapping surface in this library's own
492
+ // docs examples) sat directly on the purple gradient instead.
493
+ // Measured contrast against the gradient's darker stop
494
+ // (#764ba2): text 2.79:1, textMuted a barely-there 1.32:1 — the
495
+ // reported "nearly invisible" text. Darkened both; textMuted
496
+ // still can't clear 4.5:1 against the darkest point of this
497
+ // specific gradient with a single flat color (nothing dark
498
+ // enough to do that stays legible as "muted" against the near-
499
+ // white surface too), so this is the best available compromise
500
+ // within a single global text/textMuted pair, not a full fix —
501
+ // worth knowing if it still reads as low-contrast on the
502
+ // darkest corner of the gradient.
503
+ text: "#000000",
504
+ textMuted: "#2e2440"
472
505
  },
473
506
  radius: { sm: "12px", md: "18px", lg: "24px", xl: "32px", "2xl": "40px", full: "9999px" },
474
507
  shadow: {
@@ -1123,4 +1156,4 @@ export {
1123
1156
  getSortAriaProps,
1124
1157
  getSelectAllState
1125
1158
  };
1126
- //# sourceMappingURL=chunk-3F7OVF4J.js.map
1159
+ //# sourceMappingURL=chunk-KKRVJF3Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tokens/contract.ts","../src/tokens/themes/light.ts","../src/tokens/themes/dark.ts","../src/tokens/themes/glass.ts","../src/tokens/themes/dark-glass.ts","../src/tokens/themes/minimalism.ts","../src/tokens/themes/brutalism.ts","../src/tokens/themes/neobrutalism.ts","../src/tokens/themes/cyberpunk.ts","../src/tokens/themes/gradient.ts","../src/tokens/themes/material.ts","../src/tokens/themes/skeuomorphism.ts","../src/tokens/registry.ts","../src/tokens/accents/indigo.ts","../src/tokens/accents/violet.ts","../src/tokens/accents/teal.ts","../src/tokens/accents/rose.ts","../src/tokens/accents/amber.ts","../src/tokens/accents/emerald.ts","../src/tokens/accents/copper.ts","../src/tokens/accents/graphite.ts","../src/tokens/accents/magenta.ts","../src/tokens/accents.ts","../src/core/field.ts","../src/core/colorpicker.ts","../src/core/table.ts"],"sourcesContent":["// ============================================================\n// TOKEN CONTRACT\n//\n// This is the single most important file in the foundation.\n//\n// Every theme (light, dark, glass, cyberpunk, whatever comes\n// next) must produce an object that satisfies ThemeTokens.\n// TypeScript enforces this at compile time via `defineTheme()`\n// below — leave out a single key and the build fails with a\n// clear error naming the missing key.\n//\n// In the old codebase, themes were hand-written CSS files.\n// Nothing checked that cyberpunk.css defined every variable\n// brutalism.css did. A missing token didn't error — it just\n// silently fell back to nothing, and you only found out by\n// looking at the rendered page.\n//\n// Here, themes are TypeScript objects. CSS is *generated* from\n// them (see generate-css.ts), never hand-authored. There is\n// exactly one source of truth per theme, and it cannot be\n// incomplete.\n// ============================================================\n\n// ============================================================\n// A theme controls SHAPE, not brand color: radius, shadow style,\n// motion curves, border treatment, glass/gradient/glow effects,\n// and the neutral/semantic palette needed for legibility (a dark\n// theme's background/text MUST differ from light's — that's a\n// contrast requirement, not a brand choice). It does NOT define\n// `color.brand` — that's a separate, orthogonal axis (see\n// accents.ts) that a consumer picks independently of which theme\n// is active, and can override per-component exactly like `theme`\n// can. success/danger/warning/info stay theme-defined (their\n// exact shade can differ per theme for contrast, but their\n// meaning — green reads as success, red as danger — must not be\n// user-customizable away from that).\n// ============================================================\n\nexport interface ColorScale {\n 50: string; 100: string; 200: string; 300: string; 400: string;\n 500: string; 600: string; 700: string; 800: string; 900: string;\n}\n\nexport interface SemanticColor {\n light: string;\n subtle: string;\n base: string;\n dark: string;\n deeper: string;\n}\n\nexport interface ThemeTokens {\n meta: {\n name: string;\n label: string;\n /** Short description of the visual identity — kept out of CSS, used in docs/registry UI. */\n description: string;\n };\n\n color: {\n neutral: ColorScale & { 0: string; 950: string };\n success: SemanticColor;\n danger: SemanticColor;\n warning: SemanticColor;\n info: SemanticColor;\n /** Page/app background, not component surface. */\n background: string;\n /** Default component surface (card, input, modal body). */\n surface: string;\n /** Elevated surface (popover, dropdown, tooltip). */\n surfaceRaised: string;\n border: string;\n borderFocus: string;\n text: string;\n textMuted: string;\n textInverse: string;\n };\n\n radius: {\n sm: string; md: string; lg: string; xl: string; \"2xl\": string; full: string;\n };\n\n spacing: {\n xs: string; sm: string; md: string; lg: string; xl: string; \"2xl\": string;\n };\n\n typography: {\n fontSans: string;\n fontMono: string;\n sizeXs: string; sizeSm: string; sizeMd: string; sizeLg: string; sizeXl: string;\n weightNormal: string; weightMedium: string; weightBold: string;\n lineHeightTight: string; lineHeightNormal: string;\n };\n\n shadow: {\n xs: string; sm: string; md: string; lg: string; xl: string; \"2xl\": string;\n inner: string;\n };\n\n elevation: {\n /** z-index steps — must be consistent across every portal-based component. */\n dropdown: number;\n popover: number;\n modal: number;\n toast: number;\n tooltip: number;\n };\n\n motion: {\n durationFast: string;\n durationNormal: string;\n durationSlow: string;\n easeStandard: string;\n easeEmphasized: string;\n /** Set to '0.01ms' by a reduced-motion-aware theme variant if needed. */\n durationInstant: string;\n };\n\n border: {\n widthThin: string;\n widthMedium: string;\n widthThick: string;\n style: string;\n };\n\n effects: {\n /**\n * CSS `backdrop-filter: blur()` amount, e.g. \"16px\" or \"0px\".\n * Every non-glass theme sets this to \"0px\" — an explicit zero,\n * not an absent field, so `defineTheme`'s completeness check\n * still catches an accidentally-forgotten theme. Translucent\n * `color.surface`/`color.border` values (glass, dark-glass) are\n * only actually visible as \"glass\" when something behind them\n * is blurred; without this, a translucent white surface over a\n * plain page background is indistinguishable from opaque white.\n */\n backdropBlur: string;\n };\n}\n\n/**\n * Identity function with a strict parameter type.\n * Its only job is to make an incomplete theme a compile error\n * at the call site, with TypeScript naming the exact missing key.\n */\nexport function defineTheme(tokens: ThemeTokens): ThemeTokens {\n return tokens;\n}\n\n/** Every top-level and nested key path, used by the completeness test. */\nexport const TOKEN_CATEGORIES = [\n \"meta\", \"color\", \"radius\", \"spacing\", \"typography\", \"shadow\", \"elevation\", \"motion\", \"border\", \"effects\",\n] as const;\n\n/**\n * Every required leaf path, hardcoded independently of any\n * theme instance. This is deliberately NOT derived from\n * whichever theme happens to register first — that would make\n * the very first theme registered the unverified \"trust me\"\n * reference. Every path listed here corresponds 1:1 to a field\n * in ThemeTokens; if you add a field to the contract, add its\n * path here too (a mismatch here is caught by\n * registry.test.ts's cross-check against `light`).\n */\nexport const REQUIRED_TOKEN_PATHS = [\n \"meta.name\", \"meta.label\", \"meta.description\",\n ...[\"0\", \"50\", \"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\", \"950\"].map((k) => `color.neutral.${k}`),\n ...([\"success\", \"danger\", \"warning\", \"info\"] as const).flatMap((c) =>\n [\"light\", \"subtle\", \"base\", \"dark\", \"deeper\"].map((k) => `color.${c}.${k}`)\n ),\n \"color.background\", \"color.surface\", \"color.surfaceRaised\", \"color.border\", \"color.borderFocus\",\n \"color.text\", \"color.textMuted\", \"color.textInverse\",\n \"radius.sm\", \"radius.md\", \"radius.lg\", \"radius.xl\", \"radius.2xl\", \"radius.full\",\n \"spacing.xs\", \"spacing.sm\", \"spacing.md\", \"spacing.lg\", \"spacing.xl\", \"spacing.2xl\",\n \"typography.fontSans\", \"typography.fontMono\",\n \"typography.sizeXs\", \"typography.sizeSm\", \"typography.sizeMd\", \"typography.sizeLg\", \"typography.sizeXl\",\n \"typography.weightNormal\", \"typography.weightMedium\", \"typography.weightBold\",\n \"typography.lineHeightTight\", \"typography.lineHeightNormal\",\n \"shadow.xs\", \"shadow.sm\", \"shadow.md\", \"shadow.lg\", \"shadow.xl\", \"shadow.2xl\", \"shadow.inner\",\n \"elevation.dropdown\", \"elevation.popover\", \"elevation.modal\", \"elevation.toast\", \"elevation.tooltip\",\n \"motion.durationFast\", \"motion.durationNormal\", \"motion.durationSlow\",\n \"motion.easeStandard\", \"motion.easeEmphasized\", \"motion.durationInstant\",\n \"border.widthThin\", \"border.widthMedium\", \"border.widthThick\", \"border.style\",\n \"effects.backdropBlur\",\n] as const;\n\nfunction getAtPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce<unknown>((acc, key) => {\n if (acc === null || typeof acc !== \"object\") return undefined;\n return (acc as Record<string, unknown>)[key];\n }, obj);\n}\n\n/** Returns every required path that is missing or empty on the given theme-like object. */\nexport function findMissingTokenPaths(theme: unknown): string[] {\n return REQUIRED_TOKEN_PATHS.filter((path) => {\n const value = getAtPath(theme, path);\n return value === null || value === undefined || value === \"\";\n });\n}\n","import { defineTheme } from \"../contract\";\n\nexport const light = defineTheme({\n meta: {\n name: \"light\",\n label: \"Light\",\n description: \"Default, neutral, high-legibility surface.\",\n },\n color: {\n neutral: {\n 0: \"#ffffff\", 50: \"#f9fafb\", 100: \"#f3f4f6\", 200: \"#e5e7eb\", 300: \"#d1d5db\",\n 400: \"#9ca3af\", 500: \"#6b7280\", 600: \"#4b5563\", 700: \"#374151\", 800: \"#1f2937\",\n 900: \"#111827\", 950: \"#030712\",\n },\n success: { light: \"#d1fae5\", subtle: \"#a7f3d0\", base: \"#10b981\", dark: \"#059669\", deeper: \"#064e3b\" },\n danger: { light: \"#fee2e2\", subtle: \"#fecaca\", base: \"#ef4444\", dark: \"#dc2626\", deeper: \"#7f1d1d\" },\n warning: { light: \"#fef3c7\", subtle: \"#fde68a\", base: \"#f59e0b\", dark: \"#d97706\", deeper: \"#78350f\" },\n info: { light: \"#dbeafe\", subtle: \"#bfdbfe\", base: \"#3b82f6\", dark: \"#2563eb\", deeper: \"#1e3a5f\" },\n background: \"#ffffff\",\n surface: \"#ffffff\",\n surfaceRaised: \"#ffffff\",\n border: \"#e5e7eb\",\n // Neutral, not brand-tied — the actual focus-ring color\n // interactive components use is the picked accent\n // (--color-brand-500/600), not this. This exists for\n // non-branded emphasis borders.\n borderFocus: \"#9ca3af\",\n text: \"#111827\",\n textMuted: \"#6b7280\",\n textInverse: \"#ffffff\",\n },\n radius: { sm: \"6px\", md: \"10px\", lg: \"14px\", xl: \"18px\", \"2xl\": \"24px\", full: \"9999px\" },\n spacing: { xs: \"4px\", sm: \"8px\", md: \"12px\", lg: \"16px\", xl: \"24px\", \"2xl\": \"32px\" },\n typography: {\n fontSans: \"'Inter', system-ui, sans-serif\",\n fontMono: \"'JetBrains Mono', monospace\",\n sizeXs: \"12px\", sizeSm: \"14px\", sizeMd: \"16px\", sizeLg: \"18px\", sizeXl: \"22px\",\n weightNormal: \"400\", weightMedium: \"500\", weightBold: \"700\",\n lineHeightTight: \"1.2\", lineHeightNormal: \"1.5\",\n },\n shadow: {\n xs: \"0 1px 2px rgba(0,0,0,0.05)\",\n sm: \"0 2px 6px rgba(0,0,0,0.06)\",\n md: \"0 4px 12px rgba(0,0,0,0.08)\",\n lg: \"0 10px 24px rgba(0,0,0,0.10)\",\n xl: \"0 20px 40px rgba(0,0,0,0.12)\",\n \"2xl\": \"0 28px 56px rgba(0,0,0,0.16)\",\n inner: \"inset 0 1px 2px rgba(0,0,0,0.05)\",\n },\n elevation: { dropdown: 1000, popover: 1100, modal: 1200, toast: 1300, tooltip: 1400 },\n motion: {\n durationFast: \"120ms\", durationNormal: \"200ms\", durationSlow: \"320ms\",\n easeStandard: \"cubic-bezier(0.4, 0, 0.2, 1)\", easeEmphasized: \"cubic-bezier(0.2, 0, 0, 1)\",\n durationInstant: \"0ms\",\n },\n border: { widthThin: \"1px\", widthMedium: \"1.5px\", widthThick: \"2px\", style: \"solid\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\n\nexport const dark = defineTheme({\n meta: {\n name: \"dark\",\n label: \"Dark\",\n description: \"Low-glare surface for extended use.\",\n },\n color: {\n neutral: {\n 0: \"#030712\", 50: \"#111827\", 100: \"#1f2937\", 200: \"#374151\", 300: \"#4b5563\",\n 400: \"#6b7280\", 500: \"#9ca3af\", 600: \"#d1d5db\", 700: \"#e5e7eb\", 800: \"#f3f4f6\",\n 900: \"#f9fafb\", 950: \"#ffffff\",\n },\n success: { light: \"#064e3b\", subtle: \"#065f46\", base: \"#34d399\", dark: \"#6ee7b7\", deeper: \"#d1fae5\" },\n danger: { light: \"#7f1d1d\", subtle: \"#991b1b\", base: \"#f87171\", dark: \"#fca5a5\", deeper: \"#fee2e2\" },\n warning: { light: \"#78350f\", subtle: \"#92400e\", base: \"#fbbf24\", dark: \"#fcd34d\", deeper: \"#fef3c7\" },\n info: { light: \"#1e3a5f\", subtle: \"#1e40af\", base: \"#60a5fa\", dark: \"#93c5fd\", deeper: \"#dbeafe\" },\n background: \"#0b0f19\",\n surface: \"#131826\",\n surfaceRaised: \"#1c2333\",\n border: \"#2a3143\",\n borderFocus: \"#6b7280\",\n text: \"#f3f4f6\",\n textMuted: \"#9ca3af\",\n textInverse: \"#111827\",\n },\n radius: { sm: \"6px\", md: \"10px\", lg: \"14px\", xl: \"18px\", \"2xl\": \"24px\", full: \"9999px\" },\n spacing: { xs: \"4px\", sm: \"8px\", md: \"12px\", lg: \"16px\", xl: \"24px\", \"2xl\": \"32px\" },\n typography: {\n fontSans: \"'Inter', system-ui, sans-serif\",\n fontMono: \"'JetBrains Mono', monospace\",\n sizeXs: \"12px\", sizeSm: \"14px\", sizeMd: \"16px\", sizeLg: \"18px\", sizeXl: \"22px\",\n weightNormal: \"400\", weightMedium: \"500\", weightBold: \"700\",\n lineHeightTight: \"1.2\", lineHeightNormal: \"1.5\",\n },\n shadow: {\n xs: \"0 1px 2px rgba(0,0,0,0.4)\",\n sm: \"0 2px 6px rgba(0,0,0,0.45)\",\n md: \"0 4px 12px rgba(0,0,0,0.5)\",\n lg: \"0 10px 24px rgba(0,0,0,0.55)\",\n xl: \"0 20px 40px rgba(0,0,0,0.6)\",\n \"2xl\": \"0 28px 56px rgba(0,0,0,0.65)\",\n inner: \"inset 0 1px 2px rgba(0,0,0,0.4)\",\n },\n elevation: { dropdown: 1000, popover: 1100, modal: 1200, toast: 1300, tooltip: 1400 },\n motion: {\n durationFast: \"120ms\", durationNormal: \"200ms\", durationSlow: \"320ms\",\n easeStandard: \"cubic-bezier(0.4, 0, 0.2, 1)\", easeEmphasized: \"cubic-bezier(0.2, 0, 0, 1)\",\n durationInstant: \"0ms\",\n },\n border: { widthThin: \"1px\", widthMedium: \"1.5px\", widthThick: \"2px\", style: \"solid\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\n\nexport const glass = defineTheme({\n meta: {\n name: \"glass\",\n label: \"Glass\",\n description: \"Translucent, softly rounded, floating surfaces. Needs a rich background behind it.\",\n },\n color: {\n neutral: {\n 0: \"#ffffff\", 50: \"#f9fafb\", 100: \"#f3f4f6\", 200: \"#e5e7eb\", 300: \"#d1d5db\",\n 400: \"#9ca3af\", 500: \"#6b7280\", 600: \"#4b5563\", 700: \"#374151\", 800: \"#1f2937\",\n 900: \"#111827\", 950: \"#030712\",\n },\n success: { light: \"#d1fae5\", subtle: \"#a7f3d0\", base: \"#10b981\", dark: \"#059669\", deeper: \"#064e3b\" },\n danger: { light: \"#fee2e2\", subtle: \"#fecaca\", base: \"#ef4444\", dark: \"#dc2626\", deeper: \"#7f1d1d\" },\n warning: { light: \"#fef3c7\", subtle: \"#fde68a\", base: \"#f59e0b\", dark: \"#d97706\", deeper: \"#78350f\" },\n info: { light: \"#dbeafe\", subtle: \"#bfdbfe\", base: \"#3b82f6\", dark: \"#2563eb\", deeper: \"#1e3a5f\" },\n background: \"transparent\",\n surface: \"rgba(255,255,255,0.55)\",\n surfaceRaised: \"rgba(255,255,255,0.75)\",\n // Was rgba(255,255,255,0.35) — translucent WHITE. Composited on\n // a plain white page (the theme's own meta.description admits it\n // \"needs a rich background behind it,\" but most consumers won't\n // add one), that resolves to literal #ffffff — a 1.0:1 contrast\n // ratio, i.e. actually invisible, which is the reported vanished\n // Progress-track border. A neutral slate tint stays visible\n // against both a plain white AND a plain black fallback backdrop\n // (measured ~2.1-2.3:1 either way) — short of full 3:1 UI-contrast\n // on both extremes at once, but a large improvement over 1.0, and\n // still reads as a soft glass edge over an actual rich backdrop.\n border: \"rgba(100,116,139,0.6)\",\n borderFocus: \"#9ca3af\",\n text: \"#111827\",\n textMuted: \"rgba(17,24,39,0.65)\",\n textInverse: \"#ffffff\",\n },\n // Notably rounder than light/dark — this is a shape difference, not just color.\n radius: { sm: \"10px\", md: \"16px\", lg: \"22px\", xl: \"28px\", \"2xl\": \"36px\", full: \"9999px\" },\n spacing: { xs: \"4px\", sm: \"8px\", md: \"12px\", lg: \"16px\", xl: \"24px\", \"2xl\": \"32px\" },\n typography: {\n fontSans: \"'Inter', system-ui, sans-serif\",\n fontMono: \"'JetBrains Mono', monospace\",\n sizeXs: \"12px\", sizeSm: \"14px\", sizeMd: \"16px\", sizeLg: \"18px\", sizeXl: \"22px\",\n weightNormal: \"400\", weightMedium: \"500\", weightBold: \"700\",\n lineHeightTight: \"1.2\", lineHeightNormal: \"1.5\",\n },\n shadow: {\n xs: \"0 2px 8px rgba(0,0,0,0.06)\",\n sm: \"0 4px 16px rgba(0,0,0,0.08)\",\n md: \"0 8px 32px rgba(0,0,0,0.10)\",\n lg: \"0 16px 48px rgba(0,0,0,0.12)\",\n xl: \"0 24px 64px rgba(0,0,0,0.14)\",\n \"2xl\": \"0 32px 80px rgba(0,0,0,0.18)\",\n inner: \"inset 0 1px 0 rgba(255,255,255,0.4)\",\n },\n elevation: { dropdown: 1000, popover: 1100, modal: 1200, toast: 1300, tooltip: 1400 },\n motion: {\n // Slightly slower/softer than light/dark — matches \"everything floats\".\n durationFast: \"160ms\", durationNormal: \"260ms\", durationSlow: \"400ms\",\n easeStandard: \"cubic-bezier(0.25, 0.1, 0.25, 1)\", easeEmphasized: \"cubic-bezier(0.16, 1, 0.3, 1)\",\n durationInstant: \"0ms\",\n },\n border: { widthThin: \"1px\", widthMedium: \"1px\", widthThick: \"1.5px\", style: \"solid\" },\n effects: { backdropBlur: \"16px\" },\n});","import { defineTheme } from \"../contract\";\nimport { dark } from \"./dark\";\n\nexport const darkGlass = defineTheme({\n ...dark,\n meta: {\n name: \"dark-glass\",\n label: \"Dark Glass\",\n description: \"Translucent glass panels floating over a dark background.\",\n },\n color: {\n ...dark.color,\n background: \"#05070d\",\n surface: \"rgba(255,255,255,0.06)\",\n surfaceRaised: \"rgba(255,255,255,0.10)\",\n border: \"rgba(255,255,255,0.12)\",\n },\n radius: { sm: \"10px\", md: \"16px\", lg: \"22px\", xl: \"28px\", \"2xl\": \"36px\", full: \"9999px\" },\n shadow: {\n xs: \"0 2px 8px rgba(0,0,0,0.5)\", sm: \"0 4px 16px rgba(0,0,0,0.55)\", md: \"0 8px 32px rgba(0,0,0,0.6)\",\n lg: \"0 16px 48px rgba(0,0,0,0.65)\", xl: \"0 24px 64px rgba(0,0,0,0.7)\", \"2xl\": \"0 32px 80px rgba(0,0,0,0.75)\",\n inner: \"inset 0 1px 0 rgba(255,255,255,0.08)\",\n },\n motion: { ...dark.motion, durationFast: \"160ms\", durationNormal: \"260ms\", durationSlow: \"400ms\" },\n effects: { backdropBlur: \"18px\" },\n});\n","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const minimalism = defineTheme({\n ...light,\n meta: {\n name: \"minimalism\",\n label: \"Minimalism\",\n description: \"Reduced to essentials — thin borders, flat surfaces, no shadow, tight radius.\",\n },\n color: {\n ...light.color,\n border: \"#e2e2e2\", surface: \"#ffffff\", surfaceRaised: \"#ffffff\",\n },\n radius: { sm: \"2px\", md: \"3px\", lg: \"4px\", xl: \"6px\", \"2xl\": \"8px\", full: \"9999px\" },\n shadow: { xs: \"none\", sm: \"none\", md: \"none\", lg: \"none\", xl: \"none\", \"2xl\": \"none\", inner: \"none\" },\n border: { widthThin: \"1px\", widthMedium: \"1px\", widthThick: \"1px\", style: \"solid\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const brutalism = defineTheme({\n ...light,\n meta: {\n name: \"brutalism\",\n label: \"Brutalism\",\n description: \"Raw, unstyled web aesthetic — square corners, zero shadow, monospace type.\",\n },\n color: {\n ...light.color,\n background: \"#ffffff\", surface: \"#ffffff\", surfaceRaised: \"#ffffff\",\n border: \"#000000\", borderFocus: \"#ff0000\", text: \"#000000\",\n },\n radius: { sm: \"0px\", md: \"0px\", lg: \"0px\", xl: \"0px\", \"2xl\": \"0px\", full: \"0px\" },\n typography: { ...light.typography, fontSans: \"'Courier New', monospace\", fontMono: \"'Courier New', monospace\" },\n shadow: { xs: \"none\", sm: \"none\", md: \"none\", lg: \"none\", xl: \"none\", \"2xl\": \"none\", inner: \"none\" },\n border: { widthThin: \"1px\", widthMedium: \"2px\", widthThick: \"3px\", style: \"solid\" },\n motion: { ...light.motion, durationFast: \"0ms\", durationNormal: \"0ms\", durationSlow: \"0ms\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const neobrutalism = defineTheme({\n ...light,\n meta: {\n name: \"neobrutalism\",\n label: \"Neo Brutalism\",\n description: \"Bold black borders, flat offset shadows, saturated color blocks.\",\n },\n color: {\n ...light.color,\n background: \"#fef3c7\", surface: \"#ffffff\", surfaceRaised: \"#ffffff\",\n border: \"#000000\", borderFocus: \"#000000\",\n // light.color.warning.light (#fef3c7) is identical to this\n // theme's own background — every warning Alert/Badge/etc. was\n // rendering invisibly on the page. Bumped to the next step in\n // the same warm-amber family (matches light.color.warning.subtle)\n // so it stays on-theme but is actually visible against the page.\n warning: { ...light.color.warning, light: \"#fde68a\" },\n },\n radius: { sm: \"4px\", md: \"6px\", lg: \"8px\", xl: \"10px\", \"2xl\": \"12px\", full: \"9999px\" },\n shadow: {\n xs: \"2px 2px 0 #000000\", sm: \"3px 3px 0 #000000\", md: \"4px 4px 0 #000000\",\n lg: \"6px 6px 0 #000000\", xl: \"8px 8px 0 #000000\", \"2xl\": \"10px 10px 0 #000000\",\n inner: \"inset 2px 2px 0 #000000\",\n },\n border: { widthThin: \"2px\", widthMedium: \"3px\", widthThick: \"4px\", style: \"solid\" },\n motion: { ...light.motion, durationFast: \"80ms\", durationNormal: \"140ms\", durationSlow: \"200ms\", easeStandard: \"linear\", easeEmphasized: \"linear\" },\n effects: { backdropBlur: \"0px\" },\n});","import { defineTheme } from \"../contract\";\nimport { dark } from \"./dark\";\n\nexport const cyberpunk = defineTheme({\n ...dark,\n meta: {\n name: \"cyberpunk\",\n label: \"Cyberpunk\",\n description: \"Neon-on-black, glowing edges, high-saturation magenta/cyan accents.\",\n },\n color: {\n ...dark.color,\n background: \"#0a0014\", surface: \"#12001f\", surfaceRaised: \"#1a0230\",\n border: \"#ff2bd6\", borderFocus: \"#00f0ff\", text: \"#e8faff\", textMuted: \"#9a8cc9\",\n },\n radius: { sm: \"2px\", md: \"4px\", lg: \"6px\", xl: \"8px\", \"2xl\": \"10px\", full: \"9999px\" },\n shadow: {\n xs: \"0 0 6px rgba(255,43,214,0.5)\", sm: \"0 0 12px rgba(255,43,214,0.55)\",\n md: \"0 0 20px rgba(0,240,255,0.5)\", lg: \"0 0 32px rgba(0,240,255,0.55)\",\n xl: \"0 0 48px rgba(255,43,214,0.6)\", \"2xl\": \"0 0 64px rgba(0,240,255,0.65)\",\n inner: \"inset 0 0 8px rgba(255,43,214,0.4)\",\n },\n border: { widthThin: \"1px\", widthMedium: \"1.5px\", widthThick: \"2px\", style: \"solid\" },\n motion: { ...dark.motion, easeStandard: \"cubic-bezier(0.83,0,0.17,1)\", easeEmphasized: \"cubic-bezier(0.9,0,0.1,1)\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const gradient = defineTheme({\n ...light,\n meta: {\n name: \"gradient\",\n label: \"Gradient\",\n description: \"Vibrant, colorful transitions across surfaces and accents.\",\n },\n color: {\n ...light.color,\n background: \"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\",\n surface: \"linear-gradient(135deg, rgba(255,255,255,0.92), rgba(255,255,255,0.75))\",\n surfaceRaised: \"#ffffff\",\n border: \"rgba(118,75,162,0.25)\",\n borderFocus: \"#764ba2\",\n // text/textMuted were still light theme's values (#111827 /\n // #6b7280) — fine on the near-white `surface`, but components\n // that render straight on `background` (Timeline, Pagination,\n // Tabs — all used with no wrapping surface in this library's own\n // docs examples) sat directly on the purple gradient instead.\n // Measured contrast against the gradient's darker stop\n // (#764ba2): text 2.79:1, textMuted a barely-there 1.32:1 — the\n // reported \"nearly invisible\" text. Darkened both; textMuted\n // still can't clear 4.5:1 against the darkest point of this\n // specific gradient with a single flat color (nothing dark\n // enough to do that stays legible as \"muted\" against the near-\n // white surface too), so this is the best available compromise\n // within a single global text/textMuted pair, not a full fix —\n // worth knowing if it still reads as low-contrast on the\n // darkest corner of the gradient.\n text: \"#000000\",\n textMuted: \"#2e2440\",\n },\n radius: { sm: \"12px\", md: \"18px\", lg: \"24px\", xl: \"32px\", \"2xl\": \"40px\", full: \"9999px\" },\n shadow: {\n xs: \"0 2px 10px rgba(118,75,162,0.15)\", sm: \"0 4px 20px rgba(118,75,162,0.18)\",\n md: \"0 8px 30px rgba(118,75,162,0.22)\", lg: \"0 16px 40px rgba(118,75,162,0.26)\",\n xl: \"0 24px 56px rgba(118,75,162,0.3)\", \"2xl\": \"0 32px 72px rgba(118,75,162,0.35)\",\n inner: \"inset 0 1px 0 rgba(255,255,255,0.5)\",\n },\n motion: { ...light.motion, durationNormal: \"240ms\", durationSlow: \"380ms\" },\n effects: { backdropBlur: \"0px\" },\n});","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const material = defineTheme({\n ...light,\n meta: {\n name: \"material\",\n label: \"Material\",\n description: \"Google Material Design-inspired elevation shadows and motion curves.\",\n },\n color: {\n ...light.color,\n surface: \"#ffffff\", background: \"#fafafa\",\n },\n radius: { sm: \"4px\", md: \"8px\", lg: \"12px\", xl: \"16px\", \"2xl\": \"28px\", full: \"9999px\" },\n typography: { ...light.typography, fontSans: \"'Roboto', system-ui, sans-serif\" },\n shadow: {\n xs: \"0 1px 2px rgba(0,0,0,0.24)\",\n sm: \"0 1px 4px rgba(0,0,0,0.2), 0 1px 2px rgba(0,0,0,0.12)\",\n md: \"0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)\",\n lg: \"0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)\",\n xl: \"0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)\",\n \"2xl\": \"0 19px 38px rgba(0,0,0,0.3), 0 15px 12px rgba(0,0,0,0.22)\",\n inner: \"inset 0 1px 2px rgba(0,0,0,0.12)\",\n },\n motion: { ...light.motion, easeStandard: \"cubic-bezier(0.4,0,0.2,1)\", easeEmphasized: \"cubic-bezier(0.0,0,0.2,1)\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import { defineTheme } from \"../contract\";\nimport { light } from \"./light\";\n\nexport const skeuomorphism = defineTheme({\n ...light,\n meta: {\n name: \"skeuomorphism\",\n label: \"Skeuomorphism\",\n description: \"Realistic depth — soft embossed surfaces mimicking physical material.\",\n },\n color: {\n ...light.color,\n background: \"#e8e4da\", surface: \"#f0ece2\", surfaceRaised: \"#f7f4ec\",\n border: \"#c9c2b0\", text: \"#3a3226\",\n },\n radius: { sm: \"8px\", md: \"12px\", lg: \"18px\", xl: \"24px\", \"2xl\": \"32px\", full: \"9999px\" },\n shadow: {\n xs: \"inset 0 1px 1px rgba(255,255,255,0.8), 0 1px 3px rgba(58,50,38,0.25)\",\n sm: \"inset 0 1px 1px rgba(255,255,255,0.8), 0 2px 6px rgba(58,50,38,0.28)\",\n md: \"inset 0 1px 1px rgba(255,255,255,0.8), 0 4px 10px rgba(58,50,38,0.3)\",\n lg: \"inset 0 1px 1px rgba(255,255,255,0.8), 0 8px 18px rgba(58,50,38,0.32)\",\n xl: \"inset 0 1px 1px rgba(255,255,255,0.8), 0 14px 28px rgba(58,50,38,0.35)\",\n \"2xl\": \"inset 0 1px 1px rgba(255,255,255,0.8), 0 20px 40px rgba(58,50,38,0.38)\",\n inner: \"inset 0 2px 4px rgba(58,50,38,0.3)\",\n },\n motion: { ...light.motion, durationNormal: \"220ms\", easeStandard: \"cubic-bezier(0.34,1.56,0.64,1)\" },\n effects: { backdropBlur: \"0px\" },\n});\n","import type { ThemeTokens } from \"./contract\";\nimport { findMissingTokenPaths } from \"./contract\";\nimport { light } from \"./themes/light\";\nimport { dark } from \"./themes/dark\";\nimport { glass } from \"./themes/glass\";\nimport { darkGlass } from \"./themes/dark-glass\";\nimport { minimalism } from \"./themes/minimalism\";\nimport { brutalism } from \"./themes/brutalism\";\nimport { neobrutalism } from \"./themes/neobrutalism\";\nimport { cyberpunk } from \"./themes/cyberpunk\";\nimport { gradient } from \"./themes/gradient\";\nimport { material } from \"./themes/material\";\nimport { skeuomorphism } from \"./themes/skeuomorphism\";\n\nconst registry = new Map<string, ThemeTokens>();\n\n/**\n * Checks the theme against REQUIRED_TOKEN_PATHS — a fixed list\n * hardcoded in contract.ts, not derived from whichever theme\n * happens to register first. This is the runtime safety net for\n * themes that bypass the TypeScript-level defineTheme() check\n * (e.g. loaded from JSON at runtime rather than authored as a\n * .ts file in this repo). A theme that fails this throws\n * immediately on registration, not silently at render time on\n * whichever component hits the missing key first.\n */\nfunction assertComplete(theme: ThemeTokens): void {\n const missing = findMissingTokenPaths(theme);\n if (missing.length > 0) {\n throw new Error(\n `Theme \"${theme.meta?.name ?? \"unknown\"}\" is missing/empty required token(s): ${missing.join(\", \")}`\n );\n }\n}\n\nexport function registerTheme(theme: ThemeTokens): void {\n assertComplete(theme);\n registry.set(theme.meta.name, theme);\n}\n\nexport function getTheme(name: string): ThemeTokens | undefined {\n return registry.get(name);\n}\n\nexport function listThemes(): ThemeTokens[] {\n return Array.from(registry.values());\n}\n\n// Built-in themes register on import. Third-party/future themes\n// (Cyberpunk, Neo Brutal, Aurora, ...) call registerTheme() the\n// same way from wherever they're defined — no other file needs\n// to change.\nregisterTheme(light);\nregisterTheme(dark);\nregisterTheme(glass);\nregisterTheme(darkGlass);\nregisterTheme(minimalism);\nregisterTheme(brutalism);\nregisterTheme(neobrutalism);\nregisterTheme(cyberpunk);\nregisterTheme(gradient);\nregisterTheme(material);\nregisterTheme(skeuomorphism);\n","import type { AccentDefinition } from \"../accents\";\n\nexport const indigo: AccentDefinition = {\n name: \"indigo\",\n label: \"Indigo\",\n scale: {\n 50: \"#f0f4ff\", 100: \"#e0e8ff\", 200: \"#c7d5fe\", 300: \"#a5b4fc\", 400: \"#818cf8\",\n 500: \"#6366f1\", 600: \"#4f46e5\", 700: \"#4338ca\", 800: \"#3730a3\", 900: \"#312e81\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const violet: AccentDefinition = {\n name: \"violet\",\n label: \"Violet\",\n scale: {\n 50: \"#faf5ff\", 100: \"#f3e8ff\", 200: \"#e9d5ff\", 300: \"#d8b4fe\", 400: \"#c084fc\",\n 500: \"#a855f7\", 600: \"#9333ea\", 700: \"#7e22ce\", 800: \"#6b21a8\", 900: \"#581c87\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const teal: AccentDefinition = {\n name: \"teal\",\n label: \"Teal\",\n scale: {\n 50: \"#f0fdfa\", 100: \"#ccfbf1\", 200: \"#99f6e4\", 300: \"#5eead4\", 400: \"#2dd4bf\",\n 500: \"#14b8a6\", 600: \"#0d9488\", 700: \"#0f766e\", 800: \"#115e59\", 900: \"#134e4a\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const rose: AccentDefinition = {\n name: \"rose\",\n label: \"Rose\",\n scale: {\n 50: \"#fff1f2\", 100: \"#ffe4e6\", 200: \"#fecdd3\", 300: \"#fda4af\", 400: \"#fb7185\",\n 500: \"#f43f5e\", 600: \"#e11d48\", 700: \"#be123c\", 800: \"#9f1239\", 900: \"#881337\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const amber: AccentDefinition = {\n name: \"amber\",\n label: \"Amber\",\n scale: {\n 50: \"#fffbeb\", 100: \"#fef3c7\", 200: \"#fde68a\", 300: \"#fcd34d\", 400: \"#fbbf24\",\n 500: \"#f59e0b\", 600: \"#d97706\", 700: \"#b45309\", 800: \"#92400e\", 900: \"#78350f\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const emerald: AccentDefinition = {\n name: \"emerald\",\n label: \"Emerald\",\n scale: {\n 50: \"#ecfdf5\", 100: \"#d1fae5\", 200: \"#a7f3d0\", 300: \"#6ee7b7\", 400: \"#34d399\",\n 500: \"#10b981\", 600: \"#059669\", 700: \"#047857\", 800: \"#065f46\", 900: \"#064e3b\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const copper: AccentDefinition = {\n name: \"copper\",\n label: \"Copper\",\n scale: {\n 50: \"#fdf6ec\", 100: \"#faebd2\", 200: \"#f3d3a0\", 300: \"#e9b56b\",\n 400: \"#d99a45\", 500: \"#b9752c\", 600: \"#9c5d24\", 700: \"#7d4a1f\", 800: \"#623a1c\", 900: \"#4e2f19\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const graphite: AccentDefinition = {\n name: \"graphite\",\n label: \"Graphite\",\n scale: {\n 50: \"#fafafa\", 100: \"#f0f0f0\", 200: \"#e0e0e0\", 300: \"#c7c7c7\", 400: \"#a3a3a3\",\n 500: \"#525252\", 600: \"#404040\", 700: \"#262626\", 800: \"#171717\", 900: \"#0a0a0a\",\n },\n};\n","import type { AccentDefinition } from \"../accents\";\n\nexport const magenta: AccentDefinition = {\n name: \"magenta\",\n label: \"Magenta\",\n scale: {\n 50: \"#ffe0fb\", 100: \"#ffb3f5\", 200: \"#ff80ee\", 300: \"#ff4de6\", 400: \"#ff26e0\",\n 500: \"#ff00d9\", 600: \"#e600c4\", 700: \"#cc00af\", 800: \"#b3009a\", 900: \"#800070\",\n },\n};\n","import type { ColorScale } from \"./contract\";\n\n// ============================================================\n// ACCENT COLORS\n//\n// This is the axis a consumer actually picks their brand color\n// from — completely independent of which theme (shape/structure)\n// is active. \"Our brand is teal\" should work whether the app is\n// using the light theme, the cyberpunk theme, or any other —\n// the theme still controls radius/shadow/motion/glass-or-not,\n// the accent controls hue.\n//\n// Mirrors tokens/registry.ts's shape deliberately (registerX /\n// getX / listX) so the two systems are learned once, not twice.\n// ============================================================\n\nexport interface AccentDefinition {\n name: string;\n label: string;\n scale: ColorScale;\n}\n\nconst registry = new Map<string, AccentDefinition>();\n\nfunction assertCompleteScale(def: AccentDefinition): void {\n const missing = ([\"50\", \"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\"] as const).filter(\n (k) => !def.scale[k as unknown as keyof ColorScale]\n );\n if (missing.length > 0) {\n throw new Error(`Accent \"${def.name}\" is missing scale step(s): ${missing.join(\", \")}`);\n }\n}\n\nexport function registerAccent(def: AccentDefinition): void {\n assertCompleteScale(def);\n registry.set(def.name, def);\n}\n\nexport function getAccent(name: string): AccentDefinition | undefined {\n return registry.get(name);\n}\n\nexport function listAccents(): AccentDefinition[] {\n return Array.from(registry.values());\n}\n\n// Built-in accents register on import. A consumer's own custom\n// brand accent registers the same way — registerAccent() with a\n// name/label/scale, called from wherever they define it.\nimport { indigo } from \"./accents/indigo\";\nimport { violet } from \"./accents/violet\";\nimport { teal } from \"./accents/teal\";\nimport { rose } from \"./accents/rose\";\nimport { amber } from \"./accents/amber\";\nimport { emerald } from \"./accents/emerald\";\nimport { copper } from \"./accents/copper\";\nimport { graphite } from \"./accents/graphite\";\nimport { magenta } from \"./accents/magenta\";\n\nregisterAccent(indigo);\nregisterAccent(violet);\nregisterAccent(teal);\nregisterAccent(rose);\nregisterAccent(amber);\nregisterAccent(emerald);\nregisterAccent(copper);\nregisterAccent(graphite);\nregisterAccent(magenta);\n\nexport const DEFAULT_ACCENT = \"indigo\";\n","import type { Size } from \"./types\";\n\n// ============================================================\n// Category B (form/input primitives) shared shape.\n//\n// BUILDING-COMPONENTS.md's Category B note: \"Standard props every\n// component in this category should share: value/defaultValue,\n// onChange, disabled, error (or invalid), placeholder where\n// applicable. Decide this shape once, here, rather than letting\n// Input and NumberInput drift (the old color/radius drift, one\n// category up).\" This module is that one decision, applied by\n// every field-based component (Input, Textarea, Checkbox, Radio,\n// Toggle, and any future one) instead of each re-deriving it.\n// ============================================================\n\nexport interface FieldProps {\n disabled?: boolean;\n required?: boolean;\n /** Whether the field is in an invalid/error state. */\n error?: boolean;\n size?: Size;\n}\n\nexport interface FieldState {\n isDisabled: boolean;\n isRequired: boolean;\n isInvalid: boolean;\n size: Size;\n}\n\nexport function resolveFieldState(props: FieldProps): FieldState {\n return {\n // ?? throughout, never || (CONTRACT.md Rule 3) — `error={false}`\n // or `disabled={false}` must not be silently discarded.\n isDisabled: props.disabled ?? false,\n isRequired: props.required ?? false,\n isInvalid: props.error ?? false,\n size: props.size ?? \"md\",\n };\n}\n\n/**\n * Category B's accessibility baseline (BUILDING-COMPONENTS.md):\n * aria-invalid and aria-describedby (for an error/helper message)\n * on every field component, not just the ones an author happened\n * to remember.\n */\nexport function getFieldAriaProps(state: FieldState, describedBy?: string) {\n return {\n \"aria-invalid\": state.isInvalid ? (true as const) : undefined,\n \"aria-required\": state.isRequired ? (true as const) : undefined,\n \"aria-describedby\": describedBy,\n };\n}\n","import { resolveFieldState, getFieldAriaProps, type FieldProps, type FieldState } from \"./field\";\n\n// ============================================================\n// COLOR PICKER — pure core (Category D: Input's field shape +\n// Popover, with the popover panel composing a preset swatch grid and\n// a custom saturation/hue panel — see react/ColorPicker.tsx's own\n// header for why both, rather than the native <input type=\"color\">\n// an earlier version of this file used). This module owns the field\n// concerns: hex normalization/parsing (now including `rgb(...)`/\n// `hsl(...)` function-notation strings, since the field can display\n// either depending on which format tab is active) and swatch/dial\n// classes and ARIA — the same split datepicker.ts draws between\n// \"field concerns\" and the grid widget's own math (there, Calendar's;\n// here, the swatch grid's and the custom panel's).\n// ============================================================\n\nexport type ColorPickerVariant = \"both\" | \"presets\" | \"custom\";\n\nexport interface ColorPickerCoreProps extends FieldProps {\n /** Preset swatches offered in the popover, as hex strings. Defaults to DEFAULT_PRESETS. */\n presets?: string[];\n /**\n * Which part(s) of the popover to show. `\"both\"` (default) is the\n * preset grid plus the custom saturation/hue panel underneath it.\n * `\"presets\"` shows only the grid — a fixed palette with no\n * arbitrary-color escape hatch. `\"custom\"` shows only the\n * saturation/hue panel — no preset shortcuts at all.\n */\n variant?: ColorPickerVariant;\n}\n\nexport interface ColorPickerState extends FieldState {\n presets: string[];\n variant: ColorPickerVariant;\n}\n\nexport const DEFAULT_PRESETS: string[] = [\n \"#ef4444\",\n \"#f97316\",\n \"#f59e0b\",\n \"#eab308\",\n \"#84cc16\",\n \"#22c55e\",\n \"#10b981\",\n \"#14b8a6\",\n \"#06b6d4\",\n \"#3b82f6\",\n \"#6366f1\",\n \"#8b5cf6\",\n \"#a855f7\",\n \"#d946ef\",\n \"#ec4899\",\n \"#6b7280\",\n \"#171717\",\n \"#ffffff\",\n];\n\nexport function resolveColorPickerState(props: ColorPickerCoreProps): ColorPickerState {\n return {\n ...resolveFieldState(props),\n presets: props.presets ?? DEFAULT_PRESETS,\n variant: props.variant ?? \"both\",\n };\n}\n\n// --- hex parsing / normalization -----------------------------------\n\nconst HEX_RE = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\n/** Whether `text` is a recognizable 3- or 6-digit hex color, with or without a leading `#`. */\nexport function isValidHex(text: string): boolean {\n return HEX_RE.test(text.trim());\n}\n\n/**\n * Normalizes any accepted hex input (`\"f00\"`, `\"#f00\"`, `\"ff0000\"`,\n * `\"#FF0000\"`) into a canonical lowercase `#rrggbb` string, or `null`\n * if it isn't a valid hex color at all. The single source of truth\n * every call site (typed-text commit, swatch click, the native color\n * input's own onChange) normalizes through, the same role\n * isDateSelectable/isTimeSelectable play for their fields.\n */\nexport function normalizeHex(text: string): string | null {\n const trimmed = text.trim();\n const match = trimmed.match(HEX_RE);\n if (!match) return null;\n let hex = match[1].toLowerCase();\n if (hex.length === 3) {\n hex = hex\n .split(\"\")\n .map((c) => c + c)\n .join(\"\");\n }\n return `#${hex}`;\n}\n\n/** Whether two hex strings (however formatted) represent the same color. */\nexport function isSameColor(a: string | null | undefined, b: string | null | undefined): boolean {\n if (!a || !b) return a === b;\n const na = normalizeHex(a);\n const nb = normalizeHex(b);\n return na !== null && na === nb;\n}\n\n/** Rough perceived-lightness check, used only to decide a checkmark's contrast color on a selected swatch — not a color-science API. */\nexport function isLightColor(hex: string): boolean {\n const normalized = normalizeHex(hex);\n if (!normalized) return true;\n const r = parseInt(normalized.slice(1, 3), 16);\n const g = parseInt(normalized.slice(3, 5), 16);\n const b = parseInt(normalized.slice(5, 7), 16);\n const luma = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n return luma > 0.6;\n}\n\n// --- classes ------------------------------------------------------\n\nexport function getSwatchClasses(input: { isSelected: boolean; isActive: boolean }): string {\n return [\n \"nx-colorpicker__swatch-option\",\n input.isSelected && \"nx-colorpicker__swatch-option--selected\",\n input.isActive && \"nx-colorpicker__swatch-option--active\",\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\n// --- ARIA -----------------------------------------------------\n\nexport function getSwatchGridAriaProps(label: string) {\n return { role: \"listbox\" as const, \"aria-label\": label };\n}\n\nexport function getSwatchAriaProps(input: { isSelected: boolean; isFocusable: boolean; label: string }) {\n return {\n role: \"option\" as const,\n \"aria-selected\": input.isSelected,\n \"aria-label\": input.label,\n tabIndex: input.isFocusable ? 0 : -1,\n };\n}\n\nexport function getFieldTriggerAriaProps(state: FieldState, describedBy?: string) {\n return getFieldAriaProps(state, describedBy);\n}\n\n// --- custom panel: color space conversions --------------------------\n// The typed hex field and preset grid only ever need hex in/out, but\n// the custom panel (saturation/value area + hue slider + RGB/HSL\n// fields) needs to move between hex, RGB, HSV, and HSL freely. HSV\n// drives the SV area/hue slider (the natural space for a \"pick a hue,\n// then a shade of it\" 2D control); RGB/HSL are only ever produced for\n// display in their own format tab and round-tripped back through hex\n// on edit, so hex stays the single canonical value ColorPicker's\n// public onChange emits (Rule 10 — the public shape doesn't change).\n\nexport interface RGB {\n r: number;\n g: number;\n b: number;\n}\n\nexport interface HSV {\n h: number;\n s: number;\n v: number;\n}\n\nexport interface HSL {\n h: number;\n s: number;\n l: number;\n}\n\nexport type ColorFormat = \"hex\" | \"rgb\" | \"hsl\";\n\nexport const COLOR_FORMATS: ColorFormat[] = [\"hex\", \"rgb\", \"hsl\"];\n\nfunction clampNum(n: number, min: number, max: number): number {\n return Math.min(Math.max(n, min), max);\n}\n\n/** Hex (any accepted shape, see `normalizeHex`) to 0-255 RGB channels, or `null` if not a valid hex color. */\nexport function hexToRgb(hex: string): RGB | null {\n const normalized = normalizeHex(hex);\n if (!normalized) return null;\n return {\n r: parseInt(normalized.slice(1, 3), 16),\n g: parseInt(normalized.slice(3, 5), 16),\n b: parseInt(normalized.slice(5, 7), 16),\n };\n}/** 0-255 RGB channels (rounded, clamped) to canonical lowercase `#rrggbb`. */\nexport function rgbToHex({ r, g, b }: RGB): string {\n const channel = (n: number) => clampNum(Math.round(n), 0, 255).toString(16).padStart(2, \"0\");\n return `#${channel(r)}${channel(g)}${channel(b)}`;\n}\n\n/** 0-255 RGB to HSV (`h` in 0-360, `s`/`v` in 0-100). */\nexport function rgbToHsv({ r, g, b }: RGB): HSV {\n const rn = r / 255,\n gn = g / 255,\n bn = b / 255;\n const max = Math.max(rn, gn, bn),\n min = Math.min(rn, gn, bn);\n const d = max - min;\n let h = 0;\n if (d !== 0) {\n if (max === rn) h = ((gn - bn) / d) % 6;\n else if (max === gn) h = (bn - rn) / d + 2;\n else h = (rn - gn) / d + 4;\n h *= 60;\n if (h < 0) h += 360;\n }\n const s = max === 0 ? 0 : d / max;\n return { h, s: s * 100, v: max * 100 };\n}\n\n/** HSV (`h` in 0-360, `s`/`v` in 0-100) to 0-255 RGB. */\nexport function hsvToRgb({ h, s, v }: HSV): RGB {\n const s1 = clampNum(s, 0, 100) / 100;\n const v1 = clampNum(v, 0, 100) / 100;\n const hh = (((h % 360) + 360) % 360) / 60;\n const c = v1 * s1;\n const x = c * (1 - Math.abs((hh % 2) - 1));\n const m = v1 - c;\n let [r1, g1, b1] = [0, 0, 0];\n if (hh < 1) [r1, g1, b1] = [c, x, 0];\n else if (hh < 2) [r1, g1, b1] = [x, c, 0];\n else if (hh < 3) [r1, g1, b1] = [0, c, x];\n else if (hh < 4) [r1, g1, b1] = [0, x, c];\n else if (hh < 5) [r1, g1, b1] = [x, 0, c];\n else [r1, g1, b1] = [c, 0, x];\n return { r: (r1 + m) * 255, g: (g1 + m) * 255, b: (b1 + m) * 255 };\n}\n\n/** 0-255 RGB to HSL (`h` in 0-360, `s`/`l` in 0-100). */\nexport function rgbToHsl({ r, g, b }: RGB): HSL {\n const rn = r / 255,\n gn = g / 255,\n bn = b / 255;\n const max = Math.max(rn, gn, bn),\n min = Math.min(rn, gn, bn);\n const l = (max + min) / 2;\n const d = max - min;\n let h = 0,\n s = 0;\n if (d !== 0) {\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === rn) h = ((gn - bn) / d) % 6;\n else if (max === gn) h = (bn - rn) / d + 2;\n else h = (rn - gn) / d + 4;\n h *= 60;\n if (h < 0) h += 360;\n }\n return { h, s: s * 100, l: l * 100 };\n}\n\n/** HSL (`h` in 0-360, `s`/`l` in 0-100) to 0-255 RGB. */\nexport function hslToRgb({ h, s, l }: HSL): RGB {\n const s1 = clampNum(s, 0, 100) / 100;\n const l1 = clampNum(l, 0, 100) / 100;\n const c = (1 - Math.abs(2 * l1 - 1)) * s1;\n const hh = (((h % 360) + 360) % 360) / 60;\n const x = c * (1 - Math.abs((hh % 2) - 1));\n const m = l1 - c / 2;\n let [r1, g1, b1] = [0, 0, 0];\n if (hh < 1) [r1, g1, b1] = [c, x, 0];\n else if (hh < 2) [r1, g1, b1] = [x, c, 0];\n else if (hh < 3) [r1, g1, b1] = [0, c, x];\n else if (hh < 4) [r1, g1, b1] = [0, x, c];\n else if (hh < 5) [r1, g1, b1] = [x, 0, c];\n else [r1, g1, b1] = [c, 0, x];\n return { r: (r1 + m) * 255, g: (g1 + m) * 255, b: (b1 + m) * 255 };\n}\n\n/** Hex to HSV, or `null` if not a valid hex color — the SV-area/hue-slider's read side. */\nexport function hexToHsv(hex: string): HSV | null {\n const rgb = hexToRgb(hex);\n return rgb ? rgbToHsv(rgb) : null;\n}\n\n/** HSV to canonical hex — the SV-area/hue-slider's write side. */\nexport function hsvToHex(hsv: HSV): string {\n return rgbToHex(hsvToRgb(hsv));\n}\n\n/** HSL to canonical hex — the HSL format tab's write side. */\nexport function hslToHex(hsl: HSL): string {\n return rgbToHex(hslToRgb(hsl));\n}\n\n// --- typed-field text: parsing whichever format is on screen, and\n// producing that format back out --------------------------------\n// The field's displayed text now follows whichever format tab is\n// active in the custom panel (hex/rgb/hsl) rather than always\n// showing hex, so it needs to accept typed `rgb(...)`/`hsla(...)`\n// text back, not just hex — otherwise a person editing the field\n// while \"RGB\" is selected would have their own format rejected.\n\nconst RGB_FUNCTION_RE = /^rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/i;\nconst HSL_FUNCTION_RE = /^hsla?\\(\\s*(-?\\d{1,3})\\s*,\\s*(\\d{1,3})%\\s*,\\s*(\\d{1,3})%\\s*(?:,\\s*[\\d.]+\\s*)?\\)$/i;\n\n/** Parses hex OR `rgb(a)(...)`/`hsl(a)(...)` function-notation text into normalized hex, or `null` if it's none of those. */\nexport function parseColorInput(text: string): string | null {\n const trimmed = text.trim();\n const hex = normalizeHex(trimmed);\n if (hex) return hex;\n\n const rgbMatch = trimmed.match(RGB_FUNCTION_RE);\n if (rgbMatch) {\n const [, r, g, b] = rgbMatch;\n return rgbToHex({ r: clampNum(Number(r), 0, 255), g: clampNum(Number(g), 0, 255), b: clampNum(Number(b), 0, 255) });\n }\n\n const hslMatch = trimmed.match(HSL_FUNCTION_RE);\n if (hslMatch) {\n const [, h, s, l] = hslMatch;\n return hslToHex({ h: clampNum(Number(h), 0, 360), s: clampNum(Number(s), 0, 100), l: clampNum(Number(l), 0, 100) });\n }\n\n return null;\n}\n\n/** Renders hex as text in the given format — the field's display-side counterpart to `parseColorInput`, so what's shown always matches whichever format tab is currently active. */\nexport function formatColorValue(hex: string, format: ColorFormat): string {\n if (format === \"hex\") return hex;\n const rgb = hexToRgb(hex);\n if (!rgb) return hex;\n if (format === \"rgb\") return `rgb(${Math.round(rgb.r)}, ${Math.round(rgb.g)}, ${Math.round(rgb.b)})`;\n const hsl = rgbToHsl(rgb);\n return `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;\n}\n\n/** Arrow-key deltas for the 2D saturation/value area (Shift for a larger step) — Home/End/PageUp/PageDown aren't meaningful on a 2D surface, so only the four arrows are handled, same spirit as Slider's own keyboard set restricted to what the control actually has. */\nexport function getSvKeyboardDelta(key: string, coarse: boolean): { ds: number; dv: number } | null {\n const step = coarse ? 10 : 2;\n switch (key) {\n case \"ArrowLeft\":\n return { ds: -step, dv: 0 };\n case \"ArrowRight\":\n return { ds: step, dv: 0 };\n case \"ArrowUp\":\n return { ds: 0, dv: step };\n case \"ArrowDown\":\n return { ds: 0, dv: -step };\n default:\n return null;\n }\n}\n\n/** Clamps a saturation or value percentage into 0-100. Exported so the SV area's pointer/keyboard handlers share one clamp rather than each re-deriving it. */\nexport function clampPercent(n: number): number {\n return clampNum(n, 0, 100);\n}\n\n// --- custom panel: classes / ARIA -----------------------------------\n\nexport function getFormatTabClasses(isActive: boolean): string {\n return [\"nx-colorpicker__format-tab\", isActive && \"nx-colorpicker__format-tab--active\"].filter(Boolean).join(\" \");\n}\n\nexport function getFormatTablistAriaProps(label: string) {\n return { role: \"tablist\" as const, \"aria-label\": label };\n}\n\nexport function getFormatTabAriaProps(isActive: boolean) {\n return { role: \"tab\" as const, \"aria-selected\": isActive, tabIndex: isActive ? 0 : -1 };\n}\n\nexport function getSvThumbAriaProps(saturation: number, value: number) {\n return {\n role: \"slider\" as const,\n \"aria-label\": \"Color saturation and brightness\",\n \"aria-valuetext\": `Saturation ${Math.round(saturation)}%, brightness ${Math.round(value)}%`,\n tabIndex: 0,\n };\n}","import type { Size } from \"./types\";\n\n// ============================================================\n// TABLE — pure core (Category F: complex/stateful).\n//\n// Per BUILDING-COMPONENTS.md's own note for this component: \"sort\n// state should be lifted to props the consumer can control, not\n// trapped inside the component\" — the same controlled-value shape\n// Input/Slider/NumberInput already use. Table itself holds no sort\n// or selection state; TableHead's `sortDirection` is a prop the\n// consumer supplies, and getNextSortDirection is exported so the\n// consumer's onSort handler doesn't have to reinvent the standard\n// asc → desc → unsorted cycle. Row SELECTION is intentionally not\n// modeled here at all — TableRow just renders whatever `selected`\n// boolean it's given, and a table with checkboxes composes the real\n// Checkbox component (Rule 12) rather than Table reimplementing a\n// second one. getSelectAllState is the one piece of selection logic\n// that's genuinely shared/non-trivial (the tri-state \"select all\"\n// checkbox's own state, computed from a count) — pulled out here so\n// it's unit-tested the same way everything else pure is.\n// ============================================================\n\nexport interface TableCoreProps {\n size?: Size;\n /** Alternating row background. Default false. */\n striped?: boolean;\n /** Borders around every cell, not just horizontal row rules. Default false. */\n bordered?: boolean;\n /** Keeps the header visible while the body scrolls — only has something to stick within if an ancestor bounds the table's height (e.g. a wrapping div with max-height). Default false. */\n stickyHeader?: boolean;\n}\n\nexport interface TableState {\n size: Size;\n striped: boolean;\n bordered: boolean;\n stickyHeader: boolean;\n}\n\nexport function resolveTableState(props: TableCoreProps): TableState {\n return {\n size: props.size ?? \"md\",\n striped: props.striped ?? false,\n bordered: props.bordered ?? false,\n stickyHeader: props.stickyHeader ?? false,\n };\n}\n\nexport function getWrapperClasses(className?: string): string {\n return [\"nx-table-wrapper\", className].filter(Boolean).join(\" \");\n}\n\nexport function getTableClasses(state: TableState, className?: string): string {\n return [\n \"nx-table\",\n `nx-table--${state.size}`,\n state.striped && \"nx-table--striped\",\n state.bordered && \"nx-table--bordered\",\n state.stickyHeader && \"nx-table--sticky-header\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\nexport function getRowClasses(selected: boolean, clickable: boolean, className?: string): string {\n return [\n \"nx-table__row\",\n selected && \"nx-table__row--selected\",\n clickable && \"nx-table__row--clickable\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\nexport function getHeadCellClasses(sortable: boolean, className?: string): string {\n return [\"nx-table__head-cell\", sortable && \"nx-table__head-cell--sortable\", className].filter(Boolean).join(\" \");\n}\n\nexport function getCellClasses(className?: string): string {\n return [\"nx-table__cell\", className].filter(Boolean).join(\" \");\n}\n\n// --- Sorting ----------------------------------------------------\n\nexport type SortDirection = \"asc\" | \"desc\" | null;\n\n/** The conventional 3-state cycle a sortable header click steps through: unsorted → asc → desc → unsorted. */\nexport function getNextSortDirection(current: SortDirection): SortDirection {\n if (current === null) return \"asc\";\n if (current === \"asc\") return \"desc\";\n return null;\n}\n\nexport function getSortAriaProps(direction: SortDirection) {\n return {\n \"aria-sort\":\n direction === \"asc\" ? (\"ascending\" as const) : direction === \"desc\" ? (\"descending\" as const) : (\"none\" as const),\n };\n}\n\n// --- Selection ----------------------------------------------------\n\nexport type SelectAllState = \"none\" | \"some\" | \"all\";\n\n/** The tri-state a \"select all\" header checkbox should show, computed from how many of the total rows are currently selected. */\nexport function getSelectAllState(totalCount: number, selectedCount: number): SelectAllState {\n if (totalCount <= 0 || selectedCount <= 0) return \"none\";\n if (selectedCount >= totalCount) return \"all\";\n return \"some\";\n}"],"mappings":"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","names":["registry"]}
@@ -437,6 +437,14 @@ interface ComboboxCoreProps extends FieldProps {
437
437
  allowCustomValue?: boolean;
438
438
  }
439
439
 
440
+ type WeekStart = 0 | 1;
441
+ interface CalendarDay {
442
+ date: Date;
443
+ /** False for the leading/trailing days from adjacent months that fill out the grid. */
444
+ isCurrentMonth: boolean;
445
+ isToday: boolean;
446
+ }
447
+
440
448
  interface DatePickerCoreProps extends FieldProps {
441
449
  min?: Date;
442
450
  max?: Date;
@@ -624,4 +632,4 @@ interface MenuPoint {
624
632
  y: number;
625
633
  }
626
634
 
627
- export { type TableCoreProps as $, type AccentDefinition as A, type BadgeVariant as B, type CardLayout as C, type DropdownItemVariant as D, type PhoneCountry as E, type FieldProps as F, type PhoneInputCoreProps as G, type Placement as H, type PopoverCoreProps as I, type ProgressVariant as J, type RatingCoreProps as K, type SelectOptionItem as L, type MenuPoint as M, type SemanticColor as N, type OTPInputCoreProps as O, type PaginationItem as P, type Size as Q, REQUIRED_TOKEN_PATHS as R, type SelectAllState as S, type ThemeTokens as T, type SkeletonAnimation as U, type SkeletonVariant as V, type SliderValue as W, type SortDirection as X, type SpinnerVariant as Y, type StarFill as Z, TOKEN_CATEGORIES as _, type AccordionType as a, type TabsActivationMode as a0, type TabsOrientation as a1, type TabsVariant as a2, type TimePickerCoreProps as a3, type TimeValue as a4, type TimelineAlign as a5, type TimelineCoreProps as a6, type TimelineItemCoreProps as a7, type TimelineOrientation as a8, type TimelineStatus as a9, type PaginationCoreProps as aA, type BreadcrumbCoreProps as aB, type SkeletonCoreProps as aC, type DrawerCoreProps as aD, type ContextMenuCoreProps as aE, DEFAULT_ACCENT as aF, type ToastPosition as aa, type ToastVariant as ab, type Variant as ac, defineTheme as ad, findMissingTokenPaths as ae, getAccent as af, getNextSortDirection as ag, getSelectAllState as ah, listAccents as ai, registerAccent as aj, type BadgeCoreProps as ak, type AvatarCoreProps as al, type SpinnerCoreProps as am, type DividerCoreProps as an, type CardCoreProps as ao, type AlertCoreProps as ap, type ModalCoreProps as aq, type ProgressCoreProps as ar, type TabsCoreProps as as, type AccordionCoreProps as at, type DropdownCoreProps as au, type SelectCoreProps as av, type SliderCoreProps as aw, type ComboboxCoreProps as ax, type TimePanelMode as ay, type FileUploadCoreProps as az, type AlertVariant as b, type Alignment as c, type AvatarShape as d, type AvatarSize as e, type AvatarStatus as f, type BaseComponentProps as g, type BreadcrumbSlot as h, type CardPadding as i, type CardVariant as j, type CarouselCoreProps as k, type CarouselOrientation as l, type ColorPickerCoreProps as m, type ColorScale as n, type ComboboxOption as o, type CommandGroup as p, type CommandItem as q, DEFAULT_PRESETS as r, type DatePickerCoreProps as s, type DividerOrientation as t, type DrawerSide as u, type DrawerSize as v, type FieldState as w, type FileVerdict as x, type ModalSize as y, type OTPInputType as z };
635
+ export { TOKEN_CATEGORIES as $, type AccentDefinition as A, type BadgeVariant as B, type CalendarDay as C, type DropdownItemVariant as D, type OTPInputType as E, type FieldProps as F, type PhoneCountry as G, type PhoneInputCoreProps as H, type Placement as I, type PopoverCoreProps as J, type ProgressVariant as K, type RatingCoreProps as L, type MenuPoint as M, type SelectOptionItem as N, type OTPInputCoreProps as O, type PaginationItem as P, type SemanticColor as Q, REQUIRED_TOKEN_PATHS as R, type SelectAllState as S, type ThemeTokens as T, type Size as U, type SkeletonAnimation as V, type SkeletonVariant as W, type SliderValue as X, type SortDirection as Y, type SpinnerVariant as Z, type StarFill as _, type AccordionType as a, type TableCoreProps as a0, type TabsActivationMode as a1, type TabsOrientation as a2, type TabsVariant as a3, type TimePickerCoreProps as a4, type TimeValue as a5, type TimelineAlign as a6, type TimelineCoreProps as a7, type TimelineItemCoreProps as a8, type TimelineOrientation as a9, type TimePanelMode as aA, type FileUploadCoreProps as aB, type PaginationCoreProps as aC, type BreadcrumbCoreProps as aD, type SkeletonCoreProps as aE, type DrawerCoreProps as aF, type ContextMenuCoreProps as aG, DEFAULT_ACCENT as aH, type TimelineStatus as aa, type ToastPosition as ab, type ToastVariant as ac, type Variant as ad, type WeekStart as ae, defineTheme as af, findMissingTokenPaths as ag, getAccent as ah, getNextSortDirection as ai, getSelectAllState as aj, listAccents as ak, registerAccent as al, type BadgeCoreProps as am, type AvatarCoreProps as an, type SpinnerCoreProps as ao, type DividerCoreProps as ap, type CardCoreProps as aq, type AlertCoreProps as ar, type ModalCoreProps as as, type ProgressCoreProps as at, type TabsCoreProps as au, type AccordionCoreProps as av, type DropdownCoreProps as aw, type SelectCoreProps as ax, type SliderCoreProps as ay, type ComboboxCoreProps as az, type AlertVariant as b, type Alignment as c, type AvatarShape as d, type AvatarSize as e, type AvatarStatus as f, type BaseComponentProps as g, type BreadcrumbSlot as h, type CardLayout as i, type CardPadding as j, type CardVariant as k, type CarouselCoreProps as l, type CarouselOrientation as m, type ColorPickerCoreProps as n, type ColorScale as o, type ComboboxOption as p, type CommandGroup as q, type CommandItem as r, DEFAULT_PRESETS as s, type DatePickerCoreProps as t, type DividerOrientation as u, type DrawerSide as v, type DrawerSize as w, type FieldState as x, type FileVerdict as y, type ModalSize as z };
@@ -437,6 +437,14 @@ interface ComboboxCoreProps extends FieldProps {
437
437
  allowCustomValue?: boolean;
438
438
  }
439
439
 
440
+ type WeekStart = 0 | 1;
441
+ interface CalendarDay {
442
+ date: Date;
443
+ /** False for the leading/trailing days from adjacent months that fill out the grid. */
444
+ isCurrentMonth: boolean;
445
+ isToday: boolean;
446
+ }
447
+
440
448
  interface DatePickerCoreProps extends FieldProps {
441
449
  min?: Date;
442
450
  max?: Date;
@@ -624,4 +632,4 @@ interface MenuPoint {
624
632
  y: number;
625
633
  }
626
634
 
627
- export { type TableCoreProps as $, type AccentDefinition as A, type BadgeVariant as B, type CardLayout as C, type DropdownItemVariant as D, type PhoneCountry as E, type FieldProps as F, type PhoneInputCoreProps as G, type Placement as H, type PopoverCoreProps as I, type ProgressVariant as J, type RatingCoreProps as K, type SelectOptionItem as L, type MenuPoint as M, type SemanticColor as N, type OTPInputCoreProps as O, type PaginationItem as P, type Size as Q, REQUIRED_TOKEN_PATHS as R, type SelectAllState as S, type ThemeTokens as T, type SkeletonAnimation as U, type SkeletonVariant as V, type SliderValue as W, type SortDirection as X, type SpinnerVariant as Y, type StarFill as Z, TOKEN_CATEGORIES as _, type AccordionType as a, type TabsActivationMode as a0, type TabsOrientation as a1, type TabsVariant as a2, type TimePickerCoreProps as a3, type TimeValue as a4, type TimelineAlign as a5, type TimelineCoreProps as a6, type TimelineItemCoreProps as a7, type TimelineOrientation as a8, type TimelineStatus as a9, type PaginationCoreProps as aA, type BreadcrumbCoreProps as aB, type SkeletonCoreProps as aC, type DrawerCoreProps as aD, type ContextMenuCoreProps as aE, DEFAULT_ACCENT as aF, type ToastPosition as aa, type ToastVariant as ab, type Variant as ac, defineTheme as ad, findMissingTokenPaths as ae, getAccent as af, getNextSortDirection as ag, getSelectAllState as ah, listAccents as ai, registerAccent as aj, type BadgeCoreProps as ak, type AvatarCoreProps as al, type SpinnerCoreProps as am, type DividerCoreProps as an, type CardCoreProps as ao, type AlertCoreProps as ap, type ModalCoreProps as aq, type ProgressCoreProps as ar, type TabsCoreProps as as, type AccordionCoreProps as at, type DropdownCoreProps as au, type SelectCoreProps as av, type SliderCoreProps as aw, type ComboboxCoreProps as ax, type TimePanelMode as ay, type FileUploadCoreProps as az, type AlertVariant as b, type Alignment as c, type AvatarShape as d, type AvatarSize as e, type AvatarStatus as f, type BaseComponentProps as g, type BreadcrumbSlot as h, type CardPadding as i, type CardVariant as j, type CarouselCoreProps as k, type CarouselOrientation as l, type ColorPickerCoreProps as m, type ColorScale as n, type ComboboxOption as o, type CommandGroup as p, type CommandItem as q, DEFAULT_PRESETS as r, type DatePickerCoreProps as s, type DividerOrientation as t, type DrawerSide as u, type DrawerSize as v, type FieldState as w, type FileVerdict as x, type ModalSize as y, type OTPInputType as z };
635
+ export { TOKEN_CATEGORIES as $, type AccentDefinition as A, type BadgeVariant as B, type CalendarDay as C, type DropdownItemVariant as D, type OTPInputType as E, type FieldProps as F, type PhoneCountry as G, type PhoneInputCoreProps as H, type Placement as I, type PopoverCoreProps as J, type ProgressVariant as K, type RatingCoreProps as L, type MenuPoint as M, type SelectOptionItem as N, type OTPInputCoreProps as O, type PaginationItem as P, type SemanticColor as Q, REQUIRED_TOKEN_PATHS as R, type SelectAllState as S, type ThemeTokens as T, type Size as U, type SkeletonAnimation as V, type SkeletonVariant as W, type SliderValue as X, type SortDirection as Y, type SpinnerVariant as Z, type StarFill as _, type AccordionType as a, type TableCoreProps as a0, type TabsActivationMode as a1, type TabsOrientation as a2, type TabsVariant as a3, type TimePickerCoreProps as a4, type TimeValue as a5, type TimelineAlign as a6, type TimelineCoreProps as a7, type TimelineItemCoreProps as a8, type TimelineOrientation as a9, type TimePanelMode as aA, type FileUploadCoreProps as aB, type PaginationCoreProps as aC, type BreadcrumbCoreProps as aD, type SkeletonCoreProps as aE, type DrawerCoreProps as aF, type ContextMenuCoreProps as aG, DEFAULT_ACCENT as aH, type TimelineStatus as aa, type ToastPosition as ab, type ToastVariant as ac, type Variant as ad, type WeekStart as ae, defineTheme as af, findMissingTokenPaths as ag, getAccent as ah, getNextSortDirection as ai, getSelectAllState as aj, listAccents as ak, registerAccent as al, type BadgeCoreProps as am, type AvatarCoreProps as an, type SpinnerCoreProps as ao, type DividerCoreProps as ap, type CardCoreProps as aq, type AlertCoreProps as ar, type ModalCoreProps as as, type ProgressCoreProps as at, type TabsCoreProps as au, type AccordionCoreProps as av, type DropdownCoreProps as aw, type SelectCoreProps as ax, type SliderCoreProps as ay, type ComboboxCoreProps as az, type AlertVariant as b, type Alignment as c, type AvatarShape as d, type AvatarSize as e, type AvatarStatus as f, type BaseComponentProps as g, type BreadcrumbSlot as h, type CardLayout as i, type CardPadding as j, type CardVariant as k, type CarouselCoreProps as l, type CarouselOrientation as m, type ColorPickerCoreProps as n, type ColorScale as o, type ComboboxOption as p, type CommandGroup as q, type CommandItem as r, DEFAULT_PRESETS as s, type DatePickerCoreProps as t, type DividerOrientation as u, type DrawerSide as v, type DrawerSize as w, type FieldState as x, type FileVerdict as y, type ModalSize as z };
package/dist/index.cjs CHANGED
@@ -328,7 +328,17 @@ var glass = defineTheme({
328
328
  background: "transparent",
329
329
  surface: "rgba(255,255,255,0.55)",
330
330
  surfaceRaised: "rgba(255,255,255,0.75)",
331
- border: "rgba(255,255,255,0.35)",
331
+ // Was rgba(255,255,255,0.35) — translucent WHITE. Composited on
332
+ // a plain white page (the theme's own meta.description admits it
333
+ // "needs a rich background behind it," but most consumers won't
334
+ // add one), that resolves to literal #ffffff — a 1.0:1 contrast
335
+ // ratio, i.e. actually invisible, which is the reported vanished
336
+ // Progress-track border. A neutral slate tint stays visible
337
+ // against both a plain white AND a plain black fallback backdrop
338
+ // (measured ~2.1-2.3:1 either way) — short of full 3:1 UI-contrast
339
+ // on both extremes at once, but a large improvement over 1.0, and
340
+ // still reads as a soft glass edge over an actual rich backdrop.
341
+ border: "rgba(100,116,139,0.6)",
332
342
  borderFocus: "#9ca3af",
333
343
  text: "#111827",
334
344
  textMuted: "rgba(17,24,39,0.65)",
@@ -462,7 +472,13 @@ var neobrutalism = defineTheme({
462
472
  surface: "#ffffff",
463
473
  surfaceRaised: "#ffffff",
464
474
  border: "#000000",
465
- borderFocus: "#000000"
475
+ borderFocus: "#000000",
476
+ // light.color.warning.light (#fef3c7) is identical to this
477
+ // theme's own background — every warning Alert/Badge/etc. was
478
+ // rendering invisibly on the page. Bumped to the next step in
479
+ // the same warm-amber family (matches light.color.warning.subtle)
480
+ // so it stays on-theme but is actually visible against the page.
481
+ warning: { ...light.color.warning, light: "#fde68a" }
466
482
  },
467
483
  radius: { sm: "4px", md: "6px", lg: "8px", xl: "10px", "2xl": "12px", full: "9999px" },
468
484
  shadow: {
@@ -526,7 +542,24 @@ var gradient = defineTheme({
526
542
  surface: "linear-gradient(135deg, rgba(255,255,255,0.92), rgba(255,255,255,0.75))",
527
543
  surfaceRaised: "#ffffff",
528
544
  border: "rgba(118,75,162,0.25)",
529
- borderFocus: "#764ba2"
545
+ borderFocus: "#764ba2",
546
+ // text/textMuted were still light theme's values (#111827 /
547
+ // #6b7280) — fine on the near-white `surface`, but components
548
+ // that render straight on `background` (Timeline, Pagination,
549
+ // Tabs — all used with no wrapping surface in this library's own
550
+ // docs examples) sat directly on the purple gradient instead.
551
+ // Measured contrast against the gradient's darker stop
552
+ // (#764ba2): text 2.79:1, textMuted a barely-there 1.32:1 — the
553
+ // reported "nearly invisible" text. Darkened both; textMuted
554
+ // still can't clear 4.5:1 against the darkest point of this
555
+ // specific gradient with a single flat color (nothing dark
556
+ // enough to do that stays legible as "muted" against the near-
557
+ // white surface too), so this is the best available compromise
558
+ // within a single global text/textMuted pair, not a full fix —
559
+ // worth knowing if it still reads as low-contrast on the
560
+ // darkest corner of the gradient.
561
+ text: "#000000",
562
+ textMuted: "#2e2440"
530
563
  },
531
564
  radius: { sm: "12px", md: "18px", lg: "24px", xl: "32px", "2xl": "40px", full: "9999px" },
532
565
  shadow: {