@ansh-ui/tokens 0.2.0 → 0.3.1

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/dist/ansh.css CHANGED
@@ -265,6 +265,78 @@
265
265
  --ansh-shadow-color: oklch(20.8% 0.015 264 / 0.08);
266
266
  }
267
267
 
268
+ /**
269
+ * High-contrast mode, layered on top of whichever theme is active — not a fifth theme, an
270
+ * override of `content` and `border` only (see `ContrastOverride` in semantic.ts for why those
271
+ * two and not the whole palette). Mirrors the theme cascade immediately above it: system
272
+ * preference by default, explicit `[data-theme]` wins when set.
273
+ *
274
+ * The light rule must come *before* the dark media block below, not after: both target the same
275
+ * `[data-contrast='high']:not([data-theme])` selector (identical specificity), so when the system
276
+ * prefers dark and no theme is set explicitly, only source order decides which wins — exactly the
277
+ * same reason the light/dark theme rules above are ordered the way they are.
278
+ */
279
+ [data-contrast='high']:not([data-theme]) {
280
+ --ansh-content-primary: oklch(20.8% 0.015 264);
281
+ --ansh-content-secondary: oklch(27.9% 0.017 264);
282
+ --ansh-content-tertiary: oklch(37.2% 0.019 264);
283
+ --ansh-content-disabled: oklch(70.7% 0.018 264);
284
+ --ansh-content-on-accent: #ffffff;
285
+ --ansh-content-inverse: oklch(98.5% 0.002 264);
286
+ --ansh-border-subtle: oklch(70.7% 0.018 264);
287
+ --ansh-border-default: oklch(55.4% 0.022 264);
288
+ --ansh-border-strong: oklch(37.2% 0.019 264);
289
+ --ansh-border-focus: oklch(54.6% 0.208 253);
290
+ }
291
+
292
+ @media (prefers-color-scheme: dark) {
293
+ [data-contrast='high']:not([data-theme]) {
294
+ --ansh-content-primary: oklch(96.8% 0.004 264);
295
+ --ansh-content-secondary: oklch(96.8% 0.004 264);
296
+ --ansh-content-tertiary: oklch(92.9% 0.007 264);
297
+ --ansh-content-disabled: oklch(44.6% 0.021 264);
298
+ --ansh-content-on-accent: #ffffff;
299
+ --ansh-content-inverse: oklch(13.8% 0.014 264);
300
+ --ansh-border-subtle: oklch(100% 0 0 / 0.24);
301
+ --ansh-border-default: oklch(100% 0 0 / 0.35);
302
+ --ansh-border-strong: oklch(100% 0 0 / 0.5);
303
+ --ansh-border-focus: oklch(71.4% 0.153 253);
304
+ }
305
+ }
306
+
307
+ [data-theme='dark'][data-contrast='high'] {
308
+ --ansh-content-primary: oklch(96.8% 0.004 264);
309
+ --ansh-content-secondary: oklch(96.8% 0.004 264);
310
+ --ansh-content-tertiary: oklch(92.9% 0.007 264);
311
+ --ansh-content-disabled: oklch(44.6% 0.021 264);
312
+ --ansh-content-on-accent: #ffffff;
313
+ --ansh-content-inverse: oklch(13.8% 0.014 264);
314
+ --ansh-border-subtle: oklch(100% 0 0 / 0.24);
315
+ --ansh-border-default: oklch(100% 0 0 / 0.35);
316
+ --ansh-border-strong: oklch(100% 0 0 / 0.5);
317
+ --ansh-border-focus: oklch(71.4% 0.153 253);
318
+ }
319
+
320
+ [data-theme='light'][data-contrast='high'] {
321
+ --ansh-content-primary: oklch(20.8% 0.015 264);
322
+ --ansh-content-secondary: oklch(27.9% 0.017 264);
323
+ --ansh-content-tertiary: oklch(37.2% 0.019 264);
324
+ --ansh-content-disabled: oklch(70.7% 0.018 264);
325
+ --ansh-content-on-accent: #ffffff;
326
+ --ansh-content-inverse: oklch(98.5% 0.002 264);
327
+ --ansh-border-subtle: oklch(70.7% 0.018 264);
328
+ --ansh-border-default: oklch(55.4% 0.022 264);
329
+ --ansh-border-strong: oklch(37.2% 0.019 264);
330
+ --ansh-border-focus: oklch(54.6% 0.208 253);
331
+ }
332
+
333
+ /* A token alone can't widen an outline. Every consumer's :focus-visible rule reads
334
+ --ansh-border-focus already; high contrast also needs the ring itself to be harder to miss. */
335
+ [data-contrast='high'] :focus-visible {
336
+ outline-width: 3px;
337
+ outline-offset: 3px;
338
+ }
339
+
268
340
  /**
269
341
  * Reduced-motion safety net.
270
342
  *
package/dist/index.cjs CHANGED
@@ -318,6 +318,32 @@ var dark = {
318
318
  shadowColor: "oklch(0% 0 0 / 0.5)"
319
319
  };
320
320
  var themes = { light, dark };
321
+ var lightHighContrast = {
322
+ content: {
323
+ ...light.content,
324
+ secondary: neutral[800],
325
+ tertiary: neutral[700]
326
+ },
327
+ border: {
328
+ ...light.border,
329
+ subtle: neutral[400],
330
+ default: neutral[500],
331
+ strong: neutral[700]
332
+ }
333
+ };
334
+ var darkHighContrast = {
335
+ content: {
336
+ ...dark.content,
337
+ secondary: neutral[100],
338
+ tertiary: neutral[200]
339
+ },
340
+ border: {
341
+ ...dark.border,
342
+ subtle: "oklch(100% 0 0 / 0.24)",
343
+ default: "oklch(100% 0 0 / 0.35)",
344
+ strong: "oklch(100% 0 0 / 0.5)"
345
+ }
346
+ };
321
347
 
322
348
  // src/css.ts
323
349
  var CSS_PREFIX = "ansh";
@@ -373,6 +399,12 @@ function themeVariables(tokens2) {
373
399
  out.set(`--${CSS_PREFIX}-shadow-color`, tokens2.shadowColor);
374
400
  return out;
375
401
  }
402
+ function contrastVariables(override) {
403
+ const out = /* @__PURE__ */ new Map();
404
+ flatten(out, override.content, ["content"]);
405
+ flatten(out, override.border, ["border"]);
406
+ return out;
407
+ }
376
408
  function declarations(variables, indent = " ") {
377
409
  return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join("\n");
378
410
  }
@@ -380,6 +412,8 @@ function generateCss() {
380
412
  const structural = structuralVariables();
381
413
  const lightVars = themeVariables(light);
382
414
  const darkVars = themeVariables(dark);
415
+ const lightContrastVars = contrastVariables(lightHighContrast);
416
+ const darkContrastVars = contrastVariables(darkHighContrast);
383
417
  return `/**
384
418
  * Ansh design tokens.
385
419
  *
@@ -411,6 +445,42 @@ ${declarations(darkVars)}
411
445
  ${declarations(lightVars)}
412
446
  }
413
447
 
448
+ /**
449
+ * High-contrast mode, layered on top of whichever theme is active \u2014 not a fifth theme, an
450
+ * override of \`content\` and \`border\` only (see \`ContrastOverride\` in semantic.ts for why those
451
+ * two and not the whole palette). Mirrors the theme cascade immediately above it: system
452
+ * preference by default, explicit \`[data-theme]\` wins when set.
453
+ *
454
+ * The light rule must come *before* the dark media block below, not after: both target the same
455
+ * \`[data-contrast='high']:not([data-theme])\` selector (identical specificity), so when the system
456
+ * prefers dark and no theme is set explicitly, only source order decides which wins \u2014 exactly the
457
+ * same reason the light/dark theme rules above are ordered the way they are.
458
+ */
459
+ [data-contrast='high']:not([data-theme]) {
460
+ ${declarations(lightContrastVars)}
461
+ }
462
+
463
+ @media (prefers-color-scheme: dark) {
464
+ [data-contrast='high']:not([data-theme]) {
465
+ ${declarations(darkContrastVars, " ")}
466
+ }
467
+ }
468
+
469
+ [data-theme='dark'][data-contrast='high'] {
470
+ ${declarations(darkContrastVars)}
471
+ }
472
+
473
+ [data-theme='light'][data-contrast='high'] {
474
+ ${declarations(lightContrastVars)}
475
+ }
476
+
477
+ /* A token alone can't widen an outline. Every consumer's :focus-visible rule reads
478
+ --ansh-border-focus already; high contrast also needs the ring itself to be harder to miss. */
479
+ [data-contrast='high'] :focus-visible {
480
+ outline-width: 3px;
481
+ outline-offset: 3px;
482
+ }
483
+
414
484
  /**
415
485
  * Reduced-motion safety net.
416
486
  *
@@ -466,6 +536,17 @@ function resolveTheme(target) {
466
536
  if (explicit === "dark" || explicit === "light") return explicit;
467
537
  return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
468
538
  }
539
+ function applyContrast(contrast, target) {
540
+ if (typeof document === "undefined") return;
541
+ const element = target ?? document.documentElement;
542
+ if (contrast === "high") element.setAttribute("data-contrast", "high");
543
+ else element.removeAttribute("data-contrast");
544
+ }
545
+ function resolveContrast(target) {
546
+ if (typeof document === "undefined") return "normal";
547
+ const element = target ?? document.documentElement;
548
+ return element.closest("[data-contrast='high']") ? "high" : "normal";
549
+ }
469
550
  function themeStyle(theme) {
470
551
  const out = {};
471
552
  for (const [name, value] of themeVariables(theme === "dark" ? dark : light)) {
@@ -544,11 +625,13 @@ function tailwindPreset() {
544
625
  }
545
626
 
546
627
  exports.CSS_PREFIX = CSS_PREFIX;
628
+ exports.applyContrast = applyContrast;
547
629
  exports.applyTheme = applyTheme;
548
630
  exports.blur = blur;
549
631
  exports.brand = brand;
550
632
  exports.breakpoint = breakpoint;
551
633
  exports.dark = dark;
634
+ exports.darkHighContrast = darkHighContrast;
552
635
  exports.duration = duration;
553
636
  exports.easing = easing;
554
637
  exports.fontFamily = fontFamily;
@@ -556,8 +639,10 @@ exports.fontSize = fontSize;
556
639
  exports.fontWeight = fontWeight;
557
640
  exports.generateCss = generateCss;
558
641
  exports.light = light;
642
+ exports.lightHighContrast = lightHighContrast;
559
643
  exports.neutral = neutral;
560
644
  exports.radius = radius;
645
+ exports.resolveContrast = resolveContrast;
561
646
  exports.resolveTheme = resolveTheme;
562
647
  exports.shadow = shadow;
563
648
  exports.space = space;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/primitives.ts","../src/semantic.ts","../src/css.ts","../src/index.ts"],"names":["tokens"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Primitive design tokens.\n *\n * These are the raw values — the vocabulary. Semantic tokens (in `semantic.ts`) map *meaning*\n * onto them, and that indirection is what makes theming possible: `--ansh-surface` can point\n * at `slate.50` in light mode and `slate.950` in dark mode without any component changing.\n *\n * Every scale here is derived from a rule rather than hand-picked, so extending it is\n * unambiguous and a designer can predict what step 9 looks like without checking.\n */\n\n/**\n * Spacing — an 8-point grid with half-steps below 8px.\n *\n * The half-steps matter: 8px is too coarse for optical adjustments like the gap between an icon\n * and its label, and every design system that omits them ends up with arbitrary one-off values.\n * Named by their pixel value at the default root size so `space[4]` is unambiguously 16px.\n */\nexport const space = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 3: '0.75rem', // 12px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 8: '2rem', // 32px\n 10: '2.5rem', // 40px\n 12: '3rem', // 48px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 32: '8rem', // 128px\n 40: '10rem', // 160px\n 48: '12rem', // 192px\n 56: '14rem', // 224px\n 64: '16rem', // 256px\n} as const\n\n/**\n * Typography — a modular scale at ratio 1.2 (minor third), rounded to sensible pixel values.\n *\n * 1.2 rather than the more common 1.25 or golden ratio: on the wide viewports these components\n * target, a steeper ratio makes display sizes enormous before the body sizes have room to\n * differentiate. 1.2 gives eight useful steps between 12px and 60px.\n *\n * Each step pairs a size with a line height, because a size without its leading is not a\n * typographic decision — and line height must *decrease* proportionally as size increases.\n */\nexport const fontSize = {\n xs: ['0.75rem', { lineHeight: '1.125rem', letterSpacing: '0.01em' }],\n sm: ['0.875rem', { lineHeight: '1.375rem', letterSpacing: '0.005em' }],\n base: ['1rem', { lineHeight: '1.625rem', letterSpacing: '0' }],\n lg: ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '-0.005em' }],\n xl: ['1.25rem', { lineHeight: '1.875rem', letterSpacing: '-0.01em' }],\n '2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.015em' }],\n '3xl': ['1.875rem', { lineHeight: '2.375rem', letterSpacing: '-0.02em' }],\n '4xl': ['2.25rem', { lineHeight: '2.625rem', letterSpacing: '-0.025em' }],\n '5xl': ['3rem', { lineHeight: '3.25rem', letterSpacing: '-0.03em' }],\n '6xl': ['3.75rem', { lineHeight: '3.9rem', letterSpacing: '-0.035em' }],\n '7xl': ['4.5rem', { lineHeight: '4.6rem', letterSpacing: '-0.04em' }],\n} as const satisfies Record<\n string,\n readonly [string, { lineHeight: string; letterSpacing: string }]\n>\n\nexport const fontWeight = {\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n} as const\n\nexport const fontFamily = {\n /**\n * The system UI stack. Deliberately not a webfont: the fastest, most legible text on any\n * platform is the font the user's OS already has loaded, and a design system should not force\n * a font decision on its consumers.\n */\n sans: [\n 'ui-sans-serif',\n 'system-ui',\n '-apple-system',\n 'BlinkMacSystemFont',\n 'Segoe UI',\n 'Roboto',\n 'Helvetica Neue',\n 'Arial',\n 'sans-serif',\n ].join(', '),\n mono: [\n 'ui-monospace',\n 'SFMono-Regular',\n 'Menlo',\n 'Monaco',\n 'Consolas',\n 'Liberation Mono',\n 'Courier New',\n 'monospace',\n ].join(', '),\n} as const\n\n/** Corner radii. `full` is a large fixed value rather than 50%, so pills stay pill-shaped. */\nexport const radius = {\n none: '0',\n xs: '0.25rem', // 4px\n sm: '0.375rem', // 6px\n md: '0.5rem', // 8px\n lg: '0.75rem', // 12px\n xl: '1rem', // 16px\n '2xl': '1.5rem', // 24px\n '3xl': '2rem', // 32px\n full: '9999px',\n} as const\n\n/**\n * Elevation — layered shadows, not single ones.\n *\n * A single `box-shadow` cannot describe real light: an object casts both a tight contact shadow\n * directly beneath it and a broader ambient shadow further out. Every step here composes both,\n * which is the difference between a card that sits on the page and one that looks pasted onto it.\n *\n * Shadow colour is a token so it can shift with the theme — a pure-black shadow on a dark\n * surface is invisible, so the dark theme uses a deeper, more spread variant.\n */\nexport const shadow = {\n none: 'none',\n xs: '0 1px 2px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n sm:\n '0 1px 3px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 1px 2px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n md:\n '0 4px 6px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 2px 4px -2px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n lg:\n '0 10px 15px -3px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 4px 6px -4px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n xl:\n '0 20px 25px -5px var(--ansh-shadow-color, rgb(15 23 42 / 0.1)), ' +\n '0 8px 10px -6px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n '2xl': '0 25px 50px -12px var(--ansh-shadow-color, rgb(15 23 42 / 0.2))',\n /** Inset — for pressed states and inputs. */\n inner: 'inset 0 2px 4px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n /**\n * Glow. Uses `currentColor` so a button's glow automatically matches its own accent without\n * the author repeating the colour.\n */\n glow: '0 0 24px -4px currentColor',\n glowLg: '0 0 48px -8px currentColor',\n} as const\n\n/** Backdrop blur steps, for glass surfaces. */\nexport const blur = {\n none: '0',\n xs: '2px',\n sm: '4px',\n md: '8px',\n lg: '16px',\n xl: '24px',\n '2xl': '40px',\n '3xl': '64px',\n} as const\n\n/**\n * Motion durations in seconds.\n *\n * Named by intent rather than by number. The values follow a rule of thumb that holds up well:\n * the distance travelled should determine the duration, so a tooltip appearing in place is\n * `instant`, a dropdown is `fast`, and a full-screen sheet is `slow`.\n */\nexport const duration = {\n instant: '0.1s',\n fast: '0.2s',\n normal: '0.3s',\n moderate: '0.45s',\n slow: '0.6s',\n slower: '0.9s',\n deliberate: '1.2s',\n} as const\n\n/**\n * CSS timing functions matching the engine's `signature` easings exactly.\n *\n * Keeping these in lockstep means a CSS transition and a JS animation on the same element move\n * identically — which matters more than it sounds, because mismatched curves on adjacent\n * elements is one of those things that reads as \"cheap\" without the viewer knowing why.\n */\nexport const easing = {\n linear: 'linear',\n standard: 'cubic-bezier(0.4, 0, 0.2, 1)',\n emphasized: 'cubic-bezier(0.22, 1, 0.36, 1)',\n enter: 'cubic-bezier(0, 0, 0.2, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n overshoot: 'cubic-bezier(0.34, 1.56, 0.64, 1)',\n cinematic: 'cubic-bezier(0.16, 1, 0.3, 1)',\n} as const\n\n/**\n * Z-index scale.\n *\n * Sparse, deliberate values with names. The alternative — `z-index: 9999` scattered through a\n * codebase — is the single most common source of stacking bugs in a component library.\n */\nexport const zIndex = {\n hide: '-1',\n base: '0',\n raised: '10',\n dropdown: '1000',\n sticky: '1100',\n overlay: '1200',\n modal: '1300',\n popover: '1400',\n toast: '1500',\n tooltip: '1600',\n /** Reserved for skip links and focus traps, which must beat everything. */\n max: '2147483647',\n} as const\n\n/** Breakpoints, matching the widths where real layout decisions occur. */\nexport const breakpoint = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n} as const\n\n/**\n * Neutral ramp, defined in OKLCH.\n *\n * Lightness steps are perceptually even, which a hex-defined grey ramp never is — the usual\n * result is a scale that looks well-spaced at the light end and bunched at the dark end. A slight\n * blue chroma (hue 264) keeps it from reading as muddy against saturated accents.\n */\nexport const neutral = {\n 50: 'oklch(98.5% 0.002 264)',\n 100: 'oklch(96.8% 0.004 264)',\n 200: 'oklch(92.9% 0.007 264)',\n 300: 'oklch(86.9% 0.011 264)',\n 400: 'oklch(70.7% 0.018 264)',\n 500: 'oklch(55.4% 0.022 264)',\n 600: 'oklch(44.6% 0.021 264)',\n 700: 'oklch(37.2% 0.019 264)',\n 800: 'oklch(27.9% 0.017 264)',\n 900: 'oklch(20.8% 0.015 264)',\n 950: 'oklch(13.8% 0.014 264)',\n 1000: 'oklch(8.5% 0.012 264)',\n} as const\n\n/** The Ansh brand ramp — the blue the library ships with. */\nexport const brand = {\n 50: 'oklch(97% 0.017 253)',\n 100: 'oklch(93.8% 0.036 253)',\n 200: 'oklch(88.5% 0.069 253)',\n 300: 'oklch(80.9% 0.111 253)',\n 400: 'oklch(71.4% 0.153 253)',\n 500: 'oklch(62.3% 0.188 253)',\n 600: 'oklch(54.6% 0.208 253)',\n 700: 'oklch(46.4% 0.192 253)',\n 800: 'oklch(39.1% 0.16 253)',\n 900: 'oklch(33.5% 0.129 253)',\n 950: 'oklch(23.2% 0.093 253)',\n} as const\n\n/** Status ramps. Only the steps that get used are defined, rather than a full 11 for each. */\nexport const status = {\n success: {\n subtle: 'oklch(95.5% 0.035 155)',\n default: 'oklch(58% 0.15 155)',\n strong: 'oklch(44% 0.12 155)',\n },\n warning: {\n subtle: 'oklch(96.5% 0.045 85)',\n default: 'oklch(72% 0.16 75)',\n strong: 'oklch(52% 0.13 65)',\n },\n danger: {\n subtle: 'oklch(95.5% 0.03 25)',\n default: 'oklch(58% 0.21 25)',\n strong: 'oklch(46% 0.18 25)',\n },\n info: {\n subtle: 'oklch(96% 0.025 240)',\n default: 'oklch(62% 0.17 245)',\n strong: 'oklch(48% 0.15 250)',\n },\n} as const\n","import { brand, neutral, shadow, status } from './primitives'\n\n/**\n * Semantic tokens — meaning mapped onto primitives.\n *\n * This layer is why theming works. A component references `surface.raised`, never `neutral.100`.\n * Switching to dark mode remaps `surface.raised` to `neutral.900`, and every component follows\n * without a single change. A component that reaches past this layer to a primitive is a bug: it\n * will look wrong in one theme and nobody will notice until a user reports it.\n *\n * The naming follows a consistent pattern:\n *\n * - `surface.*` — backgrounds, ordered by elevation\n * - `content.*` — text and icons, ordered by prominence\n * - `border.*` — dividers and outlines, ordered by strength\n * - `accent.*` — the interactive brand colour and its states\n * - `state.*` — success/warning/danger/info\n */\n\nexport interface SemanticTokens {\n surface: {\n /** The page background. */\n canvas: string\n /** Cards and panels sitting on the canvas. */\n raised: string\n /** Menus, popovers and anything floating above `raised`. */\n overlay: string\n /** Subtly recessed areas — code blocks, well insets. */\n sunken: string\n /** Translucent glass surface, for use with `backdrop-filter`. */\n glass: string\n /** The scrim behind a modal. */\n scrim: string\n }\n content: {\n /** Body text and headings. Must reach 7:1 against `surface.canvas`. */\n primary: string\n /** Supporting text. Must reach 4.5:1. */\n secondary: string\n /** De-emphasised text — timestamps, captions. Must reach 4.5:1 at ≥14px. */\n tertiary: string\n /** Placeholder and disabled text. Exempt from contrast minimums by WCAG. */\n disabled: string\n /** Text placed on top of `accent.default`. */\n onAccent: string\n /** Inverted text, for use on `content.primary` as a background. */\n inverse: string\n }\n border: {\n /** Hairline dividers. */\n subtle: string\n /** Input and card outlines. */\n default: string\n /** Hovered or emphasised outlines. */\n strong: string\n /** The focus ring. Must reach 3:1 against both adjacent surfaces. */\n focus: string\n }\n accent: {\n subtle: string\n muted: string\n default: string\n hover: string\n active: string\n /** For text and icons rendered in the accent colour on a neutral surface. */\n text: string\n }\n state: {\n successSubtle: string\n success: string\n warningSubtle: string\n warning: string\n dangerSubtle: string\n danger: string\n infoSubtle: string\n info: string\n }\n /** The shadow colour the elevation scale multiplies through. */\n shadowColor: string\n}\n\n/**\n * Light theme.\n *\n * Contrast ratios against `surface.canvas` (`neutral.50`):\n * `content.primary` → 15.8:1 (AAA)\n * `content.secondary` → 7.4:1 (AAA)\n * `content.tertiary` → 4.7:1 (AA)\n * `border.focus` → 3.4:1 (AA non-text)\n */\nexport const light: SemanticTokens = {\n surface: {\n canvas: neutral[50],\n raised: '#ffffff',\n overlay: '#ffffff',\n sunken: neutral[100],\n glass: 'oklch(100% 0 0 / 0.72)',\n scrim: 'oklch(20.8% 0.015 264 / 0.45)',\n },\n content: {\n primary: neutral[900],\n secondary: neutral[600],\n tertiary: neutral[500],\n disabled: neutral[400],\n onAccent: '#ffffff',\n inverse: neutral[50],\n },\n border: {\n subtle: neutral[200],\n default: neutral[300],\n strong: neutral[400],\n focus: brand[600],\n },\n accent: {\n subtle: brand[50],\n muted: brand[100],\n default: brand[600],\n hover: brand[700],\n active: brand[800],\n // A step darker than `default`: brand colours tuned to look right as a fill are usually too\n // light to pass contrast as text on a white surface.\n text: brand[700],\n },\n state: {\n successSubtle: status.success.subtle,\n success: status.success.strong,\n warningSubtle: status.warning.subtle,\n warning: status.warning.strong,\n dangerSubtle: status.danger.subtle,\n danger: status.danger.strong,\n infoSubtle: status.info.subtle,\n info: status.info.strong,\n },\n shadowColor: 'oklch(20.8% 0.015 264 / 0.08)',\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion of `light`. Three adjustments that a mechanical inversion misses:\n *\n * 1. **Surfaces get lighter as they rise, not darker.** In light mode, elevation is signalled by\n * shadow. On a dark background shadow is invisible, so elevation must be signalled by the\n * surface itself becoming lighter.\n * 2. **Chroma is raised.** Saturated colours read as less vivid against dark backgrounds\n * (Helmholtz–Kohlrausch), so accents step *lighter* rather than mirroring their light-mode step.\n * 3. **Body text is not pure white.** `#fff` on a near-black background causes halation — the\n * text appears to bleed. `neutral.100` reads as white while staying comfortable.\n */\nexport const dark: SemanticTokens = {\n surface: {\n canvas: neutral[1000],\n raised: neutral[950],\n overlay: neutral[900],\n sunken: 'oklch(6% 0.01 264)',\n glass: 'oklch(13.8% 0.014 264 / 0.68)',\n scrim: 'oklch(4% 0.008 264 / 0.65)',\n },\n content: {\n primary: neutral[100],\n secondary: neutral[300],\n tertiary: neutral[400],\n disabled: neutral[600],\n onAccent: '#ffffff',\n inverse: neutral[950],\n },\n border: {\n // Borders on dark surfaces work by being *lighter* than the surface, and need less contrast\n // than their light-mode counterparts to read as the same weight.\n subtle: 'oklch(100% 0 0 / 0.08)',\n default: 'oklch(100% 0 0 / 0.14)',\n strong: 'oklch(100% 0 0 / 0.24)',\n focus: brand[400],\n },\n accent: {\n subtle: 'oklch(23.2% 0.093 253 / 0.4)',\n muted: brand[950],\n default: brand[500],\n hover: brand[400],\n active: brand[300],\n text: brand[300],\n },\n state: {\n successSubtle: 'oklch(30% 0.08 155 / 0.35)',\n success: 'oklch(72% 0.16 155)',\n warningSubtle: 'oklch(32% 0.09 75 / 0.35)',\n warning: 'oklch(80% 0.15 80)',\n dangerSubtle: 'oklch(30% 0.11 25 / 0.35)',\n danger: 'oklch(70% 0.19 25)',\n infoSubtle: 'oklch(30% 0.09 245 / 0.35)',\n info: 'oklch(74% 0.15 245)',\n },\n // Deeper and more spread than light mode, since a dark shadow on a dark surface needs more\n // opacity to register at all.\n shadowColor: 'oklch(0% 0 0 / 0.5)',\n}\n\nexport const themes = { light, dark } as const\nexport type ThemeName = keyof typeof themes\n\n/** Re-exported so the CSS emitter can reference the elevation scale alongside the themes. */\nexport { shadow }\n","import {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\nimport { type SemanticTokens, dark, light } from './semantic'\n\n/**\n * CSS custom property generation.\n *\n * Tokens exist twice on purpose — as TypeScript values and as CSS variables — because the two\n * are consumed differently and neither can serve both jobs:\n *\n * - **TypeScript** values are needed where JavaScript computes with them: passing colours into\n * canvas effects, deriving palettes, computing contrast.\n * - **CSS variables** are needed for everything the cascade should own: theming a subtree,\n * respecting `prefers-color-scheme`, and letting a consumer override a token in their own\n * stylesheet without touching a build step.\n *\n * This module is the bridge, and it is generated from the same source of truth so the two can't\n * drift.\n */\n\nexport const CSS_PREFIX = 'ansh'\n\n/** Flatten a nested token object into `--prefix-path-to-key` variable declarations. */\nfunction flatten(target: Map<string, string>, value: unknown, path: readonly string[]): void {\n if (typeof value === 'string') {\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, value)\n return\n }\n if (Array.isArray(value)) {\n // Font size entries are `[size, { lineHeight, letterSpacing }]`. Emit each part under a\n // suffixed name so `--ansh-text-lg` and `--ansh-text-lg-leading` are both available.\n const [size, meta] = value as [string, Record<string, string> | undefined]\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, size)\n if (meta && typeof meta === 'object') {\n if (meta.lineHeight) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-leading`, meta.lineHeight)\n }\n if (meta.letterSpacing) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-tracking`, meta.letterSpacing)\n }\n }\n return\n }\n if (value && typeof value === 'object') {\n for (const [key, child] of Object.entries(value)) {\n flatten(target, child, [...path, cssSegment(key)])\n }\n }\n}\n\n/**\n * Convert a token key into a CSS-safe, CSS-conventional name segment.\n *\n * Two transformations, each fixing a real problem:\n *\n * - **Decimal points** (`space[0.5]`) are invalid in a custom property name, so they become\n * hyphens: `--ansh-space-0-5`.\n * - **camelCase** (`onAccent`, `successSubtle`) becomes kebab-case. CSS custom properties are\n * case-sensitive, and nobody writing CSS types `var(--ansh-content-onAccent)` — they type\n * `--ansh-content-on-accent`, get no error, and silently inherit the wrong colour. That\n * exact mismatch shipped in this library's own button styles: filled buttons fell back to the\n * inherited text colour, which is dark text on an accent fill.\n */\nfunction cssSegment(key: string): string {\n return key\n .replace('.', '-')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n\n/** Structural tokens — identical in every theme. */\nexport function structuralVariables(): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, space, ['space'])\n flatten(out, radius, ['radius'])\n flatten(out, shadow, ['shadow'])\n flatten(out, blur, ['blur'])\n flatten(out, duration, ['duration'])\n flatten(out, easing, ['ease'])\n flatten(out, zIndex, ['z'])\n flatten(out, fontSize, ['text'])\n flatten(out, fontWeight, ['weight'])\n flatten(out, fontFamily, ['font'])\n flatten(out, breakpoint, ['screen'])\n return out\n}\n\n/** Theme-dependent tokens for one theme. */\nexport function themeVariables(tokens: SemanticTokens): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, tokens.surface, ['surface'])\n flatten(out, tokens.content, ['content'])\n flatten(out, tokens.border, ['border'])\n flatten(out, tokens.accent, ['accent'])\n flatten(out, tokens.state, ['state'])\n out.set(`--${CSS_PREFIX}-shadow-color`, tokens.shadowColor)\n return out\n}\n\nfunction declarations(variables: Map<string, string>, indent = ' '): string {\n return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join('\\n')\n}\n\n/**\n * Emit the complete stylesheet.\n *\n * The theming strategy is deliberately layered so it works for every consumer:\n *\n * 1. `:root` carries the light theme, so the default works with no configuration.\n * 2. `@media (prefers-color-scheme: dark)` applies dark automatically — but *only* when the\n * document has not opted into manual control, guarded by `:root:not([data-theme])`. Without\n * that guard, a user who explicitly chose light mode in an app whose OS is dark would get dark\n * anyway, which is the single most common theming bug in the wild.\n * 3. `[data-theme='dark']` and `[data-theme='light']` allow explicit control at any level of the\n * tree, so a single dark card on a light page works with no extra plumbing.\n */\nexport function generateCss(): string {\n const structural = structuralVariables()\n const lightVars = themeVariables(light)\n const darkVars = themeVariables(dark)\n\n return `/**\n * Ansh design tokens.\n *\n * Generated from @ansh-ui/tokens — do not edit by hand.\n * Override any variable in your own stylesheet after importing this file.\n */\n\n:root {\n color-scheme: light dark;\n\n${declarations(structural)}\n\n${declarations(lightVars)}\n}\n\n/* Automatic dark mode, only when the document has not opted into manual control. */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n${declarations(darkVars, ' ')}\n }\n}\n\n/* Explicit theme control. Works at any level of the tree, not just :root. */\n[data-theme='dark'] {\n${declarations(darkVars)}\n}\n\n[data-theme='light'] {\n${declarations(lightVars)}\n}\n\n/**\n * Reduced-motion safety net.\n *\n * The engine honours \\`prefers-reduced-motion\\` in JavaScript, but any CSS transition or\n * animation an application author writes is outside its reach. Neutralising them here means a\n * consumer gets correct behaviour for their own styles too, simply by importing this file.\n *\n * Durations are set to 0.01ms rather than 0 so that \\`transitionend\\` and \\`animationend\\` still\n * fire — code that waits on those events would otherwise hang forever.\n */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/**\n * Utility classes for the split-text behaviour.\n *\n * The behaviour sets \\`--ansh-index\\` and \\`--ansh-total\\` on every unit, which makes a\n * staggered reveal possible in pure CSS with no JavaScript timing at all.\n */\n.ansh-char,\n.ansh-word,\n.ansh-line {\n display: inline-block;\n /* Required for transforms to apply to inline content, and for masks to clip descenders. */\n will-change: transform, opacity;\n}\n\n.ansh-mask {\n display: inline-block;\n overflow: hidden;\n vertical-align: top;\n}\n`\n}\n\n/**\n * Apply a theme imperatively.\n *\n * Sets `data-theme` on the target, which the stylesheet above already understands. Prefer this\n * over injecting inline styles: it keeps every token in one cascade layer and lets the browser\n * do the work.\n *\n * @param theme `'light'`, `'dark'`, or `'system'` to hand control back to `prefers-color-scheme`.\n * @param target Defaults to `document.documentElement`. Pass an element to theme a subtree.\n */\nexport function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (theme === 'system') element.removeAttribute('data-theme')\n else element.setAttribute('data-theme', theme)\n}\n\n/**\n * Read the currently applied theme.\n *\n * Resolves `'system'` to whichever theme is actually in effect, because callers generally want to\n * know what the user is *seeing*, not how it was configured.\n */\nexport function resolveTheme(target?: HTMLElement): 'light' | 'dark' {\n if (typeof document === 'undefined') return 'light'\n const element = target ?? document.documentElement\n const explicit = element.closest('[data-theme]')?.getAttribute('data-theme')\n if (explicit === 'dark' || explicit === 'light') return explicit\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\n/**\n * Build an inline `style` object for a subtree override.\n *\n * Used by framework `<ThemeProvider>` components that need to apply a theme before the stylesheet\n * has necessarily loaded — during SSR, most importantly, where a flash of the wrong theme is\n * otherwise unavoidable.\n */\nexport function themeStyle(theme: 'light' | 'dark'): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [name, value] of themeVariables(theme === 'dark' ? dark : light)) {\n out[name] = value\n }\n return out\n}\n","/**\n * @ansh-ui/tokens — the Ansh design language.\n *\n * Tokens are exported both as TypeScript values (for code that computes with them) and as CSS\n * custom properties (for everything the cascade should own). Both are generated from the same\n * source, so they cannot drift.\n *\n * ```ts\n * import '@ansh-ui/tokens/ansh.css'\n * import { space, applyTheme } from '@ansh-ui/tokens'\n * ```\n */\n\nexport * from './primitives'\nexport * from './semantic'\nexport * from './css'\n\nimport {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\n\n/**\n * Every structural token in one object.\n *\n * Convenient for a Tailwind preset or a styled-components theme, where the consumer wants the\n * whole scale rather than individual imports.\n */\nexport const tokens = {\n space,\n radius,\n shadow,\n blur,\n duration,\n easing,\n zIndex,\n fontSize,\n fontWeight,\n fontFamily,\n breakpoint,\n} as const\n\nexport type Tokens = typeof tokens\n\n/**\n * A Tailwind CSS preset that maps Ansh tokens onto Tailwind's theme keys.\n *\n * Returned as a plain object rather than importing Tailwind types, so this package stays free of a\n * Tailwind dependency for the majority of consumers who don't use it.\n *\n * ```js\n * // tailwind.config.js\n * import { tailwindPreset } from '@ansh-ui/tokens'\n * export default { presets: [tailwindPreset()] }\n * ```\n */\nexport function tailwindPreset() {\n return {\n theme: {\n extend: {\n spacing: space,\n borderRadius: radius,\n boxShadow: shadow,\n blur,\n fontFamily: { sans: [fontFamily.sans], mono: [fontFamily.mono] },\n fontSize,\n fontWeight,\n screens: breakpoint,\n zIndex,\n transitionDuration: Object.fromEntries(\n Object.entries(duration).map(([key, value]) => [key, value]),\n ),\n transitionTimingFunction: easing,\n // Semantic colours are wired to the CSS variables rather than to literal values, so a\n // Tailwind class like `bg-surface-raised` follows the active theme automatically.\n colors: {\n surface: {\n canvas: 'var(--ansh-surface-canvas)',\n raised: 'var(--ansh-surface-raised)',\n overlay: 'var(--ansh-surface-overlay)',\n sunken: 'var(--ansh-surface-sunken)',\n glass: 'var(--ansh-surface-glass)',\n },\n content: {\n primary: 'var(--ansh-content-primary)',\n secondary: 'var(--ansh-content-secondary)',\n tertiary: 'var(--ansh-content-tertiary)',\n disabled: 'var(--ansh-content-disabled)',\n 'on-accent': 'var(--ansh-content-on-accent)',\n inverse: 'var(--ansh-content-inverse)',\n },\n line: {\n subtle: 'var(--ansh-border-subtle)',\n DEFAULT: 'var(--ansh-border-default)',\n strong: 'var(--ansh-border-strong)',\n focus: 'var(--ansh-border-focus)',\n },\n accent: {\n subtle: 'var(--ansh-accent-subtle)',\n muted: 'var(--ansh-accent-muted)',\n DEFAULT: 'var(--ansh-accent-default)',\n hover: 'var(--ansh-accent-hover)',\n active: 'var(--ansh-accent-active)',\n text: 'var(--ansh-accent-text)',\n },\n },\n },\n },\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/primitives.ts","../src/semantic.ts","../src/css.ts","../src/index.ts"],"names":["tokens"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Primitive design tokens.\n *\n * These are the raw values — the vocabulary. Semantic tokens (in `semantic.ts`) map *meaning*\n * onto them, and that indirection is what makes theming possible: `--ansh-surface` can point\n * at `slate.50` in light mode and `slate.950` in dark mode without any component changing.\n *\n * Every scale here is derived from a rule rather than hand-picked, so extending it is\n * unambiguous and a designer can predict what step 9 looks like without checking.\n */\n\n/**\n * Spacing — an 8-point grid with half-steps below 8px.\n *\n * The half-steps matter: 8px is too coarse for optical adjustments like the gap between an icon\n * and its label, and every design system that omits them ends up with arbitrary one-off values.\n * Named by their pixel value at the default root size so `space[4]` is unambiguously 16px.\n */\nexport const space = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 3: '0.75rem', // 12px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 8: '2rem', // 32px\n 10: '2.5rem', // 40px\n 12: '3rem', // 48px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 32: '8rem', // 128px\n 40: '10rem', // 160px\n 48: '12rem', // 192px\n 56: '14rem', // 224px\n 64: '16rem', // 256px\n} as const\n\n/**\n * Typography — a modular scale at ratio 1.2 (minor third), rounded to sensible pixel values.\n *\n * 1.2 rather than the more common 1.25 or golden ratio: on the wide viewports these components\n * target, a steeper ratio makes display sizes enormous before the body sizes have room to\n * differentiate. 1.2 gives eight useful steps between 12px and 60px.\n *\n * Each step pairs a size with a line height, because a size without its leading is not a\n * typographic decision — and line height must *decrease* proportionally as size increases.\n */\nexport const fontSize = {\n xs: ['0.75rem', { lineHeight: '1.125rem', letterSpacing: '0.01em' }],\n sm: ['0.875rem', { lineHeight: '1.375rem', letterSpacing: '0.005em' }],\n base: ['1rem', { lineHeight: '1.625rem', letterSpacing: '0' }],\n lg: ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '-0.005em' }],\n xl: ['1.25rem', { lineHeight: '1.875rem', letterSpacing: '-0.01em' }],\n '2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.015em' }],\n '3xl': ['1.875rem', { lineHeight: '2.375rem', letterSpacing: '-0.02em' }],\n '4xl': ['2.25rem', { lineHeight: '2.625rem', letterSpacing: '-0.025em' }],\n '5xl': ['3rem', { lineHeight: '3.25rem', letterSpacing: '-0.03em' }],\n '6xl': ['3.75rem', { lineHeight: '3.9rem', letterSpacing: '-0.035em' }],\n '7xl': ['4.5rem', { lineHeight: '4.6rem', letterSpacing: '-0.04em' }],\n} as const satisfies Record<\n string,\n readonly [string, { lineHeight: string; letterSpacing: string }]\n>\n\nexport const fontWeight = {\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n} as const\n\nexport const fontFamily = {\n /**\n * The system UI stack. Deliberately not a webfont: the fastest, most legible text on any\n * platform is the font the user's OS already has loaded, and a design system should not force\n * a font decision on its consumers.\n */\n sans: [\n 'ui-sans-serif',\n 'system-ui',\n '-apple-system',\n 'BlinkMacSystemFont',\n 'Segoe UI',\n 'Roboto',\n 'Helvetica Neue',\n 'Arial',\n 'sans-serif',\n ].join(', '),\n mono: [\n 'ui-monospace',\n 'SFMono-Regular',\n 'Menlo',\n 'Monaco',\n 'Consolas',\n 'Liberation Mono',\n 'Courier New',\n 'monospace',\n ].join(', '),\n} as const\n\n/** Corner radii. `full` is a large fixed value rather than 50%, so pills stay pill-shaped. */\nexport const radius = {\n none: '0',\n xs: '0.25rem', // 4px\n sm: '0.375rem', // 6px\n md: '0.5rem', // 8px\n lg: '0.75rem', // 12px\n xl: '1rem', // 16px\n '2xl': '1.5rem', // 24px\n '3xl': '2rem', // 32px\n full: '9999px',\n} as const\n\n/**\n * Elevation — layered shadows, not single ones.\n *\n * A single `box-shadow` cannot describe real light: an object casts both a tight contact shadow\n * directly beneath it and a broader ambient shadow further out. Every step here composes both,\n * which is the difference between a card that sits on the page and one that looks pasted onto it.\n *\n * Shadow colour is a token so it can shift with the theme — a pure-black shadow on a dark\n * surface is invisible, so the dark theme uses a deeper, more spread variant.\n */\nexport const shadow = {\n none: 'none',\n xs: '0 1px 2px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n sm:\n '0 1px 3px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 1px 2px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n md:\n '0 4px 6px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 2px 4px -2px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n lg:\n '0 10px 15px -3px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 4px 6px -4px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n xl:\n '0 20px 25px -5px var(--ansh-shadow-color, rgb(15 23 42 / 0.1)), ' +\n '0 8px 10px -6px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n '2xl': '0 25px 50px -12px var(--ansh-shadow-color, rgb(15 23 42 / 0.2))',\n /** Inset — for pressed states and inputs. */\n inner: 'inset 0 2px 4px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n /**\n * Glow. Uses `currentColor` so a button's glow automatically matches its own accent without\n * the author repeating the colour.\n */\n glow: '0 0 24px -4px currentColor',\n glowLg: '0 0 48px -8px currentColor',\n} as const\n\n/** Backdrop blur steps, for glass surfaces. */\nexport const blur = {\n none: '0',\n xs: '2px',\n sm: '4px',\n md: '8px',\n lg: '16px',\n xl: '24px',\n '2xl': '40px',\n '3xl': '64px',\n} as const\n\n/**\n * Motion durations in seconds.\n *\n * Named by intent rather than by number. The values follow a rule of thumb that holds up well:\n * the distance travelled should determine the duration, so a tooltip appearing in place is\n * `instant`, a dropdown is `fast`, and a full-screen sheet is `slow`.\n */\nexport const duration = {\n instant: '0.1s',\n fast: '0.2s',\n normal: '0.3s',\n moderate: '0.45s',\n slow: '0.6s',\n slower: '0.9s',\n deliberate: '1.2s',\n} as const\n\n/**\n * CSS timing functions matching the engine's `signature` easings exactly.\n *\n * Keeping these in lockstep means a CSS transition and a JS animation on the same element move\n * identically — which matters more than it sounds, because mismatched curves on adjacent\n * elements is one of those things that reads as \"cheap\" without the viewer knowing why.\n */\nexport const easing = {\n linear: 'linear',\n standard: 'cubic-bezier(0.4, 0, 0.2, 1)',\n emphasized: 'cubic-bezier(0.22, 1, 0.36, 1)',\n enter: 'cubic-bezier(0, 0, 0.2, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n overshoot: 'cubic-bezier(0.34, 1.56, 0.64, 1)',\n cinematic: 'cubic-bezier(0.16, 1, 0.3, 1)',\n} as const\n\n/**\n * Z-index scale.\n *\n * Sparse, deliberate values with names. The alternative — `z-index: 9999` scattered through a\n * codebase — is the single most common source of stacking bugs in a component library.\n */\nexport const zIndex = {\n hide: '-1',\n base: '0',\n raised: '10',\n dropdown: '1000',\n sticky: '1100',\n overlay: '1200',\n modal: '1300',\n popover: '1400',\n toast: '1500',\n tooltip: '1600',\n /** Reserved for skip links and focus traps, which must beat everything. */\n max: '2147483647',\n} as const\n\n/** Breakpoints, matching the widths where real layout decisions occur. */\nexport const breakpoint = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n} as const\n\n/**\n * Neutral ramp, defined in OKLCH.\n *\n * Lightness steps are perceptually even, which a hex-defined grey ramp never is — the usual\n * result is a scale that looks well-spaced at the light end and bunched at the dark end. A slight\n * blue chroma (hue 264) keeps it from reading as muddy against saturated accents.\n */\nexport const neutral = {\n 50: 'oklch(98.5% 0.002 264)',\n 100: 'oklch(96.8% 0.004 264)',\n 200: 'oklch(92.9% 0.007 264)',\n 300: 'oklch(86.9% 0.011 264)',\n 400: 'oklch(70.7% 0.018 264)',\n 500: 'oklch(55.4% 0.022 264)',\n 600: 'oklch(44.6% 0.021 264)',\n 700: 'oklch(37.2% 0.019 264)',\n 800: 'oklch(27.9% 0.017 264)',\n 900: 'oklch(20.8% 0.015 264)',\n 950: 'oklch(13.8% 0.014 264)',\n 1000: 'oklch(8.5% 0.012 264)',\n} as const\n\n/** The Ansh brand ramp — the blue the library ships with. */\nexport const brand = {\n 50: 'oklch(97% 0.017 253)',\n 100: 'oklch(93.8% 0.036 253)',\n 200: 'oklch(88.5% 0.069 253)',\n 300: 'oklch(80.9% 0.111 253)',\n 400: 'oklch(71.4% 0.153 253)',\n 500: 'oklch(62.3% 0.188 253)',\n 600: 'oklch(54.6% 0.208 253)',\n 700: 'oklch(46.4% 0.192 253)',\n 800: 'oklch(39.1% 0.16 253)',\n 900: 'oklch(33.5% 0.129 253)',\n 950: 'oklch(23.2% 0.093 253)',\n} as const\n\n/** Status ramps. Only the steps that get used are defined, rather than a full 11 for each. */\nexport const status = {\n success: {\n subtle: 'oklch(95.5% 0.035 155)',\n default: 'oklch(58% 0.15 155)',\n strong: 'oklch(44% 0.12 155)',\n },\n warning: {\n subtle: 'oklch(96.5% 0.045 85)',\n default: 'oklch(72% 0.16 75)',\n strong: 'oklch(52% 0.13 65)',\n },\n danger: {\n subtle: 'oklch(95.5% 0.03 25)',\n default: 'oklch(58% 0.21 25)',\n strong: 'oklch(46% 0.18 25)',\n },\n info: {\n subtle: 'oklch(96% 0.025 240)',\n default: 'oklch(62% 0.17 245)',\n strong: 'oklch(48% 0.15 250)',\n },\n} as const\n","import { brand, neutral, shadow, status } from './primitives'\n\n/**\n * Semantic tokens — meaning mapped onto primitives.\n *\n * This layer is why theming works. A component references `surface.raised`, never `neutral.100`.\n * Switching to dark mode remaps `surface.raised` to `neutral.900`, and every component follows\n * without a single change. A component that reaches past this layer to a primitive is a bug: it\n * will look wrong in one theme and nobody will notice until a user reports it.\n *\n * The naming follows a consistent pattern:\n *\n * - `surface.*` — backgrounds, ordered by elevation\n * - `content.*` — text and icons, ordered by prominence\n * - `border.*` — dividers and outlines, ordered by strength\n * - `accent.*` — the interactive brand colour and its states\n * - `state.*` — success/warning/danger/info\n */\n\nexport interface SemanticTokens {\n surface: {\n /** The page background. */\n canvas: string\n /** Cards and panels sitting on the canvas. */\n raised: string\n /** Menus, popovers and anything floating above `raised`. */\n overlay: string\n /** Subtly recessed areas — code blocks, well insets. */\n sunken: string\n /** Translucent glass surface, for use with `backdrop-filter`. */\n glass: string\n /** The scrim behind a modal. */\n scrim: string\n }\n content: {\n /** Body text and headings. Must reach 7:1 against `surface.canvas`. */\n primary: string\n /** Supporting text. Must reach 4.5:1. */\n secondary: string\n /** De-emphasised text — timestamps, captions. Must reach 4.5:1 at ≥14px. */\n tertiary: string\n /** Placeholder and disabled text. Exempt from contrast minimums by WCAG. */\n disabled: string\n /** Text placed on top of `accent.default`. */\n onAccent: string\n /** Inverted text, for use on `content.primary` as a background. */\n inverse: string\n }\n border: {\n /** Hairline dividers. */\n subtle: string\n /** Input and card outlines. */\n default: string\n /** Hovered or emphasised outlines. */\n strong: string\n /** The focus ring. Must reach 3:1 against both adjacent surfaces. */\n focus: string\n }\n accent: {\n subtle: string\n muted: string\n default: string\n hover: string\n active: string\n /** For text and icons rendered in the accent colour on a neutral surface. */\n text: string\n }\n state: {\n successSubtle: string\n success: string\n warningSubtle: string\n warning: string\n dangerSubtle: string\n danger: string\n infoSubtle: string\n info: string\n }\n /** The shadow colour the elevation scale multiplies through. */\n shadowColor: string\n}\n\n/**\n * Light theme.\n *\n * Contrast ratios against `surface.canvas` (`neutral.50`):\n * `content.primary` → 15.8:1 (AAA)\n * `content.secondary` → 7.4:1 (AAA)\n * `content.tertiary` → 4.7:1 (AA)\n * `border.focus` → 3.4:1 (AA non-text)\n */\nexport const light: SemanticTokens = {\n surface: {\n canvas: neutral[50],\n raised: '#ffffff',\n overlay: '#ffffff',\n sunken: neutral[100],\n glass: 'oklch(100% 0 0 / 0.72)',\n scrim: 'oklch(20.8% 0.015 264 / 0.45)',\n },\n content: {\n primary: neutral[900],\n secondary: neutral[600],\n tertiary: neutral[500],\n disabled: neutral[400],\n onAccent: '#ffffff',\n inverse: neutral[50],\n },\n border: {\n subtle: neutral[200],\n default: neutral[300],\n strong: neutral[400],\n focus: brand[600],\n },\n accent: {\n subtle: brand[50],\n muted: brand[100],\n default: brand[600],\n hover: brand[700],\n active: brand[800],\n // A step darker than `default`: brand colours tuned to look right as a fill are usually too\n // light to pass contrast as text on a white surface.\n text: brand[700],\n },\n state: {\n successSubtle: status.success.subtle,\n success: status.success.strong,\n warningSubtle: status.warning.subtle,\n warning: status.warning.strong,\n dangerSubtle: status.danger.subtle,\n danger: status.danger.strong,\n infoSubtle: status.info.subtle,\n info: status.info.strong,\n },\n shadowColor: 'oklch(20.8% 0.015 264 / 0.08)',\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion of `light`. Three adjustments that a mechanical inversion misses:\n *\n * 1. **Surfaces get lighter as they rise, not darker.** In light mode, elevation is signalled by\n * shadow. On a dark background shadow is invisible, so elevation must be signalled by the\n * surface itself becoming lighter.\n * 2. **Chroma is raised.** Saturated colours read as less vivid against dark backgrounds\n * (Helmholtz–Kohlrausch), so accents step *lighter* rather than mirroring their light-mode step.\n * 3. **Body text is not pure white.** `#fff` on a near-black background causes halation — the\n * text appears to bleed. `neutral.100` reads as white while staying comfortable.\n */\nexport const dark: SemanticTokens = {\n surface: {\n canvas: neutral[1000],\n raised: neutral[950],\n overlay: neutral[900],\n sunken: 'oklch(6% 0.01 264)',\n glass: 'oklch(13.8% 0.014 264 / 0.68)',\n scrim: 'oklch(4% 0.008 264 / 0.65)',\n },\n content: {\n primary: neutral[100],\n secondary: neutral[300],\n tertiary: neutral[400],\n disabled: neutral[600],\n onAccent: '#ffffff',\n inverse: neutral[950],\n },\n border: {\n // Borders on dark surfaces work by being *lighter* than the surface, and need less contrast\n // than their light-mode counterparts to read as the same weight.\n subtle: 'oklch(100% 0 0 / 0.08)',\n default: 'oklch(100% 0 0 / 0.14)',\n strong: 'oklch(100% 0 0 / 0.24)',\n focus: brand[400],\n },\n accent: {\n subtle: 'oklch(23.2% 0.093 253 / 0.4)',\n muted: brand[950],\n default: brand[500],\n hover: brand[400],\n active: brand[300],\n text: brand[300],\n },\n state: {\n successSubtle: 'oklch(30% 0.08 155 / 0.35)',\n success: 'oklch(72% 0.16 155)',\n warningSubtle: 'oklch(32% 0.09 75 / 0.35)',\n warning: 'oklch(80% 0.15 80)',\n dangerSubtle: 'oklch(30% 0.11 25 / 0.35)',\n danger: 'oklch(70% 0.19 25)',\n infoSubtle: 'oklch(30% 0.09 245 / 0.35)',\n info: 'oklch(74% 0.15 245)',\n },\n // Deeper and more spread than light mode, since a dark shadow on a dark surface needs more\n // opacity to register at all.\n shadowColor: 'oklch(0% 0 0 / 0.5)',\n}\n\nexport const themes = { light, dark } as const\nexport type ThemeName = keyof typeof themes\n\n/**\n * High-contrast overrides, layered on top of a base theme rather than a theme of their own.\n *\n * Only `content` and `border` change. `accent`, `state`, and `surface` are left alone: they were\n * already tuned against the documented minimums (`content.secondary` at 4.5:1, etc. — see the\n * field comments on `SemanticTokens` above), and re-deriving a whole second brand ramp for this\n * would be a bigger, riskier change than what high-contrast mode is actually for — text and\n * structure that's easy to misread at the *edges* of the existing palette (secondary/tertiary\n * text, subtle borders), not a different colour scheme.\n */\nexport type ContrastOverride = Pick<SemanticTokens, 'content' | 'border'>\n\nexport const lightHighContrast: ContrastOverride = {\n content: {\n ...light.content,\n secondary: neutral[800],\n tertiary: neutral[700],\n },\n border: {\n ...light.border,\n subtle: neutral[400],\n default: neutral[500],\n strong: neutral[700],\n },\n}\n\nexport const darkHighContrast: ContrastOverride = {\n content: {\n ...dark.content,\n secondary: neutral[100],\n tertiary: neutral[200],\n },\n border: {\n ...dark.border,\n subtle: 'oklch(100% 0 0 / 0.24)',\n default: 'oklch(100% 0 0 / 0.35)',\n strong: 'oklch(100% 0 0 / 0.5)',\n },\n}\n\n/** Re-exported so the CSS emitter can reference the elevation scale alongside the themes. */\nexport { shadow }\n","import {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\nimport {\n type ContrastOverride,\n type SemanticTokens,\n dark,\n darkHighContrast,\n light,\n lightHighContrast,\n} from './semantic'\n\n/**\n * CSS custom property generation.\n *\n * Tokens exist twice on purpose — as TypeScript values and as CSS variables — because the two\n * are consumed differently and neither can serve both jobs:\n *\n * - **TypeScript** values are needed where JavaScript computes with them: passing colours into\n * canvas effects, deriving palettes, computing contrast.\n * - **CSS variables** are needed for everything the cascade should own: theming a subtree,\n * respecting `prefers-color-scheme`, and letting a consumer override a token in their own\n * stylesheet without touching a build step.\n *\n * This module is the bridge, and it is generated from the same source of truth so the two can't\n * drift.\n */\n\nexport const CSS_PREFIX = 'ansh'\n\n/** Flatten a nested token object into `--prefix-path-to-key` variable declarations. */\nfunction flatten(target: Map<string, string>, value: unknown, path: readonly string[]): void {\n if (typeof value === 'string') {\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, value)\n return\n }\n if (Array.isArray(value)) {\n // Font size entries are `[size, { lineHeight, letterSpacing }]`. Emit each part under a\n // suffixed name so `--ansh-text-lg` and `--ansh-text-lg-leading` are both available.\n const [size, meta] = value as [string, Record<string, string> | undefined]\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, size)\n if (meta && typeof meta === 'object') {\n if (meta.lineHeight) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-leading`, meta.lineHeight)\n }\n if (meta.letterSpacing) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-tracking`, meta.letterSpacing)\n }\n }\n return\n }\n if (value && typeof value === 'object') {\n for (const [key, child] of Object.entries(value)) {\n flatten(target, child, [...path, cssSegment(key)])\n }\n }\n}\n\n/**\n * Convert a token key into a CSS-safe, CSS-conventional name segment.\n *\n * Two transformations, each fixing a real problem:\n *\n * - **Decimal points** (`space[0.5]`) are invalid in a custom property name, so they become\n * hyphens: `--ansh-space-0-5`.\n * - **camelCase** (`onAccent`, `successSubtle`) becomes kebab-case. CSS custom properties are\n * case-sensitive, and nobody writing CSS types `var(--ansh-content-onAccent)` — they type\n * `--ansh-content-on-accent`, get no error, and silently inherit the wrong colour. That\n * exact mismatch shipped in this library's own button styles: filled buttons fell back to the\n * inherited text colour, which is dark text on an accent fill.\n */\nfunction cssSegment(key: string): string {\n return key\n .replace('.', '-')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n\n/** Structural tokens — identical in every theme. */\nexport function structuralVariables(): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, space, ['space'])\n flatten(out, radius, ['radius'])\n flatten(out, shadow, ['shadow'])\n flatten(out, blur, ['blur'])\n flatten(out, duration, ['duration'])\n flatten(out, easing, ['ease'])\n flatten(out, zIndex, ['z'])\n flatten(out, fontSize, ['text'])\n flatten(out, fontWeight, ['weight'])\n flatten(out, fontFamily, ['font'])\n flatten(out, breakpoint, ['screen'])\n return out\n}\n\n/** Theme-dependent tokens for one theme. */\nexport function themeVariables(tokens: SemanticTokens): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, tokens.surface, ['surface'])\n flatten(out, tokens.content, ['content'])\n flatten(out, tokens.border, ['border'])\n flatten(out, tokens.accent, ['accent'])\n flatten(out, tokens.state, ['state'])\n out.set(`--${CSS_PREFIX}-shadow-color`, tokens.shadowColor)\n return out\n}\n\n/** Contrast-override tokens — only the `content` and `border` subset that high-contrast changes. */\nfunction contrastVariables(override: ContrastOverride): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, override.content, ['content'])\n flatten(out, override.border, ['border'])\n return out\n}\n\nfunction declarations(variables: Map<string, string>, indent = ' '): string {\n return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join('\\n')\n}\n\n/**\n * Emit the complete stylesheet.\n *\n * The theming strategy is deliberately layered so it works for every consumer:\n *\n * 1. `:root` carries the light theme, so the default works with no configuration.\n * 2. `@media (prefers-color-scheme: dark)` applies dark automatically — but *only* when the\n * document has not opted into manual control, guarded by `:root:not([data-theme])`. Without\n * that guard, a user who explicitly chose light mode in an app whose OS is dark would get dark\n * anyway, which is the single most common theming bug in the wild.\n * 3. `[data-theme='dark']` and `[data-theme='light']` allow explicit control at any level of the\n * tree, so a single dark card on a light page works with no extra plumbing.\n */\nexport function generateCss(): string {\n const structural = structuralVariables()\n const lightVars = themeVariables(light)\n const darkVars = themeVariables(dark)\n const lightContrastVars = contrastVariables(lightHighContrast)\n const darkContrastVars = contrastVariables(darkHighContrast)\n\n return `/**\n * Ansh design tokens.\n *\n * Generated from @ansh-ui/tokens — do not edit by hand.\n * Override any variable in your own stylesheet after importing this file.\n */\n\n:root {\n color-scheme: light dark;\n\n${declarations(structural)}\n\n${declarations(lightVars)}\n}\n\n/* Automatic dark mode, only when the document has not opted into manual control. */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n${declarations(darkVars, ' ')}\n }\n}\n\n/* Explicit theme control. Works at any level of the tree, not just :root. */\n[data-theme='dark'] {\n${declarations(darkVars)}\n}\n\n[data-theme='light'] {\n${declarations(lightVars)}\n}\n\n/**\n * High-contrast mode, layered on top of whichever theme is active — not a fifth theme, an\n * override of \\`content\\` and \\`border\\` only (see \\`ContrastOverride\\` in semantic.ts for why those\n * two and not the whole palette). Mirrors the theme cascade immediately above it: system\n * preference by default, explicit \\`[data-theme]\\` wins when set.\n *\n * The light rule must come *before* the dark media block below, not after: both target the same\n * \\`[data-contrast='high']:not([data-theme])\\` selector (identical specificity), so when the system\n * prefers dark and no theme is set explicitly, only source order decides which wins — exactly the\n * same reason the light/dark theme rules above are ordered the way they are.\n */\n[data-contrast='high']:not([data-theme]) {\n${declarations(lightContrastVars)}\n}\n\n@media (prefers-color-scheme: dark) {\n [data-contrast='high']:not([data-theme]) {\n${declarations(darkContrastVars, ' ')}\n }\n}\n\n[data-theme='dark'][data-contrast='high'] {\n${declarations(darkContrastVars)}\n}\n\n[data-theme='light'][data-contrast='high'] {\n${declarations(lightContrastVars)}\n}\n\n/* A token alone can't widen an outline. Every consumer's :focus-visible rule reads\n --ansh-border-focus already; high contrast also needs the ring itself to be harder to miss. */\n[data-contrast='high'] :focus-visible {\n outline-width: 3px;\n outline-offset: 3px;\n}\n\n/**\n * Reduced-motion safety net.\n *\n * The engine honours \\`prefers-reduced-motion\\` in JavaScript, but any CSS transition or\n * animation an application author writes is outside its reach. Neutralising them here means a\n * consumer gets correct behaviour for their own styles too, simply by importing this file.\n *\n * Durations are set to 0.01ms rather than 0 so that \\`transitionend\\` and \\`animationend\\` still\n * fire — code that waits on those events would otherwise hang forever.\n */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/**\n * Utility classes for the split-text behaviour.\n *\n * The behaviour sets \\`--ansh-index\\` and \\`--ansh-total\\` on every unit, which makes a\n * staggered reveal possible in pure CSS with no JavaScript timing at all.\n */\n.ansh-char,\n.ansh-word,\n.ansh-line {\n display: inline-block;\n /* Required for transforms to apply to inline content, and for masks to clip descenders. */\n will-change: transform, opacity;\n}\n\n.ansh-mask {\n display: inline-block;\n overflow: hidden;\n vertical-align: top;\n}\n`\n}\n\n/**\n * Apply a theme imperatively.\n *\n * Sets `data-theme` on the target, which the stylesheet above already understands. Prefer this\n * over injecting inline styles: it keeps every token in one cascade layer and lets the browser\n * do the work.\n *\n * @param theme `'light'`, `'dark'`, or `'system'` to hand control back to `prefers-color-scheme`.\n * @param target Defaults to `document.documentElement`. Pass an element to theme a subtree.\n */\nexport function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (theme === 'system') element.removeAttribute('data-theme')\n else element.setAttribute('data-theme', theme)\n}\n\n/**\n * Read the currently applied theme.\n *\n * Resolves `'system'` to whichever theme is actually in effect, because callers generally want to\n * know what the user is *seeing*, not how it was configured.\n */\nexport function resolveTheme(target?: HTMLElement): 'light' | 'dark' {\n if (typeof document === 'undefined') return 'light'\n const element = target ?? document.documentElement\n const explicit = element.closest('[data-theme]')?.getAttribute('data-theme')\n if (explicit === 'dark' || explicit === 'light') return explicit\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\n/**\n * Apply or clear high-contrast mode imperatively — the `content`/`border` override described on\n * `ContrastOverride`, layered on whichever theme is already active via `applyTheme`.\n *\n * @param contrast `'high'` or `'normal'`.\n * @param target Defaults to `document.documentElement`. Pass an element to scope a subtree.\n */\nexport function applyContrast(contrast: 'high' | 'normal', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (contrast === 'high') element.setAttribute('data-contrast', 'high')\n else element.removeAttribute('data-contrast')\n}\n\n/** Read whether high-contrast mode is currently applied, at or above `target`. */\nexport function resolveContrast(target?: HTMLElement): 'high' | 'normal' {\n if (typeof document === 'undefined') return 'normal'\n const element = target ?? document.documentElement\n return element.closest(\"[data-contrast='high']\") ? 'high' : 'normal'\n}\n\n/**\n * Build an inline `style` object for a subtree override.\n *\n * Used by framework `<ThemeProvider>` components that need to apply a theme before the stylesheet\n * has necessarily loaded — during SSR, most importantly, where a flash of the wrong theme is\n * otherwise unavoidable.\n */\nexport function themeStyle(theme: 'light' | 'dark'): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [name, value] of themeVariables(theme === 'dark' ? dark : light)) {\n out[name] = value\n }\n return out\n}\n","/**\n * @ansh-ui/tokens — the Ansh design language.\n *\n * Tokens are exported both as TypeScript values (for code that computes with them) and as CSS\n * custom properties (for everything the cascade should own). Both are generated from the same\n * source, so they cannot drift.\n *\n * ```ts\n * import '@ansh-ui/tokens/ansh.css'\n * import { space, applyTheme } from '@ansh-ui/tokens'\n * ```\n */\n\nexport * from './primitives'\nexport * from './semantic'\nexport * from './css'\n\nimport {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\n\n/**\n * Every structural token in one object.\n *\n * Convenient for a Tailwind preset or a styled-components theme, where the consumer wants the\n * whole scale rather than individual imports.\n */\nexport const tokens = {\n space,\n radius,\n shadow,\n blur,\n duration,\n easing,\n zIndex,\n fontSize,\n fontWeight,\n fontFamily,\n breakpoint,\n} as const\n\nexport type Tokens = typeof tokens\n\n/**\n * A Tailwind CSS preset that maps Ansh tokens onto Tailwind's theme keys.\n *\n * Returned as a plain object rather than importing Tailwind types, so this package stays free of a\n * Tailwind dependency for the majority of consumers who don't use it.\n *\n * ```js\n * // tailwind.config.js\n * import { tailwindPreset } from '@ansh-ui/tokens'\n * export default { presets: [tailwindPreset()] }\n * ```\n */\nexport function tailwindPreset() {\n return {\n theme: {\n extend: {\n spacing: space,\n borderRadius: radius,\n boxShadow: shadow,\n blur,\n fontFamily: { sans: [fontFamily.sans], mono: [fontFamily.mono] },\n fontSize,\n fontWeight,\n screens: breakpoint,\n zIndex,\n transitionDuration: Object.fromEntries(\n Object.entries(duration).map(([key, value]) => [key, value]),\n ),\n transitionTimingFunction: easing,\n // Semantic colours are wired to the CSS variables rather than to literal values, so a\n // Tailwind class like `bg-surface-raised` follows the active theme automatically.\n colors: {\n surface: {\n canvas: 'var(--ansh-surface-canvas)',\n raised: 'var(--ansh-surface-raised)',\n overlay: 'var(--ansh-surface-overlay)',\n sunken: 'var(--ansh-surface-sunken)',\n glass: 'var(--ansh-surface-glass)',\n },\n content: {\n primary: 'var(--ansh-content-primary)',\n secondary: 'var(--ansh-content-secondary)',\n tertiary: 'var(--ansh-content-tertiary)',\n disabled: 'var(--ansh-content-disabled)',\n 'on-accent': 'var(--ansh-content-on-accent)',\n inverse: 'var(--ansh-content-inverse)',\n },\n line: {\n subtle: 'var(--ansh-border-subtle)',\n DEFAULT: 'var(--ansh-border-default)',\n strong: 'var(--ansh-border-strong)',\n focus: 'var(--ansh-border-focus)',\n },\n accent: {\n subtle: 'var(--ansh-accent-subtle)',\n muted: 'var(--ansh-accent-muted)',\n DEFAULT: 'var(--ansh-accent-default)',\n hover: 'var(--ansh-accent-hover)',\n active: 'var(--ansh-accent-active)',\n text: 'var(--ansh-accent-text)',\n },\n },\n },\n },\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -384,6 +384,19 @@ declare const themes: {
384
384
  readonly dark: SemanticTokens;
385
385
  };
386
386
  type ThemeName = keyof typeof themes;
387
+ /**
388
+ * High-contrast overrides, layered on top of a base theme rather than a theme of their own.
389
+ *
390
+ * Only `content` and `border` change. `accent`, `state`, and `surface` are left alone: they were
391
+ * already tuned against the documented minimums (`content.secondary` at 4.5:1, etc. — see the
392
+ * field comments on `SemanticTokens` above), and re-deriving a whole second brand ramp for this
393
+ * would be a bigger, riskier change than what high-contrast mode is actually for — text and
394
+ * structure that's easy to misread at the *edges* of the existing palette (secondary/tertiary
395
+ * text, subtle borders), not a different colour scheme.
396
+ */
397
+ type ContrastOverride = Pick<SemanticTokens, 'content' | 'border'>;
398
+ declare const lightHighContrast: ContrastOverride;
399
+ declare const darkHighContrast: ContrastOverride;
387
400
 
388
401
  /**
389
402
  * CSS custom property generation.
@@ -437,6 +450,16 @@ declare function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLEle
437
450
  * know what the user is *seeing*, not how it was configured.
438
451
  */
439
452
  declare function resolveTheme(target?: HTMLElement): 'light' | 'dark';
453
+ /**
454
+ * Apply or clear high-contrast mode imperatively — the `content`/`border` override described on
455
+ * `ContrastOverride`, layered on whichever theme is already active via `applyTheme`.
456
+ *
457
+ * @param contrast `'high'` or `'normal'`.
458
+ * @param target Defaults to `document.documentElement`. Pass an element to scope a subtree.
459
+ */
460
+ declare function applyContrast(contrast: 'high' | 'normal', target?: HTMLElement): void;
461
+ /** Read whether high-contrast mode is currently applied, at or above `target`. */
462
+ declare function resolveContrast(target?: HTMLElement): 'high' | 'normal';
440
463
  /**
441
464
  * Build an inline `style` object for a subtree override.
442
465
  *
@@ -812,4 +835,5 @@ declare function tailwindPreset(): {
812
835
  };
813
836
  };
814
837
 
815
- export { CSS_PREFIX, type SemanticTokens, type ThemeName, type Tokens, applyTheme, blur, brand, breakpoint, dark, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, neutral, radius, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
838
+ export { CSS_PREFIX, applyContrast, applyTheme, blur, brand, breakpoint, dark, darkHighContrast, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, lightHighContrast, neutral, radius, resolveContrast, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
839
+ export type { ContrastOverride, SemanticTokens, ThemeName, Tokens };
package/dist/index.d.ts CHANGED
@@ -384,6 +384,19 @@ declare const themes: {
384
384
  readonly dark: SemanticTokens;
385
385
  };
386
386
  type ThemeName = keyof typeof themes;
387
+ /**
388
+ * High-contrast overrides, layered on top of a base theme rather than a theme of their own.
389
+ *
390
+ * Only `content` and `border` change. `accent`, `state`, and `surface` are left alone: they were
391
+ * already tuned against the documented minimums (`content.secondary` at 4.5:1, etc. — see the
392
+ * field comments on `SemanticTokens` above), and re-deriving a whole second brand ramp for this
393
+ * would be a bigger, riskier change than what high-contrast mode is actually for — text and
394
+ * structure that's easy to misread at the *edges* of the existing palette (secondary/tertiary
395
+ * text, subtle borders), not a different colour scheme.
396
+ */
397
+ type ContrastOverride = Pick<SemanticTokens, 'content' | 'border'>;
398
+ declare const lightHighContrast: ContrastOverride;
399
+ declare const darkHighContrast: ContrastOverride;
387
400
 
388
401
  /**
389
402
  * CSS custom property generation.
@@ -437,6 +450,16 @@ declare function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLEle
437
450
  * know what the user is *seeing*, not how it was configured.
438
451
  */
439
452
  declare function resolveTheme(target?: HTMLElement): 'light' | 'dark';
453
+ /**
454
+ * Apply or clear high-contrast mode imperatively — the `content`/`border` override described on
455
+ * `ContrastOverride`, layered on whichever theme is already active via `applyTheme`.
456
+ *
457
+ * @param contrast `'high'` or `'normal'`.
458
+ * @param target Defaults to `document.documentElement`. Pass an element to scope a subtree.
459
+ */
460
+ declare function applyContrast(contrast: 'high' | 'normal', target?: HTMLElement): void;
461
+ /** Read whether high-contrast mode is currently applied, at or above `target`. */
462
+ declare function resolveContrast(target?: HTMLElement): 'high' | 'normal';
440
463
  /**
441
464
  * Build an inline `style` object for a subtree override.
442
465
  *
@@ -812,4 +835,5 @@ declare function tailwindPreset(): {
812
835
  };
813
836
  };
814
837
 
815
- export { CSS_PREFIX, type SemanticTokens, type ThemeName, type Tokens, applyTheme, blur, brand, breakpoint, dark, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, neutral, radius, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
838
+ export { CSS_PREFIX, applyContrast, applyTheme, blur, brand, breakpoint, dark, darkHighContrast, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, lightHighContrast, neutral, radius, resolveContrast, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
839
+ export type { ContrastOverride, SemanticTokens, ThemeName, Tokens };
package/dist/index.js CHANGED
@@ -316,6 +316,32 @@ var dark = {
316
316
  shadowColor: "oklch(0% 0 0 / 0.5)"
317
317
  };
318
318
  var themes = { light, dark };
319
+ var lightHighContrast = {
320
+ content: {
321
+ ...light.content,
322
+ secondary: neutral[800],
323
+ tertiary: neutral[700]
324
+ },
325
+ border: {
326
+ ...light.border,
327
+ subtle: neutral[400],
328
+ default: neutral[500],
329
+ strong: neutral[700]
330
+ }
331
+ };
332
+ var darkHighContrast = {
333
+ content: {
334
+ ...dark.content,
335
+ secondary: neutral[100],
336
+ tertiary: neutral[200]
337
+ },
338
+ border: {
339
+ ...dark.border,
340
+ subtle: "oklch(100% 0 0 / 0.24)",
341
+ default: "oklch(100% 0 0 / 0.35)",
342
+ strong: "oklch(100% 0 0 / 0.5)"
343
+ }
344
+ };
319
345
 
320
346
  // src/css.ts
321
347
  var CSS_PREFIX = "ansh";
@@ -371,6 +397,12 @@ function themeVariables(tokens2) {
371
397
  out.set(`--${CSS_PREFIX}-shadow-color`, tokens2.shadowColor);
372
398
  return out;
373
399
  }
400
+ function contrastVariables(override) {
401
+ const out = /* @__PURE__ */ new Map();
402
+ flatten(out, override.content, ["content"]);
403
+ flatten(out, override.border, ["border"]);
404
+ return out;
405
+ }
374
406
  function declarations(variables, indent = " ") {
375
407
  return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join("\n");
376
408
  }
@@ -378,6 +410,8 @@ function generateCss() {
378
410
  const structural = structuralVariables();
379
411
  const lightVars = themeVariables(light);
380
412
  const darkVars = themeVariables(dark);
413
+ const lightContrastVars = contrastVariables(lightHighContrast);
414
+ const darkContrastVars = contrastVariables(darkHighContrast);
381
415
  return `/**
382
416
  * Ansh design tokens.
383
417
  *
@@ -409,6 +443,42 @@ ${declarations(darkVars)}
409
443
  ${declarations(lightVars)}
410
444
  }
411
445
 
446
+ /**
447
+ * High-contrast mode, layered on top of whichever theme is active \u2014 not a fifth theme, an
448
+ * override of \`content\` and \`border\` only (see \`ContrastOverride\` in semantic.ts for why those
449
+ * two and not the whole palette). Mirrors the theme cascade immediately above it: system
450
+ * preference by default, explicit \`[data-theme]\` wins when set.
451
+ *
452
+ * The light rule must come *before* the dark media block below, not after: both target the same
453
+ * \`[data-contrast='high']:not([data-theme])\` selector (identical specificity), so when the system
454
+ * prefers dark and no theme is set explicitly, only source order decides which wins \u2014 exactly the
455
+ * same reason the light/dark theme rules above are ordered the way they are.
456
+ */
457
+ [data-contrast='high']:not([data-theme]) {
458
+ ${declarations(lightContrastVars)}
459
+ }
460
+
461
+ @media (prefers-color-scheme: dark) {
462
+ [data-contrast='high']:not([data-theme]) {
463
+ ${declarations(darkContrastVars, " ")}
464
+ }
465
+ }
466
+
467
+ [data-theme='dark'][data-contrast='high'] {
468
+ ${declarations(darkContrastVars)}
469
+ }
470
+
471
+ [data-theme='light'][data-contrast='high'] {
472
+ ${declarations(lightContrastVars)}
473
+ }
474
+
475
+ /* A token alone can't widen an outline. Every consumer's :focus-visible rule reads
476
+ --ansh-border-focus already; high contrast also needs the ring itself to be harder to miss. */
477
+ [data-contrast='high'] :focus-visible {
478
+ outline-width: 3px;
479
+ outline-offset: 3px;
480
+ }
481
+
412
482
  /**
413
483
  * Reduced-motion safety net.
414
484
  *
@@ -464,6 +534,17 @@ function resolveTheme(target) {
464
534
  if (explicit === "dark" || explicit === "light") return explicit;
465
535
  return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
466
536
  }
537
+ function applyContrast(contrast, target) {
538
+ if (typeof document === "undefined") return;
539
+ const element = target ?? document.documentElement;
540
+ if (contrast === "high") element.setAttribute("data-contrast", "high");
541
+ else element.removeAttribute("data-contrast");
542
+ }
543
+ function resolveContrast(target) {
544
+ if (typeof document === "undefined") return "normal";
545
+ const element = target ?? document.documentElement;
546
+ return element.closest("[data-contrast='high']") ? "high" : "normal";
547
+ }
467
548
  function themeStyle(theme) {
468
549
  const out = {};
469
550
  for (const [name, value] of themeVariables(theme === "dark" ? dark : light)) {
@@ -541,6 +622,6 @@ function tailwindPreset() {
541
622
  };
542
623
  }
543
624
 
544
- export { CSS_PREFIX, applyTheme, blur, brand, breakpoint, dark, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, neutral, radius, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
625
+ export { CSS_PREFIX, applyContrast, applyTheme, blur, brand, breakpoint, dark, darkHighContrast, duration, easing, fontFamily, fontSize, fontWeight, generateCss, light, lightHighContrast, neutral, radius, resolveContrast, resolveTheme, shadow, space, status, structuralVariables, tailwindPreset, themeStyle, themeVariables, themes, tokens, zIndex };
545
626
  //# sourceMappingURL=index.js.map
546
627
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/primitives.ts","../src/semantic.ts","../src/css.ts","../src/index.ts"],"names":["tokens"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Primitive design tokens.\n *\n * These are the raw values — the vocabulary. Semantic tokens (in `semantic.ts`) map *meaning*\n * onto them, and that indirection is what makes theming possible: `--ansh-surface` can point\n * at `slate.50` in light mode and `slate.950` in dark mode without any component changing.\n *\n * Every scale here is derived from a rule rather than hand-picked, so extending it is\n * unambiguous and a designer can predict what step 9 looks like without checking.\n */\n\n/**\n * Spacing — an 8-point grid with half-steps below 8px.\n *\n * The half-steps matter: 8px is too coarse for optical adjustments like the gap between an icon\n * and its label, and every design system that omits them ends up with arbitrary one-off values.\n * Named by their pixel value at the default root size so `space[4]` is unambiguously 16px.\n */\nexport const space = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 3: '0.75rem', // 12px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 8: '2rem', // 32px\n 10: '2.5rem', // 40px\n 12: '3rem', // 48px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 32: '8rem', // 128px\n 40: '10rem', // 160px\n 48: '12rem', // 192px\n 56: '14rem', // 224px\n 64: '16rem', // 256px\n} as const\n\n/**\n * Typography — a modular scale at ratio 1.2 (minor third), rounded to sensible pixel values.\n *\n * 1.2 rather than the more common 1.25 or golden ratio: on the wide viewports these components\n * target, a steeper ratio makes display sizes enormous before the body sizes have room to\n * differentiate. 1.2 gives eight useful steps between 12px and 60px.\n *\n * Each step pairs a size with a line height, because a size without its leading is not a\n * typographic decision — and line height must *decrease* proportionally as size increases.\n */\nexport const fontSize = {\n xs: ['0.75rem', { lineHeight: '1.125rem', letterSpacing: '0.01em' }],\n sm: ['0.875rem', { lineHeight: '1.375rem', letterSpacing: '0.005em' }],\n base: ['1rem', { lineHeight: '1.625rem', letterSpacing: '0' }],\n lg: ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '-0.005em' }],\n xl: ['1.25rem', { lineHeight: '1.875rem', letterSpacing: '-0.01em' }],\n '2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.015em' }],\n '3xl': ['1.875rem', { lineHeight: '2.375rem', letterSpacing: '-0.02em' }],\n '4xl': ['2.25rem', { lineHeight: '2.625rem', letterSpacing: '-0.025em' }],\n '5xl': ['3rem', { lineHeight: '3.25rem', letterSpacing: '-0.03em' }],\n '6xl': ['3.75rem', { lineHeight: '3.9rem', letterSpacing: '-0.035em' }],\n '7xl': ['4.5rem', { lineHeight: '4.6rem', letterSpacing: '-0.04em' }],\n} as const satisfies Record<\n string,\n readonly [string, { lineHeight: string; letterSpacing: string }]\n>\n\nexport const fontWeight = {\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n} as const\n\nexport const fontFamily = {\n /**\n * The system UI stack. Deliberately not a webfont: the fastest, most legible text on any\n * platform is the font the user's OS already has loaded, and a design system should not force\n * a font decision on its consumers.\n */\n sans: [\n 'ui-sans-serif',\n 'system-ui',\n '-apple-system',\n 'BlinkMacSystemFont',\n 'Segoe UI',\n 'Roboto',\n 'Helvetica Neue',\n 'Arial',\n 'sans-serif',\n ].join(', '),\n mono: [\n 'ui-monospace',\n 'SFMono-Regular',\n 'Menlo',\n 'Monaco',\n 'Consolas',\n 'Liberation Mono',\n 'Courier New',\n 'monospace',\n ].join(', '),\n} as const\n\n/** Corner radii. `full` is a large fixed value rather than 50%, so pills stay pill-shaped. */\nexport const radius = {\n none: '0',\n xs: '0.25rem', // 4px\n sm: '0.375rem', // 6px\n md: '0.5rem', // 8px\n lg: '0.75rem', // 12px\n xl: '1rem', // 16px\n '2xl': '1.5rem', // 24px\n '3xl': '2rem', // 32px\n full: '9999px',\n} as const\n\n/**\n * Elevation — layered shadows, not single ones.\n *\n * A single `box-shadow` cannot describe real light: an object casts both a tight contact shadow\n * directly beneath it and a broader ambient shadow further out. Every step here composes both,\n * which is the difference between a card that sits on the page and one that looks pasted onto it.\n *\n * Shadow colour is a token so it can shift with the theme — a pure-black shadow on a dark\n * surface is invisible, so the dark theme uses a deeper, more spread variant.\n */\nexport const shadow = {\n none: 'none',\n xs: '0 1px 2px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n sm:\n '0 1px 3px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 1px 2px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n md:\n '0 4px 6px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 2px 4px -2px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n lg:\n '0 10px 15px -3px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 4px 6px -4px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n xl:\n '0 20px 25px -5px var(--ansh-shadow-color, rgb(15 23 42 / 0.1)), ' +\n '0 8px 10px -6px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n '2xl': '0 25px 50px -12px var(--ansh-shadow-color, rgb(15 23 42 / 0.2))',\n /** Inset — for pressed states and inputs. */\n inner: 'inset 0 2px 4px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n /**\n * Glow. Uses `currentColor` so a button's glow automatically matches its own accent without\n * the author repeating the colour.\n */\n glow: '0 0 24px -4px currentColor',\n glowLg: '0 0 48px -8px currentColor',\n} as const\n\n/** Backdrop blur steps, for glass surfaces. */\nexport const blur = {\n none: '0',\n xs: '2px',\n sm: '4px',\n md: '8px',\n lg: '16px',\n xl: '24px',\n '2xl': '40px',\n '3xl': '64px',\n} as const\n\n/**\n * Motion durations in seconds.\n *\n * Named by intent rather than by number. The values follow a rule of thumb that holds up well:\n * the distance travelled should determine the duration, so a tooltip appearing in place is\n * `instant`, a dropdown is `fast`, and a full-screen sheet is `slow`.\n */\nexport const duration = {\n instant: '0.1s',\n fast: '0.2s',\n normal: '0.3s',\n moderate: '0.45s',\n slow: '0.6s',\n slower: '0.9s',\n deliberate: '1.2s',\n} as const\n\n/**\n * CSS timing functions matching the engine's `signature` easings exactly.\n *\n * Keeping these in lockstep means a CSS transition and a JS animation on the same element move\n * identically — which matters more than it sounds, because mismatched curves on adjacent\n * elements is one of those things that reads as \"cheap\" without the viewer knowing why.\n */\nexport const easing = {\n linear: 'linear',\n standard: 'cubic-bezier(0.4, 0, 0.2, 1)',\n emphasized: 'cubic-bezier(0.22, 1, 0.36, 1)',\n enter: 'cubic-bezier(0, 0, 0.2, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n overshoot: 'cubic-bezier(0.34, 1.56, 0.64, 1)',\n cinematic: 'cubic-bezier(0.16, 1, 0.3, 1)',\n} as const\n\n/**\n * Z-index scale.\n *\n * Sparse, deliberate values with names. The alternative — `z-index: 9999` scattered through a\n * codebase — is the single most common source of stacking bugs in a component library.\n */\nexport const zIndex = {\n hide: '-1',\n base: '0',\n raised: '10',\n dropdown: '1000',\n sticky: '1100',\n overlay: '1200',\n modal: '1300',\n popover: '1400',\n toast: '1500',\n tooltip: '1600',\n /** Reserved for skip links and focus traps, which must beat everything. */\n max: '2147483647',\n} as const\n\n/** Breakpoints, matching the widths where real layout decisions occur. */\nexport const breakpoint = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n} as const\n\n/**\n * Neutral ramp, defined in OKLCH.\n *\n * Lightness steps are perceptually even, which a hex-defined grey ramp never is — the usual\n * result is a scale that looks well-spaced at the light end and bunched at the dark end. A slight\n * blue chroma (hue 264) keeps it from reading as muddy against saturated accents.\n */\nexport const neutral = {\n 50: 'oklch(98.5% 0.002 264)',\n 100: 'oklch(96.8% 0.004 264)',\n 200: 'oklch(92.9% 0.007 264)',\n 300: 'oklch(86.9% 0.011 264)',\n 400: 'oklch(70.7% 0.018 264)',\n 500: 'oklch(55.4% 0.022 264)',\n 600: 'oklch(44.6% 0.021 264)',\n 700: 'oklch(37.2% 0.019 264)',\n 800: 'oklch(27.9% 0.017 264)',\n 900: 'oklch(20.8% 0.015 264)',\n 950: 'oklch(13.8% 0.014 264)',\n 1000: 'oklch(8.5% 0.012 264)',\n} as const\n\n/** The Ansh brand ramp — the blue the library ships with. */\nexport const brand = {\n 50: 'oklch(97% 0.017 253)',\n 100: 'oklch(93.8% 0.036 253)',\n 200: 'oklch(88.5% 0.069 253)',\n 300: 'oklch(80.9% 0.111 253)',\n 400: 'oklch(71.4% 0.153 253)',\n 500: 'oklch(62.3% 0.188 253)',\n 600: 'oklch(54.6% 0.208 253)',\n 700: 'oklch(46.4% 0.192 253)',\n 800: 'oklch(39.1% 0.16 253)',\n 900: 'oklch(33.5% 0.129 253)',\n 950: 'oklch(23.2% 0.093 253)',\n} as const\n\n/** Status ramps. Only the steps that get used are defined, rather than a full 11 for each. */\nexport const status = {\n success: {\n subtle: 'oklch(95.5% 0.035 155)',\n default: 'oklch(58% 0.15 155)',\n strong: 'oklch(44% 0.12 155)',\n },\n warning: {\n subtle: 'oklch(96.5% 0.045 85)',\n default: 'oklch(72% 0.16 75)',\n strong: 'oklch(52% 0.13 65)',\n },\n danger: {\n subtle: 'oklch(95.5% 0.03 25)',\n default: 'oklch(58% 0.21 25)',\n strong: 'oklch(46% 0.18 25)',\n },\n info: {\n subtle: 'oklch(96% 0.025 240)',\n default: 'oklch(62% 0.17 245)',\n strong: 'oklch(48% 0.15 250)',\n },\n} as const\n","import { brand, neutral, shadow, status } from './primitives'\n\n/**\n * Semantic tokens — meaning mapped onto primitives.\n *\n * This layer is why theming works. A component references `surface.raised`, never `neutral.100`.\n * Switching to dark mode remaps `surface.raised` to `neutral.900`, and every component follows\n * without a single change. A component that reaches past this layer to a primitive is a bug: it\n * will look wrong in one theme and nobody will notice until a user reports it.\n *\n * The naming follows a consistent pattern:\n *\n * - `surface.*` — backgrounds, ordered by elevation\n * - `content.*` — text and icons, ordered by prominence\n * - `border.*` — dividers and outlines, ordered by strength\n * - `accent.*` — the interactive brand colour and its states\n * - `state.*` — success/warning/danger/info\n */\n\nexport interface SemanticTokens {\n surface: {\n /** The page background. */\n canvas: string\n /** Cards and panels sitting on the canvas. */\n raised: string\n /** Menus, popovers and anything floating above `raised`. */\n overlay: string\n /** Subtly recessed areas — code blocks, well insets. */\n sunken: string\n /** Translucent glass surface, for use with `backdrop-filter`. */\n glass: string\n /** The scrim behind a modal. */\n scrim: string\n }\n content: {\n /** Body text and headings. Must reach 7:1 against `surface.canvas`. */\n primary: string\n /** Supporting text. Must reach 4.5:1. */\n secondary: string\n /** De-emphasised text — timestamps, captions. Must reach 4.5:1 at ≥14px. */\n tertiary: string\n /** Placeholder and disabled text. Exempt from contrast minimums by WCAG. */\n disabled: string\n /** Text placed on top of `accent.default`. */\n onAccent: string\n /** Inverted text, for use on `content.primary` as a background. */\n inverse: string\n }\n border: {\n /** Hairline dividers. */\n subtle: string\n /** Input and card outlines. */\n default: string\n /** Hovered or emphasised outlines. */\n strong: string\n /** The focus ring. Must reach 3:1 against both adjacent surfaces. */\n focus: string\n }\n accent: {\n subtle: string\n muted: string\n default: string\n hover: string\n active: string\n /** For text and icons rendered in the accent colour on a neutral surface. */\n text: string\n }\n state: {\n successSubtle: string\n success: string\n warningSubtle: string\n warning: string\n dangerSubtle: string\n danger: string\n infoSubtle: string\n info: string\n }\n /** The shadow colour the elevation scale multiplies through. */\n shadowColor: string\n}\n\n/**\n * Light theme.\n *\n * Contrast ratios against `surface.canvas` (`neutral.50`):\n * `content.primary` → 15.8:1 (AAA)\n * `content.secondary` → 7.4:1 (AAA)\n * `content.tertiary` → 4.7:1 (AA)\n * `border.focus` → 3.4:1 (AA non-text)\n */\nexport const light: SemanticTokens = {\n surface: {\n canvas: neutral[50],\n raised: '#ffffff',\n overlay: '#ffffff',\n sunken: neutral[100],\n glass: 'oklch(100% 0 0 / 0.72)',\n scrim: 'oklch(20.8% 0.015 264 / 0.45)',\n },\n content: {\n primary: neutral[900],\n secondary: neutral[600],\n tertiary: neutral[500],\n disabled: neutral[400],\n onAccent: '#ffffff',\n inverse: neutral[50],\n },\n border: {\n subtle: neutral[200],\n default: neutral[300],\n strong: neutral[400],\n focus: brand[600],\n },\n accent: {\n subtle: brand[50],\n muted: brand[100],\n default: brand[600],\n hover: brand[700],\n active: brand[800],\n // A step darker than `default`: brand colours tuned to look right as a fill are usually too\n // light to pass contrast as text on a white surface.\n text: brand[700],\n },\n state: {\n successSubtle: status.success.subtle,\n success: status.success.strong,\n warningSubtle: status.warning.subtle,\n warning: status.warning.strong,\n dangerSubtle: status.danger.subtle,\n danger: status.danger.strong,\n infoSubtle: status.info.subtle,\n info: status.info.strong,\n },\n shadowColor: 'oklch(20.8% 0.015 264 / 0.08)',\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion of `light`. Three adjustments that a mechanical inversion misses:\n *\n * 1. **Surfaces get lighter as they rise, not darker.** In light mode, elevation is signalled by\n * shadow. On a dark background shadow is invisible, so elevation must be signalled by the\n * surface itself becoming lighter.\n * 2. **Chroma is raised.** Saturated colours read as less vivid against dark backgrounds\n * (Helmholtz–Kohlrausch), so accents step *lighter* rather than mirroring their light-mode step.\n * 3. **Body text is not pure white.** `#fff` on a near-black background causes halation — the\n * text appears to bleed. `neutral.100` reads as white while staying comfortable.\n */\nexport const dark: SemanticTokens = {\n surface: {\n canvas: neutral[1000],\n raised: neutral[950],\n overlay: neutral[900],\n sunken: 'oklch(6% 0.01 264)',\n glass: 'oklch(13.8% 0.014 264 / 0.68)',\n scrim: 'oklch(4% 0.008 264 / 0.65)',\n },\n content: {\n primary: neutral[100],\n secondary: neutral[300],\n tertiary: neutral[400],\n disabled: neutral[600],\n onAccent: '#ffffff',\n inverse: neutral[950],\n },\n border: {\n // Borders on dark surfaces work by being *lighter* than the surface, and need less contrast\n // than their light-mode counterparts to read as the same weight.\n subtle: 'oklch(100% 0 0 / 0.08)',\n default: 'oklch(100% 0 0 / 0.14)',\n strong: 'oklch(100% 0 0 / 0.24)',\n focus: brand[400],\n },\n accent: {\n subtle: 'oklch(23.2% 0.093 253 / 0.4)',\n muted: brand[950],\n default: brand[500],\n hover: brand[400],\n active: brand[300],\n text: brand[300],\n },\n state: {\n successSubtle: 'oklch(30% 0.08 155 / 0.35)',\n success: 'oklch(72% 0.16 155)',\n warningSubtle: 'oklch(32% 0.09 75 / 0.35)',\n warning: 'oklch(80% 0.15 80)',\n dangerSubtle: 'oklch(30% 0.11 25 / 0.35)',\n danger: 'oklch(70% 0.19 25)',\n infoSubtle: 'oklch(30% 0.09 245 / 0.35)',\n info: 'oklch(74% 0.15 245)',\n },\n // Deeper and more spread than light mode, since a dark shadow on a dark surface needs more\n // opacity to register at all.\n shadowColor: 'oklch(0% 0 0 / 0.5)',\n}\n\nexport const themes = { light, dark } as const\nexport type ThemeName = keyof typeof themes\n\n/** Re-exported so the CSS emitter can reference the elevation scale alongside the themes. */\nexport { shadow }\n","import {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\nimport { type SemanticTokens, dark, light } from './semantic'\n\n/**\n * CSS custom property generation.\n *\n * Tokens exist twice on purpose — as TypeScript values and as CSS variables — because the two\n * are consumed differently and neither can serve both jobs:\n *\n * - **TypeScript** values are needed where JavaScript computes with them: passing colours into\n * canvas effects, deriving palettes, computing contrast.\n * - **CSS variables** are needed for everything the cascade should own: theming a subtree,\n * respecting `prefers-color-scheme`, and letting a consumer override a token in their own\n * stylesheet without touching a build step.\n *\n * This module is the bridge, and it is generated from the same source of truth so the two can't\n * drift.\n */\n\nexport const CSS_PREFIX = 'ansh'\n\n/** Flatten a nested token object into `--prefix-path-to-key` variable declarations. */\nfunction flatten(target: Map<string, string>, value: unknown, path: readonly string[]): void {\n if (typeof value === 'string') {\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, value)\n return\n }\n if (Array.isArray(value)) {\n // Font size entries are `[size, { lineHeight, letterSpacing }]`. Emit each part under a\n // suffixed name so `--ansh-text-lg` and `--ansh-text-lg-leading` are both available.\n const [size, meta] = value as [string, Record<string, string> | undefined]\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, size)\n if (meta && typeof meta === 'object') {\n if (meta.lineHeight) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-leading`, meta.lineHeight)\n }\n if (meta.letterSpacing) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-tracking`, meta.letterSpacing)\n }\n }\n return\n }\n if (value && typeof value === 'object') {\n for (const [key, child] of Object.entries(value)) {\n flatten(target, child, [...path, cssSegment(key)])\n }\n }\n}\n\n/**\n * Convert a token key into a CSS-safe, CSS-conventional name segment.\n *\n * Two transformations, each fixing a real problem:\n *\n * - **Decimal points** (`space[0.5]`) are invalid in a custom property name, so they become\n * hyphens: `--ansh-space-0-5`.\n * - **camelCase** (`onAccent`, `successSubtle`) becomes kebab-case. CSS custom properties are\n * case-sensitive, and nobody writing CSS types `var(--ansh-content-onAccent)` — they type\n * `--ansh-content-on-accent`, get no error, and silently inherit the wrong colour. That\n * exact mismatch shipped in this library's own button styles: filled buttons fell back to the\n * inherited text colour, which is dark text on an accent fill.\n */\nfunction cssSegment(key: string): string {\n return key\n .replace('.', '-')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n\n/** Structural tokens — identical in every theme. */\nexport function structuralVariables(): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, space, ['space'])\n flatten(out, radius, ['radius'])\n flatten(out, shadow, ['shadow'])\n flatten(out, blur, ['blur'])\n flatten(out, duration, ['duration'])\n flatten(out, easing, ['ease'])\n flatten(out, zIndex, ['z'])\n flatten(out, fontSize, ['text'])\n flatten(out, fontWeight, ['weight'])\n flatten(out, fontFamily, ['font'])\n flatten(out, breakpoint, ['screen'])\n return out\n}\n\n/** Theme-dependent tokens for one theme. */\nexport function themeVariables(tokens: SemanticTokens): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, tokens.surface, ['surface'])\n flatten(out, tokens.content, ['content'])\n flatten(out, tokens.border, ['border'])\n flatten(out, tokens.accent, ['accent'])\n flatten(out, tokens.state, ['state'])\n out.set(`--${CSS_PREFIX}-shadow-color`, tokens.shadowColor)\n return out\n}\n\nfunction declarations(variables: Map<string, string>, indent = ' '): string {\n return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join('\\n')\n}\n\n/**\n * Emit the complete stylesheet.\n *\n * The theming strategy is deliberately layered so it works for every consumer:\n *\n * 1. `:root` carries the light theme, so the default works with no configuration.\n * 2. `@media (prefers-color-scheme: dark)` applies dark automatically — but *only* when the\n * document has not opted into manual control, guarded by `:root:not([data-theme])`. Without\n * that guard, a user who explicitly chose light mode in an app whose OS is dark would get dark\n * anyway, which is the single most common theming bug in the wild.\n * 3. `[data-theme='dark']` and `[data-theme='light']` allow explicit control at any level of the\n * tree, so a single dark card on a light page works with no extra plumbing.\n */\nexport function generateCss(): string {\n const structural = structuralVariables()\n const lightVars = themeVariables(light)\n const darkVars = themeVariables(dark)\n\n return `/**\n * Ansh design tokens.\n *\n * Generated from @ansh-ui/tokens — do not edit by hand.\n * Override any variable in your own stylesheet after importing this file.\n */\n\n:root {\n color-scheme: light dark;\n\n${declarations(structural)}\n\n${declarations(lightVars)}\n}\n\n/* Automatic dark mode, only when the document has not opted into manual control. */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n${declarations(darkVars, ' ')}\n }\n}\n\n/* Explicit theme control. Works at any level of the tree, not just :root. */\n[data-theme='dark'] {\n${declarations(darkVars)}\n}\n\n[data-theme='light'] {\n${declarations(lightVars)}\n}\n\n/**\n * Reduced-motion safety net.\n *\n * The engine honours \\`prefers-reduced-motion\\` in JavaScript, but any CSS transition or\n * animation an application author writes is outside its reach. Neutralising them here means a\n * consumer gets correct behaviour for their own styles too, simply by importing this file.\n *\n * Durations are set to 0.01ms rather than 0 so that \\`transitionend\\` and \\`animationend\\` still\n * fire — code that waits on those events would otherwise hang forever.\n */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/**\n * Utility classes for the split-text behaviour.\n *\n * The behaviour sets \\`--ansh-index\\` and \\`--ansh-total\\` on every unit, which makes a\n * staggered reveal possible in pure CSS with no JavaScript timing at all.\n */\n.ansh-char,\n.ansh-word,\n.ansh-line {\n display: inline-block;\n /* Required for transforms to apply to inline content, and for masks to clip descenders. */\n will-change: transform, opacity;\n}\n\n.ansh-mask {\n display: inline-block;\n overflow: hidden;\n vertical-align: top;\n}\n`\n}\n\n/**\n * Apply a theme imperatively.\n *\n * Sets `data-theme` on the target, which the stylesheet above already understands. Prefer this\n * over injecting inline styles: it keeps every token in one cascade layer and lets the browser\n * do the work.\n *\n * @param theme `'light'`, `'dark'`, or `'system'` to hand control back to `prefers-color-scheme`.\n * @param target Defaults to `document.documentElement`. Pass an element to theme a subtree.\n */\nexport function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (theme === 'system') element.removeAttribute('data-theme')\n else element.setAttribute('data-theme', theme)\n}\n\n/**\n * Read the currently applied theme.\n *\n * Resolves `'system'` to whichever theme is actually in effect, because callers generally want to\n * know what the user is *seeing*, not how it was configured.\n */\nexport function resolveTheme(target?: HTMLElement): 'light' | 'dark' {\n if (typeof document === 'undefined') return 'light'\n const element = target ?? document.documentElement\n const explicit = element.closest('[data-theme]')?.getAttribute('data-theme')\n if (explicit === 'dark' || explicit === 'light') return explicit\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\n/**\n * Build an inline `style` object for a subtree override.\n *\n * Used by framework `<ThemeProvider>` components that need to apply a theme before the stylesheet\n * has necessarily loaded — during SSR, most importantly, where a flash of the wrong theme is\n * otherwise unavoidable.\n */\nexport function themeStyle(theme: 'light' | 'dark'): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [name, value] of themeVariables(theme === 'dark' ? dark : light)) {\n out[name] = value\n }\n return out\n}\n","/**\n * @ansh-ui/tokens — the Ansh design language.\n *\n * Tokens are exported both as TypeScript values (for code that computes with them) and as CSS\n * custom properties (for everything the cascade should own). Both are generated from the same\n * source, so they cannot drift.\n *\n * ```ts\n * import '@ansh-ui/tokens/ansh.css'\n * import { space, applyTheme } from '@ansh-ui/tokens'\n * ```\n */\n\nexport * from './primitives'\nexport * from './semantic'\nexport * from './css'\n\nimport {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\n\n/**\n * Every structural token in one object.\n *\n * Convenient for a Tailwind preset or a styled-components theme, where the consumer wants the\n * whole scale rather than individual imports.\n */\nexport const tokens = {\n space,\n radius,\n shadow,\n blur,\n duration,\n easing,\n zIndex,\n fontSize,\n fontWeight,\n fontFamily,\n breakpoint,\n} as const\n\nexport type Tokens = typeof tokens\n\n/**\n * A Tailwind CSS preset that maps Ansh tokens onto Tailwind's theme keys.\n *\n * Returned as a plain object rather than importing Tailwind types, so this package stays free of a\n * Tailwind dependency for the majority of consumers who don't use it.\n *\n * ```js\n * // tailwind.config.js\n * import { tailwindPreset } from '@ansh-ui/tokens'\n * export default { presets: [tailwindPreset()] }\n * ```\n */\nexport function tailwindPreset() {\n return {\n theme: {\n extend: {\n spacing: space,\n borderRadius: radius,\n boxShadow: shadow,\n blur,\n fontFamily: { sans: [fontFamily.sans], mono: [fontFamily.mono] },\n fontSize,\n fontWeight,\n screens: breakpoint,\n zIndex,\n transitionDuration: Object.fromEntries(\n Object.entries(duration).map(([key, value]) => [key, value]),\n ),\n transitionTimingFunction: easing,\n // Semantic colours are wired to the CSS variables rather than to literal values, so a\n // Tailwind class like `bg-surface-raised` follows the active theme automatically.\n colors: {\n surface: {\n canvas: 'var(--ansh-surface-canvas)',\n raised: 'var(--ansh-surface-raised)',\n overlay: 'var(--ansh-surface-overlay)',\n sunken: 'var(--ansh-surface-sunken)',\n glass: 'var(--ansh-surface-glass)',\n },\n content: {\n primary: 'var(--ansh-content-primary)',\n secondary: 'var(--ansh-content-secondary)',\n tertiary: 'var(--ansh-content-tertiary)',\n disabled: 'var(--ansh-content-disabled)',\n 'on-accent': 'var(--ansh-content-on-accent)',\n inverse: 'var(--ansh-content-inverse)',\n },\n line: {\n subtle: 'var(--ansh-border-subtle)',\n DEFAULT: 'var(--ansh-border-default)',\n strong: 'var(--ansh-border-strong)',\n focus: 'var(--ansh-border-focus)',\n },\n accent: {\n subtle: 'var(--ansh-accent-subtle)',\n muted: 'var(--ansh-accent-muted)',\n DEFAULT: 'var(--ansh-accent-default)',\n hover: 'var(--ansh-accent-hover)',\n active: 'var(--ansh-accent-active)',\n text: 'var(--ansh-accent-text)',\n },\n },\n },\n },\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/primitives.ts","../src/semantic.ts","../src/css.ts","../src/index.ts"],"names":["tokens"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Primitive design tokens.\n *\n * These are the raw values — the vocabulary. Semantic tokens (in `semantic.ts`) map *meaning*\n * onto them, and that indirection is what makes theming possible: `--ansh-surface` can point\n * at `slate.50` in light mode and `slate.950` in dark mode without any component changing.\n *\n * Every scale here is derived from a rule rather than hand-picked, so extending it is\n * unambiguous and a designer can predict what step 9 looks like without checking.\n */\n\n/**\n * Spacing — an 8-point grid with half-steps below 8px.\n *\n * The half-steps matter: 8px is too coarse for optical adjustments like the gap between an icon\n * and its label, and every design system that omits them ends up with arbitrary one-off values.\n * Named by their pixel value at the default root size so `space[4]` is unambiguously 16px.\n */\nexport const space = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 3: '0.75rem', // 12px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 8: '2rem', // 32px\n 10: '2.5rem', // 40px\n 12: '3rem', // 48px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 32: '8rem', // 128px\n 40: '10rem', // 160px\n 48: '12rem', // 192px\n 56: '14rem', // 224px\n 64: '16rem', // 256px\n} as const\n\n/**\n * Typography — a modular scale at ratio 1.2 (minor third), rounded to sensible pixel values.\n *\n * 1.2 rather than the more common 1.25 or golden ratio: on the wide viewports these components\n * target, a steeper ratio makes display sizes enormous before the body sizes have room to\n * differentiate. 1.2 gives eight useful steps between 12px and 60px.\n *\n * Each step pairs a size with a line height, because a size without its leading is not a\n * typographic decision — and line height must *decrease* proportionally as size increases.\n */\nexport const fontSize = {\n xs: ['0.75rem', { lineHeight: '1.125rem', letterSpacing: '0.01em' }],\n sm: ['0.875rem', { lineHeight: '1.375rem', letterSpacing: '0.005em' }],\n base: ['1rem', { lineHeight: '1.625rem', letterSpacing: '0' }],\n lg: ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '-0.005em' }],\n xl: ['1.25rem', { lineHeight: '1.875rem', letterSpacing: '-0.01em' }],\n '2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '-0.015em' }],\n '3xl': ['1.875rem', { lineHeight: '2.375rem', letterSpacing: '-0.02em' }],\n '4xl': ['2.25rem', { lineHeight: '2.625rem', letterSpacing: '-0.025em' }],\n '5xl': ['3rem', { lineHeight: '3.25rem', letterSpacing: '-0.03em' }],\n '6xl': ['3.75rem', { lineHeight: '3.9rem', letterSpacing: '-0.035em' }],\n '7xl': ['4.5rem', { lineHeight: '4.6rem', letterSpacing: '-0.04em' }],\n} as const satisfies Record<\n string,\n readonly [string, { lineHeight: string; letterSpacing: string }]\n>\n\nexport const fontWeight = {\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n} as const\n\nexport const fontFamily = {\n /**\n * The system UI stack. Deliberately not a webfont: the fastest, most legible text on any\n * platform is the font the user's OS already has loaded, and a design system should not force\n * a font decision on its consumers.\n */\n sans: [\n 'ui-sans-serif',\n 'system-ui',\n '-apple-system',\n 'BlinkMacSystemFont',\n 'Segoe UI',\n 'Roboto',\n 'Helvetica Neue',\n 'Arial',\n 'sans-serif',\n ].join(', '),\n mono: [\n 'ui-monospace',\n 'SFMono-Regular',\n 'Menlo',\n 'Monaco',\n 'Consolas',\n 'Liberation Mono',\n 'Courier New',\n 'monospace',\n ].join(', '),\n} as const\n\n/** Corner radii. `full` is a large fixed value rather than 50%, so pills stay pill-shaped. */\nexport const radius = {\n none: '0',\n xs: '0.25rem', // 4px\n sm: '0.375rem', // 6px\n md: '0.5rem', // 8px\n lg: '0.75rem', // 12px\n xl: '1rem', // 16px\n '2xl': '1.5rem', // 24px\n '3xl': '2rem', // 32px\n full: '9999px',\n} as const\n\n/**\n * Elevation — layered shadows, not single ones.\n *\n * A single `box-shadow` cannot describe real light: an object casts both a tight contact shadow\n * directly beneath it and a broader ambient shadow further out. Every step here composes both,\n * which is the difference between a card that sits on the page and one that looks pasted onto it.\n *\n * Shadow colour is a token so it can shift with the theme — a pure-black shadow on a dark\n * surface is invisible, so the dark theme uses a deeper, more spread variant.\n */\nexport const shadow = {\n none: 'none',\n xs: '0 1px 2px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n sm:\n '0 1px 3px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 1px 2px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n md:\n '0 4px 6px -1px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 2px 4px -2px var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n lg:\n '0 10px 15px -3px var(--ansh-shadow-color, rgb(15 23 42 / 0.08)), ' +\n '0 4px 6px -4px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n xl:\n '0 20px 25px -5px var(--ansh-shadow-color, rgb(15 23 42 / 0.1)), ' +\n '0 8px 10px -6px var(--ansh-shadow-color, rgb(15 23 42 / 0.05))',\n '2xl': '0 25px 50px -12px var(--ansh-shadow-color, rgb(15 23 42 / 0.2))',\n /** Inset — for pressed states and inputs. */\n inner: 'inset 0 2px 4px 0 var(--ansh-shadow-color, rgb(15 23 42 / 0.06))',\n /**\n * Glow. Uses `currentColor` so a button's glow automatically matches its own accent without\n * the author repeating the colour.\n */\n glow: '0 0 24px -4px currentColor',\n glowLg: '0 0 48px -8px currentColor',\n} as const\n\n/** Backdrop blur steps, for glass surfaces. */\nexport const blur = {\n none: '0',\n xs: '2px',\n sm: '4px',\n md: '8px',\n lg: '16px',\n xl: '24px',\n '2xl': '40px',\n '3xl': '64px',\n} as const\n\n/**\n * Motion durations in seconds.\n *\n * Named by intent rather than by number. The values follow a rule of thumb that holds up well:\n * the distance travelled should determine the duration, so a tooltip appearing in place is\n * `instant`, a dropdown is `fast`, and a full-screen sheet is `slow`.\n */\nexport const duration = {\n instant: '0.1s',\n fast: '0.2s',\n normal: '0.3s',\n moderate: '0.45s',\n slow: '0.6s',\n slower: '0.9s',\n deliberate: '1.2s',\n} as const\n\n/**\n * CSS timing functions matching the engine's `signature` easings exactly.\n *\n * Keeping these in lockstep means a CSS transition and a JS animation on the same element move\n * identically — which matters more than it sounds, because mismatched curves on adjacent\n * elements is one of those things that reads as \"cheap\" without the viewer knowing why.\n */\nexport const easing = {\n linear: 'linear',\n standard: 'cubic-bezier(0.4, 0, 0.2, 1)',\n emphasized: 'cubic-bezier(0.22, 1, 0.36, 1)',\n enter: 'cubic-bezier(0, 0, 0.2, 1)',\n exit: 'cubic-bezier(0.4, 0, 1, 1)',\n overshoot: 'cubic-bezier(0.34, 1.56, 0.64, 1)',\n cinematic: 'cubic-bezier(0.16, 1, 0.3, 1)',\n} as const\n\n/**\n * Z-index scale.\n *\n * Sparse, deliberate values with names. The alternative — `z-index: 9999` scattered through a\n * codebase — is the single most common source of stacking bugs in a component library.\n */\nexport const zIndex = {\n hide: '-1',\n base: '0',\n raised: '10',\n dropdown: '1000',\n sticky: '1100',\n overlay: '1200',\n modal: '1300',\n popover: '1400',\n toast: '1500',\n tooltip: '1600',\n /** Reserved for skip links and focus traps, which must beat everything. */\n max: '2147483647',\n} as const\n\n/** Breakpoints, matching the widths where real layout decisions occur. */\nexport const breakpoint = {\n sm: '640px',\n md: '768px',\n lg: '1024px',\n xl: '1280px',\n '2xl': '1536px',\n} as const\n\n/**\n * Neutral ramp, defined in OKLCH.\n *\n * Lightness steps are perceptually even, which a hex-defined grey ramp never is — the usual\n * result is a scale that looks well-spaced at the light end and bunched at the dark end. A slight\n * blue chroma (hue 264) keeps it from reading as muddy against saturated accents.\n */\nexport const neutral = {\n 50: 'oklch(98.5% 0.002 264)',\n 100: 'oklch(96.8% 0.004 264)',\n 200: 'oklch(92.9% 0.007 264)',\n 300: 'oklch(86.9% 0.011 264)',\n 400: 'oklch(70.7% 0.018 264)',\n 500: 'oklch(55.4% 0.022 264)',\n 600: 'oklch(44.6% 0.021 264)',\n 700: 'oklch(37.2% 0.019 264)',\n 800: 'oklch(27.9% 0.017 264)',\n 900: 'oklch(20.8% 0.015 264)',\n 950: 'oklch(13.8% 0.014 264)',\n 1000: 'oklch(8.5% 0.012 264)',\n} as const\n\n/** The Ansh brand ramp — the blue the library ships with. */\nexport const brand = {\n 50: 'oklch(97% 0.017 253)',\n 100: 'oklch(93.8% 0.036 253)',\n 200: 'oklch(88.5% 0.069 253)',\n 300: 'oklch(80.9% 0.111 253)',\n 400: 'oklch(71.4% 0.153 253)',\n 500: 'oklch(62.3% 0.188 253)',\n 600: 'oklch(54.6% 0.208 253)',\n 700: 'oklch(46.4% 0.192 253)',\n 800: 'oklch(39.1% 0.16 253)',\n 900: 'oklch(33.5% 0.129 253)',\n 950: 'oklch(23.2% 0.093 253)',\n} as const\n\n/** Status ramps. Only the steps that get used are defined, rather than a full 11 for each. */\nexport const status = {\n success: {\n subtle: 'oklch(95.5% 0.035 155)',\n default: 'oklch(58% 0.15 155)',\n strong: 'oklch(44% 0.12 155)',\n },\n warning: {\n subtle: 'oklch(96.5% 0.045 85)',\n default: 'oklch(72% 0.16 75)',\n strong: 'oklch(52% 0.13 65)',\n },\n danger: {\n subtle: 'oklch(95.5% 0.03 25)',\n default: 'oklch(58% 0.21 25)',\n strong: 'oklch(46% 0.18 25)',\n },\n info: {\n subtle: 'oklch(96% 0.025 240)',\n default: 'oklch(62% 0.17 245)',\n strong: 'oklch(48% 0.15 250)',\n },\n} as const\n","import { brand, neutral, shadow, status } from './primitives'\n\n/**\n * Semantic tokens — meaning mapped onto primitives.\n *\n * This layer is why theming works. A component references `surface.raised`, never `neutral.100`.\n * Switching to dark mode remaps `surface.raised` to `neutral.900`, and every component follows\n * without a single change. A component that reaches past this layer to a primitive is a bug: it\n * will look wrong in one theme and nobody will notice until a user reports it.\n *\n * The naming follows a consistent pattern:\n *\n * - `surface.*` — backgrounds, ordered by elevation\n * - `content.*` — text and icons, ordered by prominence\n * - `border.*` — dividers and outlines, ordered by strength\n * - `accent.*` — the interactive brand colour and its states\n * - `state.*` — success/warning/danger/info\n */\n\nexport interface SemanticTokens {\n surface: {\n /** The page background. */\n canvas: string\n /** Cards and panels sitting on the canvas. */\n raised: string\n /** Menus, popovers and anything floating above `raised`. */\n overlay: string\n /** Subtly recessed areas — code blocks, well insets. */\n sunken: string\n /** Translucent glass surface, for use with `backdrop-filter`. */\n glass: string\n /** The scrim behind a modal. */\n scrim: string\n }\n content: {\n /** Body text and headings. Must reach 7:1 against `surface.canvas`. */\n primary: string\n /** Supporting text. Must reach 4.5:1. */\n secondary: string\n /** De-emphasised text — timestamps, captions. Must reach 4.5:1 at ≥14px. */\n tertiary: string\n /** Placeholder and disabled text. Exempt from contrast minimums by WCAG. */\n disabled: string\n /** Text placed on top of `accent.default`. */\n onAccent: string\n /** Inverted text, for use on `content.primary` as a background. */\n inverse: string\n }\n border: {\n /** Hairline dividers. */\n subtle: string\n /** Input and card outlines. */\n default: string\n /** Hovered or emphasised outlines. */\n strong: string\n /** The focus ring. Must reach 3:1 against both adjacent surfaces. */\n focus: string\n }\n accent: {\n subtle: string\n muted: string\n default: string\n hover: string\n active: string\n /** For text and icons rendered in the accent colour on a neutral surface. */\n text: string\n }\n state: {\n successSubtle: string\n success: string\n warningSubtle: string\n warning: string\n dangerSubtle: string\n danger: string\n infoSubtle: string\n info: string\n }\n /** The shadow colour the elevation scale multiplies through. */\n shadowColor: string\n}\n\n/**\n * Light theme.\n *\n * Contrast ratios against `surface.canvas` (`neutral.50`):\n * `content.primary` → 15.8:1 (AAA)\n * `content.secondary` → 7.4:1 (AAA)\n * `content.tertiary` → 4.7:1 (AA)\n * `border.focus` → 3.4:1 (AA non-text)\n */\nexport const light: SemanticTokens = {\n surface: {\n canvas: neutral[50],\n raised: '#ffffff',\n overlay: '#ffffff',\n sunken: neutral[100],\n glass: 'oklch(100% 0 0 / 0.72)',\n scrim: 'oklch(20.8% 0.015 264 / 0.45)',\n },\n content: {\n primary: neutral[900],\n secondary: neutral[600],\n tertiary: neutral[500],\n disabled: neutral[400],\n onAccent: '#ffffff',\n inverse: neutral[50],\n },\n border: {\n subtle: neutral[200],\n default: neutral[300],\n strong: neutral[400],\n focus: brand[600],\n },\n accent: {\n subtle: brand[50],\n muted: brand[100],\n default: brand[600],\n hover: brand[700],\n active: brand[800],\n // A step darker than `default`: brand colours tuned to look right as a fill are usually too\n // light to pass contrast as text on a white surface.\n text: brand[700],\n },\n state: {\n successSubtle: status.success.subtle,\n success: status.success.strong,\n warningSubtle: status.warning.subtle,\n warning: status.warning.strong,\n dangerSubtle: status.danger.subtle,\n danger: status.danger.strong,\n infoSubtle: status.info.subtle,\n info: status.info.strong,\n },\n shadowColor: 'oklch(20.8% 0.015 264 / 0.08)',\n}\n\n/**\n * Dark theme.\n *\n * Not an inversion of `light`. Three adjustments that a mechanical inversion misses:\n *\n * 1. **Surfaces get lighter as they rise, not darker.** In light mode, elevation is signalled by\n * shadow. On a dark background shadow is invisible, so elevation must be signalled by the\n * surface itself becoming lighter.\n * 2. **Chroma is raised.** Saturated colours read as less vivid against dark backgrounds\n * (Helmholtz–Kohlrausch), so accents step *lighter* rather than mirroring their light-mode step.\n * 3. **Body text is not pure white.** `#fff` on a near-black background causes halation — the\n * text appears to bleed. `neutral.100` reads as white while staying comfortable.\n */\nexport const dark: SemanticTokens = {\n surface: {\n canvas: neutral[1000],\n raised: neutral[950],\n overlay: neutral[900],\n sunken: 'oklch(6% 0.01 264)',\n glass: 'oklch(13.8% 0.014 264 / 0.68)',\n scrim: 'oklch(4% 0.008 264 / 0.65)',\n },\n content: {\n primary: neutral[100],\n secondary: neutral[300],\n tertiary: neutral[400],\n disabled: neutral[600],\n onAccent: '#ffffff',\n inverse: neutral[950],\n },\n border: {\n // Borders on dark surfaces work by being *lighter* than the surface, and need less contrast\n // than their light-mode counterparts to read as the same weight.\n subtle: 'oklch(100% 0 0 / 0.08)',\n default: 'oklch(100% 0 0 / 0.14)',\n strong: 'oklch(100% 0 0 / 0.24)',\n focus: brand[400],\n },\n accent: {\n subtle: 'oklch(23.2% 0.093 253 / 0.4)',\n muted: brand[950],\n default: brand[500],\n hover: brand[400],\n active: brand[300],\n text: brand[300],\n },\n state: {\n successSubtle: 'oklch(30% 0.08 155 / 0.35)',\n success: 'oklch(72% 0.16 155)',\n warningSubtle: 'oklch(32% 0.09 75 / 0.35)',\n warning: 'oklch(80% 0.15 80)',\n dangerSubtle: 'oklch(30% 0.11 25 / 0.35)',\n danger: 'oklch(70% 0.19 25)',\n infoSubtle: 'oklch(30% 0.09 245 / 0.35)',\n info: 'oklch(74% 0.15 245)',\n },\n // Deeper and more spread than light mode, since a dark shadow on a dark surface needs more\n // opacity to register at all.\n shadowColor: 'oklch(0% 0 0 / 0.5)',\n}\n\nexport const themes = { light, dark } as const\nexport type ThemeName = keyof typeof themes\n\n/**\n * High-contrast overrides, layered on top of a base theme rather than a theme of their own.\n *\n * Only `content` and `border` change. `accent`, `state`, and `surface` are left alone: they were\n * already tuned against the documented minimums (`content.secondary` at 4.5:1, etc. — see the\n * field comments on `SemanticTokens` above), and re-deriving a whole second brand ramp for this\n * would be a bigger, riskier change than what high-contrast mode is actually for — text and\n * structure that's easy to misread at the *edges* of the existing palette (secondary/tertiary\n * text, subtle borders), not a different colour scheme.\n */\nexport type ContrastOverride = Pick<SemanticTokens, 'content' | 'border'>\n\nexport const lightHighContrast: ContrastOverride = {\n content: {\n ...light.content,\n secondary: neutral[800],\n tertiary: neutral[700],\n },\n border: {\n ...light.border,\n subtle: neutral[400],\n default: neutral[500],\n strong: neutral[700],\n },\n}\n\nexport const darkHighContrast: ContrastOverride = {\n content: {\n ...dark.content,\n secondary: neutral[100],\n tertiary: neutral[200],\n },\n border: {\n ...dark.border,\n subtle: 'oklch(100% 0 0 / 0.24)',\n default: 'oklch(100% 0 0 / 0.35)',\n strong: 'oklch(100% 0 0 / 0.5)',\n },\n}\n\n/** Re-exported so the CSS emitter can reference the elevation scale alongside the themes. */\nexport { shadow }\n","import {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\nimport {\n type ContrastOverride,\n type SemanticTokens,\n dark,\n darkHighContrast,\n light,\n lightHighContrast,\n} from './semantic'\n\n/**\n * CSS custom property generation.\n *\n * Tokens exist twice on purpose — as TypeScript values and as CSS variables — because the two\n * are consumed differently and neither can serve both jobs:\n *\n * - **TypeScript** values are needed where JavaScript computes with them: passing colours into\n * canvas effects, deriving palettes, computing contrast.\n * - **CSS variables** are needed for everything the cascade should own: theming a subtree,\n * respecting `prefers-color-scheme`, and letting a consumer override a token in their own\n * stylesheet without touching a build step.\n *\n * This module is the bridge, and it is generated from the same source of truth so the two can't\n * drift.\n */\n\nexport const CSS_PREFIX = 'ansh'\n\n/** Flatten a nested token object into `--prefix-path-to-key` variable declarations. */\nfunction flatten(target: Map<string, string>, value: unknown, path: readonly string[]): void {\n if (typeof value === 'string') {\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, value)\n return\n }\n if (Array.isArray(value)) {\n // Font size entries are `[size, { lineHeight, letterSpacing }]`. Emit each part under a\n // suffixed name so `--ansh-text-lg` and `--ansh-text-lg-leading` are both available.\n const [size, meta] = value as [string, Record<string, string> | undefined]\n target.set(`--${CSS_PREFIX}-${path.join('-')}`, size)\n if (meta && typeof meta === 'object') {\n if (meta.lineHeight) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-leading`, meta.lineHeight)\n }\n if (meta.letterSpacing) {\n target.set(`--${CSS_PREFIX}-${path.join('-')}-tracking`, meta.letterSpacing)\n }\n }\n return\n }\n if (value && typeof value === 'object') {\n for (const [key, child] of Object.entries(value)) {\n flatten(target, child, [...path, cssSegment(key)])\n }\n }\n}\n\n/**\n * Convert a token key into a CSS-safe, CSS-conventional name segment.\n *\n * Two transformations, each fixing a real problem:\n *\n * - **Decimal points** (`space[0.5]`) are invalid in a custom property name, so they become\n * hyphens: `--ansh-space-0-5`.\n * - **camelCase** (`onAccent`, `successSubtle`) becomes kebab-case. CSS custom properties are\n * case-sensitive, and nobody writing CSS types `var(--ansh-content-onAccent)` — they type\n * `--ansh-content-on-accent`, get no error, and silently inherit the wrong colour. That\n * exact mismatch shipped in this library's own button styles: filled buttons fell back to the\n * inherited text colour, which is dark text on an accent fill.\n */\nfunction cssSegment(key: string): string {\n return key\n .replace('.', '-')\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .toLowerCase()\n}\n\n/** Structural tokens — identical in every theme. */\nexport function structuralVariables(): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, space, ['space'])\n flatten(out, radius, ['radius'])\n flatten(out, shadow, ['shadow'])\n flatten(out, blur, ['blur'])\n flatten(out, duration, ['duration'])\n flatten(out, easing, ['ease'])\n flatten(out, zIndex, ['z'])\n flatten(out, fontSize, ['text'])\n flatten(out, fontWeight, ['weight'])\n flatten(out, fontFamily, ['font'])\n flatten(out, breakpoint, ['screen'])\n return out\n}\n\n/** Theme-dependent tokens for one theme. */\nexport function themeVariables(tokens: SemanticTokens): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, tokens.surface, ['surface'])\n flatten(out, tokens.content, ['content'])\n flatten(out, tokens.border, ['border'])\n flatten(out, tokens.accent, ['accent'])\n flatten(out, tokens.state, ['state'])\n out.set(`--${CSS_PREFIX}-shadow-color`, tokens.shadowColor)\n return out\n}\n\n/** Contrast-override tokens — only the `content` and `border` subset that high-contrast changes. */\nfunction contrastVariables(override: ContrastOverride): Map<string, string> {\n const out = new Map<string, string>()\n flatten(out, override.content, ['content'])\n flatten(out, override.border, ['border'])\n return out\n}\n\nfunction declarations(variables: Map<string, string>, indent = ' '): string {\n return [...variables].map(([name, value]) => `${indent}${name}: ${value};`).join('\\n')\n}\n\n/**\n * Emit the complete stylesheet.\n *\n * The theming strategy is deliberately layered so it works for every consumer:\n *\n * 1. `:root` carries the light theme, so the default works with no configuration.\n * 2. `@media (prefers-color-scheme: dark)` applies dark automatically — but *only* when the\n * document has not opted into manual control, guarded by `:root:not([data-theme])`. Without\n * that guard, a user who explicitly chose light mode in an app whose OS is dark would get dark\n * anyway, which is the single most common theming bug in the wild.\n * 3. `[data-theme='dark']` and `[data-theme='light']` allow explicit control at any level of the\n * tree, so a single dark card on a light page works with no extra plumbing.\n */\nexport function generateCss(): string {\n const structural = structuralVariables()\n const lightVars = themeVariables(light)\n const darkVars = themeVariables(dark)\n const lightContrastVars = contrastVariables(lightHighContrast)\n const darkContrastVars = contrastVariables(darkHighContrast)\n\n return `/**\n * Ansh design tokens.\n *\n * Generated from @ansh-ui/tokens — do not edit by hand.\n * Override any variable in your own stylesheet after importing this file.\n */\n\n:root {\n color-scheme: light dark;\n\n${declarations(structural)}\n\n${declarations(lightVars)}\n}\n\n/* Automatic dark mode, only when the document has not opted into manual control. */\n@media (prefers-color-scheme: dark) {\n :root:not([data-theme]) {\n${declarations(darkVars, ' ')}\n }\n}\n\n/* Explicit theme control. Works at any level of the tree, not just :root. */\n[data-theme='dark'] {\n${declarations(darkVars)}\n}\n\n[data-theme='light'] {\n${declarations(lightVars)}\n}\n\n/**\n * High-contrast mode, layered on top of whichever theme is active — not a fifth theme, an\n * override of \\`content\\` and \\`border\\` only (see \\`ContrastOverride\\` in semantic.ts for why those\n * two and not the whole palette). Mirrors the theme cascade immediately above it: system\n * preference by default, explicit \\`[data-theme]\\` wins when set.\n *\n * The light rule must come *before* the dark media block below, not after: both target the same\n * \\`[data-contrast='high']:not([data-theme])\\` selector (identical specificity), so when the system\n * prefers dark and no theme is set explicitly, only source order decides which wins — exactly the\n * same reason the light/dark theme rules above are ordered the way they are.\n */\n[data-contrast='high']:not([data-theme]) {\n${declarations(lightContrastVars)}\n}\n\n@media (prefers-color-scheme: dark) {\n [data-contrast='high']:not([data-theme]) {\n${declarations(darkContrastVars, ' ')}\n }\n}\n\n[data-theme='dark'][data-contrast='high'] {\n${declarations(darkContrastVars)}\n}\n\n[data-theme='light'][data-contrast='high'] {\n${declarations(lightContrastVars)}\n}\n\n/* A token alone can't widen an outline. Every consumer's :focus-visible rule reads\n --ansh-border-focus already; high contrast also needs the ring itself to be harder to miss. */\n[data-contrast='high'] :focus-visible {\n outline-width: 3px;\n outline-offset: 3px;\n}\n\n/**\n * Reduced-motion safety net.\n *\n * The engine honours \\`prefers-reduced-motion\\` in JavaScript, but any CSS transition or\n * animation an application author writes is outside its reach. Neutralising them here means a\n * consumer gets correct behaviour for their own styles too, simply by importing this file.\n *\n * Durations are set to 0.01ms rather than 0 so that \\`transitionend\\` and \\`animationend\\` still\n * fire — code that waits on those events would otherwise hang forever.\n */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n\n/**\n * Utility classes for the split-text behaviour.\n *\n * The behaviour sets \\`--ansh-index\\` and \\`--ansh-total\\` on every unit, which makes a\n * staggered reveal possible in pure CSS with no JavaScript timing at all.\n */\n.ansh-char,\n.ansh-word,\n.ansh-line {\n display: inline-block;\n /* Required for transforms to apply to inline content, and for masks to clip descenders. */\n will-change: transform, opacity;\n}\n\n.ansh-mask {\n display: inline-block;\n overflow: hidden;\n vertical-align: top;\n}\n`\n}\n\n/**\n * Apply a theme imperatively.\n *\n * Sets `data-theme` on the target, which the stylesheet above already understands. Prefer this\n * over injecting inline styles: it keeps every token in one cascade layer and lets the browser\n * do the work.\n *\n * @param theme `'light'`, `'dark'`, or `'system'` to hand control back to `prefers-color-scheme`.\n * @param target Defaults to `document.documentElement`. Pass an element to theme a subtree.\n */\nexport function applyTheme(theme: 'light' | 'dark' | 'system', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (theme === 'system') element.removeAttribute('data-theme')\n else element.setAttribute('data-theme', theme)\n}\n\n/**\n * Read the currently applied theme.\n *\n * Resolves `'system'` to whichever theme is actually in effect, because callers generally want to\n * know what the user is *seeing*, not how it was configured.\n */\nexport function resolveTheme(target?: HTMLElement): 'light' | 'dark' {\n if (typeof document === 'undefined') return 'light'\n const element = target ?? document.documentElement\n const explicit = element.closest('[data-theme]')?.getAttribute('data-theme')\n if (explicit === 'dark' || explicit === 'light') return explicit\n return typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n}\n\n/**\n * Apply or clear high-contrast mode imperatively — the `content`/`border` override described on\n * `ContrastOverride`, layered on whichever theme is already active via `applyTheme`.\n *\n * @param contrast `'high'` or `'normal'`.\n * @param target Defaults to `document.documentElement`. Pass an element to scope a subtree.\n */\nexport function applyContrast(contrast: 'high' | 'normal', target?: HTMLElement): void {\n if (typeof document === 'undefined') return\n const element = target ?? document.documentElement\n if (contrast === 'high') element.setAttribute('data-contrast', 'high')\n else element.removeAttribute('data-contrast')\n}\n\n/** Read whether high-contrast mode is currently applied, at or above `target`. */\nexport function resolveContrast(target?: HTMLElement): 'high' | 'normal' {\n if (typeof document === 'undefined') return 'normal'\n const element = target ?? document.documentElement\n return element.closest(\"[data-contrast='high']\") ? 'high' : 'normal'\n}\n\n/**\n * Build an inline `style` object for a subtree override.\n *\n * Used by framework `<ThemeProvider>` components that need to apply a theme before the stylesheet\n * has necessarily loaded — during SSR, most importantly, where a flash of the wrong theme is\n * otherwise unavoidable.\n */\nexport function themeStyle(theme: 'light' | 'dark'): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [name, value] of themeVariables(theme === 'dark' ? dark : light)) {\n out[name] = value\n }\n return out\n}\n","/**\n * @ansh-ui/tokens — the Ansh design language.\n *\n * Tokens are exported both as TypeScript values (for code that computes with them) and as CSS\n * custom properties (for everything the cascade should own). Both are generated from the same\n * source, so they cannot drift.\n *\n * ```ts\n * import '@ansh-ui/tokens/ansh.css'\n * import { space, applyTheme } from '@ansh-ui/tokens'\n * ```\n */\n\nexport * from './primitives'\nexport * from './semantic'\nexport * from './css'\n\nimport {\n blur,\n breakpoint,\n duration,\n easing,\n fontFamily,\n fontSize,\n fontWeight,\n radius,\n shadow,\n space,\n zIndex,\n} from './primitives'\n\n/**\n * Every structural token in one object.\n *\n * Convenient for a Tailwind preset or a styled-components theme, where the consumer wants the\n * whole scale rather than individual imports.\n */\nexport const tokens = {\n space,\n radius,\n shadow,\n blur,\n duration,\n easing,\n zIndex,\n fontSize,\n fontWeight,\n fontFamily,\n breakpoint,\n} as const\n\nexport type Tokens = typeof tokens\n\n/**\n * A Tailwind CSS preset that maps Ansh tokens onto Tailwind's theme keys.\n *\n * Returned as a plain object rather than importing Tailwind types, so this package stays free of a\n * Tailwind dependency for the majority of consumers who don't use it.\n *\n * ```js\n * // tailwind.config.js\n * import { tailwindPreset } from '@ansh-ui/tokens'\n * export default { presets: [tailwindPreset()] }\n * ```\n */\nexport function tailwindPreset() {\n return {\n theme: {\n extend: {\n spacing: space,\n borderRadius: radius,\n boxShadow: shadow,\n blur,\n fontFamily: { sans: [fontFamily.sans], mono: [fontFamily.mono] },\n fontSize,\n fontWeight,\n screens: breakpoint,\n zIndex,\n transitionDuration: Object.fromEntries(\n Object.entries(duration).map(([key, value]) => [key, value]),\n ),\n transitionTimingFunction: easing,\n // Semantic colours are wired to the CSS variables rather than to literal values, so a\n // Tailwind class like `bg-surface-raised` follows the active theme automatically.\n colors: {\n surface: {\n canvas: 'var(--ansh-surface-canvas)',\n raised: 'var(--ansh-surface-raised)',\n overlay: 'var(--ansh-surface-overlay)',\n sunken: 'var(--ansh-surface-sunken)',\n glass: 'var(--ansh-surface-glass)',\n },\n content: {\n primary: 'var(--ansh-content-primary)',\n secondary: 'var(--ansh-content-secondary)',\n tertiary: 'var(--ansh-content-tertiary)',\n disabled: 'var(--ansh-content-disabled)',\n 'on-accent': 'var(--ansh-content-on-accent)',\n inverse: 'var(--ansh-content-inverse)',\n },\n line: {\n subtle: 'var(--ansh-border-subtle)',\n DEFAULT: 'var(--ansh-border-default)',\n strong: 'var(--ansh-border-strong)',\n focus: 'var(--ansh-border-focus)',\n },\n accent: {\n subtle: 'var(--ansh-accent-subtle)',\n muted: 'var(--ansh-accent-muted)',\n DEFAULT: 'var(--ansh-accent-default)',\n hover: 'var(--ansh-accent-hover)',\n active: 'var(--ansh-accent-active)',\n text: 'var(--ansh-accent-text)',\n },\n },\n },\n },\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ansh-ui/tokens",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Ansh design tokens — spacing, typography, elevation, motion and colour, as TypeScript and CSS custom properties.",
5
5
  "license": "MIT",
6
6
  "type": "module",