@loidolt/theme-tokens 0.7.0 → 0.8.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/index.js CHANGED
@@ -1,47 +1,4 @@
1
- // src/contrast.ts
2
- var contrastRequirements = {
3
- AA: { normal: 4.5, large: 3 },
4
- AAA: { normal: 7, large: 4.5 }
5
- };
6
- var channels = (hex, caller) => {
7
- const match = /^#?([\da-f]{3}|[\da-f]{6})$/i.exec(hex.trim());
8
- if (!match) throw new RangeError(`${caller}: invalid hex colour ${JSON.stringify(hex)}`);
9
- const digits = match[1].length === 3 ? [...match[1]].map((digit) => digit + digit).join("") : match[1];
10
- return [0, 2, 4].map((index) => parseInt(digits.slice(index, index + 2), 16));
11
- };
12
- var luminanceOf = (hex, caller) => {
13
- const [r, g, b] = channels(hex, caller).map((channel) => channel / 255).map((channel) => channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4);
14
- return 0.2126 * r + 0.7152 * g + 0.0722 * b;
15
- };
16
- function getLuminance(hex) {
17
- return luminanceOf(hex, "getLuminance");
18
- }
19
- function getContrastRatio(foreground, background) {
20
- const [high, low] = [
21
- luminanceOf(foreground, "getContrastRatio"),
22
- luminanceOf(background, "getContrastRatio")
23
- ].sort((a, b) => b - a);
24
- return (high + 0.05) / (low + 0.05);
25
- }
26
- function meetsContrast(foreground, background, { level = "AA", size = "normal" } = {}) {
27
- return getContrastRatio(foreground, background) >= contrastRequirements[level][size];
28
- }
29
- function validateContrast(foreground, background) {
30
- const ratio = getContrastRatio(foreground, background);
31
- return {
32
- ratio,
33
- ratioString: `${ratio.toFixed(2)}:1`,
34
- passesAANormal: ratio >= contrastRequirements.AA.normal,
35
- passesAALarge: ratio >= contrastRequirements.AA.large,
36
- passesAAANormal: ratio >= contrastRequirements.AAA.normal,
37
- passesAAALarge: ratio >= contrastRequirements.AAA.large
38
- };
39
- }
40
- function getContrastTextColor(background, { dark = "#20231d", light = "#f5f2e9" } = {}) {
41
- return getContrastRatio(dark, background) >= getContrastRatio(light, background) ? dark : light;
42
- }
43
-
44
- // src/index.ts
1
+ // src/tokens.ts
45
2
  var ref = (name) => ({ $ref: `--loidolt-${name}` });
46
3
  var isRef = (value) => typeof value === "object" && value !== null && "$ref" in value;
47
4
  var kebab = (value) => value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`).replace(/([a-z])(\d)/g, "$1-$2");
@@ -281,6 +238,61 @@ var semanticDefs = {
281
238
  syntaxParameter: ref("color-syntax-parameter"),
282
239
  syntaxPunctuation: ref("color-syntax-punctuation")
283
240
  };
241
+ var roleDefs = {
242
+ /** Buttons, boxed fields, toggle groups, switches, swatches, tooltips. */
243
+ radiusControl: ref("border-radius"),
244
+ /** Rows and items inside a rounded container (menu items, list rows, filmstrip frames). */
245
+ radiusInner: "0px",
246
+ /** Cards, panels, tables, alerts, code blocks, thumbnails. */
247
+ radiusSurface: ref("border-radius"),
248
+ /** Dialogs, popovers, menus, toasts. Drawers stay square: they are anchored to an edge. */
249
+ radiusOverlay: ref("border-radius"),
250
+ /** Width of the keyboard focus ring. WCAG 2.4.13 wants at least 2px; keep it there. */
251
+ strokeFocus: "2px",
252
+ /** Selected-tab, active-nav and selected-row indicators. */
253
+ strokeIndicator: "2px",
254
+ /** The status bar on the leading edge of an alert or toast. */
255
+ strokeAccent: "3px",
256
+ /*
257
+ * Density. Discrete roles rather than one runtime multiplier: computed values stay readable in
258
+ * devtools, and a preset can move one role without dragging the rest. `definePreset({ density })`
259
+ * scales them all at build time when one knob is what you want.
260
+ */
261
+ padControlX: "0.85rem",
262
+ padControlXSm: "0.65rem",
263
+ padControlXLg: "1.2rem",
264
+ padControlY: "0.5rem",
265
+ padControlYSm: "0.38rem",
266
+ /** Underlined fields: vertical, then horizontal. Boxed fields use `pad-control-x-sm` inline. */
267
+ padField: "0.45rem 0.15rem",
268
+ padItem: "0.65rem 0.55rem",
269
+ padCell: "0.7rem 0.8rem",
270
+ padCallout: "0.8rem 1rem",
271
+ padSurface: ref("space-4"),
272
+ padOverlay: "1rem 1.25rem",
273
+ padPopover: "0.45rem",
274
+ padBarX: "1.35rem",
275
+ padPane: "1.25rem",
276
+ padPage: ref("space-6"),
277
+ /** Between a field's label, control and help text. */
278
+ gapField: "0.35rem",
279
+ /** Between the buttons of a dialog footer or an empty state. */
280
+ gapActions: ref("space-2"),
281
+ /*
282
+ * Voice: how labels and controls speak. The default shouts — small uppercase utility type,
283
+ * tracked out — and a preset can bring it back to sentence case. Tracking roles keep a unit
284
+ * because stylesheets derive from them with `calc()`.
285
+ */
286
+ labelTransform: "uppercase",
287
+ labelTracking: ref("font-tracking-utility"),
288
+ labelTrackingWide: ref("font-tracking-wide"),
289
+ labelWeight: "400",
290
+ controlTransform: "uppercase",
291
+ controlTracking: "0.08em",
292
+ controlWeight: "400",
293
+ headingWeight: "500",
294
+ strongWeight: "600"
295
+ };
284
296
  var PRIMITIVE_GROUPS = [
285
297
  ["color", colors],
286
298
  ["font", typography],
@@ -302,6 +314,7 @@ function flattenTokens() {
302
314
  const out = [];
303
315
  for (const [prefix, tree] of PRIMITIVE_GROUPS) flattenInto([prefix], tree, out);
304
316
  for (const [name, value] of Object.entries(semanticDefs)) out.push([cssVarName([name]), value]);
317
+ for (const [name, value] of Object.entries(roleDefs)) out.push([cssVarName([name]), value]);
305
318
  return out;
306
319
  }
307
320
  function generateCss() {
@@ -319,12 +332,14 @@ function generateCss() {
319
332
  var resolved = new Map(
320
333
  flattenTokens().filter((entry) => typeof entry[1] === "string")
321
334
  );
322
- var semantic = Object.fromEntries(
323
- Object.entries(semanticDefs).map(([name, value]) => [
335
+ var resolveDefs = (defs) => Object.fromEntries(
336
+ Object.entries(defs).map(([name, value]) => [
324
337
  name,
325
338
  isRef(value) ? resolved.get(value.$ref) ?? "" : value
326
339
  ])
327
340
  );
341
+ var semantic = resolveDefs(semanticDefs);
342
+ var roles = resolveDefs(roleDefs);
328
343
  var darkSemantic = {
329
344
  background: "#161814",
330
345
  surface: "#1e211c",
@@ -503,36 +518,461 @@ var tokens = {
503
518
  breakpoints,
504
519
  aspectRatio,
505
520
  semantic,
506
- darkSemantic
521
+ darkSemantic,
522
+ roles
523
+ };
524
+
525
+ // src/contrast.ts
526
+ var contrastRequirements = {
527
+ AA: { normal: 4.5, large: 3 },
528
+ AAA: { normal: 7, large: 4.5 }
529
+ };
530
+ var channels = (hex, caller) => {
531
+ const match = /^#?([\da-f]{3}|[\da-f]{6})$/i.exec(hex.trim());
532
+ if (!match) throw new RangeError(`${caller}: invalid hex colour ${JSON.stringify(hex)}`);
533
+ const digits = match[1].length === 3 ? [...match[1]].map((digit) => digit + digit).join("") : match[1];
534
+ return [0, 2, 4].map((index) => parseInt(digits.slice(index, index + 2), 16));
535
+ };
536
+ var luminanceOf = (hex, caller) => {
537
+ const [r, g, b] = channels(hex, caller).map((channel) => channel / 255).map((channel) => channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4);
538
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
539
+ };
540
+ function getLuminance(hex) {
541
+ return luminanceOf(hex, "getLuminance");
542
+ }
543
+ function getContrastRatio(foreground, background) {
544
+ const [high, low] = [
545
+ luminanceOf(foreground, "getContrastRatio"),
546
+ luminanceOf(background, "getContrastRatio")
547
+ ].sort((a, b) => b - a);
548
+ return (high + 0.05) / (low + 0.05);
549
+ }
550
+ function meetsContrast(foreground, background, { level = "AA", size = "normal" } = {}) {
551
+ return getContrastRatio(foreground, background) >= contrastRequirements[level][size];
552
+ }
553
+ function validateContrast(foreground, background) {
554
+ const ratio = getContrastRatio(foreground, background);
555
+ return {
556
+ ratio,
557
+ ratioString: `${ratio.toFixed(2)}:1`,
558
+ passesAANormal: ratio >= contrastRequirements.AA.normal,
559
+ passesAALarge: ratio >= contrastRequirements.AA.large,
560
+ passesAAANormal: ratio >= contrastRequirements.AAA.normal,
561
+ passesAAALarge: ratio >= contrastRequirements.AAA.large
562
+ };
563
+ }
564
+ function getContrastTextColor(background, { dark = "#20231d", light = "#f5f2e9" } = {}) {
565
+ return getContrastRatio(dark, background) >= getContrastRatio(light, background) ? dark : light;
566
+ }
567
+ function contrastPairs(t) {
568
+ return [
569
+ ["accent text on background", t.textAccent, t.background, 4.5],
570
+ ["accent text on surface", t.textAccent, t.surface, 4.5],
571
+ ["accent text on surface-alt", t.textAccent, t.surfaceAlt, 4.5],
572
+ ["muted text on background", t.textMuted, t.background, 4.5],
573
+ ["muted text on surface", t.textMuted, t.surface, 4.5],
574
+ // The recessed fill a default badge sits on.
575
+ ["muted text on the sunken surface", t.textMuted, t.surfaceSunken, 4.5],
576
+ ["body text on background", t.text, t.background, 4.5],
577
+ ["body text on surface", t.text, t.surface, 4.5],
578
+ ["inverse text on the inverse surface", t.textInverse, t.surfaceInverse, 4.5],
579
+ ["on-accent over accent", t.onAccent, t.accent, 4.5],
580
+ ["on-accent over accent hover", t.onAccent, t.accentHover, 4.5],
581
+ ["on-danger over danger", t.onDanger, t.danger, 4.5],
582
+ ["on-danger over danger hover", t.onDanger, t.dangerHover, 4.5],
583
+ ["on-success over success", t.onSuccess, t.success, 4.5],
584
+ ["on-warning over warning", t.onWarning, t.warning, 4.5],
585
+ ["on-info over info", t.onInfo, t.info, 4.5],
586
+ ["danger text on surface", t.textDanger, t.surface, 4.5],
587
+ ["danger text on surface-alt", t.textDanger, t.surfaceAlt, 4.5],
588
+ ["success text on surface", t.textSuccess, t.surface, 4.5],
589
+ ["warning text on surface", t.textWarning, t.surface, 4.5],
590
+ ["info text on surface", t.textInfo, t.surface, 4.5],
591
+ ["control border on the input surface", t.borderControl, t.surfaceInput, 3],
592
+ ["control border on background", t.borderControl, t.background, 3],
593
+ ["control border on surface", t.borderControl, t.surface, 3],
594
+ ["control border on surface-alt", t.borderControl, t.surfaceAlt, 3],
595
+ ["focus ring on background", t.focusRing, t.background, 3],
596
+ ["focus ring on surface", t.focusRing, t.surface, 3]
597
+ ];
598
+ }
599
+ function auditContrast(colors2) {
600
+ return contrastPairs(colors2).map(([name, foreground, background, required]) => {
601
+ const ratio = getContrastRatio(foreground, background);
602
+ return { name, foreground, background, ratio, required, pass: ratio >= required };
603
+ });
604
+ }
605
+
606
+ // src/presets/define.ts
607
+ var PRIMITIVE_GROUPS2 = { typography, spacing, sizing, borders, shadows, motion };
608
+ var PRIMITIVE_PREFIX = {
609
+ typography: "font",
610
+ spacing: "space",
611
+ sizing: "size",
612
+ borders: "border",
613
+ shadows: "shadow",
614
+ motion: "motion"
615
+ };
616
+ var flatten = (prefix, tree) => {
617
+ const out = [];
618
+ flattenInto([prefix], tree, out);
619
+ return out;
620
+ };
621
+ var baseState = () => ({
622
+ primitives: new Map(
623
+ Object.keys(PRIMITIVE_GROUPS2).flatMap(
624
+ (group) => flatten(PRIMITIVE_PREFIX[group], PRIMITIVE_GROUPS2[group])
625
+ )
626
+ ),
627
+ roles: { ...roleDefs },
628
+ light: { ...semanticDefs },
629
+ dark: { ...darkSemantic }
630
+ });
631
+ var states = /* @__PURE__ */ new WeakMap();
632
+ var NAME = /^[a-z][a-z0-9-]*$/;
633
+ var DENSITY_ROLE = /^(pad|gap)[A-Z]/;
634
+ var LENGTH = /(-?\d*\.?\d+)(rem|px|em)\b/g;
635
+ var round = (value) => String(Number(value.toFixed(4)));
636
+ var scaleLengths = (value, factor) => value.replace(
637
+ LENGTH,
638
+ (_, amount, unit) => `${round(parseFloat(amount) * factor)}${unit}`
639
+ );
640
+ var roleName = (name) => cssVarName([name]);
641
+ var cssValue = (value) => isRef(value) ? `var(${value.$ref})` : value;
642
+ var defaultValues = new Map(flattenTokens());
643
+ var resolveIn = (state) => {
644
+ const lookup = (name) => state.primitives.get(name) ?? defaultValues.get(name);
645
+ const resolve = (value, seen = /* @__PURE__ */ new Set()) => {
646
+ if (!isRef(value)) return value;
647
+ if (seen.has(value.$ref)) throw new Error(`Circular token reference through ${value.$ref}`);
648
+ const target = lookup(value.$ref);
649
+ if (target === void 0) throw new Error(`Unknown token reference ${value.$ref}`);
650
+ return resolve(target, /* @__PURE__ */ new Set([...seen, value.$ref]));
651
+ };
652
+ return resolve;
653
+ };
654
+ var assertKnownKeys = (what, given, known) => {
655
+ for (const key of Object.keys(given ?? {})) {
656
+ if (!(key in known)) throw new Error(`Unknown ${what} "${key}"`);
657
+ }
658
+ };
659
+ function definePreset(definition) {
660
+ const { name, primitives = {}, roles: roles2 = {}, density, colors: colors2, fontImport } = definition;
661
+ if (!NAME.test(name)) {
662
+ throw new Error(`Preset name "${name}" must be lowercase letters, digits and dashes`);
663
+ }
664
+ assertKnownKeys("primitive group", primitives, PRIMITIVE_GROUPS2);
665
+ assertKnownKeys("role", roles2, roleDefs);
666
+ assertKnownKeys("colour role", colors2?.light, semanticDefs);
667
+ assertKnownKeys("colour role", colors2?.dark, semanticDefs);
668
+ if (colors2) {
669
+ const missing = Object.keys(colors2.light).filter((key) => !(key in colors2.dark));
670
+ if (missing.length) {
671
+ throw new Error(`Preset "${name}" sets ${missing.join(", ")} for light but not for dark`);
672
+ }
673
+ }
674
+ if (density !== void 0 && !(density >= 0.5 && density <= 1.5)) {
675
+ throw new Error(`Preset "${name}" density must be between 0.5 and 1.5, got ${density}`);
676
+ }
677
+ const parent = definition.extends ? states.get(definition.extends) : baseState();
678
+ if (!parent) throw new Error(`Preset "${name}" extends something that is not a preset`);
679
+ const state = {
680
+ primitives: new Map(parent.primitives),
681
+ roles: { ...parent.roles },
682
+ light: { ...parent.light, ...colors2?.light },
683
+ dark: { ...parent.dark, ...colors2?.dark }
684
+ };
685
+ for (const [group, overrides] of Object.entries(primitives)) {
686
+ for (const [property, value] of flatten(PRIMITIVE_PREFIX[group], overrides)) {
687
+ if (!state.primitives.has(property)) throw new Error(`Unknown primitive ${property}`);
688
+ state.primitives.set(property, value);
689
+ }
690
+ }
691
+ const resolve = resolveIn(state);
692
+ for (const role of Object.keys(state.roles)) {
693
+ const explicit = roles2[role];
694
+ if (explicit !== void 0) state.roles[role] = explicit;
695
+ else if (density !== void 0 && density !== 1 && DENSITY_ROLE.test(role)) {
696
+ state.roles[role] = scaleLengths(resolve(state.roles[role]), density);
697
+ }
698
+ }
699
+ for (const role of Object.keys(state.roles)) {
700
+ const value = state.roles[role];
701
+ if (value === "0" && role.startsWith("stroke")) state.roles[role] = "0px";
702
+ if (value === "0" && role.endsWith("Tracking")) state.roles[role] = "0em";
703
+ }
704
+ const focus = /^([\d.]+)px$/.exec(resolve(state.roles.strokeFocus));
705
+ if (focus && parseFloat(focus[1]) < 2) {
706
+ throw new Error(`Preset "${name}" focus ring must stay at least 2px wide (WCAG 2.4.13)`);
707
+ }
708
+ const resolveAll = (record) => Object.fromEntries(
709
+ Object.entries(record).map(([key, value]) => [key, resolve(value)])
710
+ );
711
+ const preset = {
712
+ name,
713
+ label: definition.label ?? name.charAt(0).toUpperCase() + name.slice(1),
714
+ description: definition.description,
715
+ fontImports: [fontImport ?? []].flat(),
716
+ declarations: {
717
+ shape: [
718
+ ...state.primitives,
719
+ ...Object.entries(state.roles).map(
720
+ ([role, value]) => [roleName(role), cssValue(value)]
721
+ )
722
+ ],
723
+ light: Object.entries(state.light).map(
724
+ ([role, value]) => [roleName(role), cssValue(value)]
725
+ ),
726
+ dark: Object.entries(state.dark).map(([role, value]) => [roleName(role), value])
727
+ },
728
+ resolved: {
729
+ roles: resolveAll(state.roles),
730
+ light: resolveAll(state.light),
731
+ dark: resolveAll(state.dark)
732
+ }
733
+ };
734
+ states.set(preset, state);
735
+ return preset;
736
+ }
737
+ var block = (selector, lines, indent = "") => [
738
+ `${indent}${selector} {`,
739
+ ...lines.map((line) => `${indent} ${line}`),
740
+ `${indent}}`
741
+ ];
742
+ var declare = (entries) => entries.map(([name, value]) => `${name}: ${value};`);
743
+ var selectors = (name, scope) => {
744
+ if (scope === "root") {
745
+ return {
746
+ shape: ":root",
747
+ light: ":root:not([data-theme='dark'])",
748
+ dark: ":root[data-theme='dark']",
749
+ auto: ":root:root:not([data-theme='light'])"
750
+ };
751
+ }
752
+ const p = `[data-preset='${name}']`;
753
+ return {
754
+ shape: p,
755
+ light: `${p}:not([data-theme='dark'], [data-theme='dark'] *)`,
756
+ dark: `${p}[data-theme='dark'],
757
+ [data-theme='dark'] ${p}`,
758
+ auto: `${p}:root:not([data-theme='light']),
759
+ :root:not([data-theme='light']) ${p}:not([data-theme='light'], [data-theme='light'] *)`
760
+ };
507
761
  };
762
+ var comment = (text) => text.replaceAll("*/", "* /");
763
+ function generatePresetCss(preset, options = {}) {
764
+ const { scope = "attribute", scheme = "light" } = options;
765
+ const select = selectors(preset.name, scope);
766
+ const header = [
767
+ `/* ${comment(`${preset.label} preset${preset.description ? ` \u2014 ${preset.description}` : ""}`)}`,
768
+ " Generated by definePreset(). Do not edit directly. */"
769
+ ];
770
+ if (scheme === "light") {
771
+ return `${[
772
+ ...preset.fontImports.map((url) => `@import url(${JSON.stringify(url)});`),
773
+ ...header,
774
+ ...block(select.shape, declare(preset.declarations.shape)),
775
+ ...block(select.light, declare(preset.declarations.light))
776
+ ].join("\n")}
777
+ `;
778
+ }
779
+ const dark = ["color-scheme: dark;", ...declare(preset.declarations.dark)];
780
+ const lines = [...header, ...block(select.dark, dark)];
781
+ if (scheme === "dark-auto") {
782
+ lines.push(
783
+ "",
784
+ "@media (prefers-color-scheme: dark) {",
785
+ ...block(select.auto.replaceAll("\n", "\n "), dark, " "),
786
+ "}"
787
+ );
788
+ }
789
+ return `${lines.join("\n")}
790
+ `;
791
+ }
792
+ function presetStylesheets(preset) {
793
+ const files = {};
794
+ for (const scope of ["attribute", "root"]) {
795
+ const base = scope === "root" ? `${preset.name}.root` : preset.name;
796
+ files[`${base}.css`] = generatePresetCss(preset, { scope, scheme: "light" });
797
+ files[`${base}-dark.css`] = generatePresetCss(preset, { scope, scheme: "dark" });
798
+ files[`${base}-dark-auto.css`] = generatePresetCss(preset, { scope, scheme: "dark-auto" });
799
+ }
800
+ return files;
801
+ }
802
+
803
+ // src/presets/compact.ts
804
+ var compact = definePreset({
805
+ name: "compact",
806
+ label: "Compact",
807
+ description: "The Loidolt look with tighter padding and smaller controls.",
808
+ density: 0.75,
809
+ primitives: {
810
+ sizing: {
811
+ // 28px: still above the 24px WCAG 2.5.8 minimum.
812
+ controlSm: "1.75rem",
813
+ control: "2.125rem",
814
+ controlLg: "2.5rem",
815
+ topbar: "3.25rem",
816
+ contextbar: "2.25rem"
817
+ }
818
+ }
819
+ });
820
+
821
+ // src/presets/loidolt.ts
822
+ var loidolt = definePreset({
823
+ name: "loidolt",
824
+ label: "Loidolt",
825
+ description: "Square corners, tracked uppercase labels, warm paper and orange."
826
+ });
827
+
828
+ // src/presets/soft.ts
829
+ var systemSans = 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
830
+ var soft = definePreset({
831
+ name: "soft",
832
+ label: "Soft",
833
+ description: "Rounded corners, sentence-case labels, cool neutrals and a blue accent.",
834
+ density: 1.15,
835
+ primitives: {
836
+ typography: {
837
+ display: systemSans,
838
+ utility: systemSans,
839
+ // Sentence case at 11px is harder to read than uppercase at 11px; give it the extra pixel.
840
+ size: { xs: "0.75rem" }
841
+ },
842
+ borders: { radius: "6px" }
843
+ },
844
+ roles: {
845
+ radiusControl: "6px",
846
+ radiusInner: "4px",
847
+ radiusSurface: "8px",
848
+ radiusOverlay: "10px",
849
+ labelTransform: "none",
850
+ labelTracking: "0em",
851
+ labelTrackingWide: "0.02em",
852
+ labelWeight: "500",
853
+ controlTransform: "none",
854
+ controlTracking: "0em",
855
+ controlWeight: "500",
856
+ headingWeight: "600"
857
+ },
858
+ colors: {
859
+ light: {
860
+ background: "#f4f6f8",
861
+ surface: "#ffffff",
862
+ surfaceAlt: "#f8fafc",
863
+ surfaceSunken: "#e9edf2",
864
+ surfacePaper: "#ffffff",
865
+ surfaceInverse: "#1c2430",
866
+ surfaceInput: "#ffffff",
867
+ text: "#1c2430",
868
+ textMuted: "#556070",
869
+ textInverse: "#f4f6f8",
870
+ textAccent: "#1d4ed8",
871
+ border: "#d5dbe3",
872
+ borderSoft: "#e4e8ee",
873
+ borderStrong: "#8792a2",
874
+ borderControl: "#7b8696",
875
+ borderSunken: "#d5dbe3",
876
+ accent: "#2563eb",
877
+ accentHover: "#1d4ed8",
878
+ onAccent: "#ffffff",
879
+ danger: "#c62828",
880
+ dangerHover: "#a51d1d",
881
+ onDanger: "#ffffff",
882
+ textDanger: "#b42318",
883
+ success: "#1f7a4d",
884
+ onSuccess: "#ffffff",
885
+ textSuccess: "#1a6a42",
886
+ warning: "#a15c07",
887
+ onWarning: "#ffffff",
888
+ textWarning: "#8a4b06",
889
+ info: "#0e6b8c",
890
+ onInfo: "#ffffff",
891
+ textInfo: "#0b5c78",
892
+ focusRing: "#2563eb",
893
+ shadowColor: "#1c2430"
894
+ },
895
+ dark: {
896
+ background: "#11151b",
897
+ surface: "#181d25",
898
+ surfaceAlt: "#1e2430",
899
+ surfaceSunken: "#0c0f13",
900
+ surfacePaper: "#ffffff",
901
+ surfaceInverse: "#e6eaf0",
902
+ surfaceInput: "#1e2430",
903
+ text: "#e6eaf0",
904
+ textMuted: "#9aa5b4",
905
+ textInverse: "#11151b",
906
+ textAccent: "#8ab4ff",
907
+ border: "#2d3542",
908
+ borderSoft: "#232a35",
909
+ borderStrong: "#5b6677",
910
+ borderControl: "#6f7a8b",
911
+ borderSunken: "#1f2630",
912
+ accent: "#6aa1ff",
913
+ accentHover: "#8ab4ff",
914
+ onAccent: "#0c1220",
915
+ danger: "#f07167",
916
+ dangerHover: "#f4928a",
917
+ onDanger: "#11151b",
918
+ textDanger: "#f59a92",
919
+ success: "#5cc08a",
920
+ onSuccess: "#11151b",
921
+ textSuccess: "#74cf9c",
922
+ warning: "#e0a24a",
923
+ onWarning: "#11151b",
924
+ textWarning: "#e8b468",
925
+ info: "#5bb5d6",
926
+ onInfo: "#11151b",
927
+ textInfo: "#7cc6e2",
928
+ focusRing: "#8ab4ff",
929
+ shadowColor: "#000000"
930
+ }
931
+ }
932
+ });
933
+
934
+ // src/presets/index.ts
935
+ var builtInPresets = [loidolt, soft, compact];
936
+
937
+ // src/index.ts
508
938
  var index_default = tokens;
509
939
  export {
510
940
  aspectRatio,
941
+ auditContrast,
511
942
  borders,
512
943
  breakpoints,
944
+ builtInPresets,
513
945
  chartColors,
514
946
  chartRoles,
515
947
  colors,
948
+ compact,
949
+ contrastPairs,
516
950
  contrastRequirements,
517
951
  cssVarName,
518
952
  darkSemantic,
519
953
  index_default as default,
954
+ definePreset,
520
955
  flattenTokens,
521
956
  generateCss,
522
957
  generateDarkCss,
958
+ generatePresetCss,
523
959
  getContrastRatio,
524
960
  getContrastTextColor,
525
961
  getLuminance,
962
+ loidolt,
526
963
  mapColors,
527
964
  mapRoles,
528
965
  meetsContrast,
529
966
  motion,
967
+ presetStylesheets,
530
968
  resolveRoles,
531
969
  roleValue,
532
970
  roleVar,
971
+ roles,
533
972
  semantic,
534
973
  shadows,
535
974
  sizing,
975
+ soft,
536
976
  spacing,
537
977
  syntaxColors,
538
978
  syntaxRoles,