@epilot/spark-ui 0.11.1 → 0.12.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.
Files changed (125) hide show
  1. package/dist/components/avatar.d.cts +1 -1
  2. package/dist/components/avatar.d.ts +1 -1
  3. package/dist/components/badge.d.cts +1 -1
  4. package/dist/components/badge.d.ts +1 -1
  5. package/dist/components/bar-chart.js +1 -1
  6. package/dist/components/box.cjs +3 -2
  7. package/dist/components/box.cjs.map +1 -1
  8. package/dist/components/box.d.cts +8 -1
  9. package/dist/components/box.d.ts +8 -1
  10. package/dist/components/box.js +3 -2
  11. package/dist/components/box.js.map +1 -1
  12. package/dist/components/button-group.d.cts +1 -1
  13. package/dist/components/button-group.d.ts +1 -1
  14. package/dist/components/button.d.cts +2 -2
  15. package/dist/components/button.d.ts +2 -2
  16. package/dist/components/calendar.cjs +2 -2
  17. package/dist/components/calendar.cjs.map +1 -1
  18. package/dist/components/calendar.js +2 -2
  19. package/dist/components/calendar.js.map +1 -1
  20. package/dist/components/callout.cjs +1 -1
  21. package/dist/components/callout.cjs.map +1 -1
  22. package/dist/components/callout.d.cts +3 -3
  23. package/dist/components/callout.d.ts +3 -3
  24. package/dist/components/callout.js +1 -1
  25. package/dist/components/callout.js.map +1 -1
  26. package/dist/components/card.cjs +3 -2
  27. package/dist/components/card.cjs.map +1 -1
  28. package/dist/components/card.d.cts +7 -1
  29. package/dist/components/card.d.ts +7 -1
  30. package/dist/components/card.js +3 -2
  31. package/dist/components/card.js.map +1 -1
  32. package/dist/components/checkbox.d.cts +1 -1
  33. package/dist/components/checkbox.d.ts +1 -1
  34. package/dist/components/field.d.cts +1 -1
  35. package/dist/components/field.d.ts +1 -1
  36. package/dist/components/icon.cjs +1 -1
  37. package/dist/components/icon.js +1 -1
  38. package/dist/components/input-group.cjs +1 -1
  39. package/dist/components/input-group.cjs.map +1 -1
  40. package/dist/components/input-group.js +1 -1
  41. package/dist/components/input-group.js.map +1 -1
  42. package/dist/components/input.d.cts +1 -1
  43. package/dist/components/input.d.ts +1 -1
  44. package/dist/components/line-chart.cjs +1 -1
  45. package/dist/components/line-chart.js +2 -2
  46. package/dist/components/list.d.cts +1 -1
  47. package/dist/components/list.d.ts +1 -1
  48. package/dist/components/marker.d.cts +1 -1
  49. package/dist/components/marker.d.ts +1 -1
  50. package/dist/components/pill.cjs +20 -13
  51. package/dist/components/pill.cjs.map +1 -1
  52. package/dist/components/pill.d.cts +1 -1
  53. package/dist/components/pill.d.ts +1 -1
  54. package/dist/components/pill.js +20 -13
  55. package/dist/components/pill.js.map +1 -1
  56. package/dist/components/power-history-chart.cjs +1 -1
  57. package/dist/components/power-history-chart.js +2 -2
  58. package/dist/components/progress.cjs +1 -1
  59. package/dist/components/progress.cjs.map +1 -1
  60. package/dist/components/progress.js +1 -1
  61. package/dist/components/progress.js.map +1 -1
  62. package/dist/components/radio-card-group.cjs.map +1 -1
  63. package/dist/components/radio-card-group.js.map +1 -1
  64. package/dist/components/radio.d.cts +1 -1
  65. package/dist/components/radio.d.ts +1 -1
  66. package/dist/components/schedule-list.cjs +10 -7
  67. package/dist/components/schedule-list.cjs.map +1 -1
  68. package/dist/components/schedule-list.js +10 -7
  69. package/dist/components/schedule-list.js.map +1 -1
  70. package/dist/components/segmented-control.d.cts +1 -1
  71. package/dist/components/segmented-control.d.ts +1 -1
  72. package/dist/components/select.cjs +1 -1
  73. package/dist/components/select.d.cts +1 -1
  74. package/dist/components/select.d.ts +1 -1
  75. package/dist/components/select.js +1 -1
  76. package/dist/components/solar-forecast-chart.cjs +1 -1
  77. package/dist/components/solar-forecast-chart.js +2 -2
  78. package/dist/components/switch.d.cts +1 -1
  79. package/dist/components/switch.d.ts +1 -1
  80. package/dist/components/textarea.d.cts +1 -1
  81. package/dist/components/textarea.d.ts +1 -1
  82. package/dist/components/theme.cjs +18 -6
  83. package/dist/components/theme.cjs.map +1 -1
  84. package/dist/components/theme.d.cts +16 -2
  85. package/dist/components/theme.d.ts +16 -2
  86. package/dist/components/theme.js +19 -7
  87. package/dist/components/theme.js.map +1 -1
  88. package/dist/{generate-radix-colors-Bw-RYaV4.d.ts → generate-radix-colors-BY4Wjsm7.d.cts} +4 -2
  89. package/dist/{generate-radix-colors-Bw-RYaV4.d.cts → generate-radix-colors-BY4Wjsm7.d.ts} +4 -2
  90. package/dist/icons/material-symbol.cjs +1 -1
  91. package/dist/icons/material-symbol.cjs.map +1 -1
  92. package/dist/icons/material-symbol.js +1 -1
  93. package/dist/icons/material-symbol.js.map +1 -1
  94. package/dist/lib/accent-theme.cjs +367 -16
  95. package/dist/lib/accent-theme.cjs.map +1 -1
  96. package/dist/lib/accent-theme.d.cts +75 -6
  97. package/dist/lib/accent-theme.d.ts +75 -6
  98. package/dist/lib/accent-theme.js +365 -18
  99. package/dist/lib/accent-theme.js.map +1 -1
  100. package/dist/lib/container-chrome.cjs +9 -7
  101. package/dist/lib/container-chrome.cjs.map +1 -1
  102. package/dist/lib/container-chrome.d.cts +4 -3
  103. package/dist/lib/container-chrome.d.ts +4 -3
  104. package/dist/lib/container-chrome.js +9 -8
  105. package/dist/lib/container-chrome.js.map +1 -1
  106. package/dist/lib/generate-radix-colors.cjs +7 -0
  107. package/dist/lib/generate-radix-colors.cjs.map +1 -1
  108. package/dist/lib/generate-radix-colors.d.cts +2 -2
  109. package/dist/lib/generate-radix-colors.d.ts +2 -2
  110. package/dist/lib/generate-radix-colors.js +6 -1
  111. package/dist/lib/generate-radix-colors.js.map +1 -1
  112. package/dist/lib/input-box-variants.d.cts +1 -1
  113. package/dist/lib/input-box-variants.d.ts +1 -1
  114. package/dist/lib/theme-types.cjs +19 -0
  115. package/dist/lib/theme-types.cjs.map +1 -0
  116. package/dist/lib/theme-types.d.cts +2 -2
  117. package/dist/lib/theme-types.d.ts +2 -2
  118. package/dist/lib/theme-types.js +17 -1
  119. package/dist/lib/theme-types.js.map +1 -0
  120. package/dist/styles/material-symbol.css +3 -0
  121. package/dist/styles/spark-default.css +148 -0
  122. package/dist/styles/utilities.css +9 -8
  123. package/dist/{theme-types-1yB0d8mp.d.ts → theme-types-Bn5E15-P.d.cts} +12 -3
  124. package/dist/{theme-types-1yB0d8mp.d.cts → theme-types-Bn5E15-P.d.ts} +12 -3
  125. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"radio-card-group.cjs","names":["React"],"sources":["../../src/components/radio-card-group.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface RadioCardGroupContextValue {\n value: string | undefined\n onValueChange: (value: string) => void\n disabled?: boolean\n name: string\n}\n\nconst RadioCardGroupContext = React.createContext<\n RadioCardGroupContextValue | undefined\n>(undefined)\n\nconst ARROW_STEP: Record<string, 1 | -1> = {\n ArrowDown: 1,\n ArrowRight: 1,\n ArrowUp: -1,\n ArrowLeft: -1,\n}\n\ninterface RadioCardGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n disabled?: boolean\n /** Optional name used for ARIA grouping. Defaults to a generated id. */\n name?: string\n /** How many `--spark-layout-gap` units apart each card sits. */\n gap?: number\n}\n\nconst RadioCardGroup = React.forwardRef<HTMLDivElement, RadioCardGroupProps>(\n (\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled,\n name,\n gap = 2,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const generatedName = React.useId()\n const [internalValue, setInternalValue] = React.useState<\n string | undefined\n >(defaultValue)\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp : internalValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n const ctx = React.useMemo<RadioCardGroupContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n disabled,\n name: name ?? generatedName,\n }),\n [value, handleValueChange, disabled, name, generatedName],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const step = ARROW_STEP[event.key]\n if (step === undefined && event.key !== 'Home' && event.key !== 'End')\n return\n const radios = [\n ...event.currentTarget.querySelectorAll<HTMLButtonElement>(\n '[role=\"radio\"]:not(:disabled)',\n ),\n ]\n if (radios.length === 0) return\n event.preventDefault()\n\n let next = 0\n if (event.key === 'End') {\n next = radios.length - 1\n } else if (step !== undefined) {\n const current = radios.indexOf(\n document.activeElement as HTMLButtonElement,\n )\n if (current !== -1) {\n next = (current + step + radios.length) % radios.length\n }\n }\n const target = radios[next]\n if (!target) return\n target.focus()\n target.click()\n }\n\n return (\n <RadioCardGroupContext.Provider value={ctx}>\n <div\n ref={ref}\n role=\"radiogroup\"\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*var(--radio-card-group-gap-steps,2))]',\n className,\n )}\n style={\n {\n '--radio-card-group-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...props}\n >\n {children}\n </div>\n </RadioCardGroupContext.Provider>\n )\n },\n)\n\nRadioCardGroup.displayName = 'RadioCardGroup'\n\ninterface RadioCardGroupItemProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n value: string\n}\n\nconst RadioCardGroupItem = React.forwardRef<\n HTMLButtonElement,\n RadioCardGroupItemProps\n>(({ value, className, children, disabled, onClick, ...props }, ref) => {\n const ctx = React.useContext(RadioCardGroupContext)\n if (!ctx) {\n throw new Error('RadioCardGroupItem must be used within a RadioCardGroup')\n }\n\n const checked = ctx.value === value\n const isDisabled = disabled ?? ctx.disabled\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n data-state={checked ? 'checked' : 'unchecked'}\n tabIndex={checked || ctx.value === undefined ? 0 : -1}\n disabled={isDisabled}\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented && !isDisabled) {\n ctx.onValueChange(value)\n }\n }}\n className={cn(\n 'h-12 w-full rounded-lg px-4 text-base font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n checked\n ? 'border border-accent bg-base-accent-soft text-accent'\n : 'border border-transparent bg-base-gray-soft text-gray hover:bg-gray-a3',\n className,\n )}\n {...props}\n >\n {children}\n </button>\n )\n})\n\nRadioCardGroupItem.displayName = 'RadioCardGroupItem'\n\nexport { RadioCardGroup, RadioCardGroupItem }\nexport type { RadioCardGroupProps, RadioCardGroupItemProps }\n"],"mappings":";;;;;;;;AAUA,MAAM,wBAAwBA,MAAM,cAElC,KAAA,CAAS;AAEX,MAAM,aAAqC;CACzC,WAAW;CACX,YAAY;CACZ,SAAS;CACT,WAAW;AACb;AAaA,MAAM,iBAAiBA,MAAM,YAEzB,EACE,OAAO,WACP,cACA,eACA,UACA,MACA,MAAM,GACN,WACA,OACA,UACA,GAAG,SAEL,QACG;CACH,MAAM,gBAAgBA,MAAM,MAAM;CAClC,MAAM,CAAC,eAAe,oBAAoBA,MAAM,SAE9C,YAAY;CACd,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,QAAQ,eAAe,YAAY;CAEzC,MAAM,oBAAoBA,MAAM,aAC7B,SAAiB;EAChB,IAAI,CAAC,cAAc,iBAAiB,IAAI;EACxC,gBAAgB,IAAI;CACtB,GACA,CAAC,cAAc,aAAa,CAC9B;CAEA,MAAM,MAAMA,MAAM,eACT;EACL;EACA,eAAe;EACf;EACA,MAAM,QAAQ;CAChB,IACA;EAAC;EAAO;EAAmB;EAAU;EAAM;CAAa,CAC1D;CAEA,MAAM,iBAAiB,UAA+C;EACpE,MAAM,OAAO,WAAW,MAAM;EAC9B,IAAI,SAAS,KAAA,KAAa,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAC9D;EACF,MAAM,SAAS,CACb,GAAG,MAAM,cAAc,iBACrB,iCACF,CACF;EACA,IAAI,OAAO,WAAW,GAAG;EACzB,MAAM,eAAe;EAErB,IAAI,OAAO;EACX,IAAI,MAAM,QAAQ,OAChB,OAAO,OAAO,SAAS;OAClB,IAAI,SAAS,KAAA,GAAW;GAC7B,MAAM,UAAU,OAAO,QACrB,SAAS,aACX;GACA,IAAI,YAAY,IACd,QAAQ,UAAU,OAAO,OAAO,UAAU,OAAO;EAErD;EACA,MAAM,SAAS,OAAO;EACtB,IAAI,CAAC,QAAQ;EACb,OAAO,MAAM;EACb,OAAO,MAAM;CACf;CAEA,OACE,iBAAA,GAAA,kBAAA,KAAC,sBAAsB,UAAvB;EAAgC,OAAO;YACrC,iBAAA,GAAA,kBAAA,KAAC,OAAD;GACO;GACL,MAAK;GACL,WAAW;GACX,YAAA,GAAA,OAAA,IACE,yFACA,SACF;GACA,OACE;IACE,gCAAgC;IAChC,GAAG;GACL;GAEF,GAAI;GAEH;EACE,CAAA;CACyB,CAAA;AAEpC,CACF;AAEA,eAAe,cAAc;AAS7B,MAAM,qBAAqBA,MAAM,YAG9B,EAAE,OAAO,WAAW,UAAU,UAAU,SAAS,GAAG,SAAS,QAAQ;CACtE,MAAM,MAAMA,MAAM,WAAW,qBAAqB;CAClD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,UAAU,IAAI,UAAU;CAC9B,MAAM,aAAa,YAAY,IAAI;CAEnC,OACE,iBAAA,GAAA,kBAAA,KAAC,UAAD;EACO;EACL,MAAK;EACL,MAAK;EACL,gBAAc;EACd,cAAY,UAAU,YAAY;EAClC,UAAU,WAAW,IAAI,UAAU,KAAA,IAAY,IAAI;EACnD,UAAU;EACV,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,IAAI,CAAC,MAAM,oBAAoB,CAAC,YAC9B,IAAI,cAAc,KAAK;EAE3B;EACA,YAAA,GAAA,OAAA,IACE,qMACA,UACI,yDACA,0EACJ,SACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,CAAC;AAED,mBAAmB,cAAc"}
1
+ {"version":3,"file":"radio-card-group.cjs","names":["React"],"sources":["../../src/components/radio-card-group.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface RadioCardGroupContextValue {\n value: string | undefined\n onValueChange: (value: string) => void\n disabled?: boolean\n name: string\n}\n\nconst RadioCardGroupContext = React.createContext<\n RadioCardGroupContextValue | undefined\n>(undefined)\n\nconst ARROW_STEP: Record<string, 1 | -1> = {\n ArrowDown: 1,\n ArrowRight: 1,\n ArrowUp: -1,\n ArrowLeft: -1,\n}\n\ninterface RadioCardGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n disabled?: boolean\n /** Optional name used for ARIA grouping. Defaults to a generated id. */\n name?: string\n /** How many `--spark-layout-gap` units apart each card sits. */\n gap?: number\n}\n\nconst RadioCardGroup = React.forwardRef<HTMLDivElement, RadioCardGroupProps>(\n (\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled,\n name,\n gap = 2,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const generatedName = React.useId()\n const [internalValue, setInternalValue] = React.useState<\n string | undefined\n >(defaultValue)\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp : internalValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n const ctx = React.useMemo<RadioCardGroupContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n disabled,\n name: name ?? generatedName,\n }),\n [value, handleValueChange, disabled, name, generatedName],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const step = ARROW_STEP[event.key]\n if (step === undefined && event.key !== 'Home' && event.key !== 'End')\n return\n const radios = [\n ...event.currentTarget.querySelectorAll<HTMLButtonElement>(\n '[role=\"radio\"]:not(:disabled)',\n ),\n ]\n if (radios.length === 0) return\n event.preventDefault()\n\n let next = 0\n if (event.key === 'End') {\n next = radios.length - 1\n } else if (step !== undefined) {\n const current = radios.indexOf(\n document.activeElement as HTMLButtonElement,\n )\n if (current !== -1) {\n next = (current + step + radios.length) % radios.length\n }\n }\n const target = radios[next]\n if (!target) return\n target.focus()\n target.click()\n }\n\n return (\n <RadioCardGroupContext.Provider value={ctx}>\n {/* oxlint-disable-next-line jsx-a11y/interactive-supports-focus -- radiogroup is a composite: the tab stop belongs on the roving radios, not the container */}\n <div\n ref={ref}\n role=\"radiogroup\"\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*var(--radio-card-group-gap-steps,2))]',\n className,\n )}\n style={\n {\n '--radio-card-group-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...props}\n >\n {children}\n </div>\n </RadioCardGroupContext.Provider>\n )\n },\n)\n\nRadioCardGroup.displayName = 'RadioCardGroup'\n\ninterface RadioCardGroupItemProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n value: string\n}\n\nconst RadioCardGroupItem = React.forwardRef<\n HTMLButtonElement,\n RadioCardGroupItemProps\n>(({ value, className, children, disabled, onClick, ...props }, ref) => {\n const ctx = React.useContext(RadioCardGroupContext)\n if (!ctx) {\n throw new Error('RadioCardGroupItem must be used within a RadioCardGroup')\n }\n\n const checked = ctx.value === value\n const isDisabled = disabled ?? ctx.disabled\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n data-state={checked ? 'checked' : 'unchecked'}\n tabIndex={checked || ctx.value === undefined ? 0 : -1}\n disabled={isDisabled}\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented && !isDisabled) {\n ctx.onValueChange(value)\n }\n }}\n className={cn(\n 'h-12 w-full rounded-lg px-4 text-base font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n checked\n ? 'border border-accent bg-base-accent-soft text-accent'\n : 'border border-transparent bg-base-gray-soft text-gray hover:bg-gray-a3',\n className,\n )}\n {...props}\n >\n {children}\n </button>\n )\n})\n\nRadioCardGroupItem.displayName = 'RadioCardGroupItem'\n\nexport { RadioCardGroup, RadioCardGroupItem }\nexport type { RadioCardGroupProps, RadioCardGroupItemProps }\n"],"mappings":";;;;;;;;AAUA,MAAM,wBAAwBA,MAAM,cAElC,KAAA,CAAS;AAEX,MAAM,aAAqC;CACzC,WAAW;CACX,YAAY;CACZ,SAAS;CACT,WAAW;AACb;AAaA,MAAM,iBAAiBA,MAAM,YAEzB,EACE,OAAO,WACP,cACA,eACA,UACA,MACA,MAAM,GACN,WACA,OACA,UACA,GAAG,SAEL,QACG;CACH,MAAM,gBAAgBA,MAAM,MAAM;CAClC,MAAM,CAAC,eAAe,oBAAoBA,MAAM,SAE9C,YAAY;CACd,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,QAAQ,eAAe,YAAY;CAEzC,MAAM,oBAAoBA,MAAM,aAC7B,SAAiB;EAChB,IAAI,CAAC,cAAc,iBAAiB,IAAI;EACxC,gBAAgB,IAAI;CACtB,GACA,CAAC,cAAc,aAAa,CAC9B;CAEA,MAAM,MAAMA,MAAM,eACT;EACL;EACA,eAAe;EACf;EACA,MAAM,QAAQ;CAChB,IACA;EAAC;EAAO;EAAmB;EAAU;EAAM;CAAa,CAC1D;CAEA,MAAM,iBAAiB,UAA+C;EACpE,MAAM,OAAO,WAAW,MAAM;EAC9B,IAAI,SAAS,KAAA,KAAa,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAC9D;EACF,MAAM,SAAS,CACb,GAAG,MAAM,cAAc,iBACrB,iCACF,CACF;EACA,IAAI,OAAO,WAAW,GAAG;EACzB,MAAM,eAAe;EAErB,IAAI,OAAO;EACX,IAAI,MAAM,QAAQ,OAChB,OAAO,OAAO,SAAS;OAClB,IAAI,SAAS,KAAA,GAAW;GAC7B,MAAM,UAAU,OAAO,QACrB,SAAS,aACX;GACA,IAAI,YAAY,IACd,QAAQ,UAAU,OAAO,OAAO,UAAU,OAAO;EAErD;EACA,MAAM,SAAS,OAAO;EACtB,IAAI,CAAC,QAAQ;EACb,OAAO,MAAM;EACb,OAAO,MAAM;CACf;CAEA,OACE,iBAAA,GAAA,kBAAA,KAAC,sBAAsB,UAAvB;EAAgC,OAAO;YAErC,iBAAA,GAAA,kBAAA,KAAC,OAAD;GACO;GACL,MAAK;GACL,WAAW;GACX,YAAA,GAAA,OAAA,IACE,yFACA,SACF;GACA,OACE;IACE,gCAAgC;IAChC,GAAG;GACL;GAEF,GAAI;GAEH;EACE,CAAA;CACyB,CAAA;AAEpC,CACF;AAEA,eAAe,cAAc;AAS7B,MAAM,qBAAqBA,MAAM,YAG9B,EAAE,OAAO,WAAW,UAAU,UAAU,SAAS,GAAG,SAAS,QAAQ;CACtE,MAAM,MAAMA,MAAM,WAAW,qBAAqB;CAClD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,UAAU,IAAI,UAAU;CAC9B,MAAM,aAAa,YAAY,IAAI;CAEnC,OACE,iBAAA,GAAA,kBAAA,KAAC,UAAD;EACO;EACL,MAAK;EACL,MAAK;EACL,gBAAc;EACd,cAAY,UAAU,YAAY;EAClC,UAAU,WAAW,IAAI,UAAU,KAAA,IAAY,IAAI;EACnD,UAAU;EACV,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,IAAI,CAAC,MAAM,oBAAoB,CAAC,YAC9B,IAAI,cAAc,KAAK;EAE3B;EACA,YAAA,GAAA,OAAA,IACE,qMACA,UACI,yDACA,0EACJ,SACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,CAAC;AAED,mBAAmB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"radio-card-group.js","names":["React"],"sources":["../../src/components/radio-card-group.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface RadioCardGroupContextValue {\n value: string | undefined\n onValueChange: (value: string) => void\n disabled?: boolean\n name: string\n}\n\nconst RadioCardGroupContext = React.createContext<\n RadioCardGroupContextValue | undefined\n>(undefined)\n\nconst ARROW_STEP: Record<string, 1 | -1> = {\n ArrowDown: 1,\n ArrowRight: 1,\n ArrowUp: -1,\n ArrowLeft: -1,\n}\n\ninterface RadioCardGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n disabled?: boolean\n /** Optional name used for ARIA grouping. Defaults to a generated id. */\n name?: string\n /** How many `--spark-layout-gap` units apart each card sits. */\n gap?: number\n}\n\nconst RadioCardGroup = React.forwardRef<HTMLDivElement, RadioCardGroupProps>(\n (\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled,\n name,\n gap = 2,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const generatedName = React.useId()\n const [internalValue, setInternalValue] = React.useState<\n string | undefined\n >(defaultValue)\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp : internalValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n const ctx = React.useMemo<RadioCardGroupContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n disabled,\n name: name ?? generatedName,\n }),\n [value, handleValueChange, disabled, name, generatedName],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const step = ARROW_STEP[event.key]\n if (step === undefined && event.key !== 'Home' && event.key !== 'End')\n return\n const radios = [\n ...event.currentTarget.querySelectorAll<HTMLButtonElement>(\n '[role=\"radio\"]:not(:disabled)',\n ),\n ]\n if (radios.length === 0) return\n event.preventDefault()\n\n let next = 0\n if (event.key === 'End') {\n next = radios.length - 1\n } else if (step !== undefined) {\n const current = radios.indexOf(\n document.activeElement as HTMLButtonElement,\n )\n if (current !== -1) {\n next = (current + step + radios.length) % radios.length\n }\n }\n const target = radios[next]\n if (!target) return\n target.focus()\n target.click()\n }\n\n return (\n <RadioCardGroupContext.Provider value={ctx}>\n <div\n ref={ref}\n role=\"radiogroup\"\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*var(--radio-card-group-gap-steps,2))]',\n className,\n )}\n style={\n {\n '--radio-card-group-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...props}\n >\n {children}\n </div>\n </RadioCardGroupContext.Provider>\n )\n },\n)\n\nRadioCardGroup.displayName = 'RadioCardGroup'\n\ninterface RadioCardGroupItemProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n value: string\n}\n\nconst RadioCardGroupItem = React.forwardRef<\n HTMLButtonElement,\n RadioCardGroupItemProps\n>(({ value, className, children, disabled, onClick, ...props }, ref) => {\n const ctx = React.useContext(RadioCardGroupContext)\n if (!ctx) {\n throw new Error('RadioCardGroupItem must be used within a RadioCardGroup')\n }\n\n const checked = ctx.value === value\n const isDisabled = disabled ?? ctx.disabled\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n data-state={checked ? 'checked' : 'unchecked'}\n tabIndex={checked || ctx.value === undefined ? 0 : -1}\n disabled={isDisabled}\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented && !isDisabled) {\n ctx.onValueChange(value)\n }\n }}\n className={cn(\n 'h-12 w-full rounded-lg px-4 text-base font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n checked\n ? 'border border-accent bg-base-accent-soft text-accent'\n : 'border border-transparent bg-base-gray-soft text-gray hover:bg-gray-a3',\n className,\n )}\n {...props}\n >\n {children}\n </button>\n )\n})\n\nRadioCardGroupItem.displayName = 'RadioCardGroupItem'\n\nexport { RadioCardGroup, RadioCardGroupItem }\nexport type { RadioCardGroupProps, RadioCardGroupItemProps }\n"],"mappings":";;;;;AAUA,MAAM,wBAAwBA,QAAM,cAElC,KAAA,CAAS;AAEX,MAAM,aAAqC;CACzC,WAAW;CACX,YAAY;CACZ,SAAS;CACT,WAAW;AACb;AAaA,MAAM,iBAAiBA,QAAM,YAEzB,EACE,OAAO,WACP,cACA,eACA,UACA,MACA,MAAM,GACN,WACA,OACA,UACA,GAAG,SAEL,QACG;CACH,MAAM,gBAAgBA,QAAM,MAAM;CAClC,MAAM,CAAC,eAAe,oBAAoBA,QAAM,SAE9C,YAAY;CACd,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,QAAQ,eAAe,YAAY;CAEzC,MAAM,oBAAoBA,QAAM,aAC7B,SAAiB;EAChB,IAAI,CAAC,cAAc,iBAAiB,IAAI;EACxC,gBAAgB,IAAI;CACtB,GACA,CAAC,cAAc,aAAa,CAC9B;CAEA,MAAM,MAAMA,QAAM,eACT;EACL;EACA,eAAe;EACf;EACA,MAAM,QAAQ;CAChB,IACA;EAAC;EAAO;EAAmB;EAAU;EAAM;CAAa,CAC1D;CAEA,MAAM,iBAAiB,UAA+C;EACpE,MAAM,OAAO,WAAW,MAAM;EAC9B,IAAI,SAAS,KAAA,KAAa,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAC9D;EACF,MAAM,SAAS,CACb,GAAG,MAAM,cAAc,iBACrB,iCACF,CACF;EACA,IAAI,OAAO,WAAW,GAAG;EACzB,MAAM,eAAe;EAErB,IAAI,OAAO;EACX,IAAI,MAAM,QAAQ,OAChB,OAAO,OAAO,SAAS;OAClB,IAAI,SAAS,KAAA,GAAW;GAC7B,MAAM,UAAU,OAAO,QACrB,SAAS,aACX;GACA,IAAI,YAAY,IACd,QAAQ,UAAU,OAAO,OAAO,UAAU,OAAO;EAErD;EACA,MAAM,SAAS,OAAO;EACtB,IAAI,CAAC,QAAQ;EACb,OAAO,MAAM;EACb,OAAO,MAAM;CACf;CAEA,OACE,oBAAC,sBAAsB,UAAvB;EAAgC,OAAO;YACrC,oBAAC,OAAD;GACO;GACL,MAAK;GACL,WAAW;GACX,WAAW,GACT,yFACA,SACF;GACA,OACE;IACE,gCAAgC;IAChC,GAAG;GACL;GAEF,GAAI;GAEH;EACE,CAAA;CACyB,CAAA;AAEpC,CACF;AAEA,eAAe,cAAc;AAS7B,MAAM,qBAAqBA,QAAM,YAG9B,EAAE,OAAO,WAAW,UAAU,UAAU,SAAS,GAAG,SAAS,QAAQ;CACtE,MAAM,MAAMA,QAAM,WAAW,qBAAqB;CAClD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,UAAU,IAAI,UAAU;CAC9B,MAAM,aAAa,YAAY,IAAI;CAEnC,OACE,oBAAC,UAAD;EACO;EACL,MAAK;EACL,MAAK;EACL,gBAAc;EACd,cAAY,UAAU,YAAY;EAClC,UAAU,WAAW,IAAI,UAAU,KAAA,IAAY,IAAI;EACnD,UAAU;EACV,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,IAAI,CAAC,MAAM,oBAAoB,CAAC,YAC9B,IAAI,cAAc,KAAK;EAE3B;EACA,WAAW,GACT,qMACA,UACI,yDACA,0EACJ,SACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,CAAC;AAED,mBAAmB,cAAc"}
1
+ {"version":3,"file":"radio-card-group.js","names":["React"],"sources":["../../src/components/radio-card-group.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface RadioCardGroupContextValue {\n value: string | undefined\n onValueChange: (value: string) => void\n disabled?: boolean\n name: string\n}\n\nconst RadioCardGroupContext = React.createContext<\n RadioCardGroupContextValue | undefined\n>(undefined)\n\nconst ARROW_STEP: Record<string, 1 | -1> = {\n ArrowDown: 1,\n ArrowRight: 1,\n ArrowUp: -1,\n ArrowLeft: -1,\n}\n\ninterface RadioCardGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n disabled?: boolean\n /** Optional name used for ARIA grouping. Defaults to a generated id. */\n name?: string\n /** How many `--spark-layout-gap` units apart each card sits. */\n gap?: number\n}\n\nconst RadioCardGroup = React.forwardRef<HTMLDivElement, RadioCardGroupProps>(\n (\n {\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled,\n name,\n gap = 2,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const generatedName = React.useId()\n const [internalValue, setInternalValue] = React.useState<\n string | undefined\n >(defaultValue)\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp : internalValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next)\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n const ctx = React.useMemo<RadioCardGroupContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n disabled,\n name: name ?? generatedName,\n }),\n [value, handleValueChange, disabled, name, generatedName],\n )\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const step = ARROW_STEP[event.key]\n if (step === undefined && event.key !== 'Home' && event.key !== 'End')\n return\n const radios = [\n ...event.currentTarget.querySelectorAll<HTMLButtonElement>(\n '[role=\"radio\"]:not(:disabled)',\n ),\n ]\n if (radios.length === 0) return\n event.preventDefault()\n\n let next = 0\n if (event.key === 'End') {\n next = radios.length - 1\n } else if (step !== undefined) {\n const current = radios.indexOf(\n document.activeElement as HTMLButtonElement,\n )\n if (current !== -1) {\n next = (current + step + radios.length) % radios.length\n }\n }\n const target = radios[next]\n if (!target) return\n target.focus()\n target.click()\n }\n\n return (\n <RadioCardGroupContext.Provider value={ctx}>\n {/* oxlint-disable-next-line jsx-a11y/interactive-supports-focus -- radiogroup is a composite: the tab stop belongs on the roving radios, not the container */}\n <div\n ref={ref}\n role=\"radiogroup\"\n onKeyDown={handleKeyDown}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*var(--radio-card-group-gap-steps,2))]',\n className,\n )}\n style={\n {\n '--radio-card-group-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...props}\n >\n {children}\n </div>\n </RadioCardGroupContext.Provider>\n )\n },\n)\n\nRadioCardGroup.displayName = 'RadioCardGroup'\n\ninterface RadioCardGroupItemProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n value: string\n}\n\nconst RadioCardGroupItem = React.forwardRef<\n HTMLButtonElement,\n RadioCardGroupItemProps\n>(({ value, className, children, disabled, onClick, ...props }, ref) => {\n const ctx = React.useContext(RadioCardGroupContext)\n if (!ctx) {\n throw new Error('RadioCardGroupItem must be used within a RadioCardGroup')\n }\n\n const checked = ctx.value === value\n const isDisabled = disabled ?? ctx.disabled\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n data-state={checked ? 'checked' : 'unchecked'}\n tabIndex={checked || ctx.value === undefined ? 0 : -1}\n disabled={isDisabled}\n onClick={(event) => {\n onClick?.(event)\n if (!event.defaultPrevented && !isDisabled) {\n ctx.onValueChange(value)\n }\n }}\n className={cn(\n 'h-12 w-full rounded-lg px-4 text-base font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n checked\n ? 'border border-accent bg-base-accent-soft text-accent'\n : 'border border-transparent bg-base-gray-soft text-gray hover:bg-gray-a3',\n className,\n )}\n {...props}\n >\n {children}\n </button>\n )\n})\n\nRadioCardGroupItem.displayName = 'RadioCardGroupItem'\n\nexport { RadioCardGroup, RadioCardGroupItem }\nexport type { RadioCardGroupProps, RadioCardGroupItemProps }\n"],"mappings":";;;;;AAUA,MAAM,wBAAwBA,QAAM,cAElC,KAAA,CAAS;AAEX,MAAM,aAAqC;CACzC,WAAW;CACX,YAAY;CACZ,SAAS;CACT,WAAW;AACb;AAaA,MAAM,iBAAiBA,QAAM,YAEzB,EACE,OAAO,WACP,cACA,eACA,UACA,MACA,MAAM,GACN,WACA,OACA,UACA,GAAG,SAEL,QACG;CACH,MAAM,gBAAgBA,QAAM,MAAM;CAClC,MAAM,CAAC,eAAe,oBAAoBA,QAAM,SAE9C,YAAY;CACd,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,QAAQ,eAAe,YAAY;CAEzC,MAAM,oBAAoBA,QAAM,aAC7B,SAAiB;EAChB,IAAI,CAAC,cAAc,iBAAiB,IAAI;EACxC,gBAAgB,IAAI;CACtB,GACA,CAAC,cAAc,aAAa,CAC9B;CAEA,MAAM,MAAMA,QAAM,eACT;EACL;EACA,eAAe;EACf;EACA,MAAM,QAAQ;CAChB,IACA;EAAC;EAAO;EAAmB;EAAU;EAAM;CAAa,CAC1D;CAEA,MAAM,iBAAiB,UAA+C;EACpE,MAAM,OAAO,WAAW,MAAM;EAC9B,IAAI,SAAS,KAAA,KAAa,MAAM,QAAQ,UAAU,MAAM,QAAQ,OAC9D;EACF,MAAM,SAAS,CACb,GAAG,MAAM,cAAc,iBACrB,iCACF,CACF;EACA,IAAI,OAAO,WAAW,GAAG;EACzB,MAAM,eAAe;EAErB,IAAI,OAAO;EACX,IAAI,MAAM,QAAQ,OAChB,OAAO,OAAO,SAAS;OAClB,IAAI,SAAS,KAAA,GAAW;GAC7B,MAAM,UAAU,OAAO,QACrB,SAAS,aACX;GACA,IAAI,YAAY,IACd,QAAQ,UAAU,OAAO,OAAO,UAAU,OAAO;EAErD;EACA,MAAM,SAAS,OAAO;EACtB,IAAI,CAAC,QAAQ;EACb,OAAO,MAAM;EACb,OAAO,MAAM;CACf;CAEA,OACE,oBAAC,sBAAsB,UAAvB;EAAgC,OAAO;YAErC,oBAAC,OAAD;GACO;GACL,MAAK;GACL,WAAW;GACX,WAAW,GACT,yFACA,SACF;GACA,OACE;IACE,gCAAgC;IAChC,GAAG;GACL;GAEF,GAAI;GAEH;EACE,CAAA;CACyB,CAAA;AAEpC,CACF;AAEA,eAAe,cAAc;AAS7B,MAAM,qBAAqBA,QAAM,YAG9B,EAAE,OAAO,WAAW,UAAU,UAAU,SAAS,GAAG,SAAS,QAAQ;CACtE,MAAM,MAAMA,QAAM,WAAW,qBAAqB;CAClD,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,UAAU,IAAI,UAAU;CAC9B,MAAM,aAAa,YAAY,IAAI;CAEnC,OACE,oBAAC,UAAD;EACO;EACL,MAAK;EACL,MAAK;EACL,gBAAc;EACd,cAAY,UAAU,YAAY;EAClC,UAAU,WAAW,IAAI,UAAU,KAAA,IAAY,IAAI;EACnD,UAAU;EACV,UAAU,UAAU;GAClB,UAAU,KAAK;GACf,IAAI,CAAC,MAAM,oBAAoB,CAAC,YAC9B,IAAI,cAAc,KAAK;EAE3B;EACA,WAAW,GACT,qMACA,UACI,yDACA,0EACJ,SACF;EACA,GAAI;EAEH;CACK,CAAA;AAEZ,CAAC;AAED,mBAAmB,cAAc"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import * as React$1 from "react";
5
5
  import { Radio as Radio$1 } from "@base-ui/react/radio";
6
6
  import { RadioGroup as RadioGroup$1 } from "@base-ui/react/radio-group";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import * as React$1 from "react";
5
5
  import { Radio as Radio$1 } from "@base-ui/react/radio";
6
6
  import { RadioGroup as RadioGroup$1 } from "@base-ui/react/radio-group";
@@ -34,13 +34,15 @@ const ScheduleEntry = react.forwardRef(({ children, className, disabled, onClick
34
34
  const interactive = onClick !== void 0 && !disabled;
35
35
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
36
36
  ref,
37
- role: interactive ? "button" : void 0,
38
- tabIndex: interactive ? 0 : void 0,
39
- onClick: interactive ? onClick : void 0,
40
- onKeyDown: interactive ? (event) => {
41
- if (event.key === "Enter" || event.key === " ") {
42
- event.preventDefault();
43
- onClick();
37
+ ...interactive ? {
38
+ role: "button",
39
+ tabIndex: 0,
40
+ onClick,
41
+ onKeyDown: (event) => {
42
+ if (event.key === "Enter" || event.key === " ") {
43
+ event.preventDefault();
44
+ onClick();
45
+ }
44
46
  }
45
47
  } : void 0,
46
48
  "aria-disabled": disabled || void 0,
@@ -72,6 +74,7 @@ ScheduleEntrySubtitle.displayName = "ScheduleEntrySubtitle";
72
74
  * don't fire the parent `ScheduleEntry`'s `onClick`. */
73
75
  const ScheduleEntryActions = react.forwardRef(({ className, onClick, ...props }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
74
76
  ref,
77
+ role: "presentation",
75
78
  onClick: (event) => {
76
79
  event.stopPropagation();
77
80
  onClick?.(event);
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-list.cjs","names":["React","MaterialSymbol"],"sources":["../../src/components/schedule-list.tsx"],"sourcesContent":["import * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\nconst ScheduleList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*2)]',\n className,\n )}\n {...props}\n />\n))\n\nScheduleList.displayName = 'ScheduleList'\n\nconst ScheduleListEmpty = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('px-3 py-2 text-sm text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleListEmpty.displayName = 'ScheduleListEmpty'\n\ninterface ScheduleListAddProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Optional icon override; defaults to a `+`. */\n icon?: React.ReactNode\n}\n\nconst ScheduleListAdd = React.forwardRef<\n HTMLButtonElement,\n ScheduleListAddProps\n>(({ children, className, icon, type = 'button', ...props }, ref) => (\n <button\n ref={ref}\n type={type}\n className={cn(\n 'inline-flex h-11 w-full items-center justify-center gap-1.5 rounded-2xl border border-dashed border-gray text-sm font-medium text-gray-light transition-colors hover:border-spark-a8 hover:bg-base-accent-soft hover:text-accent focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {icon ?? <MaterialSymbol className=\"text-[14px]\" name=\"add\" />}\n {children}\n </button>\n))\n\nScheduleListAdd.displayName = 'ScheduleListAdd'\n\ninterface ScheduleEntryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Make the row interactive — enables hover, role=button, keyboard activation. */\n onClick?: () => void\n disabled?: boolean\n}\n\nconst ScheduleEntry = React.forwardRef<HTMLDivElement, ScheduleEntryProps>(\n ({ children, className, disabled, onClick, ...props }, ref) => {\n const interactive = onClick !== undefined && !disabled\n return (\n <div\n ref={ref}\n role={interactive ? 'button' : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={interactive ? onClick : undefined}\n onKeyDown={\n interactive\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onClick()\n }\n }\n : undefined\n }\n aria-disabled={disabled || undefined}\n className={cn(\n 'flex items-center gap-3 rounded-2xl bg-base-gray-soft px-3 py-2.5 transition-colors',\n interactive &&\n 'cursor-pointer hover:bg-gray-a3 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n },\n)\n\nScheduleEntry.displayName = 'ScheduleEntry'\n\nconst ScheduleEntryContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col gap-0.5', className)}\n {...props}\n />\n))\n\nScheduleEntryContent.displayName = 'ScheduleEntryContent'\n\nconst ScheduleEntryTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-0 items-center gap-2 truncate text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n))\n\nScheduleEntryTitle.displayName = 'ScheduleEntryTitle'\n\nconst ScheduleEntrySubtitle = React.forwardRef<\n HTMLSpanElement,\n React.HTMLAttributes<HTMLSpanElement>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n className={cn('truncate text-xs text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleEntrySubtitle.displayName = 'ScheduleEntrySubtitle'\n\n/** Right-aligned action area. Stops click propagation so inner controls\n * don't fire the parent `ScheduleEntry`'s `onClick`. */\nconst ScheduleEntryActions = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, onClick, ...props }, ref) => (\n <div\n ref={ref}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn('flex shrink-0 items-center gap-1.5', className)}\n {...props}\n />\n))\n\nScheduleEntryActions.displayName = 'ScheduleEntryActions'\n\ninterface ScheduleEntryDeleteProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nconst ScheduleEntryDelete = React.forwardRef<\n HTMLButtonElement,\n ScheduleEntryDeleteProps\n>(\n (\n {\n 'aria-label': ariaLabel = 'Delete schedule entry',\n children,\n className,\n onClick,\n type = 'button',\n ...props\n },\n ref,\n ) => (\n <button\n ref={ref}\n type={type}\n aria-label={ariaLabel}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn(\n 'inline-flex size-8 shrink-0 items-center justify-center rounded-circle text-gray-light transition-colors hover:bg-base-error-soft hover:text-error focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children ?? <MaterialSymbol className=\"text-[14px]\" name=\"delete\" />}\n </button>\n ),\n)\n\nScheduleEntryDelete.displayName = 'ScheduleEntryDelete'\n\nexport {\n ScheduleEntry,\n ScheduleEntryActions,\n ScheduleEntryContent,\n ScheduleEntryDelete,\n ScheduleEntrySubtitle,\n ScheduleEntryTitle,\n ScheduleList,\n ScheduleListAdd,\n ScheduleListEmpty,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"schedule-list.cjs","names":["React","MaterialSymbol"],"sources":["../../src/components/schedule-list.tsx"],"sourcesContent":["import * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\nconst ScheduleList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*2)]',\n className,\n )}\n {...props}\n />\n))\n\nScheduleList.displayName = 'ScheduleList'\n\nconst ScheduleListEmpty = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('px-3 py-2 text-sm text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleListEmpty.displayName = 'ScheduleListEmpty'\n\ninterface ScheduleListAddProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Optional icon override; defaults to a `+`. */\n icon?: React.ReactNode\n}\n\nconst ScheduleListAdd = React.forwardRef<\n HTMLButtonElement,\n ScheduleListAddProps\n>(({ children, className, icon, type = 'button', ...props }, ref) => (\n <button\n ref={ref}\n type={type}\n className={cn(\n 'inline-flex h-11 w-full items-center justify-center gap-1.5 rounded-2xl border border-dashed border-gray text-sm font-medium text-gray-light transition-colors hover:border-spark-a8 hover:bg-base-accent-soft hover:text-accent focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {icon ?? <MaterialSymbol className=\"text-[14px]\" name=\"add\" />}\n {children}\n </button>\n))\n\nScheduleListAdd.displayName = 'ScheduleListAdd'\n\ninterface ScheduleEntryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Make the row interactive — enables hover, role=button, keyboard activation. */\n onClick?: () => void\n disabled?: boolean\n}\n\nconst ScheduleEntry = React.forwardRef<HTMLDivElement, ScheduleEntryProps>(\n ({ children, className, disabled, onClick, ...props }, ref) => {\n const interactive = onClick !== undefined && !disabled\n // role, tab stop and key handler travel together -- the row is never\n // clickable without Enter/Space, and never focusable without a role\n const interaction = interactive\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick,\n onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onClick()\n }\n },\n }\n : undefined\n return (\n <div\n ref={ref}\n {...interaction}\n aria-disabled={disabled || undefined}\n className={cn(\n 'flex items-center gap-3 rounded-2xl bg-base-gray-soft px-3 py-2.5 transition-colors',\n interactive &&\n 'cursor-pointer hover:bg-gray-a3 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n },\n)\n\nScheduleEntry.displayName = 'ScheduleEntry'\n\nconst ScheduleEntryContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col gap-0.5', className)}\n {...props}\n />\n))\n\nScheduleEntryContent.displayName = 'ScheduleEntryContent'\n\nconst ScheduleEntryTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-0 items-center gap-2 truncate text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n))\n\nScheduleEntryTitle.displayName = 'ScheduleEntryTitle'\n\nconst ScheduleEntrySubtitle = React.forwardRef<\n HTMLSpanElement,\n React.HTMLAttributes<HTMLSpanElement>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n className={cn('truncate text-xs text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleEntrySubtitle.displayName = 'ScheduleEntrySubtitle'\n\n/** Right-aligned action area. Stops click propagation so inner controls\n * don't fire the parent `ScheduleEntry`'s `onClick`. */\nconst ScheduleEntryActions = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, onClick, ...props }, ref) => (\n <div\n ref={ref}\n // a layout wrapper, not a control: the handler only shields the inner\n // buttons' clicks (keyboard activation included) from the parent row\n role=\"presentation\"\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn('flex shrink-0 items-center gap-1.5', className)}\n {...props}\n />\n))\n\nScheduleEntryActions.displayName = 'ScheduleEntryActions'\n\ninterface ScheduleEntryDeleteProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nconst ScheduleEntryDelete = React.forwardRef<\n HTMLButtonElement,\n ScheduleEntryDeleteProps\n>(\n (\n {\n 'aria-label': ariaLabel = 'Delete schedule entry',\n children,\n className,\n onClick,\n type = 'button',\n ...props\n },\n ref,\n ) => (\n <button\n ref={ref}\n type={type}\n aria-label={ariaLabel}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn(\n 'inline-flex size-8 shrink-0 items-center justify-center rounded-circle text-gray-light transition-colors hover:bg-base-error-soft hover:text-error focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children ?? <MaterialSymbol className=\"text-[14px]\" name=\"delete\" />}\n </button>\n ),\n)\n\nScheduleEntryDelete.displayName = 'ScheduleEntryDelete'\n\nexport {\n ScheduleEntry,\n ScheduleEntryActions,\n ScheduleEntryContent,\n ScheduleEntryDelete,\n ScheduleEntrySubtitle,\n ScheduleEntryTitle,\n ScheduleList,\n ScheduleListAdd,\n ScheduleListEmpty,\n}\n"],"mappings":"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"}
@@ -31,13 +31,15 @@ const ScheduleEntry = React$1.forwardRef(({ children, className, disabled, onCli
31
31
  const interactive = onClick !== void 0 && !disabled;
32
32
  return /* @__PURE__ */ jsx("div", {
33
33
  ref,
34
- role: interactive ? "button" : void 0,
35
- tabIndex: interactive ? 0 : void 0,
36
- onClick: interactive ? onClick : void 0,
37
- onKeyDown: interactive ? (event) => {
38
- if (event.key === "Enter" || event.key === " ") {
39
- event.preventDefault();
40
- onClick();
34
+ ...interactive ? {
35
+ role: "button",
36
+ tabIndex: 0,
37
+ onClick,
38
+ onKeyDown: (event) => {
39
+ if (event.key === "Enter" || event.key === " ") {
40
+ event.preventDefault();
41
+ onClick();
42
+ }
41
43
  }
42
44
  } : void 0,
43
45
  "aria-disabled": disabled || void 0,
@@ -69,6 +71,7 @@ ScheduleEntrySubtitle.displayName = "ScheduleEntrySubtitle";
69
71
  * don't fire the parent `ScheduleEntry`'s `onClick`. */
70
72
  const ScheduleEntryActions = React$1.forwardRef(({ className, onClick, ...props }, ref) => /* @__PURE__ */ jsx("div", {
71
73
  ref,
74
+ role: "presentation",
72
75
  onClick: (event) => {
73
76
  event.stopPropagation();
74
77
  onClick?.(event);
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-list.js","names":["React"],"sources":["../../src/components/schedule-list.tsx"],"sourcesContent":["import * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\nconst ScheduleList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*2)]',\n className,\n )}\n {...props}\n />\n))\n\nScheduleList.displayName = 'ScheduleList'\n\nconst ScheduleListEmpty = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('px-3 py-2 text-sm text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleListEmpty.displayName = 'ScheduleListEmpty'\n\ninterface ScheduleListAddProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Optional icon override; defaults to a `+`. */\n icon?: React.ReactNode\n}\n\nconst ScheduleListAdd = React.forwardRef<\n HTMLButtonElement,\n ScheduleListAddProps\n>(({ children, className, icon, type = 'button', ...props }, ref) => (\n <button\n ref={ref}\n type={type}\n className={cn(\n 'inline-flex h-11 w-full items-center justify-center gap-1.5 rounded-2xl border border-dashed border-gray text-sm font-medium text-gray-light transition-colors hover:border-spark-a8 hover:bg-base-accent-soft hover:text-accent focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {icon ?? <MaterialSymbol className=\"text-[14px]\" name=\"add\" />}\n {children}\n </button>\n))\n\nScheduleListAdd.displayName = 'ScheduleListAdd'\n\ninterface ScheduleEntryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Make the row interactive — enables hover, role=button, keyboard activation. */\n onClick?: () => void\n disabled?: boolean\n}\n\nconst ScheduleEntry = React.forwardRef<HTMLDivElement, ScheduleEntryProps>(\n ({ children, className, disabled, onClick, ...props }, ref) => {\n const interactive = onClick !== undefined && !disabled\n return (\n <div\n ref={ref}\n role={interactive ? 'button' : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={interactive ? onClick : undefined}\n onKeyDown={\n interactive\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onClick()\n }\n }\n : undefined\n }\n aria-disabled={disabled || undefined}\n className={cn(\n 'flex items-center gap-3 rounded-2xl bg-base-gray-soft px-3 py-2.5 transition-colors',\n interactive &&\n 'cursor-pointer hover:bg-gray-a3 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n },\n)\n\nScheduleEntry.displayName = 'ScheduleEntry'\n\nconst ScheduleEntryContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col gap-0.5', className)}\n {...props}\n />\n))\n\nScheduleEntryContent.displayName = 'ScheduleEntryContent'\n\nconst ScheduleEntryTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-0 items-center gap-2 truncate text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n))\n\nScheduleEntryTitle.displayName = 'ScheduleEntryTitle'\n\nconst ScheduleEntrySubtitle = React.forwardRef<\n HTMLSpanElement,\n React.HTMLAttributes<HTMLSpanElement>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n className={cn('truncate text-xs text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleEntrySubtitle.displayName = 'ScheduleEntrySubtitle'\n\n/** Right-aligned action area. Stops click propagation so inner controls\n * don't fire the parent `ScheduleEntry`'s `onClick`. */\nconst ScheduleEntryActions = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, onClick, ...props }, ref) => (\n <div\n ref={ref}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn('flex shrink-0 items-center gap-1.5', className)}\n {...props}\n />\n))\n\nScheduleEntryActions.displayName = 'ScheduleEntryActions'\n\ninterface ScheduleEntryDeleteProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nconst ScheduleEntryDelete = React.forwardRef<\n HTMLButtonElement,\n ScheduleEntryDeleteProps\n>(\n (\n {\n 'aria-label': ariaLabel = 'Delete schedule entry',\n children,\n className,\n onClick,\n type = 'button',\n ...props\n },\n ref,\n ) => (\n <button\n ref={ref}\n type={type}\n aria-label={ariaLabel}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn(\n 'inline-flex size-8 shrink-0 items-center justify-center rounded-circle text-gray-light transition-colors hover:bg-base-error-soft hover:text-error focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children ?? <MaterialSymbol className=\"text-[14px]\" name=\"delete\" />}\n </button>\n ),\n)\n\nScheduleEntryDelete.displayName = 'ScheduleEntryDelete'\n\nexport {\n ScheduleEntry,\n ScheduleEntryActions,\n ScheduleEntryContent,\n ScheduleEntryDelete,\n ScheduleEntrySubtitle,\n ScheduleEntryTitle,\n ScheduleList,\n ScheduleListAdd,\n ScheduleListEmpty,\n}\n"],"mappings":";;;;;;AAIA,MAAM,eAAeA,QAAM,YAGxB,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GACT,uDACA,SACF;CACA,GAAI;AACL,CAAA,CACF;AAED,aAAa,cAAc;AAE3B,MAAM,oBAAoBA,QAAM,YAG7B,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,KAAD;CACO;CACL,WAAW,GAAG,qCAAqC,SAAS;CAC5D,GAAI;AACL,CAAA,CACF;AAED,kBAAkB,cAAc;AAOhC,MAAM,kBAAkBA,QAAM,YAG3B,EAAE,UAAU,WAAW,MAAM,OAAO,UAAU,GAAG,SAAS,QAC3D,qBAAC,UAAD;CACO;CACC;CACN,WAAW,GACT,kWACA,SACF;CACA,GAAI;WAPN,CASG,QAAQ,oBAAC,gBAAD;EAAgB,WAAU;EAAc,MAAK;CAAO,CAAA,GAC5D,QACK;EACT;AAED,gBAAgB,cAAc;AAQ9B,MAAM,gBAAgBA,QAAM,YACzB,EAAE,UAAU,WAAW,UAAU,SAAS,GAAG,SAAS,QAAQ;CAC7D,MAAM,cAAc,YAAY,KAAA,KAAa,CAAC;CAC9C,OACE,oBAAC,OAAD;EACO;EACL,MAAM,cAAc,WAAW,KAAA;EAC/B,UAAU,cAAc,IAAI,KAAA;EAC5B,SAAS,cAAc,UAAU,KAAA;EACjC,WACE,eACK,UAAU;GACT,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;IAC9C,MAAM,eAAe;IACrB,QAAQ;GACV;EACF,IACA,KAAA;EAEN,iBAAe,YAAY,KAAA;EAC3B,WAAW,GACT,uFACA,eACE,iHACF,YAAY,iCACZ,SACF;EACA,GAAI;EAEH;CACE,CAAA;AAET,CACF;AAEA,cAAc,cAAc;AAE5B,MAAM,uBAAuBA,QAAM,YAGhC,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,wCAAwC,SAAS;CAC/D,GAAI;AACL,CAAA,CACF;AAED,qBAAqB,cAAc;AAEnC,MAAM,qBAAqBA,QAAM,YAG9B,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GACT,0EACA,SACF;CACA,GAAI;AACL,CAAA,CACF;AAED,mBAAmB,cAAc;AAEjC,MAAM,wBAAwBA,QAAM,YAGjC,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,QAAD;CACO;CACL,WAAW,GAAG,oCAAoC,SAAS;CAC3D,GAAI;AACL,CAAA,CACF;AAED,sBAAsB,cAAc;;;AAIpC,MAAM,uBAAuBA,QAAM,YAGhC,EAAE,WAAW,SAAS,GAAG,SAAS,QACnC,oBAAC,OAAD;CACO;CACL,UAAU,UAAU;EAClB,MAAM,gBAAgB;EACtB,UAAU,KAAK;CACjB;CACA,WAAW,GAAG,sCAAsC,SAAS;CAC7D,GAAI;AACL,CAAA,CACF;AAED,qBAAqB,cAAc;AAInC,MAAM,sBAAsBA,QAAM,YAK9B,EACE,cAAc,YAAY,yBAC1B,UACA,WACA,SACA,OAAO,UACP,GAAG,SAEL,QAEA,oBAAC,UAAD;CACO;CACC;CACN,cAAY;CACZ,UAAU,UAAU;EAClB,MAAM,gBAAgB;EACtB,UAAU,KAAK;CACjB;CACA,WAAW,GACT,oRACA,SACF;CACA,GAAI;WAEH,YAAY,oBAAC,gBAAD;EAAgB,WAAU;EAAc,MAAK;CAAU,CAAA;AAC9D,CAAA,CAEZ;AAEA,oBAAoB,cAAc"}
1
+ {"version":3,"file":"schedule-list.js","names":["React"],"sources":["../../src/components/schedule-list.tsx"],"sourcesContent":["import * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\nconst ScheduleList = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-[calc(var(--spark-layout-gap)*2)]',\n className,\n )}\n {...props}\n />\n))\n\nScheduleList.displayName = 'ScheduleList'\n\nconst ScheduleListEmpty = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('px-3 py-2 text-sm text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleListEmpty.displayName = 'ScheduleListEmpty'\n\ninterface ScheduleListAddProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Optional icon override; defaults to a `+`. */\n icon?: React.ReactNode\n}\n\nconst ScheduleListAdd = React.forwardRef<\n HTMLButtonElement,\n ScheduleListAddProps\n>(({ children, className, icon, type = 'button', ...props }, ref) => (\n <button\n ref={ref}\n type={type}\n className={cn(\n 'inline-flex h-11 w-full items-center justify-center gap-1.5 rounded-2xl border border-dashed border-gray text-sm font-medium text-gray-light transition-colors hover:border-spark-a8 hover:bg-base-accent-soft hover:text-accent focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {icon ?? <MaterialSymbol className=\"text-[14px]\" name=\"add\" />}\n {children}\n </button>\n))\n\nScheduleListAdd.displayName = 'ScheduleListAdd'\n\ninterface ScheduleEntryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Make the row interactive — enables hover, role=button, keyboard activation. */\n onClick?: () => void\n disabled?: boolean\n}\n\nconst ScheduleEntry = React.forwardRef<HTMLDivElement, ScheduleEntryProps>(\n ({ children, className, disabled, onClick, ...props }, ref) => {\n const interactive = onClick !== undefined && !disabled\n // role, tab stop and key handler travel together -- the row is never\n // clickable without Enter/Space, and never focusable without a role\n const interaction = interactive\n ? {\n role: 'button' as const,\n tabIndex: 0,\n onClick,\n onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n onClick()\n }\n },\n }\n : undefined\n return (\n <div\n ref={ref}\n {...interaction}\n aria-disabled={disabled || undefined}\n className={cn(\n 'flex items-center gap-3 rounded-2xl bg-base-gray-soft px-3 py-2.5 transition-colors',\n interactive &&\n 'cursor-pointer hover:bg-gray-a3 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n },\n)\n\nScheduleEntry.displayName = 'ScheduleEntry'\n\nconst ScheduleEntryContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col gap-0.5', className)}\n {...props}\n />\n))\n\nScheduleEntryContent.displayName = 'ScheduleEntryContent'\n\nconst ScheduleEntryTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-0 items-center gap-2 truncate text-sm font-medium text-gray',\n className,\n )}\n {...props}\n />\n))\n\nScheduleEntryTitle.displayName = 'ScheduleEntryTitle'\n\nconst ScheduleEntrySubtitle = React.forwardRef<\n HTMLSpanElement,\n React.HTMLAttributes<HTMLSpanElement>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n className={cn('truncate text-xs text-gray-light', className)}\n {...props}\n />\n))\n\nScheduleEntrySubtitle.displayName = 'ScheduleEntrySubtitle'\n\n/** Right-aligned action area. Stops click propagation so inner controls\n * don't fire the parent `ScheduleEntry`'s `onClick`. */\nconst ScheduleEntryActions = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, onClick, ...props }, ref) => (\n <div\n ref={ref}\n // a layout wrapper, not a control: the handler only shields the inner\n // buttons' clicks (keyboard activation included) from the parent row\n role=\"presentation\"\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn('flex shrink-0 items-center gap-1.5', className)}\n {...props}\n />\n))\n\nScheduleEntryActions.displayName = 'ScheduleEntryActions'\n\ninterface ScheduleEntryDeleteProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\nconst ScheduleEntryDelete = React.forwardRef<\n HTMLButtonElement,\n ScheduleEntryDeleteProps\n>(\n (\n {\n 'aria-label': ariaLabel = 'Delete schedule entry',\n children,\n className,\n onClick,\n type = 'button',\n ...props\n },\n ref,\n ) => (\n <button\n ref={ref}\n type={type}\n aria-label={ariaLabel}\n onClick={(event) => {\n event.stopPropagation()\n onClick?.(event)\n }}\n className={cn(\n 'inline-flex size-8 shrink-0 items-center justify-center rounded-circle text-gray-light transition-colors hover:bg-base-error-soft hover:text-error focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children ?? <MaterialSymbol className=\"text-[14px]\" name=\"delete\" />}\n </button>\n ),\n)\n\nScheduleEntryDelete.displayName = 'ScheduleEntryDelete'\n\nexport {\n ScheduleEntry,\n ScheduleEntryActions,\n ScheduleEntryContent,\n ScheduleEntryDelete,\n ScheduleEntrySubtitle,\n ScheduleEntryTitle,\n ScheduleList,\n ScheduleListAdd,\n ScheduleListEmpty,\n}\n"],"mappings":";;;;;;AAIA,MAAM,eAAeA,QAAM,YAGxB,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GACT,uDACA,SACF;CACA,GAAI;AACL,CAAA,CACF;AAED,aAAa,cAAc;AAE3B,MAAM,oBAAoBA,QAAM,YAG7B,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,KAAD;CACO;CACL,WAAW,GAAG,qCAAqC,SAAS;CAC5D,GAAI;AACL,CAAA,CACF;AAED,kBAAkB,cAAc;AAOhC,MAAM,kBAAkBA,QAAM,YAG3B,EAAE,UAAU,WAAW,MAAM,OAAO,UAAU,GAAG,SAAS,QAC3D,qBAAC,UAAD;CACO;CACC;CACN,WAAW,GACT,kWACA,SACF;CACA,GAAI;WAPN,CASG,QAAQ,oBAAC,gBAAD;EAAgB,WAAU;EAAc,MAAK;CAAO,CAAA,GAC5D,QACK;EACT;AAED,gBAAgB,cAAc;AAQ9B,MAAM,gBAAgBA,QAAM,YACzB,EAAE,UAAU,WAAW,UAAU,SAAS,GAAG,SAAS,QAAQ;CAC7D,MAAM,cAAc,YAAY,KAAA,KAAa,CAAC;CAgB9C,OACE,oBAAC,OAAD;EACO;EACL,GAhBgB,cAChB;GACE,MAAM;GACN,UAAU;GACV;GACA,YAAY,UAA+C;IACzD,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;KAC9C,MAAM,eAAe;KACrB,QAAQ;IACV;GACF;EACF,IACA,KAAA;EAKA,iBAAe,YAAY,KAAA;EAC3B,WAAW,GACT,uFACA,eACE,iHACF,YAAY,iCACZ,SACF;EACA,GAAI;EAEH;CACE,CAAA;AAET,CACF;AAEA,cAAc,cAAc;AAE5B,MAAM,uBAAuBA,QAAM,YAGhC,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GAAG,wCAAwC,SAAS;CAC/D,GAAI;AACL,CAAA,CACF;AAED,qBAAqB,cAAc;AAEnC,MAAM,qBAAqBA,QAAM,YAG9B,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,OAAD;CACO;CACL,WAAW,GACT,0EACA,SACF;CACA,GAAI;AACL,CAAA,CACF;AAED,mBAAmB,cAAc;AAEjC,MAAM,wBAAwBA,QAAM,YAGjC,EAAE,WAAW,GAAG,SAAS,QAC1B,oBAAC,QAAD;CACO;CACL,WAAW,GAAG,oCAAoC,SAAS;CAC3D,GAAI;AACL,CAAA,CACF;AAED,sBAAsB,cAAc;;;AAIpC,MAAM,uBAAuBA,QAAM,YAGhC,EAAE,WAAW,SAAS,GAAG,SAAS,QACnC,oBAAC,OAAD;CACO;CAGL,MAAK;CACL,UAAU,UAAU;EAClB,MAAM,gBAAgB;EACtB,UAAU,KAAK;CACjB;CACA,WAAW,GAAG,sCAAsC,SAAS;CAC7D,GAAI;AACL,CAAA,CACF;AAED,qBAAqB,cAAc;AAInC,MAAM,sBAAsBA,QAAM,YAK9B,EACE,cAAc,YAAY,yBAC1B,UACA,WACA,SACA,OAAO,UACP,GAAG,SAEL,QAEA,oBAAC,UAAD;CACO;CACC;CACN,cAAY;CACZ,UAAU,UAAU;EAClB,MAAM,gBAAgB;EACtB,UAAU,KAAK;CACjB;CACA,WAAW,GACT,oRACA,SACF;CACA,GAAI;WAEH,YAAY,oBAAC,gBAAD;EAAgB,WAAU;EAAc,MAAK;CAAU,CAAA;AAC9D,CAAA,CAEZ;AAEA,oBAAoB,cAAc"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import * as React$1 from "react";
5
5
  import { Tabs } from "@base-ui/react/tabs";
6
6
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import * as React$1 from "react";
5
5
  import { Tabs } from "@base-ui/react/tabs";
6
6
 
@@ -2,8 +2,8 @@
2
2
  "use client";
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  const require_chunk = require("../chunk-DY84GLCh.cjs");
5
- const require_lib_input_box_variants = require("../lib/input-box-variants.cjs");
6
5
  const require_icons_material_symbol = require("../icons/material-symbol.cjs");
6
+ const require_lib_input_box_variants = require("../lib/input-box-variants.cjs");
7
7
  const require_components_field = require("./field.cjs");
8
8
  let react = require("react");
9
9
  react = require_chunk.__toESM(react);
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { a as SparkInputStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import * as React$1 from "react";
5
5
  import { Select as Select$1 } from "@base-ui/react/select";
6
6
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { a as SparkInputStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import * as React$1 from "react";
5
5
  import { Select as Select$1 } from "@base-ui/react/select";
6
6
 
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  "use client";
3
3
  import { cn } from "../utils/cn.js";
4
- import { boxChrome } from "../lib/input-box-variants.js";
5
4
  import { MaterialSymbol } from "../icons/material-symbol.js";
5
+ import { boxChrome } from "../lib/input-box-variants.js";
6
6
  import { useFieldControl } from "./field.js";
7
7
  import "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  __esModule: { value: true },
4
4
  [Symbol.toStringTag]: { value: "Module" }
5
5
  });
6
+ const require_icons_material_symbol = require("../icons/material-symbol.cjs");
6
7
  require("../utils/chars.cjs");
7
8
  const require_utils_format = require("../utils/format.cjs");
8
- const require_icons_material_symbol = require("../icons/material-symbol.cjs");
9
9
  const require_components_line_chart = require("./line-chart.cjs");
10
10
  let react = require("react");
11
11
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import "../utils/chars.js";
3
- import { oneDecimalFormat } from "../utils/format.js";
4
2
  import { cn } from "../utils/cn.js";
5
3
  import { MaterialSymbol } from "../icons/material-symbol.js";
4
+ import "../utils/chars.js";
5
+ import { oneDecimalFormat } from "../utils/format.js";
6
6
  import { LineChart } from "./line-chart.js";
7
7
  import { useEffect, useRef, useState } from "react";
8
8
  import { jsx } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.cjs";
4
4
  import { Switch as Switch$1 } from "@base-ui/react/switch";
5
5
 
6
6
  //#region src/components/switch.d.ts
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { u as SparkStyle } from "../theme-types-1yB0d8mp.js";
3
+ import { f as SparkStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import { Switch as Switch$1 } from "@base-ui/react/switch";
5
5
 
6
6
  //#region src/components/switch.d.ts
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.cjs";
3
+ import { a as SparkInputStyle } from "../theme-types-Bn5E15-P.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-1yB0d8mp.js";
3
+ import { a as SparkInputStyle } from "../theme-types-Bn5E15-P.js";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/textarea.d.ts
@@ -2,6 +2,7 @@
2
2
  "use client";
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  const require_chunk = require("../chunk-DY84GLCh.cjs");
5
+ const require_lib_theme_types = require("../lib/theme-types.cjs");
5
6
  const require_lib_accent_theme = require("../lib/accent-theme.cjs");
6
7
  let react = require("react");
7
8
  react = require_chunk.__toESM(react);
@@ -18,7 +19,7 @@ function useTheme() {
18
19
  return react.useContext(ThemeContext);
19
20
  }
20
21
  /** Optional sugar: writes the theming `data-*` attrs + accent `--spark-*` vars onto a wrapper. */
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) {
22
+ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, neutralColor, radius, scaling, spacing, styleVariant, highContrast, inverted, labelPosition, inputStyle, inputColor, cardVariant, cardColor, appearance, fontHeading, fontBody, render, className, style, children, ...rest }, ref) {
22
23
  const parent = useTheme();
23
24
  const value = react.useMemo(() => ({
24
25
  accentColor: accentColor ?? parent.accentColor,
@@ -29,6 +30,7 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
29
30
  spacing: spacing ?? parent.spacing,
30
31
  styleVariant: styleVariant ?? parent.styleVariant,
31
32
  highContrast: highContrast ?? parent.highContrast,
33
+ inverted: inverted ?? parent.inverted,
32
34
  labelPosition: labelPosition ?? parent.labelPosition,
33
35
  inputStyle: inputStyle ?? parent.inputStyle,
34
36
  inputColor: inputColor ?? parent.inputColor,
@@ -46,6 +48,7 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
46
48
  spacing,
47
49
  styleVariant,
48
50
  highContrast,
51
+ inverted,
49
52
  labelPosition,
50
53
  inputStyle,
51
54
  inputColor,
@@ -57,7 +60,11 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
57
60
  parent
58
61
  ]);
59
62
  const scopeId = react.useId();
60
- const resolvedNeutralColor = neutralColor === "auto" ? require_lib_accent_theme.getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT) : neutralColor;
63
+ const rawNeutralColor = neutralColor === "auto" ? require_lib_accent_theme.resolveAutoNeutral(value.accentColor ?? DEFAULT_ACCENT, backgroundColor) : neutralColor;
64
+ const neutralColorIsValid = rawNeutralColor === void 0 || require_lib_theme_types.isSparkNeutralFamily(rawNeutralColor) || require_lib_accent_theme.isParsableColor(rawNeutralColor);
65
+ if (!neutralColorIsValid) console.warn(`[Theme] Ignoring invalid neutralColor "${rawNeutralColor}" — falling back to the accent-matched family.`);
66
+ const resolvedNeutralColor = neutralColorIsValid ? rawNeutralColor : require_lib_accent_theme.getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT);
67
+ const neutralColorAttr = resolvedNeutralColor === void 0 ? void 0 : require_lib_theme_types.isSparkNeutralFamily(resolvedNeutralColor) ? resolvedNeutralColor : require_lib_accent_theme.getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT);
61
68
  const accent = react.useMemo(() => {
62
69
  const empty = {
63
70
  inlineVars: {},
@@ -81,15 +88,18 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
81
88
  const emit = (scale, custom) => custom ? [...require_lib_accent_theme.accentSparkVars(scale), ...require_lib_accent_theme.neutralSparkVars(scale)] : require_lib_accent_theme.accentSparkVars(scale);
82
89
  const build = (appearance) => {
83
90
  const opts = optsFor(appearance);
84
- return emit(require_lib_accent_theme.generateAccentScale(hex, appearance, opts), opts != null);
91
+ const scale = require_lib_accent_theme.generateAccentScale(hex, appearance, opts);
92
+ return emit(inverted ? require_lib_accent_theme.invertAccentScale(scale) : scale, opts != null);
85
93
  };
86
94
  if (value.appearance) return {
87
95
  inlineVars: toVars(build(value.appearance)),
88
96
  css: "",
89
97
  scoped: false
90
98
  };
91
- const light = build("light");
92
- const dark = build("dark");
99
+ const offCanvasNeutrals = backgroundColor ? require_lib_accent_theme.neutralFamilyVars(resolvedNeutralColor ?? "slate") : [];
100
+ const scaleFor = (appearance) => bgAppearance === appearance ? build(appearance) : [...build(appearance), ...offCanvasNeutrals];
101
+ const light = scaleFor("light");
102
+ const dark = scaleFor("dark");
93
103
  const sel = `[data-spark-scope="${scopeId}"]`;
94
104
  return {
95
105
  inlineVars: {},
@@ -103,6 +113,7 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
103
113
  }, [
104
114
  accentColor,
105
115
  backgroundColor,
116
+ inverted,
106
117
  resolvedNeutralColor,
107
118
  value.accentColor,
108
119
  value.appearance,
@@ -114,12 +125,13 @@ const Theme = react.forwardRef(function Theme({ accentColor, backgroundColor, ne
114
125
  ref,
115
126
  props: (0, _base_ui_react_merge_props.mergeProps)({
116
127
  className: (0, cnfast.cn)("spark-theme", appearance, className),
117
- "data-neutral-color": resolvedNeutralColor,
128
+ "data-neutral-color": neutralColorAttr,
118
129
  "data-radius": radius,
119
130
  "data-scaling": scaling,
120
131
  "data-spacing": spacing,
121
132
  "data-style": styleVariant,
122
133
  "data-high-contrast": highContrast ? "" : void 0,
134
+ "data-inverted": inverted ? "" : void 0,
123
135
  "data-label-position": labelPosition,
124
136
  "data-input-style": inputStyle,
125
137
  "data-input-color": inputColor,
@@ -1 +1 @@
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":"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"}
1
+ {"version":3,"file":"theme.cjs","names":["React","resolveAutoNeutral","isSparkNeutralFamily","isParsableColor","getMatchingNeutral","CURATED_ACCENTS","appearanceForBackground","accentSparkVars","neutralSparkVars","generateAccentScale","invertAccentScale","neutralFamilyVars"],"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 invertAccentScale,\n isParsableColor,\n neutralFamilyVars,\n neutralSparkVars,\n resolveAutoNeutral,\n type Appearance,\n type SparkAccentScale,\n} from '../lib/accent-theme'\nimport {\n isSparkNeutralFamily,\n type SparkCardColor,\n type SparkCardVariant,\n type SparkInputColor,\n type SparkInputStyle,\n type SparkLabelPosition,\n type SparkNeutral,\n type SparkRadius,\n type SparkScaling,\n type SparkSpacing,\n type 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 /**\n * A curated family name, an arbitrary color to seed the neutral scale, or `'auto'` to\n * resolve one — preferring `backgroundColor`'s own hue when it's perceptibly tinted,\n * else pairing with the accent (Radix's `grayColor=\"auto\"`). A custom seed (from `auto`\n * or set directly) only regenerates the scale alongside a `backgroundColor`; without\n * one, `data-neutral-color` falls back to the accent-matched family and that's what\n * actually paints.\n */\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 /**\n * Orthogonal to `styleVariant`: re-casts the accent scale for use ON its own solid fill,\n * for controls sitting on a solid accent surface (a `<Card variant=\"solid\" color=\"accent\">`),\n * where a solid control would otherwise paint the same `--spark-9` as the card and vanish.\n * Swaps step 9 with its contrast ink, so the fill/ink pair stays WCAG-safe for any accent.\n */\n inverted?: 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 inverted,\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 inverted: inverted ?? parent.inverted,\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 inverted,\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 canvas's own tint when it has one, else the\n // effective accent (Radix's grayColor=\"auto\") — see resolveAutoNeutral. Reads the\n // OWN backgroundColor, not the merged value.backgroundColor: optsFor (below) only\n // ever regenerates against a scope's own canvas too, so preferring an inherited one\n // here would resolve a seed that then gets silently discarded.\n const rawNeutralColor =\n neutralColor === 'auto'\n ? resolveAutoNeutral(\n value.accentColor ?? DEFAULT_ACCENT,\n backgroundColor,\n )\n : neutralColor\n\n // A custom neutral that isn't a recognized family must be a real, parseable color —\n // reject invalid input here (e.g. a typo'd family name like \"slat\") so it can't throw\n // deep inside the shared generator, where the catch below would otherwise blame\n // accentColor/backgroundColor without ever naming neutralColor as the actual cause.\n const neutralColorIsValid =\n rawNeutralColor === undefined ||\n isSparkNeutralFamily(rawNeutralColor) ||\n isParsableColor(rawNeutralColor)\n if (!neutralColorIsValid) {\n console.warn(\n `[Theme] Ignoring invalid neutralColor \"${rawNeutralColor}\" — falling back to the accent-matched family.`,\n )\n }\n const resolvedNeutralColor = neutralColorIsValid\n ? rawNeutralColor\n : getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT)\n\n // The DOM attribute stays one of the 6 static families `[data-neutral-color]` has CSS\n // for — a raw color (from the canvas-tinted auto path, or an arbitrary neutralColor\n // prop) falls back to its accent-matched family here instead, so the attribute is\n // always CSS-selectable/debuggable rather than a sentinel nothing matches.\n // generateAccentScale still gets the real resolvedNeutralColor for generation, below —\n // this substitution is display-only, and doesn't by itself guarantee the *other*\n // appearance's neutrals in ambient (no explicit `appearance`) mode: that's a\n // pre-existing cross-appearance leak in the same family as review-findings.md #5, not\n // something this attribute fallback fixes or regresses.\n const neutralColorAttr =\n resolvedNeutralColor === undefined\n ? undefined\n : isSparkNeutralFamily(resolvedNeutralColor)\n ? resolvedNeutralColor\n : getMatchingNeutral(value.accentColor ?? DEFAULT_ACCENT)\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 const scale = generateAccentScale(hex, appearance, opts)\n // `inverted` re-casts the accent for a solid-accent surface; the neutral ramp is\n // unrelated to that swap, so it passes through untouched.\n return emit(inverted ? invertAccentScale(scale) : scale, 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 //\n // Both blocks must declare the SAME tokens. A custom canvas only regenerates\n // neutrals for its own appearance (see optsFor), and a custom property the other\n // block leaves undeclared keeps its sibling's value rather than falling back — so\n // the off-canvas appearance would paint this one's canvas-tinted neutrals, and\n // being unlayered they'd beat `[data-neutral-color]`'s @layer base mapping too.\n // Point it at the static family instead: the same seed the canvas side was given,\n // so the two appearances agree on family and differ only in canvas.\n const offCanvasNeutrals = backgroundColor\n ? neutralFamilyVars(resolvedNeutralColor ?? 'slate')\n : []\n const scaleFor = (appearance: Appearance) =>\n bgAppearance === appearance\n ? build(appearance)\n : [...build(appearance), ...offCanvasNeutrals]\n const light = scaleFor('light')\n const dark = scaleFor('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 inverted,\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': neutralColorAttr,\n 'data-radius': radius,\n 'data-scaling': scaling,\n 'data-spacing': spacing,\n 'data-style': styleVariant,\n 'data-high-contrast': highContrast ? '' : undefined,\n 'data-inverted': inverted ? '' : 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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"}
@@ -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-1yB0d8mp.cjs";
3
+ import { a as SparkInputStyle, d as SparkSpacing, f as SparkStyle, i as SparkInputColor, l as SparkRadius, n as SparkCardColor, o as SparkLabelPosition, r as SparkCardVariant, s as SparkNeutral, u as SparkScaling } from "../theme-types-Bn5E15-P.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";
@@ -16,7 +16,14 @@ interface ThemeValue {
16
16
  * `#ffffff` / `#000000` default, and neutrals stay on the static Radix families.
17
17
  */
18
18
  backgroundColor?: string;
19
- /** A neutral name, or `'auto'` to pair one with the accent (Radix's `grayColor="auto"`). */
19
+ /**
20
+ * A curated family name, an arbitrary color to seed the neutral scale, or `'auto'` to
21
+ * resolve one — preferring `backgroundColor`'s own hue when it's perceptibly tinted,
22
+ * else pairing with the accent (Radix's `grayColor="auto"`). A custom seed (from `auto`
23
+ * or set directly) only regenerates the scale alongside a `backgroundColor`; without
24
+ * one, `data-neutral-color` falls back to the accent-matched family and that's what
25
+ * actually paints.
26
+ */
20
27
  neutralColor?: SparkNeutral;
21
28
  radius?: SparkRadius;
22
29
  scaling?: SparkScaling;
@@ -24,6 +31,13 @@ interface ThemeValue {
24
31
  styleVariant?: SparkStyle;
25
32
  /** Orthogonal to `styleVariant`: shifts any style toward higher-contrast steps. */
26
33
  highContrast?: boolean;
34
+ /**
35
+ * Orthogonal to `styleVariant`: re-casts the accent scale for use ON its own solid fill,
36
+ * for controls sitting on a solid accent surface (a `<Card variant="solid" color="accent">`),
37
+ * where a solid control would otherwise paint the same `--spark-9` as the card and vanish.
38
+ * Swaps step 9 with its contrast ink, so the fill/ink pair stays WCAG-safe for any accent.
39
+ */
40
+ inverted?: boolean;
27
41
  labelPosition?: SparkLabelPosition;
28
42
  inputStyle?: SparkInputStyle;
29
43
  inputColor?: SparkInputColor;