nuvox 0.1.2 → 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.
- package/CHANGELOG.md +75 -0
- package/dist/{chunk-3F7OVF4J.js → chunk-KKRVJF3Y.js} +37 -4
- package/dist/chunk-KKRVJF3Y.js.map +1 -0
- package/dist/index.cjs +36 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.cjs +48 -6
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.css +12 -2
- package/dist/react/index.css.map +1 -1
- package/dist/react/index.js +13 -4
- package/dist/react/index.js.map +1 -1
- package/dist/themes/generated.css +4 -4
- package/package.json +1 -1
- package/dist/chunk-3F7OVF4J.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,81 @@
|
|
|
3
3
|
All notable changes to this project are documented here.
|
|
4
4
|
Format loosely follows [Keep a Changelog](https://keepachangelog.com/).
|
|
5
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
|
+
|
|
6
81
|
## [0.1.2]
|
|
7
82
|
|
|
8
83
|
### Fixed
|
|
@@ -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
|
-
|
|
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-
|
|
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"]}
|
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
|
-
|
|
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: {
|