@epilot/spark-ui 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +9 -1
  2. package/dist/components/avatar.d.cts +1 -1
  3. package/dist/components/avatar.d.ts +1 -1
  4. package/dist/components/badge.cjs +1 -1
  5. package/dist/components/badge.cjs.map +1 -1
  6. package/dist/components/badge.d.cts +1 -1
  7. package/dist/components/badge.d.ts +1 -1
  8. package/dist/components/badge.js +1 -1
  9. package/dist/components/badge.js.map +1 -1
  10. package/dist/components/bar-chart.cjs +4 -7
  11. package/dist/components/bar-chart.cjs.map +1 -1
  12. package/dist/components/bar-chart.js +4 -7
  13. package/dist/components/bar-chart.js.map +1 -1
  14. package/dist/components/battery-progress-row.cjs +6 -7
  15. package/dist/components/battery-progress-row.cjs.map +1 -1
  16. package/dist/components/battery-progress-row.js +6 -7
  17. package/dist/components/battery-progress-row.js.map +1 -1
  18. package/dist/components/box.cjs +42 -0
  19. package/dist/components/box.cjs.map +1 -0
  20. package/dist/components/box.d.cts +35 -0
  21. package/dist/components/box.d.ts +35 -0
  22. package/dist/components/box.js +41 -0
  23. package/dist/components/box.js.map +1 -0
  24. package/dist/components/bubble.d.cts +1 -1
  25. package/dist/components/button-group.d.cts +1 -1
  26. package/dist/components/button-group.d.ts +1 -1
  27. package/dist/components/button.cjs +1 -1
  28. package/dist/components/button.cjs.map +1 -1
  29. package/dist/components/button.d.cts +2 -2
  30. package/dist/components/button.d.ts +2 -2
  31. package/dist/components/button.js +1 -1
  32. package/dist/components/button.js.map +1 -1
  33. package/dist/components/card.cjs +10 -14
  34. package/dist/components/card.cjs.map +1 -1
  35. package/dist/components/card.d.cts +6 -3
  36. package/dist/components/card.d.ts +6 -3
  37. package/dist/components/card.js +10 -14
  38. package/dist/components/card.js.map +1 -1
  39. package/dist/components/checkbox.cjs +4 -2
  40. package/dist/components/checkbox.cjs.map +1 -1
  41. package/dist/components/checkbox.d.cts +1 -1
  42. package/dist/components/checkbox.d.ts +1 -1
  43. package/dist/components/checkbox.js +4 -2
  44. package/dist/components/checkbox.js.map +1 -1
  45. package/dist/components/empty-state.cjs +4 -7
  46. package/dist/components/empty-state.cjs.map +1 -1
  47. package/dist/components/empty-state.js +4 -7
  48. package/dist/components/empty-state.js.map +1 -1
  49. package/dist/components/field.cjs +43 -10
  50. package/dist/components/field.cjs.map +1 -1
  51. package/dist/components/field.d.cts +19 -2
  52. package/dist/components/field.d.ts +19 -2
  53. package/dist/components/field.js +43 -11
  54. package/dist/components/field.js.map +1 -1
  55. package/dist/components/icon.cjs +12 -9
  56. package/dist/components/icon.cjs.map +1 -1
  57. package/dist/components/icon.d.cts +6 -2
  58. package/dist/components/icon.d.ts +6 -2
  59. package/dist/components/icon.js +12 -9
  60. package/dist/components/icon.js.map +1 -1
  61. package/dist/components/input.d.cts +1 -1
  62. package/dist/components/input.d.ts +1 -1
  63. package/dist/components/marker.d.cts +1 -1
  64. package/dist/components/marker.d.ts +1 -1
  65. package/dist/components/metering-row.cjs +28 -11
  66. package/dist/components/metering-row.cjs.map +1 -1
  67. package/dist/components/metering-row.js +28 -11
  68. package/dist/components/metering-row.js.map +1 -1
  69. package/dist/components/pill.cjs +1 -1
  70. package/dist/components/pill.cjs.map +1 -1
  71. package/dist/components/pill.d.cts +1 -1
  72. package/dist/components/pill.d.ts +1 -1
  73. package/dist/components/pill.js +1 -1
  74. package/dist/components/pill.js.map +1 -1
  75. package/dist/components/radio.cjs +4 -2
  76. package/dist/components/radio.cjs.map +1 -1
  77. package/dist/components/radio.d.cts +3 -1
  78. package/dist/components/radio.d.ts +3 -1
  79. package/dist/components/radio.js +4 -2
  80. package/dist/components/radio.js.map +1 -1
  81. package/dist/components/segmented-control.d.cts +1 -1
  82. package/dist/components/segmented-control.d.ts +1 -1
  83. package/dist/components/select.d.cts +1 -1
  84. package/dist/components/select.d.ts +1 -1
  85. package/dist/components/switch.cjs +3 -1
  86. package/dist/components/switch.cjs.map +1 -1
  87. package/dist/components/switch.d.cts +3 -1
  88. package/dist/components/switch.d.ts +3 -1
  89. package/dist/components/switch.js +3 -1
  90. package/dist/components/switch.js.map +1 -1
  91. package/dist/components/textarea.d.cts +1 -1
  92. package/dist/components/textarea.d.ts +1 -1
  93. package/dist/components/theme.cjs +35 -9
  94. package/dist/components/theme.cjs.map +1 -1
  95. package/dist/components/theme.d.cts +12 -1
  96. package/dist/components/theme.d.ts +12 -1
  97. package/dist/components/theme.js +36 -10
  98. package/dist/components/theme.js.map +1 -1
  99. package/dist/icons/material-symbol.cjs +1 -0
  100. package/dist/icons/material-symbol.cjs.map +1 -1
  101. package/dist/icons/material-symbol.js +1 -0
  102. package/dist/icons/material-symbol.js.map +1 -1
  103. package/dist/lib/accent-theme.cjs +102 -14
  104. package/dist/lib/accent-theme.cjs.map +1 -1
  105. package/dist/lib/accent-theme.d.cts +29 -4
  106. package/dist/lib/accent-theme.d.ts +29 -4
  107. package/dist/lib/accent-theme.js +100 -15
  108. package/dist/lib/accent-theme.js.map +1 -1
  109. package/dist/lib/container-chrome.cjs +53 -0
  110. package/dist/lib/container-chrome.cjs.map +1 -0
  111. package/dist/lib/container-chrome.d.cts +15 -0
  112. package/dist/lib/container-chrome.d.ts +15 -0
  113. package/dist/lib/container-chrome.js +48 -0
  114. package/dist/lib/container-chrome.js.map +1 -0
  115. package/dist/lib/input-box-variants.d.cts +1 -1
  116. package/dist/lib/input-box-variants.d.ts +1 -1
  117. package/dist/lib/theme-types.d.cts +1 -1
  118. package/dist/lib/theme-types.d.ts +1 -1
  119. package/dist/styles/spark-default.css +34 -8
  120. package/dist/{theme-types-8wjgiNA_.d.ts → theme-types-1yB0d8mp.d.cts} +6 -6
  121. package/dist/{theme-types-8wjgiNA_.d.cts → theme-types-1yB0d8mp.d.ts} +6 -6
  122. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"switch.cjs","names":["accentByColor","SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n className={cn(\n 'peer relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors',\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQA,0BAAAA,cAAc,SAAS,KAAA;CACvD,OACE,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,OAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EACnB,YAAA,GAAA,OAAA,IACE,qGACA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,iBAAA,GAAA,kBAAA,KAACA,sBAAAA,OAAgB,OAAjB;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IACE,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
1
+ {"version":3,"file":"switch.cjs","names":["accentByColor","SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors',\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQA,0BAAAA,cAAc,SAAS,KAAA;CACvD,OACE,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,OAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,iBAAA,GAAA,kBAAA,KAAC,UAAD,CAAS,CAAA;EAC3B,YAAA,GAAA,OAAA,IACE,qGACA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,iBAAA,GAAA,kBAAA,KAACA,sBAAAA,OAAgB,OAAjB;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IACE,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-8wjgiNA_.cjs";
3
+ import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
4
4
  import { Switch as Switch$1 } from "@base-ui/react/switch";
5
5
 
6
6
  //#region src/components/switch.d.ts
@@ -25,6 +25,8 @@ declare function Switch({
25
25
  color,
26
26
  size: _size,
27
27
  variant: _variant,
28
+ render,
29
+ nativeButton,
28
30
  ...props
29
31
  }: SwitchProps): import("react/jsx-runtime").JSX.Element;
30
32
  //#endregion
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-8wjgiNA_.js";
3
+ import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
4
4
  import { Switch as Switch$1 } from "@base-ui/react/switch";
5
5
 
6
6
  //#region src/components/switch.d.ts
@@ -25,6 +25,8 @@ declare function Switch({
25
25
  color,
26
26
  size: _size,
27
27
  variant: _variant,
28
+ render,
29
+ nativeButton,
28
30
  ...props
29
31
  }: SwitchProps): import("react/jsx-runtime").JSX.Element;
30
32
  //#endregion
@@ -4,13 +4,15 @@ import { accentByColor } from "../lib/accent-colors.js";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { Switch as Switch$1 } from "@base-ui/react/switch";
6
6
  //#region src/components/switch.tsx
7
- function Switch({ className, styleVariant, color, size: _size, variant: _variant, ...props }) {
7
+ function Switch({ className, styleVariant, color, size: _size, variant: _variant, render, nativeButton, ...props }) {
8
8
  const dataStyle = styleVariant !== void 0 || color !== void 0 ? styleVariant ?? "solid" : void 0;
9
9
  const dataAccentColor = color ? accentByColor[color] : void 0;
10
10
  return /* @__PURE__ */ jsx(Switch$1.Root, {
11
11
  "data-slot": "switch",
12
12
  "data-style": dataStyle,
13
13
  "data-accent-color": dataAccentColor,
14
+ nativeButton: nativeButton ?? render === void 0,
15
+ render: render ?? /* @__PURE__ */ jsx("button", {}),
14
16
  className: cn("peer relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors", "before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']", "rounded-(--spark-rounded-xl)", "shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-disabled:pointer-events-none data-disabled:opacity-50", "data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]", "data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]", className),
15
17
  ...props,
16
18
  children: /* @__PURE__ */ jsx(Switch$1.Thumb, {
@@ -1 +1 @@
1
- {"version":3,"file":"switch.js","names":["SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n className={cn(\n 'peer relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors',\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQ,cAAc,SAAS,KAAA;CACvD,OACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EACnB,WAAW,GACT,qGACA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,oBAACA,SAAgB,OAAjB;GACE,aAAU;GACV,WAAW,GACT,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
1
+ {"version":3,"file":"switch.js","names":["SwitchPrimitive"],"sources":["../../src/components/switch.tsx"],"sourcesContent":["import { Switch as SwitchPrimitive } from '@base-ui/react/switch'\nimport { accentByColor } from '../lib/accent-colors'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type SparkSwitchColor = 'accent' | 'neutral' | 'danger'\n\ntype SwitchProps = SwitchPrimitive.Root.Props & {\n styleVariant?: SparkStyle\n color?: SparkSwitchColor\n /**\n * @deprecated The switch now renders a single size. Accepted for back-compat\n * but ignored.\n */\n size?: 'sm' | 'base' | 'lg'\n /**\n * @deprecated Use `color=\"danger\"` for a destructive/error switch. Accepted\n * for back-compat but ignored.\n */\n variant?: 'primary' | 'destructive'\n}\n\nfunction Switch({\n className,\n styleVariant,\n color,\n size: _size,\n variant: _variant,\n render,\n nativeButton,\n ...props\n}: SwitchProps) {\n const hasLook = styleVariant !== undefined || color !== undefined\n const dataStyle = hasLook ? (styleVariant ?? 'solid') : undefined\n const dataAccentColor = color ? accentByColor[color] : undefined\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-style={dataStyle}\n data-accent-color={dataAccentColor}\n // a native button owns the caller's `id`; on Base UI's default <span> the\n // `id` lands on the hidden input and the control gets a generated one\n nativeButton={nativeButton ?? render === undefined}\n render={render ?? <button />}\n className={cn(\n 'peer relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center p-[2px] transition-colors',\n \"before:absolute before:inset-x-0 before:top-1/2 before:h-10 before:-translate-y-1/2 before:content-['']\",\n 'rounded-(--spark-rounded-xl)',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.05),inset_0_0_0_1px_var(--spark-switch-ring,transparent)]',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n 'data-unchecked:bg-gray-a5 data-unchecked:[--spark-switch-ring:var(--spark-switch-idle-border,transparent)]',\n 'data-checked:bg-(--spark-switch-track,var(--spark-9)) data-checked:[--spark-switch-ring:var(--spark-style-border,transparent)]',\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className={cn(\n 'pointer-events-none block size-5 bg-(--spark-switch-thumb,var(--spark-on-solid,#fff)) shadow-xs transition-transform',\n 'rounded-(--spark-rounded-lg)',\n 'data-checked:translate-x-4 data-unchecked:translate-x-0',\n )}\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\nexport type { SwitchProps }\n"],"mappings":";;;;;;AAsBA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,OACN,SAAS,UACT,QACA,cACA,GAAG,SACW;CAEd,MAAM,YADU,iBAAiB,KAAA,KAAa,UAAU,KAAA,IAC3B,gBAAgB,UAAW,KAAA;CACxD,MAAM,kBAAkB,QAAQ,cAAc,SAAS,KAAA;CACvD,OACE,oBAACA,SAAgB,MAAjB;EACE,aAAU;EACV,cAAY;EACZ,qBAAmB;EAGnB,cAAc,gBAAgB,WAAW,KAAA;EACzC,QAAQ,UAAU,oBAAC,UAAD,CAAS,CAAA;EAC3B,WAAW,GACT,qGACA,2GACA,gCACA,6FACA,iFACA,8DACA,8GACA,kIACA,SACF;EACA,GAAI;YAEJ,oBAACA,SAAgB,OAAjB;GACE,aAAU;GACV,WAAW,GACT,wHACA,gCACA,yDACF;EACD,CAAA;CACmB,CAAA;AAE1B"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-8wjgiNA_.cjs";
3
+ import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.cjs";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/textarea.d.ts
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-8wjgiNA_.js";
3
+ import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.js";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/textarea.d.ts
@@ -10,16 +10,19 @@ let _base_ui_react_merge_props = require("@base-ui/react/merge-props");
10
10
  let _base_ui_react_use_render = require("@base-ui/react/use-render");
11
11
  let cnfast = require("cnfast");
12
12
  //#region src/components/theme.tsx
13
+ /** The epilot brand accent — the scale `spark-default.css` ships statically. */
14
+ const DEFAULT_ACCENT = "#005EB4";
13
15
  const ThemeContext = react.createContext({});
14
16
  /** Merged theme values from enclosing `<Theme>` providers. */
15
17
  function useTheme() {
16
18
  return react.useContext(ThemeContext);
17
19
  }
18
20
  /** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */
19
- const Theme = react.forwardRef(function Theme({ accentColor, neutralColor, radius, scaling, spacing, styleVariant, highContrast, labelPosition, inputStyle, inputColor, cardVariant, cardColor, appearance, render, className, style, children, ...rest }, ref) {
21
+ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, neutralColor, radius, scaling, spacing, styleVariant, highContrast, labelPosition, inputStyle, inputColor, cardVariant, cardColor, appearance, fontHeading, fontBody, render, className, style, children, ...rest }, ref) {
20
22
  const parent = useTheme();
21
23
  const value = react.useMemo(() => ({
22
24
  accentColor: accentColor ?? parent.accentColor,
25
+ backgroundColor: backgroundColor ?? parent.backgroundColor,
23
26
  neutralColor: neutralColor ?? parent.neutralColor,
24
27
  radius: radius ?? parent.radius,
25
28
  scaling: scaling ?? parent.scaling,
@@ -31,9 +34,12 @@ const Theme = react.forwardRef(function Theme({ accentColor, neutralColor, radiu
31
34
  inputColor: inputColor ?? parent.inputColor,
32
35
  cardVariant: cardVariant ?? parent.cardVariant,
33
36
  cardColor: cardColor ?? parent.cardColor,
34
- appearance: appearance ?? parent.appearance
37
+ appearance: appearance ?? parent.appearance,
38
+ fontHeading: fontHeading ?? parent.fontHeading,
39
+ fontBody: fontBody ?? parent.fontBody
35
40
  }), [
36
41
  accentColor,
42
+ backgroundColor,
37
43
  neutralColor,
38
44
  radius,
39
45
  scaling,
@@ -46,29 +52,44 @@ const Theme = react.forwardRef(function Theme({ accentColor, neutralColor, radiu
46
52
  cardVariant,
47
53
  cardColor,
48
54
  appearance,
55
+ fontHeading,
56
+ fontBody,
49
57
  parent
50
58
  ]);
51
59
  const scopeId = react.useId();
60
+ const resolvedNeutralColor = neutralColor === "auto" ? require_lib_accent_theme.getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT) : neutralColor;
52
61
  const accent = react.useMemo(() => {
53
62
  const empty = {
54
63
  inlineVars: {},
55
64
  css: "",
56
65
  scoped: false
57
66
  };
58
- if (!accentColor) return empty;
67
+ if (!accentColor && !backgroundColor) return empty;
59
68
  const toVars = (decls) => Object.fromEntries(decls.filter((decl) => decl.includes(":")).map((decl) => {
60
69
  const i = decl.indexOf(":");
61
70
  return [decl.slice(0, i).trim(), decl.slice(i + 1).replace(/;$/, "").trim()];
62
71
  }));
63
72
  try {
64
- const hex = require_lib_accent_theme.CURATED_ACCENTS[accentColor] ?? accentColor;
73
+ const source = value.accentColor ?? DEFAULT_ACCENT;
74
+ const hex = require_lib_accent_theme.CURATED_ACCENTS[source] ?? source;
75
+ const bgAppearance = backgroundColor ? require_lib_accent_theme.appearanceForBackground(backgroundColor) : void 0;
76
+ if (backgroundColor && value.appearance && bgAppearance !== value.appearance) console.warn(`[Theme] Ignoring backgroundColor "${backgroundColor}": it reads as a ${bgAppearance} canvas on an appearance="${value.appearance}" scope. Pass a ${value.appearance} colour, or set it on a scope whose appearance matches.`);
77
+ const optsFor = (appearance) => backgroundColor && bgAppearance === appearance ? {
78
+ background: backgroundColor,
79
+ neutral: resolvedNeutralColor ?? "slate"
80
+ } : void 0;
81
+ const emit = (scale, custom) => custom ? [...require_lib_accent_theme.accentSparkVars(scale), ...require_lib_accent_theme.neutralSparkVars(scale)] : require_lib_accent_theme.accentSparkVars(scale);
82
+ const build = (appearance) => {
83
+ const opts = optsFor(appearance);
84
+ return emit(require_lib_accent_theme.generateAccentScale(hex, appearance, opts), opts != null);
85
+ };
65
86
  if (value.appearance) return {
66
- inlineVars: toVars(require_lib_accent_theme.accentSparkVars(require_lib_accent_theme.generateAccentScale(hex, value.appearance))),
87
+ inlineVars: toVars(build(value.appearance)),
67
88
  css: "",
68
89
  scoped: false
69
90
  };
70
- const light = require_lib_accent_theme.accentSparkVars(require_lib_accent_theme.generateAccentScale(hex, "light"));
71
- const dark = require_lib_accent_theme.accentSparkVars(require_lib_accent_theme.generateAccentScale(hex, "dark"));
91
+ const light = build("light");
92
+ const dark = build("dark");
72
93
  const sel = `[data-spark-scope="${scopeId}"]`;
73
94
  return {
74
95
  inlineVars: {},
@@ -76,15 +97,17 @@ const Theme = react.forwardRef(function Theme({ accentColor, neutralColor, radiu
76
97
  scoped: true
77
98
  };
78
99
  } catch (error) {
79
- console.warn(`[Theme] Ignoring invalid accentColor "${accentColor}".`, error);
100
+ console.warn(`[Theme] Ignoring invalid accentColor "${accentColor}" / backgroundColor "${backgroundColor}".`, error);
80
101
  return empty;
81
102
  }
82
103
  }, [
83
104
  accentColor,
105
+ backgroundColor,
106
+ resolvedNeutralColor,
107
+ value.accentColor,
84
108
  value.appearance,
85
109
  scopeId
86
110
  ]);
87
- const resolvedNeutralColor = neutralColor === "auto" ? require_lib_accent_theme.getMatchingNeutral(value.accentColor ?? "#005EB4") : neutralColor;
88
111
  const element = (0, _base_ui_react_use_render.useRender)({
89
112
  defaultTagName: "div",
90
113
  render,
@@ -105,6 +128,9 @@ const Theme = react.forwardRef(function Theme({ accentColor, neutralColor, radiu
105
128
  "data-spark-scope": accent.scoped ? scopeId : void 0,
106
129
  style: {
107
130
  ...accent.inlineVars,
131
+ ...backgroundColor ? { backgroundColor: "var(--spark-background)" } : null,
132
+ ...fontHeading ? { "--spark-font-heading": fontHeading } : null,
133
+ ...fontBody ? { "--spark-font-body": fontBody } : null,
108
134
  ...style
109
135
  },
110
136
  children
@@ -1 +1 @@
1
- {"version":3,"file":"theme.cjs","names":["React","CURATED_ACCENTS","accentSparkVars","generateAccentScale","getMatchingNeutral"],"sources":["../../src/components/theme.tsx"],"sourcesContent":["'use client'\n\nimport { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n CURATED_ACCENTS,\n accentSparkVars,\n generateAccentScale,\n getMatchingNeutral,\n type Appearance,\n} from '../lib/accent-theme'\nimport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\n\nexport interface ThemeValue {\n /** Curated accent name or a custom hex. */\n accentColor?: string\n /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor=\"auto\"`). */\n neutralColor?: SparkNeutral\n radius?: SparkRadius\n scaling?: SparkScaling\n spacing?: SparkSpacing\n styleVariant?: SparkStyle\n /** Orthogonal to `styleVariant`: shifts any style toward higher-contrast steps. */\n highContrast?: boolean\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n /** App-level default `<Card>` chrome; a per-card `variant` prop overrides it. */\n cardVariant?: SparkCardVariant\n /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */\n cardColor?: SparkCardColor\n appearance?: Appearance\n}\n\nconst ThemeContext = React.createContext<ThemeValue>({})\n\n/** Merged theme values from enclosing `<Theme>` providers. */\nexport function useTheme(): ThemeValue {\n return React.useContext(ThemeContext)\n}\n\nexport interface ThemeProps\n extends useRender.ComponentProps<'div'>, ThemeValue {}\n\n/** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */\nexport const Theme = React.forwardRef<HTMLDivElement, ThemeProps>(\n function Theme(\n {\n accentColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n render,\n className,\n style,\n children,\n ...rest\n },\n ref,\n ) {\n const parent = useTheme()\n\n const value = React.useMemo<ThemeValue>(\n () => ({\n accentColor: accentColor ?? parent.accentColor,\n neutralColor: neutralColor ?? parent.neutralColor,\n radius: radius ?? parent.radius,\n scaling: scaling ?? parent.scaling,\n spacing: spacing ?? parent.spacing,\n styleVariant: styleVariant ?? parent.styleVariant,\n highContrast: highContrast ?? parent.highContrast,\n labelPosition: labelPosition ?? parent.labelPosition,\n inputStyle: inputStyle ?? parent.inputStyle,\n inputColor: inputColor ?? parent.inputColor,\n cardVariant: cardVariant ?? parent.cardVariant,\n cardColor: cardColor ?? parent.cardColor,\n appearance: appearance ?? parent.appearance,\n }),\n [\n accentColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n parent,\n ],\n )\n\n // Scope id for the ambient-appearance case (both scales emitted in a <style>).\n const scopeId = React.useId()\n\n const accent = React.useMemo(() => {\n const empty = {\n inlineVars: {} as React.CSSProperties,\n css: '',\n scoped: false,\n }\n if (!accentColor) return empty\n\n const toVars = (decls: string[]) =>\n Object.fromEntries(\n decls\n .filter((decl) => decl.includes(':'))\n .map((decl) => {\n const i = decl.indexOf(':')\n return [\n decl.slice(0, i).trim(),\n decl\n .slice(i + 1)\n .replace(/;$/, '')\n .trim(),\n ]\n }),\n ) as React.CSSProperties\n\n try {\n const hex = CURATED_ACCENTS[accentColor] ?? accentColor\n\n // Explicit appearance → single-scale inline vars. Correct for a light\n // island inside a dark page (which must NOT pick up the dark scale).\n if (value.appearance) {\n return {\n inlineVars: toVars(\n accentSparkVars(generateAccentScale(hex, value.appearance)),\n ),\n css: '',\n scoped: false,\n }\n }\n\n // Ambient appearance → emit BOTH scales in a scoped <style> so the\n // `.dark` class selects the right one. Without this, a single-appearance\n // inline scale (default light) breaks components in dark mode.\n const light = accentSparkVars(generateAccentScale(hex, 'light'))\n const dark = accentSparkVars(generateAccentScale(hex, 'dark'))\n const sel = `[data-spark-scope=\"${scopeId}\"]`\n const css = `${sel}{${light.join('')}}:is(.dark,.dark-theme) ${sel}{${dark.join('')}}`\n return { inlineVars: {} as React.CSSProperties, css, scoped: true }\n } catch (error) {\n // A bad accentColor must not throw through render — fall back to the default theme.\n console.warn(\n `[Theme] Ignoring invalid accentColor \"${accentColor}\".`,\n error,\n )\n return empty\n }\n }, [accentColor, value.appearance, scopeId])\n\n // 'auto' pairs a neutral with the effective accent (Radix's grayColor=\"auto\").\n const resolvedNeutralColor =\n neutralColor === 'auto'\n ? getMatchingNeutral(value.accentColor ?? '#005EB4')\n : neutralColor\n\n const element = useRender({\n defaultTagName: 'div',\n render,\n ref,\n props: mergeProps<'div'>(\n {\n className: cn('spark-theme', appearance, className),\n 'data-neutral-color': resolvedNeutralColor,\n 'data-radius': radius,\n 'data-scaling': scaling,\n 'data-spacing': spacing,\n 'data-style': styleVariant,\n 'data-high-contrast': highContrast ? '' : undefined,\n 'data-label-position': labelPosition,\n 'data-input-style': inputStyle,\n 'data-input-color': inputColor,\n 'data-card-variant': cardVariant,\n 'data-card-color': cardColor === 'accent' ? 'accent' : undefined,\n 'data-spark-scope': accent.scoped ? scopeId : undefined,\n style: { ...accent.inlineVars, ...style },\n children,\n } as React.ComponentProps<'div'>,\n rest,\n ),\n })\n\n return (\n <ThemeContext.Provider value={value}>\n {accent.css ? <style>{accent.css}</style> : null}\n {element}\n </ThemeContext.Provider>\n )\n },\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"theme.cjs","names":["React","getMatchingNeutral","CURATED_ACCENTS","appearanceForBackground","accentSparkVars","neutralSparkVars","generateAccentScale"],"sources":["../../src/components/theme.tsx"],"sourcesContent":["'use client'\n\nimport { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n CURATED_ACCENTS,\n accentSparkVars,\n appearanceForBackground,\n generateAccentScale,\n getMatchingNeutral,\n neutralSparkVars,\n type Appearance,\n type SparkAccentScale,\n} from '../lib/accent-theme'\nimport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\n\n/** The epilot brand accent — the scale `spark-default.css` ships statically. */\nconst DEFAULT_ACCENT = '#005EB4'\n\nexport interface ThemeValue {\n /** Curated accent name or a custom hex. */\n accentColor?: string\n /**\n * Page canvas as a custom hex. Regenerates BOTH the accent and neutral scales against\n * it (each alpha step is composited against the canvas, so a saturated colour needs\n * the neutral ramp regenerated too, not just the accent). Unset → the fixed\n * `#ffffff` / `#000000` default, and neutrals stay on the static Radix families.\n */\n backgroundColor?: string\n /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor=\"auto\"`). */\n neutralColor?: SparkNeutral\n radius?: SparkRadius\n scaling?: SparkScaling\n spacing?: SparkSpacing\n styleVariant?: SparkStyle\n /** Orthogonal to `styleVariant`: shifts any style toward higher-contrast steps. */\n highContrast?: boolean\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n /** App-level default `<Card>` chrome; a per-card `variant` prop overrides it. */\n cardVariant?: SparkCardVariant\n /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */\n cardColor?: SparkCardColor\n appearance?: Appearance\n /** Font stack for `h1`–`h6`. Any valid CSS `font-family` value. */\n fontHeading?: string\n /** Font stack for everything else. Any valid CSS `font-family` value. */\n fontBody?: string\n}\n\nconst ThemeContext = React.createContext<ThemeValue>({})\n\n/** Merged theme values from enclosing `<Theme>` providers. */\nexport function useTheme(): ThemeValue {\n return React.useContext(ThemeContext)\n}\n\nexport interface ThemeProps\n extends useRender.ComponentProps<'div'>, ThemeValue {}\n\n/** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */\nexport const Theme = React.forwardRef<HTMLDivElement, ThemeProps>(\n function Theme(\n {\n accentColor,\n backgroundColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n fontHeading,\n fontBody,\n render,\n className,\n style,\n children,\n ...rest\n },\n ref,\n ) {\n const parent = useTheme()\n\n const value = React.useMemo<ThemeValue>(\n () => ({\n accentColor: accentColor ?? parent.accentColor,\n backgroundColor: backgroundColor ?? parent.backgroundColor,\n neutralColor: neutralColor ?? parent.neutralColor,\n radius: radius ?? parent.radius,\n scaling: scaling ?? parent.scaling,\n spacing: spacing ?? parent.spacing,\n styleVariant: styleVariant ?? parent.styleVariant,\n highContrast: highContrast ?? parent.highContrast,\n labelPosition: labelPosition ?? parent.labelPosition,\n inputStyle: inputStyle ?? parent.inputStyle,\n inputColor: inputColor ?? parent.inputColor,\n cardVariant: cardVariant ?? parent.cardVariant,\n cardColor: cardColor ?? parent.cardColor,\n appearance: appearance ?? parent.appearance,\n fontHeading: fontHeading ?? parent.fontHeading,\n fontBody: fontBody ?? parent.fontBody,\n }),\n [\n accentColor,\n backgroundColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n fontHeading,\n fontBody,\n parent,\n ],\n )\n\n // Scope id for the ambient-appearance case (both scales emitted in a <style>).\n const scopeId = React.useId()\n\n // 'auto' pairs a neutral with the effective accent (Radix's grayColor=\"auto\").\n const resolvedNeutralColor =\n neutralColor === 'auto'\n ? getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT)\n : neutralColor\n\n const accent = React.useMemo(() => {\n const empty = {\n inlineVars: {} as React.CSSProperties,\n css: '',\n scoped: false,\n }\n // A custom canvas generates even with no accent of its own: the neutral ramp is\n // composited against it, and --spark-background has to carry it.\n if (!accentColor && !backgroundColor) return empty\n\n const toVars = (decls: string[]) =>\n Object.fromEntries(\n decls\n .filter((decl) => decl.includes(':'))\n .map((decl) => {\n const i = decl.indexOf(':')\n return [\n decl.slice(0, i).trim(),\n decl\n .slice(i + 1)\n .replace(/;$/, '')\n .trim(),\n ]\n }),\n ) as React.CSSProperties\n\n try {\n const source = value.accentColor ?? DEFAULT_ACCENT\n const hex = CURATED_ACCENTS[source] ?? source\n\n // A canvas has a polarity, unlike an accent hue: a yellow page is a *light*\n // page, and reusing it for the dark scale yields light ink on a light canvas\n // (measured 1.16:1). So the custom canvas applies to the appearance it actually\n // belongs to, and the other keeps its default. One knob still covers the common\n // case — a tenant wanting both sets an explicit appearance per scope.\n const bgAppearance = backgroundColor\n ? appearanceForBackground(backgroundColor)\n : undefined\n\n // Honouring a mismatched canvas would paint light ink on a light page, so it's\n // dropped — but say so, or the prop looks broken.\n if (\n backgroundColor &&\n value.appearance &&\n bgAppearance !== value.appearance\n ) {\n console.warn(\n `[Theme] Ignoring backgroundColor \"${backgroundColor}\": it reads as a ${bgAppearance} canvas on an appearance=\"${value.appearance}\" scope. Pass a ${value.appearance} colour, or set it on a scope whose appearance matches.`,\n )\n }\n\n // Default to slate so a regenerated neutral stays in the family the static\n // `:root` default already points at, rather than the generator's ECP gray seed.\n const optsFor = (appearance: Appearance) =>\n backgroundColor && bgAppearance === appearance\n ? {\n background: backgroundColor,\n neutral: resolvedNeutralColor ?? ('slate' as const),\n }\n : undefined\n\n // Neutrals are only worth regenerating against a custom canvas — see\n // neutralSparkVars. Without one the static Radix families are already correct.\n const emit = (scale: SparkAccentScale, custom: boolean) =>\n custom\n ? [...accentSparkVars(scale), ...neutralSparkVars(scale)]\n : accentSparkVars(scale)\n\n const build = (appearance: Appearance) => {\n const opts = optsFor(appearance)\n return emit(generateAccentScale(hex, appearance, opts), opts != null)\n }\n\n // Explicit appearance → single-scale inline vars. Correct for a light\n // island inside a dark page (which must NOT pick up the dark scale).\n if (value.appearance) {\n return {\n inlineVars: toVars(build(value.appearance)),\n css: '',\n scoped: false,\n }\n }\n\n // Ambient appearance → emit BOTH scales in a scoped <style> so the\n // `.dark` class selects the right one. Without this, a single-appearance\n // inline scale (default light) breaks components in dark mode.\n const light = build('light')\n const dark = build('dark')\n const sel = `[data-spark-scope=\"${scopeId}\"]`\n const css = `${sel}{${light.join('')}}:is(.dark,.dark-theme) ${sel}{${dark.join('')}}`\n return { inlineVars: {} as React.CSSProperties, css, scoped: true }\n } catch (error) {\n // A bad accentColor/backgroundColor must not throw through render — fall back\n // to the default theme.\n console.warn(\n `[Theme] Ignoring invalid accentColor \"${accentColor}\" / backgroundColor \"${backgroundColor}\".`,\n error,\n )\n return empty\n }\n }, [\n accentColor,\n backgroundColor,\n resolvedNeutralColor,\n value.accentColor,\n value.appearance,\n scopeId,\n ])\n\n const element = useRender({\n defaultTagName: 'div',\n render,\n ref,\n props: mergeProps<'div'>(\n {\n className: cn('spark-theme', appearance, className),\n 'data-neutral-color': resolvedNeutralColor,\n 'data-radius': radius,\n 'data-scaling': scaling,\n 'data-spacing': spacing,\n 'data-style': styleVariant,\n 'data-high-contrast': highContrast ? '' : undefined,\n 'data-label-position': labelPosition,\n 'data-input-style': inputStyle,\n 'data-input-color': inputColor,\n 'data-card-variant': cardVariant,\n 'data-card-color': cardColor === 'accent' ? 'accent' : undefined,\n 'data-spark-scope': accent.scoped ? scopeId : undefined,\n style: {\n ...accent.inlineVars,\n // Paint the canvas we were handed, else the prop emits a token and visibly\n // does nothing. Reads the var (not the raw prop) so the scoped <style>'s\n // per-appearance value still wins under ambient appearance.\n ...(backgroundColor\n ? { backgroundColor: 'var(--spark-background)' }\n : null),\n ...(fontHeading ? { '--spark-font-heading': fontHeading } : null),\n ...(fontBody ? { '--spark-font-body': fontBody } : null),\n ...style,\n } as React.CSSProperties,\n children,\n } as React.ComponentProps<'div'>,\n rest,\n ),\n })\n\n return (\n <ThemeContext.Provider value={value}>\n {accent.css ? <style>{accent.css}</style> : null}\n {element}\n </ThemeContext.Provider>\n )\n },\n)\n"],"mappings":";;;;;;;;;;;;;AA2CA,MAAM,iBAAiB;AAkCvB,MAAM,eAAeA,MAAM,cAA0B,CAAC,CAAC;;AAGvD,SAAgB,WAAuB;CACrC,OAAOA,MAAM,WAAW,YAAY;AACtC;;AAMA,MAAa,QAAQA,MAAM,WACzB,SAAS,MACP,EACE,aACA,iBACA,cACA,QACA,SACA,SACA,cACA,cACA,eACA,YACA,YACA,aACA,WACA,YACA,aACA,UACA,QACA,WACA,OACA,UACA,GAAG,QAEL,KACA;CACA,MAAM,SAAS,SAAS;CAExB,MAAM,QAAQA,MAAM,eACX;EACL,aAAa,eAAe,OAAO;EACnC,iBAAiB,mBAAmB,OAAO;EAC3C,cAAc,gBAAgB,OAAO;EACrC,QAAQ,UAAU,OAAO;EACzB,SAAS,WAAW,OAAO;EAC3B,SAAS,WAAW,OAAO;EAC3B,cAAc,gBAAgB,OAAO;EACrC,cAAc,gBAAgB,OAAO;EACrC,eAAe,iBAAiB,OAAO;EACvC,YAAY,cAAc,OAAO;EACjC,YAAY,cAAc,OAAO;EACjC,aAAa,eAAe,OAAO;EACnC,WAAW,aAAa,OAAO;EAC/B,YAAY,cAAc,OAAO;EACjC,aAAa,eAAe,OAAO;EACnC,UAAU,YAAY,OAAO;CAC/B,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAGA,MAAM,UAAUA,MAAM,MAAM;CAG5B,MAAM,uBACJ,iBAAiB,SACbC,yBAAAA,mBAAmB,MAAM,eAAe,cAAc,IACtD;CAEN,MAAM,SAASD,MAAM,cAAc;EACjC,MAAM,QAAQ;GACZ,YAAY,CAAC;GACb,KAAK;GACL,QAAQ;EACV;EAGA,IAAI,CAAC,eAAe,CAAC,iBAAiB,OAAO;EAE7C,MAAM,UAAU,UACd,OAAO,YACL,MACG,QAAQ,SAAS,KAAK,SAAS,GAAG,CAAC,EACnC,KAAK,SAAS;GACb,MAAM,IAAI,KAAK,QAAQ,GAAG;GAC1B,OAAO,CACL,KAAK,MAAM,GAAG,CAAC,EAAE,KAAK,GACtB,KACG,MAAM,IAAI,CAAC,EACX,QAAQ,MAAM,EAAE,EAChB,KAAK,CACV;EACF,CAAC,CACL;EAEF,IAAI;GACF,MAAM,SAAS,MAAM,eAAe;GACpC,MAAM,MAAME,yBAAAA,gBAAgB,WAAW;GAOvC,MAAM,eAAe,kBACjBC,yBAAAA,wBAAwB,eAAe,IACvC,KAAA;GAIJ,IACE,mBACA,MAAM,cACN,iBAAiB,MAAM,YAEvB,QAAQ,KACN,qCAAqC,gBAAgB,mBAAmB,aAAa,4BAA4B,MAAM,WAAW,kBAAkB,MAAM,WAAW,wDACvK;GAKF,MAAM,WAAW,eACf,mBAAmB,iBAAiB,aAChC;IACE,YAAY;IACZ,SAAS,wBAAyB;GACpC,IACA,KAAA;GAIN,MAAM,QAAQ,OAAyB,WACrC,SACI,CAAC,GAAGC,yBAAAA,gBAAgB,KAAK,GAAG,GAAGC,yBAAAA,iBAAiB,KAAK,CAAC,IACtDD,yBAAAA,gBAAgB,KAAK;GAE3B,MAAM,SAAS,eAA2B;IACxC,MAAM,OAAO,QAAQ,UAAU;IAC/B,OAAO,KAAKE,yBAAAA,oBAAoB,KAAK,YAAY,IAAI,GAAG,QAAQ,IAAI;GACtE;GAIA,IAAI,MAAM,YACR,OAAO;IACL,YAAY,OAAO,MAAM,MAAM,UAAU,CAAC;IAC1C,KAAK;IACL,QAAQ;GACV;GAMF,MAAM,QAAQ,MAAM,OAAO;GAC3B,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,MAAM,sBAAsB,QAAQ;GAE1C,OAAO;IAAE,YAAY,CAAC;IAA0B,KAAA,GADjC,IAAI,GAAG,MAAM,KAAK,EAAE,EAAE,0BAA0B,IAAI,GAAG,KAAK,KAAK,EAAE,EAAE;IAC/B,QAAQ;GAAK;EACpE,SAAS,OAAO;GAGd,QAAQ,KACN,yCAAyC,YAAY,uBAAuB,gBAAgB,KAC5F,KACF;GACA,OAAO;EACT;CACF,GAAG;EACD;EACA;EACA;EACA,MAAM;EACN,MAAM;EACN;CACF,CAAC;CAED,MAAM,WAAA,GAAA,0BAAA,WAAoB;EACxB,gBAAgB;EAChB;EACA;EACA,QAAA,GAAA,2BAAA,YACE;GACE,YAAA,GAAA,OAAA,IAAc,eAAe,YAAY,SAAS;GAClD,sBAAsB;GACtB,eAAe;GACf,gBAAgB;GAChB,gBAAgB;GAChB,cAAc;GACd,sBAAsB,eAAe,KAAK,KAAA;GAC1C,uBAAuB;GACvB,oBAAoB;GACpB,oBAAoB;GACpB,qBAAqB;GACrB,mBAAmB,cAAc,WAAW,WAAW,KAAA;GACvD,oBAAoB,OAAO,SAAS,UAAU,KAAA;GAC9C,OAAO;IACL,GAAG,OAAO;IAIV,GAAI,kBACA,EAAE,iBAAiB,0BAA0B,IAC7C;IACJ,GAAI,cAAc,EAAE,wBAAwB,YAAY,IAAI;IAC5D,GAAI,WAAW,EAAE,qBAAqB,SAAS,IAAI;IACnD,GAAG;GACL;GACA;EACF,GACA,IACF;CACF,CAAC;CAED,OACE,iBAAA,GAAA,kBAAA,MAAC,aAAa,UAAd;EAA8B;YAA9B,CACG,OAAO,MAAM,iBAAA,GAAA,kBAAA,KAAC,SAAD,EAAA,UAAQ,OAAO,IAAW,CAAA,IAAI,MAC3C,OACoB;;AAE3B,CACF"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { a as SparkLabelPosition, c as SparkScaling, i as SparkInputStyle, l as SparkSpacing, n as SparkCardVariant, o as SparkNeutral, r as SparkInputColor, s as SparkRadius, t as SparkCardColor, u as SparkStyle } from "../theme-types-8wjgiNA_.cjs";
3
+ import { a as SparkLabelPosition, c as SparkScaling, i as SparkInputStyle, l as SparkSpacing, n as SparkCardVariant, o as SparkNeutral, r as SparkInputColor, s as SparkRadius, t as SparkCardColor, u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
4
4
  import { Appearance } from "../lib/accent-theme.cjs";
5
5
  import * as React$1 from "react";
6
6
  import { useRender } from "@base-ui/react/use-render";
@@ -9,6 +9,13 @@ import { useRender } from "@base-ui/react/use-render";
9
9
  interface ThemeValue {
10
10
  /** Curated accent name or a custom hex. */
11
11
  accentColor?: string;
12
+ /**
13
+ * Page canvas as a custom hex. Regenerates BOTH the accent and neutral scales against
14
+ * it (each alpha step is composited against the canvas, so a saturated colour needs
15
+ * the neutral ramp regenerated too, not just the accent). Unset → the fixed
16
+ * `#ffffff` / `#000000` default, and neutrals stay on the static Radix families.
17
+ */
18
+ backgroundColor?: string;
12
19
  /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor="auto"`). */
13
20
  neutralColor?: SparkNeutral;
14
21
  radius?: SparkRadius;
@@ -25,6 +32,10 @@ interface ThemeValue {
25
32
  /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */
26
33
  cardColor?: SparkCardColor;
27
34
  appearance?: Appearance;
35
+ /** Font stack for `h1`–`h6`. Any valid CSS `font-family` value. */
36
+ fontHeading?: string;
37
+ /** Font stack for everything else. Any valid CSS `font-family` value. */
38
+ fontBody?: string;
28
39
  }
29
40
  /** Merged theme values from enclosing `<Theme>` providers. */
30
41
  declare function useTheme(): ThemeValue;
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { a as SparkLabelPosition, c as SparkScaling, i as SparkInputStyle, l as SparkSpacing, n as SparkCardVariant, o as SparkNeutral, r as SparkInputColor, s as SparkRadius, t as SparkCardColor, u as SparkStyle } from "../theme-types-8wjgiNA_.js";
3
+ import { a as SparkLabelPosition, c as SparkScaling, i as SparkInputStyle, l as SparkSpacing, n as SparkCardVariant, o as SparkNeutral, r as SparkInputColor, s as SparkRadius, t as SparkCardColor, u as SparkStyle } from "../theme-types-1yB0d8mp.js";
4
4
  import { Appearance } from "../lib/accent-theme.js";
5
5
  import * as React$1 from "react";
6
6
  import { useRender } from "@base-ui/react/use-render";
@@ -9,6 +9,13 @@ import { useRender } from "@base-ui/react/use-render";
9
9
  interface ThemeValue {
10
10
  /** Curated accent name or a custom hex. */
11
11
  accentColor?: string;
12
+ /**
13
+ * Page canvas as a custom hex. Regenerates BOTH the accent and neutral scales against
14
+ * it (each alpha step is composited against the canvas, so a saturated colour needs
15
+ * the neutral ramp regenerated too, not just the accent). Unset → the fixed
16
+ * `#ffffff` / `#000000` default, and neutrals stay on the static Radix families.
17
+ */
18
+ backgroundColor?: string;
12
19
  /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor="auto"`). */
13
20
  neutralColor?: SparkNeutral;
14
21
  radius?: SparkRadius;
@@ -25,6 +32,10 @@ interface ThemeValue {
25
32
  /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */
26
33
  cardColor?: SparkCardColor;
27
34
  appearance?: Appearance;
35
+ /** Font stack for `h1`–`h6`. Any valid CSS `font-family` value. */
36
+ fontHeading?: string;
37
+ /** Font stack for everything else. Any valid CSS `font-family` value. */
38
+ fontBody?: string;
28
39
  }
29
40
  /** Merged theme values from enclosing `<Theme>` providers. */
30
41
  declare function useTheme(): ThemeValue;
@@ -1,22 +1,25 @@
1
1
  "use client";
2
2
  "use client";
3
3
  import { cn } from "../utils/cn.js";
4
- import { CURATED_ACCENTS, accentSparkVars, generateAccentScale, getMatchingNeutral } from "../lib/accent-theme.js";
4
+ import { CURATED_ACCENTS, accentSparkVars, appearanceForBackground, generateAccentScale, getMatchingNeutral, neutralSparkVars } from "../lib/accent-theme.js";
5
5
  import * as React$1 from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { mergeProps } from "@base-ui/react/merge-props";
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  //#region src/components/theme.tsx
10
+ /** The epilot brand accent — the scale `spark-default.css` ships statically. */
11
+ const DEFAULT_ACCENT = "#005EB4";
10
12
  const ThemeContext = React$1.createContext({});
11
13
  /** Merged theme values from enclosing `<Theme>` providers. */
12
14
  function useTheme() {
13
15
  return React$1.useContext(ThemeContext);
14
16
  }
15
17
  /** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */
16
- const Theme = React$1.forwardRef(function Theme({ accentColor, neutralColor, radius, scaling, spacing, styleVariant, highContrast, labelPosition, inputStyle, inputColor, cardVariant, cardColor, appearance, render, className, style, children, ...rest }, ref) {
18
+ const Theme = React$1.forwardRef(function Theme({ accentColor, backgroundColor, neutralColor, radius, scaling, spacing, styleVariant, highContrast, labelPosition, inputStyle, inputColor, cardVariant, cardColor, appearance, fontHeading, fontBody, render, className, style, children, ...rest }, ref) {
17
19
  const parent = useTheme();
18
20
  const value = React$1.useMemo(() => ({
19
21
  accentColor: accentColor ?? parent.accentColor,
22
+ backgroundColor: backgroundColor ?? parent.backgroundColor,
20
23
  neutralColor: neutralColor ?? parent.neutralColor,
21
24
  radius: radius ?? parent.radius,
22
25
  scaling: scaling ?? parent.scaling,
@@ -28,9 +31,12 @@ const Theme = React$1.forwardRef(function Theme({ accentColor, neutralColor, rad
28
31
  inputColor: inputColor ?? parent.inputColor,
29
32
  cardVariant: cardVariant ?? parent.cardVariant,
30
33
  cardColor: cardColor ?? parent.cardColor,
31
- appearance: appearance ?? parent.appearance
34
+ appearance: appearance ?? parent.appearance,
35
+ fontHeading: fontHeading ?? parent.fontHeading,
36
+ fontBody: fontBody ?? parent.fontBody
32
37
  }), [
33
38
  accentColor,
39
+ backgroundColor,
34
40
  neutralColor,
35
41
  radius,
36
42
  scaling,
@@ -43,29 +49,44 @@ const Theme = React$1.forwardRef(function Theme({ accentColor, neutralColor, rad
43
49
  cardVariant,
44
50
  cardColor,
45
51
  appearance,
52
+ fontHeading,
53
+ fontBody,
46
54
  parent
47
55
  ]);
48
56
  const scopeId = React$1.useId();
57
+ const resolvedNeutralColor = neutralColor === "auto" ? getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT) : neutralColor;
49
58
  const accent = React$1.useMemo(() => {
50
59
  const empty = {
51
60
  inlineVars: {},
52
61
  css: "",
53
62
  scoped: false
54
63
  };
55
- if (!accentColor) return empty;
64
+ if (!accentColor && !backgroundColor) return empty;
56
65
  const toVars = (decls) => Object.fromEntries(decls.filter((decl) => decl.includes(":")).map((decl) => {
57
66
  const i = decl.indexOf(":");
58
67
  return [decl.slice(0, i).trim(), decl.slice(i + 1).replace(/;$/, "").trim()];
59
68
  }));
60
69
  try {
61
- const hex = CURATED_ACCENTS[accentColor] ?? accentColor;
70
+ const source = value.accentColor ?? DEFAULT_ACCENT;
71
+ const hex = CURATED_ACCENTS[source] ?? source;
72
+ const bgAppearance = backgroundColor ? appearanceForBackground(backgroundColor) : void 0;
73
+ if (backgroundColor && value.appearance && bgAppearance !== value.appearance) console.warn(`[Theme] Ignoring backgroundColor "${backgroundColor}": it reads as a ${bgAppearance} canvas on an appearance="${value.appearance}" scope. Pass a ${value.appearance} colour, or set it on a scope whose appearance matches.`);
74
+ const optsFor = (appearance) => backgroundColor && bgAppearance === appearance ? {
75
+ background: backgroundColor,
76
+ neutral: resolvedNeutralColor ?? "slate"
77
+ } : void 0;
78
+ const emit = (scale, custom) => custom ? [...accentSparkVars(scale), ...neutralSparkVars(scale)] : accentSparkVars(scale);
79
+ const build = (appearance) => {
80
+ const opts = optsFor(appearance);
81
+ return emit(generateAccentScale(hex, appearance, opts), opts != null);
82
+ };
62
83
  if (value.appearance) return {
63
- inlineVars: toVars(accentSparkVars(generateAccentScale(hex, value.appearance))),
84
+ inlineVars: toVars(build(value.appearance)),
64
85
  css: "",
65
86
  scoped: false
66
87
  };
67
- const light = accentSparkVars(generateAccentScale(hex, "light"));
68
- const dark = accentSparkVars(generateAccentScale(hex, "dark"));
88
+ const light = build("light");
89
+ const dark = build("dark");
69
90
  const sel = `[data-spark-scope="${scopeId}"]`;
70
91
  return {
71
92
  inlineVars: {},
@@ -73,15 +94,17 @@ const Theme = React$1.forwardRef(function Theme({ accentColor, neutralColor, rad
73
94
  scoped: true
74
95
  };
75
96
  } catch (error) {
76
- console.warn(`[Theme] Ignoring invalid accentColor "${accentColor}".`, error);
97
+ console.warn(`[Theme] Ignoring invalid accentColor "${accentColor}" / backgroundColor "${backgroundColor}".`, error);
77
98
  return empty;
78
99
  }
79
100
  }, [
80
101
  accentColor,
102
+ backgroundColor,
103
+ resolvedNeutralColor,
104
+ value.accentColor,
81
105
  value.appearance,
82
106
  scopeId
83
107
  ]);
84
- const resolvedNeutralColor = neutralColor === "auto" ? getMatchingNeutral(value.accentColor ?? "#005EB4") : neutralColor;
85
108
  const element = useRender({
86
109
  defaultTagName: "div",
87
110
  render,
@@ -102,6 +125,9 @@ const Theme = React$1.forwardRef(function Theme({ accentColor, neutralColor, rad
102
125
  "data-spark-scope": accent.scoped ? scopeId : void 0,
103
126
  style: {
104
127
  ...accent.inlineVars,
128
+ ...backgroundColor ? { backgroundColor: "var(--spark-background)" } : null,
129
+ ...fontHeading ? { "--spark-font-heading": fontHeading } : null,
130
+ ...fontBody ? { "--spark-font-body": fontBody } : null,
105
131
  ...style
106
132
  },
107
133
  children
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","names":["React"],"sources":["../../src/components/theme.tsx"],"sourcesContent":["'use client'\n\nimport { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n CURATED_ACCENTS,\n accentSparkVars,\n generateAccentScale,\n getMatchingNeutral,\n type Appearance,\n} from '../lib/accent-theme'\nimport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\n\nexport interface ThemeValue {\n /** Curated accent name or a custom hex. */\n accentColor?: string\n /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor=\"auto\"`). */\n neutralColor?: SparkNeutral\n radius?: SparkRadius\n scaling?: SparkScaling\n spacing?: SparkSpacing\n styleVariant?: SparkStyle\n /** Orthogonal to `styleVariant`: shifts any style toward higher-contrast steps. */\n highContrast?: boolean\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n /** App-level default `<Card>` chrome; a per-card `variant` prop overrides it. */\n cardVariant?: SparkCardVariant\n /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */\n cardColor?: SparkCardColor\n appearance?: Appearance\n}\n\nconst ThemeContext = React.createContext<ThemeValue>({})\n\n/** Merged theme values from enclosing `<Theme>` providers. */\nexport function useTheme(): ThemeValue {\n return React.useContext(ThemeContext)\n}\n\nexport interface ThemeProps\n extends useRender.ComponentProps<'div'>, ThemeValue {}\n\n/** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */\nexport const Theme = React.forwardRef<HTMLDivElement, ThemeProps>(\n function Theme(\n {\n accentColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n render,\n className,\n style,\n children,\n ...rest\n },\n ref,\n ) {\n const parent = useTheme()\n\n const value = React.useMemo<ThemeValue>(\n () => ({\n accentColor: accentColor ?? parent.accentColor,\n neutralColor: neutralColor ?? parent.neutralColor,\n radius: radius ?? parent.radius,\n scaling: scaling ?? parent.scaling,\n spacing: spacing ?? parent.spacing,\n styleVariant: styleVariant ?? parent.styleVariant,\n highContrast: highContrast ?? parent.highContrast,\n labelPosition: labelPosition ?? parent.labelPosition,\n inputStyle: inputStyle ?? parent.inputStyle,\n inputColor: inputColor ?? parent.inputColor,\n cardVariant: cardVariant ?? parent.cardVariant,\n cardColor: cardColor ?? parent.cardColor,\n appearance: appearance ?? parent.appearance,\n }),\n [\n accentColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n parent,\n ],\n )\n\n // Scope id for the ambient-appearance case (both scales emitted in a <style>).\n const scopeId = React.useId()\n\n const accent = React.useMemo(() => {\n const empty = {\n inlineVars: {} as React.CSSProperties,\n css: '',\n scoped: false,\n }\n if (!accentColor) return empty\n\n const toVars = (decls: string[]) =>\n Object.fromEntries(\n decls\n .filter((decl) => decl.includes(':'))\n .map((decl) => {\n const i = decl.indexOf(':')\n return [\n decl.slice(0, i).trim(),\n decl\n .slice(i + 1)\n .replace(/;$/, '')\n .trim(),\n ]\n }),\n ) as React.CSSProperties\n\n try {\n const hex = CURATED_ACCENTS[accentColor] ?? accentColor\n\n // Explicit appearance → single-scale inline vars. Correct for a light\n // island inside a dark page (which must NOT pick up the dark scale).\n if (value.appearance) {\n return {\n inlineVars: toVars(\n accentSparkVars(generateAccentScale(hex, value.appearance)),\n ),\n css: '',\n scoped: false,\n }\n }\n\n // Ambient appearance → emit BOTH scales in a scoped <style> so the\n // `.dark` class selects the right one. Without this, a single-appearance\n // inline scale (default light) breaks components in dark mode.\n const light = accentSparkVars(generateAccentScale(hex, 'light'))\n const dark = accentSparkVars(generateAccentScale(hex, 'dark'))\n const sel = `[data-spark-scope=\"${scopeId}\"]`\n const css = `${sel}{${light.join('')}}:is(.dark,.dark-theme) ${sel}{${dark.join('')}}`\n return { inlineVars: {} as React.CSSProperties, css, scoped: true }\n } catch (error) {\n // A bad accentColor must not throw through render — fall back to the default theme.\n console.warn(\n `[Theme] Ignoring invalid accentColor \"${accentColor}\".`,\n error,\n )\n return empty\n }\n }, [accentColor, value.appearance, scopeId])\n\n // 'auto' pairs a neutral with the effective accent (Radix's grayColor=\"auto\").\n const resolvedNeutralColor =\n neutralColor === 'auto'\n ? getMatchingNeutral(value.accentColor ?? '#005EB4')\n : neutralColor\n\n const element = useRender({\n defaultTagName: 'div',\n render,\n ref,\n props: mergeProps<'div'>(\n {\n className: cn('spark-theme', appearance, className),\n 'data-neutral-color': resolvedNeutralColor,\n 'data-radius': radius,\n 'data-scaling': scaling,\n 'data-spacing': spacing,\n 'data-style': styleVariant,\n 'data-high-contrast': highContrast ? '' : undefined,\n 'data-label-position': labelPosition,\n 'data-input-style': inputStyle,\n 'data-input-color': inputColor,\n 'data-card-variant': cardVariant,\n 'data-card-color': cardColor === 'accent' ? 'accent' : undefined,\n 'data-spark-scope': accent.scoped ? scopeId : undefined,\n style: { ...accent.inlineVars, ...style },\n children,\n } as React.ComponentProps<'div'>,\n rest,\n ),\n })\n\n return (\n <ThemeContext.Provider value={value}>\n {accent.css ? <style>{accent.css}</style> : null}\n {element}\n </ThemeContext.Provider>\n )\n },\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"theme.js","names":["React"],"sources":["../../src/components/theme.tsx"],"sourcesContent":["'use client'\n\nimport { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport {\n CURATED_ACCENTS,\n accentSparkVars,\n appearanceForBackground,\n generateAccentScale,\n getMatchingNeutral,\n neutralSparkVars,\n type Appearance,\n type SparkAccentScale,\n} from '../lib/accent-theme'\nimport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\nexport type {\n SparkCardColor,\n SparkCardVariant,\n SparkInputColor,\n SparkInputStyle,\n SparkLabelPosition,\n SparkNeutral,\n SparkRadius,\n SparkScaling,\n SparkSpacing,\n SparkStyle,\n} from '../lib/theme-types'\n\n/** The epilot brand accent — the scale `spark-default.css` ships statically. */\nconst DEFAULT_ACCENT = '#005EB4'\n\nexport interface ThemeValue {\n /** Curated accent name or a custom hex. */\n accentColor?: string\n /**\n * Page canvas as a custom hex. Regenerates BOTH the accent and neutral scales against\n * it (each alpha step is composited against the canvas, so a saturated colour needs\n * the neutral ramp regenerated too, not just the accent). Unset → the fixed\n * `#ffffff` / `#000000` default, and neutrals stay on the static Radix families.\n */\n backgroundColor?: string\n /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor=\"auto\"`). */\n neutralColor?: SparkNeutral\n radius?: SparkRadius\n scaling?: SparkScaling\n spacing?: SparkSpacing\n styleVariant?: SparkStyle\n /** Orthogonal to `styleVariant`: shifts any style toward higher-contrast steps. */\n highContrast?: boolean\n labelPosition?: SparkLabelPosition\n inputStyle?: SparkInputStyle\n inputColor?: SparkInputColor\n /** App-level default `<Card>` chrome; a per-card `variant` prop overrides it. */\n cardVariant?: SparkCardVariant\n /** App-level default `<Card>` palette; a per-card `color` prop overrides it. */\n cardColor?: SparkCardColor\n appearance?: Appearance\n /** Font stack for `h1`–`h6`. Any valid CSS `font-family` value. */\n fontHeading?: string\n /** Font stack for everything else. Any valid CSS `font-family` value. */\n fontBody?: string\n}\n\nconst ThemeContext = React.createContext<ThemeValue>({})\n\n/** Merged theme values from enclosing `<Theme>` providers. */\nexport function useTheme(): ThemeValue {\n return React.useContext(ThemeContext)\n}\n\nexport interface ThemeProps\n extends useRender.ComponentProps<'div'>, ThemeValue {}\n\n/** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */\nexport const Theme = React.forwardRef<HTMLDivElement, ThemeProps>(\n function Theme(\n {\n accentColor,\n backgroundColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n fontHeading,\n fontBody,\n render,\n className,\n style,\n children,\n ...rest\n },\n ref,\n ) {\n const parent = useTheme()\n\n const value = React.useMemo<ThemeValue>(\n () => ({\n accentColor: accentColor ?? parent.accentColor,\n backgroundColor: backgroundColor ?? parent.backgroundColor,\n neutralColor: neutralColor ?? parent.neutralColor,\n radius: radius ?? parent.radius,\n scaling: scaling ?? parent.scaling,\n spacing: spacing ?? parent.spacing,\n styleVariant: styleVariant ?? parent.styleVariant,\n highContrast: highContrast ?? parent.highContrast,\n labelPosition: labelPosition ?? parent.labelPosition,\n inputStyle: inputStyle ?? parent.inputStyle,\n inputColor: inputColor ?? parent.inputColor,\n cardVariant: cardVariant ?? parent.cardVariant,\n cardColor: cardColor ?? parent.cardColor,\n appearance: appearance ?? parent.appearance,\n fontHeading: fontHeading ?? parent.fontHeading,\n fontBody: fontBody ?? parent.fontBody,\n }),\n [\n accentColor,\n backgroundColor,\n neutralColor,\n radius,\n scaling,\n spacing,\n styleVariant,\n highContrast,\n labelPosition,\n inputStyle,\n inputColor,\n cardVariant,\n cardColor,\n appearance,\n fontHeading,\n fontBody,\n parent,\n ],\n )\n\n // Scope id for the ambient-appearance case (both scales emitted in a <style>).\n const scopeId = React.useId()\n\n // 'auto' pairs a neutral with the effective accent (Radix's grayColor=\"auto\").\n const resolvedNeutralColor =\n neutralColor === 'auto'\n ? getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT)\n : neutralColor\n\n const accent = React.useMemo(() => {\n const empty = {\n inlineVars: {} as React.CSSProperties,\n css: '',\n scoped: false,\n }\n // A custom canvas generates even with no accent of its own: the neutral ramp is\n // composited against it, and --spark-background has to carry it.\n if (!accentColor && !backgroundColor) return empty\n\n const toVars = (decls: string[]) =>\n Object.fromEntries(\n decls\n .filter((decl) => decl.includes(':'))\n .map((decl) => {\n const i = decl.indexOf(':')\n return [\n decl.slice(0, i).trim(),\n decl\n .slice(i + 1)\n .replace(/;$/, '')\n .trim(),\n ]\n }),\n ) as React.CSSProperties\n\n try {\n const source = value.accentColor ?? DEFAULT_ACCENT\n const hex = CURATED_ACCENTS[source] ?? source\n\n // A canvas has a polarity, unlike an accent hue: a yellow page is a *light*\n // page, and reusing it for the dark scale yields light ink on a light canvas\n // (measured 1.16:1). So the custom canvas applies to the appearance it actually\n // belongs to, and the other keeps its default. One knob still covers the common\n // case — a tenant wanting both sets an explicit appearance per scope.\n const bgAppearance = backgroundColor\n ? appearanceForBackground(backgroundColor)\n : undefined\n\n // Honouring a mismatched canvas would paint light ink on a light page, so it's\n // dropped — but say so, or the prop looks broken.\n if (\n backgroundColor &&\n value.appearance &&\n bgAppearance !== value.appearance\n ) {\n console.warn(\n `[Theme] Ignoring backgroundColor \"${backgroundColor}\": it reads as a ${bgAppearance} canvas on an appearance=\"${value.appearance}\" scope. Pass a ${value.appearance} colour, or set it on a scope whose appearance matches.`,\n )\n }\n\n // Default to slate so a regenerated neutral stays in the family the static\n // `:root` default already points at, rather than the generator's ECP gray seed.\n const optsFor = (appearance: Appearance) =>\n backgroundColor && bgAppearance === appearance\n ? {\n background: backgroundColor,\n neutral: resolvedNeutralColor ?? ('slate' as const),\n }\n : undefined\n\n // Neutrals are only worth regenerating against a custom canvas — see\n // neutralSparkVars. Without one the static Radix families are already correct.\n const emit = (scale: SparkAccentScale, custom: boolean) =>\n custom\n ? [...accentSparkVars(scale), ...neutralSparkVars(scale)]\n : accentSparkVars(scale)\n\n const build = (appearance: Appearance) => {\n const opts = optsFor(appearance)\n return emit(generateAccentScale(hex, appearance, opts), opts != null)\n }\n\n // Explicit appearance → single-scale inline vars. Correct for a light\n // island inside a dark page (which must NOT pick up the dark scale).\n if (value.appearance) {\n return {\n inlineVars: toVars(build(value.appearance)),\n css: '',\n scoped: false,\n }\n }\n\n // Ambient appearance → emit BOTH scales in a scoped <style> so the\n // `.dark` class selects the right one. Without this, a single-appearance\n // inline scale (default light) breaks components in dark mode.\n const light = build('light')\n const dark = build('dark')\n const sel = `[data-spark-scope=\"${scopeId}\"]`\n const css = `${sel}{${light.join('')}}:is(.dark,.dark-theme) ${sel}{${dark.join('')}}`\n return { inlineVars: {} as React.CSSProperties, css, scoped: true }\n } catch (error) {\n // A bad accentColor/backgroundColor must not throw through render — fall back\n // to the default theme.\n console.warn(\n `[Theme] Ignoring invalid accentColor \"${accentColor}\" / backgroundColor \"${backgroundColor}\".`,\n error,\n )\n return empty\n }\n }, [\n accentColor,\n backgroundColor,\n resolvedNeutralColor,\n value.accentColor,\n value.appearance,\n scopeId,\n ])\n\n const element = useRender({\n defaultTagName: 'div',\n render,\n ref,\n props: mergeProps<'div'>(\n {\n className: cn('spark-theme', appearance, className),\n 'data-neutral-color': resolvedNeutralColor,\n 'data-radius': radius,\n 'data-scaling': scaling,\n 'data-spacing': spacing,\n 'data-style': styleVariant,\n 'data-high-contrast': highContrast ? '' : undefined,\n 'data-label-position': labelPosition,\n 'data-input-style': inputStyle,\n 'data-input-color': inputColor,\n 'data-card-variant': cardVariant,\n 'data-card-color': cardColor === 'accent' ? 'accent' : undefined,\n 'data-spark-scope': accent.scoped ? scopeId : undefined,\n style: {\n ...accent.inlineVars,\n // Paint the canvas we were handed, else the prop emits a token and visibly\n // does nothing. Reads the var (not the raw prop) so the scoped <style>'s\n // per-appearance value still wins under ambient appearance.\n ...(backgroundColor\n ? { backgroundColor: 'var(--spark-background)' }\n : null),\n ...(fontHeading ? { '--spark-font-heading': fontHeading } : null),\n ...(fontBody ? { '--spark-font-body': fontBody } : null),\n ...style,\n } as React.CSSProperties,\n children,\n } as React.ComponentProps<'div'>,\n rest,\n ),\n })\n\n return (\n <ThemeContext.Provider value={value}>\n {accent.css ? <style>{accent.css}</style> : null}\n {element}\n </ThemeContext.Provider>\n )\n },\n)\n"],"mappings":"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"}
@@ -87,6 +87,7 @@ const materialSymbolIconNames = [
87
87
  const materialSymbolIconNamesString = [...materialSymbolIconNames].sort().join(",");
88
88
  const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`;
89
89
  const MaterialSymbol = ({ name, className }) => {
90
+ if (!materialSymbolIconNames.includes(name)) console.warn(`[MaterialSymbol] "${name}" isn't a recognized icon name — it will render as literal text, not an icon. See materialSymbolIconNames from '@epilot/spark-ui/icons' for the full set.`);
90
91
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
91
92
  "aria-hidden": "true",
92
93
  className: (0, cnfast.cn)("material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none", className),
@@ -1 +1 @@
1
- {"version":3,"file":"material-symbol.cjs","names":[],"sources":["../../src/icons/material-symbol.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport const materialSymbolIconNames = [\n 'access_time',\n 'add',\n 'alarm',\n 'arrow_downward',\n 'arrow_upward',\n 'auto_awesome',\n 'bar_chart',\n 'battery_0_bar',\n 'battery_1_bar',\n 'battery_2_bar',\n 'battery_3_bar',\n 'battery_4_bar',\n 'battery_5_bar',\n 'battery_6_bar',\n 'battery_charging_20',\n 'battery_charging_30',\n 'battery_charging_50',\n 'battery_charging_60',\n 'battery_charging_80',\n 'battery_charging_90',\n 'battery_charging_full',\n 'battery_full',\n 'bolt',\n 'calendar_month',\n 'cancel',\n 'check',\n 'check_circle',\n 'chevron_left',\n 'chevron_right',\n 'circle',\n 'close',\n 'close_fullscreen',\n 'content_copy',\n 'dashboard_2',\n 'delete',\n 'dishwasher',\n 'drag_indicator',\n 'edit',\n 'edit_square',\n 'electric_bolt',\n 'electric_car',\n 'electrical_services',\n 'ev_station',\n 'expand_more',\n 'heat_pump',\n 'home',\n 'info',\n 'laundry',\n 'layers',\n 'local_fire_department',\n 'more_vert',\n 'open_in_full',\n 'open_in_new',\n 'payments',\n 'pending',\n 'power',\n 'search',\n 'power_settings_new',\n 'price_change',\n 'recycling',\n 'refresh',\n 'schedule',\n 'settings',\n 'solar_power',\n 'speed',\n 'sunny',\n 'partly_cloudy_day',\n 'cloudy',\n 'rainy',\n 'weather_snowy',\n 'swap_vert',\n 'thermostat',\n 'toggle_on',\n 'track_changes',\n 'trending_down',\n 'trending_up',\n 'tune',\n 'warning',\n 'wifi_off',\n] as const\n\nexport const materialSymbolIconNamesString = [...materialSymbolIconNames]\n .sort()\n .join(',')\nexport const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`\n\nexport type MaterialSymbolIconName = (typeof materialSymbolIconNames)[number]\n\nexport type MaterialSymbolProps = {\n name: MaterialSymbolIconName\n className?: string\n}\n\nconst MaterialSymbol = ({ name, className }: MaterialSymbolProps) => {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n // !important: the Google Fonts stylesheet is unlayered (24px) and beats every layered\n // utility — callers size the icon via --spark-icon-size, not font-size classes\n 'material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none',\n className,\n )}\n translate=\"no\"\n >\n {name}\n </span>\n )\n}\nMaterialSymbol.displayName = 'MaterialSymbol'\n\nexport { MaterialSymbol }\n"],"mappings":";;;;;AAEA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gCAAgC,CAAC,GAAG,uBAAuB,EACrE,KAAK,EACL,KAAK,GAAG;AACX,MAAa,6BAA6B,+GAA+G,8BAA8B;AASvL,MAAM,kBAAkB,EAAE,MAAM,gBAAqC;CACnE,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,eAAY;EACZ,YAAA,GAAA,OAAA,IAGE,iHACA,SACF;EACA,WAAU;YAET;CACG,CAAA;AAEV;AACA,eAAe,cAAc"}
1
+ {"version":3,"file":"material-symbol.cjs","names":[],"sources":["../../src/icons/material-symbol.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport const materialSymbolIconNames = [\n 'access_time',\n 'add',\n 'alarm',\n 'arrow_downward',\n 'arrow_upward',\n 'auto_awesome',\n 'bar_chart',\n 'battery_0_bar',\n 'battery_1_bar',\n 'battery_2_bar',\n 'battery_3_bar',\n 'battery_4_bar',\n 'battery_5_bar',\n 'battery_6_bar',\n 'battery_charging_20',\n 'battery_charging_30',\n 'battery_charging_50',\n 'battery_charging_60',\n 'battery_charging_80',\n 'battery_charging_90',\n 'battery_charging_full',\n 'battery_full',\n 'bolt',\n 'calendar_month',\n 'cancel',\n 'check',\n 'check_circle',\n 'chevron_left',\n 'chevron_right',\n 'circle',\n 'close',\n 'close_fullscreen',\n 'content_copy',\n 'dashboard_2',\n 'delete',\n 'dishwasher',\n 'drag_indicator',\n 'edit',\n 'edit_square',\n 'electric_bolt',\n 'electric_car',\n 'electrical_services',\n 'ev_station',\n 'expand_more',\n 'heat_pump',\n 'home',\n 'info',\n 'laundry',\n 'layers',\n 'local_fire_department',\n 'more_vert',\n 'open_in_full',\n 'open_in_new',\n 'payments',\n 'pending',\n 'power',\n 'search',\n 'power_settings_new',\n 'price_change',\n 'recycling',\n 'refresh',\n 'schedule',\n 'settings',\n 'solar_power',\n 'speed',\n 'sunny',\n 'partly_cloudy_day',\n 'cloudy',\n 'rainy',\n 'weather_snowy',\n 'swap_vert',\n 'thermostat',\n 'toggle_on',\n 'track_changes',\n 'trending_down',\n 'trending_up',\n 'tune',\n 'warning',\n 'wifi_off',\n] as const\n\nexport const materialSymbolIconNamesString = [...materialSymbolIconNames]\n .sort()\n .join(',')\nexport const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`\n\nexport type MaterialSymbolIconName = (typeof materialSymbolIconNames)[number]\n\nexport type MaterialSymbolProps = {\n name: MaterialSymbolIconName\n className?: string\n}\n\nconst MaterialSymbol = ({ name, className }: MaterialSymbolProps) => {\n if (!materialSymbolIconNames.includes(name)) {\n console.warn(\n `[MaterialSymbol] \"${name}\" isn't a recognized icon name — it will render as literal text, not an icon. See materialSymbolIconNames from '@epilot/spark-ui/icons' for the full set.`,\n )\n }\n\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n // !important: the Google Fonts stylesheet is unlayered (24px) and beats every layered\n // utility — callers size the icon via --spark-icon-size, not font-size classes\n 'material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none',\n className,\n )}\n translate=\"no\"\n >\n {name}\n </span>\n )\n}\nMaterialSymbol.displayName = 'MaterialSymbol'\n\nexport { MaterialSymbol }\n"],"mappings":";;;;;AAEA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gCAAgC,CAAC,GAAG,uBAAuB,EACrE,KAAK,EACL,KAAK,GAAG;AACX,MAAa,6BAA6B,+GAA+G,8BAA8B;AASvL,MAAM,kBAAkB,EAAE,MAAM,gBAAqC;CACnE,IAAI,CAAC,wBAAwB,SAAS,IAAI,GACxC,QAAQ,KACN,qBAAqB,KAAK,0JAC5B;CAGF,OACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,eAAY;EACZ,YAAA,GAAA,OAAA,IAGE,iHACA,SACF;EACA,WAAU;YAET;CACG,CAAA;AAEV;AACA,eAAe,cAAc"}
@@ -86,6 +86,7 @@ const materialSymbolIconNames = [
86
86
  const materialSymbolIconNamesString = [...materialSymbolIconNames].sort().join(",");
87
87
  const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`;
88
88
  const MaterialSymbol = ({ name, className }) => {
89
+ if (!materialSymbolIconNames.includes(name)) console.warn(`[MaterialSymbol] "${name}" isn't a recognized icon name — it will render as literal text, not an icon. See materialSymbolIconNames from '@epilot/spark-ui/icons' for the full set.`);
89
90
  return /* @__PURE__ */ jsx("span", {
90
91
  "aria-hidden": "true",
91
92
  className: cn("material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none", className),
@@ -1 +1 @@
1
- {"version":3,"file":"material-symbol.js","names":[],"sources":["../../src/icons/material-symbol.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport const materialSymbolIconNames = [\n 'access_time',\n 'add',\n 'alarm',\n 'arrow_downward',\n 'arrow_upward',\n 'auto_awesome',\n 'bar_chart',\n 'battery_0_bar',\n 'battery_1_bar',\n 'battery_2_bar',\n 'battery_3_bar',\n 'battery_4_bar',\n 'battery_5_bar',\n 'battery_6_bar',\n 'battery_charging_20',\n 'battery_charging_30',\n 'battery_charging_50',\n 'battery_charging_60',\n 'battery_charging_80',\n 'battery_charging_90',\n 'battery_charging_full',\n 'battery_full',\n 'bolt',\n 'calendar_month',\n 'cancel',\n 'check',\n 'check_circle',\n 'chevron_left',\n 'chevron_right',\n 'circle',\n 'close',\n 'close_fullscreen',\n 'content_copy',\n 'dashboard_2',\n 'delete',\n 'dishwasher',\n 'drag_indicator',\n 'edit',\n 'edit_square',\n 'electric_bolt',\n 'electric_car',\n 'electrical_services',\n 'ev_station',\n 'expand_more',\n 'heat_pump',\n 'home',\n 'info',\n 'laundry',\n 'layers',\n 'local_fire_department',\n 'more_vert',\n 'open_in_full',\n 'open_in_new',\n 'payments',\n 'pending',\n 'power',\n 'search',\n 'power_settings_new',\n 'price_change',\n 'recycling',\n 'refresh',\n 'schedule',\n 'settings',\n 'solar_power',\n 'speed',\n 'sunny',\n 'partly_cloudy_day',\n 'cloudy',\n 'rainy',\n 'weather_snowy',\n 'swap_vert',\n 'thermostat',\n 'toggle_on',\n 'track_changes',\n 'trending_down',\n 'trending_up',\n 'tune',\n 'warning',\n 'wifi_off',\n] as const\n\nexport const materialSymbolIconNamesString = [...materialSymbolIconNames]\n .sort()\n .join(',')\nexport const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`\n\nexport type MaterialSymbolIconName = (typeof materialSymbolIconNames)[number]\n\nexport type MaterialSymbolProps = {\n name: MaterialSymbolIconName\n className?: string\n}\n\nconst MaterialSymbol = ({ name, className }: MaterialSymbolProps) => {\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n // !important: the Google Fonts stylesheet is unlayered (24px) and beats every layered\n // utility — callers size the icon via --spark-icon-size, not font-size classes\n 'material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none',\n className,\n )}\n translate=\"no\"\n >\n {name}\n </span>\n )\n}\nMaterialSymbol.displayName = 'MaterialSymbol'\n\nexport { MaterialSymbol }\n"],"mappings":";;;;AAEA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gCAAgC,CAAC,GAAG,uBAAuB,EACrE,KAAK,EACL,KAAK,GAAG;AACX,MAAa,6BAA6B,+GAA+G,8BAA8B;AASvL,MAAM,kBAAkB,EAAE,MAAM,gBAAqC;CACnE,OACE,oBAAC,QAAD;EACE,eAAY;EACZ,WAAW,GAGT,iHACA,SACF;EACA,WAAU;YAET;CACG,CAAA;AAEV;AACA,eAAe,cAAc"}
1
+ {"version":3,"file":"material-symbol.js","names":[],"sources":["../../src/icons/material-symbol.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport const materialSymbolIconNames = [\n 'access_time',\n 'add',\n 'alarm',\n 'arrow_downward',\n 'arrow_upward',\n 'auto_awesome',\n 'bar_chart',\n 'battery_0_bar',\n 'battery_1_bar',\n 'battery_2_bar',\n 'battery_3_bar',\n 'battery_4_bar',\n 'battery_5_bar',\n 'battery_6_bar',\n 'battery_charging_20',\n 'battery_charging_30',\n 'battery_charging_50',\n 'battery_charging_60',\n 'battery_charging_80',\n 'battery_charging_90',\n 'battery_charging_full',\n 'battery_full',\n 'bolt',\n 'calendar_month',\n 'cancel',\n 'check',\n 'check_circle',\n 'chevron_left',\n 'chevron_right',\n 'circle',\n 'close',\n 'close_fullscreen',\n 'content_copy',\n 'dashboard_2',\n 'delete',\n 'dishwasher',\n 'drag_indicator',\n 'edit',\n 'edit_square',\n 'electric_bolt',\n 'electric_car',\n 'electrical_services',\n 'ev_station',\n 'expand_more',\n 'heat_pump',\n 'home',\n 'info',\n 'laundry',\n 'layers',\n 'local_fire_department',\n 'more_vert',\n 'open_in_full',\n 'open_in_new',\n 'payments',\n 'pending',\n 'power',\n 'search',\n 'power_settings_new',\n 'price_change',\n 'recycling',\n 'refresh',\n 'schedule',\n 'settings',\n 'solar_power',\n 'speed',\n 'sunny',\n 'partly_cloudy_day',\n 'cloudy',\n 'rainy',\n 'weather_snowy',\n 'swap_vert',\n 'thermostat',\n 'toggle_on',\n 'track_changes',\n 'trending_down',\n 'trending_up',\n 'tune',\n 'warning',\n 'wifi_off',\n] as const\n\nexport const materialSymbolIconNamesString = [...materialSymbolIconNames]\n .sort()\n .join(',')\nexport const materialSymbolIconNamesURL = `https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20,400,0,0&icon_names=${materialSymbolIconNamesString}&display=block`\n\nexport type MaterialSymbolIconName = (typeof materialSymbolIconNames)[number]\n\nexport type MaterialSymbolProps = {\n name: MaterialSymbolIconName\n className?: string\n}\n\nconst MaterialSymbol = ({ name, className }: MaterialSymbolProps) => {\n if (!materialSymbolIconNames.includes(name)) {\n console.warn(\n `[MaterialSymbol] \"${name}\" isn't a recognized icon name — it will render as literal text, not an icon. See materialSymbolIconNames from '@epilot/spark-ui/icons' for the full set.`,\n )\n }\n\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n // !important: the Google Fonts stylesheet is unlayered (24px) and beats every layered\n // utility — callers size the icon via --spark-icon-size, not font-size classes\n 'material-symbols-rounded inline-block shrink-0 text-(length:--spark-icon-size,20px)! leading-none select-none',\n className,\n )}\n translate=\"no\"\n >\n {name}\n </span>\n )\n}\nMaterialSymbol.displayName = 'MaterialSymbol'\n\nexport { MaterialSymbol }\n"],"mappings":";;;;AAEA,MAAa,0BAA0B;CACrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,gCAAgC,CAAC,GAAG,uBAAuB,EACrE,KAAK,EACL,KAAK,GAAG;AACX,MAAa,6BAA6B,+GAA+G,8BAA8B;AASvL,MAAM,kBAAkB,EAAE,MAAM,gBAAqC;CACnE,IAAI,CAAC,wBAAwB,SAAS,IAAI,GACxC,QAAQ,KACN,qBAAqB,KAAK,0JAC5B;CAGF,OACE,oBAAC,QAAD;EACE,eAAY;EACZ,WAAW,GAGT,iHACA,SACF;EACA,WAAU;YAET;CACG,CAAA;AAEV;AACA,eAAe,cAAc"}