@epilot/spark-ui 0.10.1 → 0.11.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 (176) hide show
  1. package/README.md +9 -1
  2. package/dist/components/accordion.cjs +1 -1
  3. package/dist/components/accordion.d.ts +1 -1
  4. package/dist/components/accordion.js +1 -1
  5. package/dist/components/attachment.d.cts +1 -1
  6. package/dist/components/attachment.d.ts +1 -1
  7. package/dist/components/avatar.d.cts +1 -1
  8. package/dist/components/avatar.d.ts +1 -1
  9. package/dist/components/badge.cjs +1 -1
  10. package/dist/components/badge.cjs.map +1 -1
  11. package/dist/components/badge.d.cts +1 -1
  12. package/dist/components/badge.d.ts +1 -1
  13. package/dist/components/badge.js +1 -1
  14. package/dist/components/badge.js.map +1 -1
  15. package/dist/components/bar-chart.cjs +6 -8
  16. package/dist/components/bar-chart.cjs.map +1 -1
  17. package/dist/components/bar-chart.js +7 -9
  18. package/dist/components/bar-chart.js.map +1 -1
  19. package/dist/components/battery-progress-row.cjs +6 -7
  20. package/dist/components/battery-progress-row.cjs.map +1 -1
  21. package/dist/components/battery-progress-row.js +6 -7
  22. package/dist/components/battery-progress-row.js.map +1 -1
  23. package/dist/components/box.cjs +42 -0
  24. package/dist/components/box.cjs.map +1 -0
  25. package/dist/components/box.d.cts +35 -0
  26. package/dist/components/box.d.ts +35 -0
  27. package/dist/components/box.js +41 -0
  28. package/dist/components/box.js.map +1 -0
  29. package/dist/components/bubble.d.cts +1 -1
  30. package/dist/components/bubble.d.ts +1 -1
  31. package/dist/components/button-group.d.cts +1 -1
  32. package/dist/components/button-group.d.ts +1 -1
  33. package/dist/components/button.cjs +1 -1
  34. package/dist/components/button.cjs.map +1 -1
  35. package/dist/components/button.d.cts +3 -3
  36. package/dist/components/button.d.ts +3 -3
  37. package/dist/components/button.js +1 -1
  38. package/dist/components/button.js.map +1 -1
  39. package/dist/components/callout.d.cts +1 -1
  40. package/dist/components/callout.d.ts +1 -1
  41. package/dist/components/card.cjs +10 -14
  42. package/dist/components/card.cjs.map +1 -1
  43. package/dist/components/card.d.cts +6 -3
  44. package/dist/components/card.d.ts +6 -3
  45. package/dist/components/card.js +10 -14
  46. package/dist/components/card.js.map +1 -1
  47. package/dist/components/checkbox.d.cts +1 -1
  48. package/dist/components/checkbox.d.ts +1 -1
  49. package/dist/components/empty-state.cjs +4 -7
  50. package/dist/components/empty-state.cjs.map +1 -1
  51. package/dist/components/empty-state.js +4 -7
  52. package/dist/components/empty-state.js.map +1 -1
  53. package/dist/components/field.cjs +43 -10
  54. package/dist/components/field.cjs.map +1 -1
  55. package/dist/components/field.d.cts +19 -2
  56. package/dist/components/field.d.ts +19 -2
  57. package/dist/components/field.js +43 -11
  58. package/dist/components/field.js.map +1 -1
  59. package/dist/components/icon.cjs +12 -9
  60. package/dist/components/icon.cjs.map +1 -1
  61. package/dist/components/icon.d.cts +6 -2
  62. package/dist/components/icon.d.ts +6 -2
  63. package/dist/components/icon.js +12 -9
  64. package/dist/components/icon.js.map +1 -1
  65. package/dist/components/info-block.d.cts +1 -1
  66. package/dist/components/info-block.d.ts +1 -1
  67. package/dist/components/input-otp.cjs +1 -1
  68. package/dist/components/input-otp.js +1 -1
  69. package/dist/components/input.cjs +1 -1
  70. package/dist/components/input.d.cts +1 -1
  71. package/dist/components/input.d.ts +1 -1
  72. package/dist/components/input.js +1 -1
  73. package/dist/components/layout.cjs +6 -2
  74. package/dist/components/layout.cjs.map +1 -1
  75. package/dist/components/layout.d.cts +9 -2
  76. package/dist/components/layout.d.ts +8 -2
  77. package/dist/components/layout.js +6 -2
  78. package/dist/components/layout.js.map +1 -1
  79. package/dist/components/line-chart.cjs +2 -2
  80. package/dist/components/line-chart.js +3 -3
  81. package/dist/components/list.cjs +46 -14
  82. package/dist/components/list.cjs.map +1 -1
  83. package/dist/components/list.d.cts +27 -3
  84. package/dist/components/list.d.ts +27 -3
  85. package/dist/components/list.js +46 -14
  86. package/dist/components/list.js.map +1 -1
  87. package/dist/components/marker.d.cts +1 -1
  88. package/dist/components/marker.d.ts +1 -1
  89. package/dist/components/metering-row.cjs +28 -11
  90. package/dist/components/metering-row.cjs.map +1 -1
  91. package/dist/components/metering-row.js +28 -11
  92. package/dist/components/metering-row.js.map +1 -1
  93. package/dist/components/page-header.d.cts +1 -1
  94. package/dist/components/page-header.d.ts +1 -1
  95. package/dist/components/pill.cjs +2 -2
  96. package/dist/components/pill.cjs.map +1 -1
  97. package/dist/components/pill.d.cts +1 -1
  98. package/dist/components/pill.d.ts +1 -1
  99. package/dist/components/pill.js +2 -2
  100. package/dist/components/pill.js.map +1 -1
  101. package/dist/components/popover.cjs +16 -13
  102. package/dist/components/popover.cjs.map +1 -1
  103. package/dist/components/popover.d.cts +2 -1
  104. package/dist/components/popover.d.ts +2 -1
  105. package/dist/components/popover.js +16 -13
  106. package/dist/components/popover.js.map +1 -1
  107. package/dist/components/power-history-chart.cjs +2 -2
  108. package/dist/components/power-history-chart.js +3 -3
  109. package/dist/components/power-history.cjs +1 -1
  110. package/dist/components/power-history.js +1 -1
  111. package/dist/components/power-network.cjs +1 -1
  112. package/dist/components/power-network.js +1 -1
  113. package/dist/components/radio-card-group.cjs +6 -2
  114. package/dist/components/radio-card-group.cjs.map +1 -1
  115. package/dist/components/radio-card-group.d.cts +2 -0
  116. package/dist/components/radio-card-group.d.ts +2 -0
  117. package/dist/components/radio-card-group.js +6 -2
  118. package/dist/components/radio-card-group.js.map +1 -1
  119. package/dist/components/radio.cjs +6 -2
  120. package/dist/components/radio.cjs.map +1 -1
  121. package/dist/components/radio.d.cts +7 -3
  122. package/dist/components/radio.d.ts +7 -3
  123. package/dist/components/radio.js +6 -2
  124. package/dist/components/radio.js.map +1 -1
  125. package/dist/components/segmented-control.d.cts +1 -1
  126. package/dist/components/segmented-control.d.ts +1 -1
  127. package/dist/components/select.cjs +22 -19
  128. package/dist/components/select.cjs.map +1 -1
  129. package/dist/components/select.d.cts +3 -2
  130. package/dist/components/select.d.ts +3 -2
  131. package/dist/components/select.js +22 -19
  132. package/dist/components/select.js.map +1 -1
  133. package/dist/components/solar-forecast-chart.cjs +1 -1
  134. package/dist/components/solar-forecast-chart.js +2 -2
  135. package/dist/components/switch.d.cts +1 -1
  136. package/dist/components/switch.d.ts +1 -1
  137. package/dist/components/tabs.cjs +4 -3
  138. package/dist/components/tabs.cjs.map +1 -1
  139. package/dist/components/tabs.d.cts +9 -0
  140. package/dist/components/tabs.d.ts +9 -0
  141. package/dist/components/tabs.js +4 -3
  142. package/dist/components/tabs.js.map +1 -1
  143. package/dist/components/textarea.cjs +1 -1
  144. package/dist/components/textarea.d.cts +1 -1
  145. package/dist/components/textarea.d.ts +1 -1
  146. package/dist/components/textarea.js +1 -1
  147. package/dist/components/theme.cjs +35 -9
  148. package/dist/components/theme.cjs.map +1 -1
  149. package/dist/components/theme.d.cts +12 -1
  150. package/dist/components/theme.d.ts +12 -1
  151. package/dist/components/theme.js +36 -10
  152. package/dist/components/theme.js.map +1 -1
  153. package/dist/icons/material-symbol.cjs +1 -0
  154. package/dist/icons/material-symbol.cjs.map +1 -1
  155. package/dist/icons/material-symbol.js +1 -0
  156. package/dist/icons/material-symbol.js.map +1 -1
  157. package/dist/lib/accent-theme.cjs +102 -14
  158. package/dist/lib/accent-theme.cjs.map +1 -1
  159. package/dist/lib/accent-theme.d.cts +29 -4
  160. package/dist/lib/accent-theme.d.ts +29 -4
  161. package/dist/lib/accent-theme.js +100 -15
  162. package/dist/lib/accent-theme.js.map +1 -1
  163. package/dist/lib/container-chrome.cjs +53 -0
  164. package/dist/lib/container-chrome.cjs.map +1 -0
  165. package/dist/lib/container-chrome.d.cts +15 -0
  166. package/dist/lib/container-chrome.d.ts +15 -0
  167. package/dist/lib/container-chrome.js +48 -0
  168. package/dist/lib/container-chrome.js.map +1 -0
  169. package/dist/lib/input-box-variants.d.cts +1 -1
  170. package/dist/lib/input-box-variants.d.ts +1 -1
  171. package/dist/lib/theme-types.d.cts +1 -1
  172. package/dist/lib/theme-types.d.ts +1 -1
  173. package/dist/styles/spark-default.css +34 -8
  174. package/dist/{theme-types-8wjgiNA_.d.ts → theme-types-1yB0d8mp.d.cts} +6 -6
  175. package/dist/{theme-types-8wjgiNA_.d.cts → theme-types-1yB0d8mp.d.ts} +6 -6
  176. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"icon.js","names":[],"sources":["../../src/components/icon.tsx"],"sourcesContent":["import * as React from 'react'\nimport {\n MaterialSymbol,\n type MaterialSymbolIconName,\n} from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\ninterface IconProps extends React.HTMLAttributes<HTMLSpanElement> {\n name?: MaterialSymbolIconName\n /** Fill treatment. Neutral (gray) by default; colour is opt-in via className. */\n variant?: 'soft' | 'surface' | 'solid' | 'ghost' | 'outline'\n size?: 'small' | 'default' | 'medium'\n}\n\n// Icon is a display element, so it is colour-INDEPENDENT: every variant paints with the\n// neutral gray scale (tracks the neutral knob, not the accent). Colour is a per-instance\n// className override (e.g. bg-base-error-soft text-error), which wins over the base via\n// tailwind-merge. Ink flows through --icon-ink so that override still wins under high\n// contrast, which only re-points the var: data-high-contrast (on the icon or an ancestor)\n// darkens the glyph a11→a12 and strengthens the surface/outline border →a11. solid is\n// already max-contrast, so HC leaves it unchanged. border-box keeps the frame size\n// constant when surface/outline add their 1px edge.\nconst variantClasses = {\n soft: 'bg-[var(--color-gray-a3)] [[data-high-contrast]_&]:[--icon-ink:var(--color-gray-a12)]',\n surface:\n 'border border-[color:var(--icon-bd,var(--color-gray-a6))] bg-[var(--color-gray-a2)] [[data-high-contrast]_&]:[--icon-ink:var(--color-gray-a12)] [[data-high-contrast]_&]:[--icon-bd:var(--color-gray-a11)]',\n solid: 'bg-[var(--color-gray-12)] text-[color:var(--color-gray-1)]',\n ghost: '[[data-high-contrast]_&]:[--icon-ink:var(--color-gray-a12)]',\n outline:\n 'border border-[color:var(--icon-bd,var(--color-gray-a8))] [[data-high-contrast]_&]:[--icon-ink:var(--color-gray-a12)] [[data-high-contrast]_&]:[--icon-bd:var(--color-gray-a11)]',\n}\n\n// Frame + glyph sizes are spacing-derived so both track the scaling/spacing knobs.\nconst sizeClasses = {\n small: 'size-6 [--spark-icon-size:calc(var(--spacing)*4)]',\n default: 'size-8 [--spark-icon-size:calc(var(--spacing)*5)]',\n medium: 'size-10 [--spark-icon-size:calc(var(--spacing)*6)]',\n}\n\nfunction Icon({\n className,\n name,\n children,\n variant = 'soft',\n size = 'default',\n ...props\n}: IconProps) {\n return (\n <span\n data-slot=\"icon\"\n // labeled = meaningful image; otherwise decorative (the glyph is aria-hidden)\n role={'aria-label' in props ? 'img' : undefined}\n className={cn(\n 'box-border inline-flex shrink-0 items-center justify-center',\n // Button's pill idiom: radius=full → circle, other radii → rounded square\n 'rounded-[max(var(--spark-rounded-lg),var(--spark-rounded-full))]',\n 'text-[color:var(--icon-ink,var(--color-gray-a11))]',\n variantClasses[variant],\n sizeClasses[size],\n className,\n )}\n {...props}\n >\n {children ?? (name ? <MaterialSymbol name={name} /> : null)}\n </span>\n )\n}\n\nIcon.displayName = 'Icon'\n\nexport { Icon }\nexport type { IconProps }\n"],"mappings":";;;;;;AAsBA,MAAM,iBAAiB;CACrB,MAAM;CACN,SACE;CACF,OAAO;CACP,OAAO;CACP,SACE;AACJ;AAGA,MAAM,cAAc;CAClB,OAAO;CACP,SAAS;CACT,QAAQ;AACV;AAEA,SAAS,KAAK,EACZ,WACA,MACA,UACA,UAAU,QACV,OAAO,WACP,GAAG,SACS;CACZ,OACE,oBAAC,QAAD;EACE,aAAU;EAEV,MAAM,gBAAgB,QAAQ,QAAQ,KAAA;EACtC,WAAW,GACT,+DAEA,oEACA,sDACA,eAAe,UACf,YAAY,OACZ,SACF;EACA,GAAI;YAEH,aAAa,OAAO,oBAAC,gBAAD,EAAsB,KAAO,CAAA,IAAI;CAClD,CAAA;AAEV;AAEA,KAAK,cAAc"}
1
+ {"version":3,"file":"icon.js","names":[],"sources":["../../src/components/icon.tsx"],"sourcesContent":["import * as React from 'react'\nimport {\n MaterialSymbol,\n type MaterialSymbolIconName,\n} from '../icons/material-symbol'\nimport { accentByColor, type SparkAccentColor } from '../lib/accent-colors'\nimport { cn } from '../utils/cn'\n\ninterface IconProps extends React.HTMLAttributes<HTMLSpanElement> {\n name?: MaterialSymbolIconName\n /** Fill treatment. */\n variant?: 'soft' | 'surface' | 'solid' | 'ghost' | 'outline'\n /** Colour axis, matching Button/Pill/Avatar. Neutral (gray) by default. */\n color?: SparkAccentColor\n size?: 'small' | 'medium' | 'large' | 'xl'\n}\n\n// Every variant reads its fill/ink/border off the accent scale (--spark-*), the same\n// indirection Button/Pill/Avatar use for their `color` prop — data-accent-color re-points\n// --spark-* to gray/red/green/orange, so `color` recolours all five variants without any\n// icon-specific colour plumbing. --icon-bg/--icon-ink/--icon-bd stay the outer override\n// (a consumer className still wins via tailwind-merge over either). data-high-contrast\n// (on the icon or an ancestor) darkens the glyph a11→a12 and strengthens the\n// surface/outline border →a11. solid pairs --spark-9 with --spark-contrast, the same\n// default pair every other `data-style='solid'` consumer uses (Button's own recipe is\n// literally `bg-(--spark-style-bg,var(--spark-9)) text-(--spark-style-fg,var(--spark-contrast))`)\n// — and boosts to --spark-12/--spark-1 under HC, spark-default.css's own designated\n// `[data-high-contrast] [data-style='solid']` pair, so solid gets the same HC step-up as\n// every other variant instead of statically sitting at what used to be *only* the HC value.\n// border-box keeps the frame size constant when surface/outline add their 1px edge.\nconst variantClasses = {\n soft: 'bg-(--icon-bg,var(--spark-a3)) [[data-high-contrast]_&]:[--icon-ink:var(--spark-a12)]',\n surface:\n 'border border-[color:var(--icon-bd,var(--spark-a6))] bg-(--icon-bg,var(--spark-a2)) [[data-high-contrast]_&]:[--icon-ink:var(--spark-a12)] [[data-high-contrast]_&]:[--icon-bd:var(--spark-a11)]',\n solid:\n 'bg-(--icon-bg,var(--spark-9)) text-(--icon-ink,var(--spark-contrast)) [[data-high-contrast]_&]:[--icon-bg:var(--spark-12)] [[data-high-contrast]_&]:[--icon-ink:var(--spark-1)]',\n ghost: '[[data-high-contrast]_&]:[--icon-ink:var(--spark-a12)]',\n outline:\n 'border border-[color:var(--icon-bd,var(--spark-a8))] [[data-high-contrast]_&]:[--icon-ink:var(--spark-a12)] [[data-high-contrast]_&]:[--icon-bd:var(--spark-a11)]',\n}\n\n// Frame + glyph sizes are spacing-derived so both track the scaling/spacing knobs.\nconst sizeClasses = {\n small: 'size-6 [--spark-icon-size:calc(var(--spacing)*4)]',\n medium: 'size-8 [--spark-icon-size:calc(var(--spacing)*5)]',\n large: 'size-10 [--spark-icon-size:calc(var(--spacing)*6)]',\n xl: 'size-12 [--spark-icon-size:calc(var(--spacing)*7)]',\n}\n\nfunction Icon({\n className,\n name,\n children,\n variant = 'soft',\n color = 'neutral',\n size = 'medium',\n ...props\n}: IconProps) {\n return (\n <span\n data-accent-color={accentByColor[color]}\n data-slot=\"icon\"\n // labeled = meaningful image; otherwise decorative (the glyph is aria-hidden)\n role={'aria-label' in props ? 'img' : undefined}\n className={cn(\n 'box-border inline-flex shrink-0 items-center justify-center',\n // Button's pill idiom: radius=full → circle, other radii → rounded square\n 'rounded-[max(var(--spark-rounded-lg),var(--spark-rounded-full))]',\n 'text-[color:var(--icon-ink,var(--spark-a11))]',\n variantClasses[variant],\n sizeClasses[size],\n className,\n )}\n {...props}\n >\n {children ?? (name ? <MaterialSymbol name={name} /> : null)}\n </span>\n )\n}\n\nIcon.displayName = 'Icon'\n\nexport { Icon }\nexport type { IconProps }\n"],"mappings":";;;;;;;AA8BA,MAAM,iBAAiB;CACrB,MAAM;CACN,SACE;CACF,OACE;CACF,OAAO;CACP,SACE;AACJ;AAGA,MAAM,cAAc;CAClB,OAAO;CACP,QAAQ;CACR,OAAO;CACP,IAAI;AACN;AAEA,SAAS,KAAK,EACZ,WACA,MACA,UACA,UAAU,QACV,QAAQ,WACR,OAAO,UACP,GAAG,SACS;CACZ,OACE,oBAAC,QAAD;EACE,qBAAmB,cAAc;EACjC,aAAU;EAEV,MAAM,gBAAgB,QAAQ,QAAQ,KAAA;EACtC,WAAW,GACT,+DAEA,oEACA,iDACA,eAAe,UACf,YAAY,OACZ,SACF;EACA,GAAI;YAEH,aAAa,OAAO,oBAAC,gBAAD,EAAsB,KAAO,CAAA,IAAI;CAClD,CAAA;AAEV;AAEA,KAAK,cAAc"}
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
5
5
 
6
6
  //#region src/components/info-block.d.ts
7
7
  declare const InfoBlock: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
8
- variant?: "bare" | "default" | null | undefined;
8
+ variant?: "default" | "bare" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLDivElement>>;
10
10
  declare const InfoBlockIcon: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
11
11
  declare const InfoBlockContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
5
5
 
6
6
  //#region src/components/info-block.d.ts
7
7
  declare const InfoBlock: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
8
- variant?: "bare" | "default" | null | undefined;
8
+ variant?: "default" | "bare" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLDivElement>>;
10
10
  declare const InfoBlockIcon: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
11
11
  declare const InfoBlockContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_components_field = require("./field.cjs");
4
3
  const require_lib_input_box_variants = require("../lib/input-box-variants.cjs");
4
+ const require_components_field = require("./field.cjs");
5
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
6
  let class_variance_authority = require("class-variance-authority");
7
7
  let _base_ui_react_otp_field = require("@base-ui/react/otp-field");
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../utils/cn.js";
3
- import { useFieldControl } from "./field.js";
4
3
  import { GHOST_UNDERLINE, boxChrome } from "../lib/input-box-variants.js";
4
+ import { useFieldControl } from "./field.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { cva } from "class-variance-authority";
7
7
  import { OTPField } from "@base-ui/react/otp-field";
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-DY84GLCh.cjs");
4
- const require_components_field = require("./field.cjs");
5
4
  const require_lib_input_box_variants = require("../lib/input-box-variants.cjs");
5
+ const require_components_field = require("./field.cjs");
6
6
  let react = require("react");
7
7
  react = require_chunk.__toESM(react);
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-8wjgiNA_.cjs";
3
+ import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.cjs";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/input.d.ts
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { i as SparkInputStyle } from "../theme-types-8wjgiNA_.js";
3
+ import { i as SparkInputStyle } from "../theme-types-1yB0d8mp.js";
4
4
  import * as React$1 from "react";
5
5
 
6
6
  //#region src/components/input.d.ts
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { cn } from "../utils/cn.js";
3
- import { useFieldControl } from "./field.js";
4
3
  import { GHOST_UNDERLINE, boxChrome } from "../lib/input-box-variants.js";
4
+ import { useFieldControl } from "./field.js";
5
5
  import * as React$1 from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { cva } from "class-variance-authority";
@@ -2,9 +2,13 @@
2
2
  let react_jsx_runtime = require("react/jsx-runtime");
3
3
  let cnfast = require("cnfast");
4
4
  //#region src/components/layout.tsx
5
- const PageContainer = ({ className, ...rest }) => {
5
+ const PageContainer = ({ className, gap = 4, style, ...rest }) => {
6
6
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7
- className: (0, cnfast.cn)("mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)] md:max-w-152", className),
7
+ className: (0, cnfast.cn)("mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*var(--page-container-gap-steps,4))] md:max-w-152", className),
8
+ style: {
9
+ "--page-container-gap-steps": gap,
10
+ ...style
11
+ },
8
12
  ...rest
9
13
  });
10
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"layout.cjs","names":[],"sources":["../../src/components/layout.tsx"],"sourcesContent":["import type React from 'react'\nimport { cn } from '../utils/cn'\n\nconst PageContainer = ({ className, ...rest }: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn(\n 'mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)] md:max-w-152',\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport default PageContainer\n"],"mappings":";;;;AAGA,MAAM,iBAAiB,EAAE,WAAW,GAAG,WAAwC;CAC7E,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,OAAA,IACE,mFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"layout.cjs","names":[],"sources":["../../src/components/layout.tsx"],"sourcesContent":["import type React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface PageContainerProps extends React.ComponentProps<'div'> {\n /** How many `--spark-layout-gap` units apart each section sits. */\n gap?: number\n}\n\nconst PageContainer = ({\n className,\n gap = 4,\n style,\n ...rest\n}: PageContainerProps) => {\n return (\n <div\n className={cn(\n 'mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*var(--page-container-gap-steps,4))] md:max-w-152',\n className,\n )}\n style={\n {\n '--page-container-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...rest}\n />\n )\n}\n\nexport default PageContainer\nexport type { PageContainerProps }\n"],"mappings":";;;;AAQA,MAAM,iBAAiB,EACrB,WACA,MAAM,GACN,OACA,GAAG,WACqB;CACxB,OACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,YAAA,GAAA,OAAA,IACE,mHACA,SACF;EACA,OACE;GACE,8BAA8B;GAC9B,GAAG;EACL;EAEF,GAAI;CACL,CAAA;AAEL"}
@@ -3,9 +3,16 @@
3
3
  import React from "react";
4
4
 
5
5
  //#region src/components/layout.d.ts
6
+ interface PageContainerProps extends React.ComponentProps<'div'> {
7
+ /** How many `--spark-layout-gap` units apart each section sits. */
8
+ gap?: number;
9
+ }
6
10
  declare const PageContainer: ({
7
11
  className,
12
+ gap,
13
+ style,
8
14
  ...rest
9
- }: React.ComponentProps<"div">) => import("react/jsx-runtime").JSX.Element;
10
- export = PageContainer;
15
+ }: PageContainerProps) => import("react/jsx-runtime").JSX.Element;
16
+ //#endregion
17
+ export { type PageContainerProps, PageContainer as default };
11
18
  //# sourceMappingURL=layout.d.cts.map
@@ -3,10 +3,16 @@
3
3
  import React from "react";
4
4
 
5
5
  //#region src/components/layout.d.ts
6
+ interface PageContainerProps extends React.ComponentProps<'div'> {
7
+ /** How many `--spark-layout-gap` units apart each section sits. */
8
+ gap?: number;
9
+ }
6
10
  declare const PageContainer: ({
7
11
  className,
12
+ gap,
13
+ style,
8
14
  ...rest
9
- }: React.ComponentProps<"div">) => import("react/jsx-runtime").JSX.Element;
15
+ }: PageContainerProps) => import("react/jsx-runtime").JSX.Element;
10
16
  //#endregion
11
- export { PageContainer as default };
17
+ export { type PageContainerProps, PageContainer as default };
12
18
  //# sourceMappingURL=layout.d.ts.map
@@ -2,9 +2,13 @@
2
2
  import { cn } from "../utils/cn.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/layout.tsx
5
- const PageContainer = ({ className, ...rest }) => {
5
+ const PageContainer = ({ className, gap = 4, style, ...rest }) => {
6
6
  return /* @__PURE__ */ jsx("div", {
7
- className: cn("mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)] md:max-w-152", className),
7
+ className: cn("mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*var(--page-container-gap-steps,4))] md:max-w-152", className),
8
+ style: {
9
+ "--page-container-gap-steps": gap,
10
+ ...style
11
+ },
8
12
  ...rest
9
13
  });
10
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"layout.js","names":[],"sources":["../../src/components/layout.tsx"],"sourcesContent":["import type React from 'react'\nimport { cn } from '../utils/cn'\n\nconst PageContainer = ({ className, ...rest }: React.ComponentProps<'div'>) => {\n return (\n <div\n className={cn(\n 'mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*4)] md:max-w-152',\n className,\n )}\n {...rest}\n />\n )\n}\n\nexport default PageContainer\n"],"mappings":";;;;AAGA,MAAM,iBAAiB,EAAE,WAAW,GAAG,WAAwC;CAC7E,OACE,oBAAC,OAAD;EACE,WAAW,GACT,mFACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"layout.js","names":[],"sources":["../../src/components/layout.tsx"],"sourcesContent":["import type React from 'react'\nimport { cn } from '../utils/cn'\n\ninterface PageContainerProps extends React.ComponentProps<'div'> {\n /** How many `--spark-layout-gap` units apart each section sits. */\n gap?: number\n}\n\nconst PageContainer = ({\n className,\n gap = 4,\n style,\n ...rest\n}: PageContainerProps) => {\n return (\n <div\n className={cn(\n 'mx-auto flex w-full flex-col gap-[calc(var(--spark-layout-gap)*var(--page-container-gap-steps,4))] md:max-w-152',\n className,\n )}\n style={\n {\n '--page-container-gap-steps': gap,\n ...style,\n } as React.CSSProperties\n }\n {...rest}\n />\n )\n}\n\nexport default PageContainer\nexport type { PageContainerProps }\n"],"mappings":";;;;AAQA,MAAM,iBAAiB,EACrB,WACA,MAAM,GACN,OACA,GAAG,WACqB;CACxB,OACE,oBAAC,OAAD;EACE,WAAW,GACT,mHACA,SACF;EACA,OACE;GACE,8BAA8B;GAC9B,GAAG;EACL;EAEF,GAAI;CACL,CAAA;AAEL"}
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_chunk = require("../chunk-DY84GLCh.cjs");
4
+ const require_hooks_use_chart_zoom = require("../hooks/use-chart-zoom.cjs");
4
5
  const require_hooks_use_reduced_motion = require("../hooks/use-reduced-motion.cjs");
5
6
  const require_utils_format = require("../utils/format.cjs");
6
7
  const require_utils_chart_scale = require("../utils/chart-scale.cjs");
7
- const require_components_chart = require("./chart.cjs");
8
- const require_hooks_use_chart_zoom = require("../hooks/use-chart-zoom.cjs");
9
8
  const require_utils_chart_time_ticks = require("../utils/chart-time-ticks.cjs");
9
+ const require_components_chart = require("./chart.cjs");
10
10
  let react = require("react");
11
11
  react = require_chunk.__toESM(react);
12
12
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -1,11 +1,11 @@
1
1
  "use client";
2
- import { cn } from "../utils/cn.js";
2
+ import { useAnimatedChartDomain, useChartZoom } from "../hooks/use-chart-zoom.js";
3
3
  import { useReducedMotion } from "../hooks/use-reduced-motion.js";
4
4
  import { localeNumberFormat } from "../utils/format.js";
5
5
  import { buildYAxisScale, formatYAxisTick } from "../utils/chart-scale.js";
6
- import { ChartTooltipCard, ChartZoomResetButton, clampTooltipPosition, useMeasuredSize } from "./chart.js";
7
- import { useAnimatedChartDomain, useChartZoom } from "../hooks/use-chart-zoom.js";
8
6
  import { buildTimeTicks } from "../utils/chart-time-ticks.js";
7
+ import { cn } from "../utils/cn.js";
8
+ import { ChartTooltipCard, ChartZoomResetButton, clampTooltipPosition, useMeasuredSize } from "./chart.js";
9
9
  import * as React$1 from "react";
10
10
  import { useCallback, useMemo } from "react";
11
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -8,42 +8,74 @@ let react_jsx_runtime = require("react/jsx-runtime");
8
8
  let _base_ui_react_use_render = require("@base-ui/react/use-render");
9
9
  let cnfast = require("cnfast");
10
10
  //#region src/components/list.tsx
11
+ const radiusRowClasses = {
12
+ none: "group-data-[radius=none]/list:first:rounded-t-none group-data-[radius=none]/list:last:rounded-b-none",
13
+ sm: "group-data-[radius=sm]/list:first:rounded-t-sm group-data-[radius=sm]/list:last:rounded-b-sm",
14
+ md: "group-data-[radius=md]/list:first:rounded-t-md group-data-[radius=md]/list:last:rounded-b-md",
15
+ lg: "group-data-[radius=lg]/list:first:rounded-t-lg group-data-[radius=lg]/list:last:rounded-b-lg",
16
+ xl: "group-data-[radius=xl]/list:first:rounded-t-xl group-data-[radius=xl]/list:last:rounded-b-xl",
17
+ "2xl": "group-data-[radius=2xl]/list:first:rounded-t-2xl group-data-[radius=2xl]/list:last:rounded-b-2xl",
18
+ "3xl": "group-data-[radius=3xl]/list:first:rounded-t-3xl group-data-[radius=3xl]/list:last:rounded-b-3xl",
19
+ full: "group-data-[radius=full]/list:first:rounded-t-full group-data-[radius=full]/list:last:rounded-b-full"
20
+ };
11
21
  const ListItemContext = react.createContext({ recent: false });
12
22
  const ListItemColumnContext = react.createContext({ isEnd: false });
13
- function List({ className, variant = "soft", ...props }) {
23
+ function List({ className, variant = "soft", color = "neutral", radius = "md", gap = .5, style, ...props }) {
14
24
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
15
25
  role: "list",
16
26
  "data-slot": "list",
17
27
  "data-variant": variant,
18
- className: (0, cnfast.cn)("group/list m-0 list-none p-0", "data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-[calc(var(--spark-layout-gap)*0.5)]", "data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]:gap-[calc(var(--spark-layout-gap)*0.5)]", className),
28
+ "data-look": color === "accent" ? `${variant}-accent` : variant,
29
+ "data-radius": radius,
30
+ className: (0, cnfast.cn)("group/list m-0 list-none p-0", "data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]", "data-[variant=solid]:flex data-[variant=solid]:flex-col data-[variant=solid]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]", "data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]", className),
31
+ style: {
32
+ "--list-gap-steps": gap,
33
+ ...variant === "solid" && {
34
+ "--list-item-fg": color === "accent" ? "var(--spark-contrast)" : "var(--neutral-contrast)",
35
+ "--list-item-fg-muted": color === "accent" ? "var(--spark-contrast)" : "var(--neutral-contrast)"
36
+ },
37
+ ...style
38
+ },
19
39
  ...props
20
40
  });
21
41
  }
22
42
  function ListItem({ className, children, recent, selected, skeleton, render, ...props }) {
23
43
  const interactive = !skeleton && render != null;
24
44
  const recentCtx = react.useMemo(() => ({ recent: recent ?? false }), [recent]);
45
+ const rendersAnchorOrButton = react.isValidElement(render) && (render.type === "a" || render.type === "button");
46
+ const childArray = skeleton ? void 0 : react.Children.toArray(children);
47
+ const leadingChild = childArray?.find((child) => react.isValidElement(child) && child.type === ListItemLeading);
48
+ const hoistLeading = rendersAnchorOrButton && Boolean(leadingChild?.props.interactive);
49
+ const leading = hoistLeading ? leadingChild : void 0;
25
50
  const row = (0, _base_ui_react_use_render.useRender)({
26
51
  defaultTagName: "div",
27
52
  render: skeleton ? void 0 : render,
28
53
  props: {
29
54
  "data-slot": "list-item-row",
30
55
  "aria-hidden": skeleton ? true : void 0,
31
- className: (0, cnfast.cn)("flex min-h-[2.75rem] w-full items-center gap-4 rounded-[inherit] px-4 py-3 text-left no-underline", !skeleton && selected && "bg-spark-a3", interactive && [
56
+ className: (0, cnfast.cn)("flex min-h-[2.75rem] items-center gap-4 py-3 text-left no-underline", hoistLeading ? "min-w-0 flex-1 pr-4" : "w-full rounded-[inherit] px-4", !hoistLeading && !skeleton && selected && "bg-spark-a3", interactive && [
32
57
  "group/row cursor-pointer transition-colors duration-150 motion-reduce:transition-none",
33
- "hover:bg-spark-a3 focus-visible:bg-spark-a3",
34
- "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden",
35
- "disabled:pointer-events-none disabled:opacity-50"
58
+ "disabled:pointer-events-none disabled:opacity-50",
59
+ hoistLeading ? "focus-visible:outline-hidden" : ["hover:bg-spark-a3 focus-visible:bg-spark-a3", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden"]
36
60
  ]),
37
- children: skeleton ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListItemSkeleton, {}) : children
61
+ children: skeleton ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListItemSkeleton, {}) : hoistLeading ? childArray?.filter((child) => child !== leadingChild) : children
38
62
  }
39
63
  });
40
64
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
41
65
  "data-slot": "list-item",
42
- className: (0, cnfast.cn)("relative has-focus-visible:z-10", "group-data-[variant=soft]/list:rounded-md group-data-[variant=soft]/list:bg-gray-a2 dark:group-data-[variant=soft]/list:bg-gray-a3", "group-data-[variant=surface]/list:bg-gray-2", "group-data-[variant=surface]/list:border-x group-data-[variant=surface]/list:border-t group-data-[variant=surface]/list:border-gray-a6 group-data-[variant=surface]/list:first:rounded-t-md group-data-[variant=surface]/list:last:rounded-b-md group-data-[variant=surface]/list:last:border-b", "group-data-[variant=outline]/list:border-x group-data-[variant=outline]/list:border-t group-data-[variant=outline]/list:border-gray-a6 group-data-[variant=outline]/list:first:rounded-t-md group-data-[variant=outline]/list:last:rounded-b-md group-data-[variant=outline]/list:last:border-b", className),
66
+ className: (0, cnfast.cn)("relative has-focus-visible:z-10", hoistLeading && [
67
+ "flex min-w-0 items-center gap-4 pl-4",
68
+ !skeleton && selected && "bg-spark-a3",
69
+ interactive && [
70
+ "cursor-pointer",
71
+ "hover:bg-spark-a3 has-focus-visible:bg-spark-a3",
72
+ "has-focus-visible:ring-2 has-focus-visible:ring-offset-2"
73
+ ]
74
+ ], "group-data-[variant=surface]/list:border-x group-data-[variant=surface]/list:border-t group-data-[variant=surface]/list:last:border-b", "group-data-[variant=outline]/list:border-x group-data-[variant=outline]/list:border-t group-data-[variant=outline]/list:last:border-b", "group-data-[look=soft]/list:bg-gray-a2 dark:group-data-[look=soft]/list:bg-gray-a3", "group-data-[look=soft-accent]/list:bg-(--spark-a3)", "group-data-[look=surface]/list:border-gray-a6 group-data-[look=surface]/list:bg-gray-2", "group-data-[look=surface-accent]/list:border-spark-a6 group-data-[look=surface-accent]/list:bg-(--spark-surface)", "group-data-[look=outline]/list:border-gray-a6", "group-data-[look=outline-accent]/list:border-spark-a6", "group-data-[look=solid]/list:bg-(--neutral-1)", "group-data-[look=solid-accent]/list:bg-spark-9", Object.values(radiusRowClasses), className),
43
75
  ...props,
44
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListItemContext.Provider, {
76
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ListItemContext.Provider, {
45
77
  value: recentCtx,
46
- children: row
78
+ children: [leading, row]
47
79
  })
48
80
  });
49
81
  }
@@ -60,7 +92,7 @@ function ListItemSkeleton() {
60
92
  })
61
93
  ] });
62
94
  }
63
- function ListItemLeading({ className, ...props }) {
95
+ function ListItemLeading({ className, interactive: _interactive, ...props }) {
64
96
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
65
97
  "data-slot": "list-item-leading",
66
98
  className: (0, cnfast.cn)("flex shrink-0 items-center", className),
@@ -81,7 +113,7 @@ function ListItemContent({ className, align = "start", ...props }) {
81
113
  function ListItemPreline({ className, ...props }) {
82
114
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
83
115
  "data-slot": "list-item-preline",
84
- className: (0, cnfast.cn)("block w-full truncate text-sm text-gray-11", className),
116
+ className: (0, cnfast.cn)("block w-full truncate text-sm text-(--list-item-fg-muted,var(--neutral-11))", className),
85
117
  ...props
86
118
  });
87
119
  }
@@ -91,7 +123,7 @@ function ListItemTitle({ className, children, ...props }) {
91
123
  const showDot = recent && !isEnd;
92
124
  const title = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
93
125
  "data-slot": "list-item-title",
94
- className: (0, cnfast.cn)(showDot ? "min-w-0 truncate" : "block w-full truncate", "text-base font-bold text-gray-12", className),
126
+ className: (0, cnfast.cn)(showDot ? "min-w-0 truncate" : "block w-full truncate", "text-base font-bold text-(--list-item-fg,var(--neutral-12))", className),
95
127
  ...props,
96
128
  children
97
129
  });
@@ -108,7 +140,7 @@ function ListItemTitle({ className, children, ...props }) {
108
140
  function ListItemSubline({ className, ...props }) {
109
141
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
110
142
  "data-slot": "list-item-subline",
111
- className: (0, cnfast.cn)("block w-full truncate text-sm text-gray-11", className),
143
+ className: (0, cnfast.cn)("block w-full truncate text-sm text-(--list-item-fg-muted,var(--neutral-11))", className),
112
144
  ...props
113
145
  });
114
146
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list.cjs","names":["React","Skeleton"],"sources":["../../src/components/list.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { Skeleton } from './skeleton'\n\ntype ListVariant = 'soft' | 'surface' | 'outline' | 'ghost'\n\n// ListItem publishes `recent` so ListItemTitle can render the inline recency dot; the\n// column context lets the title show it only on the primary (start) column, never the\n// value column of a two-column row.\nconst ListItemContext = React.createContext<{ recent: boolean }>({\n recent: false,\n})\nconst ListItemColumnContext = React.createContext<{ isEnd: boolean }>({\n isEnd: false,\n})\n\ninterface ListProps extends React.ComponentProps<'ul'> {\n /** A prop, not the ambient `data-style` knob — that would cascade into row content. */\n variant?: ListVariant\n}\n\nfunction List({ className, variant = 'soft', ...props }: ListProps) {\n return (\n <ul\n // role=list keeps list semantics even under list-style:none (Safari drops them).\n role=\"list\"\n data-slot=\"list\"\n // group/list + data-variant drive every item's per-variant chrome (below).\n data-variant={variant}\n className={cn(\n 'group/list m-0 list-none p-0',\n // soft = separate cards → stack with a small gap (the gap IS the divider). ghost\n // shares that same gap for spacing but no fill/border (see ListItem's chrome\n // block, which has no ghost selector). surface/outline glue rows into one panel.\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-[calc(var(--spark-layout-gap)*0.5)]',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]:gap-[calc(var(--spark-layout-gap)*0.5)]',\n className,\n )}\n {...props}\n />\n )\n}\n\ninterface ListItemProps extends React.ComponentProps<'li'> {\n /** The \"recently changed\" accent dot. */\n recent?: boolean\n /** Persistent accent-tint (e.g. the active document). */\n selected?: boolean\n /** Loading placeholder (Figma `skeleton=true`). */\n skeleton?: boolean\n /**\n * Base UI polymorphism for the inner row. Pass `<a href/>` or `<button/>` to make\n * the row interactive (accent-on-hover/focus, cursor, focus ring). Omit → static row.\n */\n render?: useRender.RenderProp\n}\n\nfunction ListItem({\n className,\n children,\n recent,\n selected,\n skeleton,\n render,\n ...props\n}: ListItemProps) {\n // Skeleton rows are decorative placeholders — never render as a real <a>/<button>. An\n // aria-hidden anchor would still be focusable (WCAG 4.1.2), so skeleton forces a plain,\n // non-interactive <div> regardless of `render`.\n const interactive = !skeleton && render != null\n\n const recentCtx = React.useMemo(() => ({ recent: recent ?? false }), [recent])\n\n const row = useRender({\n defaultTagName: 'div',\n render: skeleton ? undefined : render,\n props: {\n 'data-slot': 'list-item-row',\n // skeleton is a decorative placeholder → keep it out of the a11y tree.\n 'aria-hidden': skeleton ? true : undefined,\n className: cn(\n // row layout from Figma 2217-1667; min-h is a HARD 44px floor (WCAG 2.5.5),\n // py/gap/text still scale past it via the spacing/scaling knobs. no-underline\n // resets the default <a> decoration when the row renders as a link.\n 'flex min-h-[2.75rem] w-full items-center gap-4 rounded-[inherit] px-4 py-3 text-left no-underline',\n !skeleton && selected && 'bg-spark-a3',\n interactive && [\n 'group/row cursor-pointer transition-colors duration-150 motion-reduce:transition-none',\n // neutral at rest → subtle accent tint on hover/focus (the affordance goes\n // accent too, in ListItemTrailing; title + leading stay neutral).\n 'hover:bg-spark-a3 focus-visible:bg-spark-a3',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'disabled:pointer-events-none disabled:opacity-50',\n ],\n ),\n children: skeleton ? <ListItemSkeleton /> : children,\n },\n })\n\n return (\n <li\n data-slot=\"list-item\"\n className={cn(\n 'relative has-focus-visible:z-10',\n 'group-data-[variant=soft]/list:rounded-md group-data-[variant=soft]/list:bg-gray-a2 dark:group-data-[variant=soft]/list:bg-gray-a3',\n 'group-data-[variant=surface]/list:bg-gray-2',\n 'group-data-[variant=surface]/list:border-x group-data-[variant=surface]/list:border-t group-data-[variant=surface]/list:border-gray-a6 group-data-[variant=surface]/list:first:rounded-t-md group-data-[variant=surface]/list:last:rounded-b-md group-data-[variant=surface]/list:last:border-b',\n 'group-data-[variant=outline]/list:border-x group-data-[variant=outline]/list:border-t group-data-[variant=outline]/list:border-gray-a6 group-data-[variant=outline]/list:first:rounded-t-md group-data-[variant=outline]/list:last:rounded-b-md group-data-[variant=outline]/list:last:border-b',\n className,\n )}\n {...props}\n >\n <ListItemContext.Provider value={recentCtx}>\n {row}\n </ListItemContext.Provider>\n </li>\n )\n}\n\nfunction ListItemSkeleton() {\n // Compose the shared Skeleton primitive so the placeholder matches every other skeleton\n // (token + radius + animation + motion-reduce).\n return (\n <>\n <Skeleton className=\"size-10 shrink-0 rounded-full\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Skeleton className=\"h-3.5 w-1/3\" />\n <Skeleton className=\"h-3.5 w-2/3\" />\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col items-end gap-2\">\n <Skeleton className=\"h-3.5 w-1/4\" />\n <Skeleton className=\"h-3.5 w-1/2\" />\n </div>\n </>\n )\n}\n\nfunction ListItemLeading({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"list-item-leading\"\n className={cn('flex shrink-0 items-center', className)}\n {...props}\n />\n )\n}\n\ninterface ListItemContentProps extends React.ComponentProps<'div'> {\n /** `end` right-aligns the column (the value column). */\n align?: 'start' | 'end'\n}\n\nfunction ListItemContent({\n className,\n align = 'start',\n ...props\n}: ListItemContentProps) {\n const columnCtx = React.useMemo(() => ({ isEnd: align === 'end' }), [align])\n return (\n <ListItemColumnContext.Provider value={columnCtx}>\n <div\n data-slot=\"list-item-content\"\n className={cn(\n 'flex min-w-0 flex-1 flex-col gap-1',\n align === 'end' ? 'items-end text-right' : 'items-start text-left',\n className,\n )}\n {...props}\n />\n </ListItemColumnContext.Provider>\n )\n}\n\nfunction ListItemPreline({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"list-item-preline\"\n className={cn('block w-full truncate text-sm text-gray-11', className)}\n {...props}\n />\n )\n}\n\nfunction ListItemTitle({\n className,\n children,\n ...props\n}: React.ComponentProps<'span'>) {\n const { recent } = React.useContext(ListItemContext)\n const { isEnd } = React.useContext(ListItemColumnContext)\n // recency dot sits inline, immediately left of the title (Figma 1310-977) — only on the\n // primary (start) column, so a two-column value row's value never carries it.\n const showDot = recent && !isEnd\n\n // className/{...props} always land on THIS span (the one that truncates), so a caller's\n // override (e.g. `title`, `line-clamp-2 whitespace-normal`) behaves identically whether\n // or not the dot renders — only the wrapping structure differs below.\n const title = (\n <span\n data-slot=\"list-item-title\"\n className={cn(\n showDot ? 'min-w-0 truncate' : 'block w-full truncate',\n 'text-base font-bold text-gray-12',\n className,\n )}\n {...props}\n >\n {children}\n </span>\n )\n\n if (!showDot) {\n // No dot: stay a plain block so the column's text alignment (e.g. an end column's\n // text-right) governs the title directly.\n return title\n }\n\n return (\n <span className=\"flex w-full items-center gap-2\">\n <span\n aria-hidden=\"true\"\n data-slot=\"list-item-indicator\"\n className=\"size-2 shrink-0 rounded-full bg-spark-9\"\n />\n {title}\n </span>\n )\n}\n\nfunction ListItemSubline({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"list-item-subline\"\n className={cn('block w-full truncate text-sm text-gray-11', className)}\n {...props}\n />\n )\n}\n\nfunction ListItemTrailing({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"list-item-trailing\"\n className={cn(\n 'flex shrink-0 items-center text-gray-11',\n // interactive rows tint the affordance accent on hover/focus (group/row is set on\n // the interactive inner row; absent on static rows, so this simply never fires).\n // Relies on the child reading currentColor (MaterialSymbol does) — the colour-\n // independent Icon component hardcodes its own ink and won't pick this up; use\n // MaterialSymbol here, not Icon.\n 'transition-colors duration-150 motion-reduce:transition-none',\n 'group-hover/row:text-spark-a11 group-focus-visible/row:text-spark-a11',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport {\n List,\n ListItem,\n ListItemContent,\n ListItemLeading,\n ListItemPreline,\n ListItemSubline,\n ListItemTitle,\n ListItemTrailing,\n}\nexport type { ListProps, ListItemProps, ListItemContentProps, ListVariant }\n"],"mappings":"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"}
1
+ {"version":3,"file":"list.cjs","names":["React","Skeleton"],"sources":["../../src/components/list.tsx"],"sourcesContent":["import { useRender } from '@base-ui/react/use-render'\nimport * as React from 'react'\nimport type { ContainerRadius } from '../lib/container-chrome'\nimport type { SparkCardColor, SparkCardVariant } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\nimport { Skeleton } from './skeleton'\n\ntype ListVariant = SparkCardVariant\ntype ListRadius = ContainerRadius\n\n// Rounds only the first/last row of a run, regardless of variant — harmless on ghost\n// (nothing painted to clip). Keyed on `data-radius` alone: unlike fill (below), rounding\n// doesn't depend on variant/color, so no compound group-data selector is needed.\nconst radiusRowClasses: Record<ListRadius, string> = {\n none: 'group-data-[radius=none]/list:first:rounded-t-none group-data-[radius=none]/list:last:rounded-b-none',\n sm: 'group-data-[radius=sm]/list:first:rounded-t-sm group-data-[radius=sm]/list:last:rounded-b-sm',\n md: 'group-data-[radius=md]/list:first:rounded-t-md group-data-[radius=md]/list:last:rounded-b-md',\n lg: 'group-data-[radius=lg]/list:first:rounded-t-lg group-data-[radius=lg]/list:last:rounded-b-lg',\n xl: 'group-data-[radius=xl]/list:first:rounded-t-xl group-data-[radius=xl]/list:last:rounded-b-xl',\n '2xl':\n 'group-data-[radius=2xl]/list:first:rounded-t-2xl group-data-[radius=2xl]/list:last:rounded-b-2xl',\n '3xl':\n 'group-data-[radius=3xl]/list:first:rounded-t-3xl group-data-[radius=3xl]/list:last:rounded-b-3xl',\n full: 'group-data-[radius=full]/list:first:rounded-t-full group-data-[radius=full]/list:last:rounded-b-full',\n}\n\n// ListItem publishes `recent` so ListItemTitle can render the inline recency dot; the\n// column context lets the title show it only on the primary (start) column, never the\n// value column of a two-column row.\nconst ListItemContext = React.createContext<{ recent: boolean }>({\n recent: false,\n})\nconst ListItemColumnContext = React.createContext<{ isEnd: boolean }>({\n isEnd: false,\n})\n\ninterface ListProps extends React.ComponentProps<'ul'> {\n /** A prop, not the ambient `data-style` knob — that would cascade into row content. */\n variant?: ListVariant\n /** Chrome palette. `neutral` (default) tracks the app neutral; `accent` tints with the brand accent. */\n color?: SparkCardColor\n /** Corner radius, as a named step. Unset → `md`, today's fixed behaviour. */\n radius?: ListRadius\n /** How many `--spark-layout-gap` units apart each row sits (`soft`/`solid`/`ghost` only). */\n gap?: number\n}\n\nfunction List({\n className,\n variant = 'soft',\n color = 'neutral',\n radius = 'md',\n gap = 0.5,\n style,\n ...props\n}: ListProps) {\n // Fill/border-colour needs BOTH axes at once (e.g. \"soft, tinted with accent\"), which a\n // single group-data selector can't express and chaining two on the same named group\n // can't either (that generates a descendant match between two *different* ancestors,\n // not one ancestor bearing both attributes). Resolving the pair to one value up front\n // sidesteps it entirely — see the `data-look` selectors on ListItem below.\n const look = color === 'accent' ? `${variant}-accent` : variant\n return (\n <ul\n // role=list keeps list semantics even under list-style:none (Safari drops them).\n role=\"list\"\n data-slot=\"list\"\n // group/list + data-variant drive every item's per-variant chrome (below).\n data-variant={variant}\n data-look={look}\n data-radius={radius}\n className={cn(\n 'group/list m-0 list-none p-0',\n // soft/solid = separate rows → stack with a small gap (the gap IS the divider).\n // ghost shares that same gap for spacing but no fill/border (see ListItem's\n // chrome block, which has no ghost selector). surface/outline glue rows into one\n // panel with no gap at all.\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]',\n 'data-[variant=solid]:flex data-[variant=solid]:flex-col data-[variant=solid]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]:gap-[calc(var(--spark-layout-gap)*var(--list-gap-steps,0.5))]',\n className,\n )}\n style={\n {\n '--list-gap-steps': gap,\n // solid's fill inverts far enough that the row's own ink must invert with it\n // (unlike soft/surface/outline's translucent tints, where the default ink\n // stays legible regardless of colour) — matches Card's own solid recipe,\n // where fg and fg-muted both collapse to the one contrast-guaranteed step.\n ...(variant === 'solid' && {\n '--list-item-fg':\n color === 'accent'\n ? 'var(--spark-contrast)'\n : 'var(--neutral-contrast)',\n '--list-item-fg-muted':\n color === 'accent'\n ? 'var(--spark-contrast)'\n : 'var(--neutral-contrast)',\n }),\n ...style,\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\ninterface ListItemProps extends React.ComponentProps<'li'> {\n /** The \"recently changed\" accent dot. */\n recent?: boolean\n /** Persistent accent-tint (e.g. the active document). */\n selected?: boolean\n /** Loading placeholder (Figma `skeleton=true`). */\n skeleton?: boolean\n /**\n * Base UI polymorphism for the inner row. Pass `<a href/>` or `<button/>` to make\n * the row interactive (accent-on-hover/focus, cursor, focus ring). Omit → static row.\n */\n render?: useRender.RenderProp\n}\n\nfunction ListItem({\n className,\n children,\n recent,\n selected,\n skeleton,\n render,\n ...props\n}: ListItemProps) {\n // Skeleton rows are decorative placeholders — never render as a real <a>/<button>. An\n // aria-hidden anchor would still be focusable (WCAG 4.1.2), so skeleton forces a plain,\n // non-interactive <div> regardless of `render`.\n const interactive = !skeleton && render != null\n\n const recentCtx = React.useMemo(() => ({ recent: recent ?? false }), [recent])\n\n // Only a ListItemLeading actually marked `interactive` (a Checkbox/Radio/Button) needs\n // to move outside `render`'s element, and only when `render` is literally an <a>/\n // <button> — nesting a focusable control inside another interactive element is invalid\n // HTML and double-fires clicks. A `render` of anything else (a `<Card/>`, say) has no\n // such conflict: it isn't natively interactive itself, so a control inside it is valid,\n // unduplicated HTML, and hoisting would only pull the control outside whatever that\n // element paints (its fill, border, rounded corner) for no reason. A plain icon\n // (interactive unset) is the same story from the other side — either way, Leading stays\n // inside the row by default, so the whole visual row remains one click/tap target.\n const rendersAnchorOrButton =\n React.isValidElement(render) &&\n (render.type === 'a' || render.type === 'button')\n const childArray = skeleton ? undefined : React.Children.toArray(children)\n const leadingChild = childArray?.find(\n (child): child is React.ReactElement<ListItemLeadingProps> =>\n React.isValidElement(child) && child.type === ListItemLeading,\n )\n const hoistLeading =\n rendersAnchorOrButton && Boolean(leadingChild?.props.interactive)\n const leading = hoistLeading ? leadingChild : undefined\n\n const row = useRender({\n defaultTagName: 'div',\n render: skeleton ? undefined : render,\n props: {\n 'data-slot': 'list-item-row',\n // skeleton is a decorative placeholder → keep it out of the a11y tree.\n 'aria-hidden': skeleton ? true : undefined,\n className: cn(\n // row layout from Figma 2217-1667; min-h is a HARD 44px floor (WCAG 2.5.5),\n // py/gap/text still scale past it via the spacing/scaling knobs. no-underline\n // resets the default <a> decoration when the row renders as a link.\n 'flex min-h-[2.75rem] items-center gap-4 py-3 text-left no-underline',\n hoistLeading ? 'min-w-0 flex-1 pr-4' : 'w-full rounded-[inherit] px-4',\n // not hoisted → this row IS the whole visual item (no outer <li> chrome), so\n // selection tint lives here, same as a row with no leading slot at all.\n !hoistLeading && !skeleton && selected && 'bg-spark-a3',\n interactive && [\n 'group/row cursor-pointer transition-colors duration-150 motion-reduce:transition-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n hoistLeading\n ? // the custom focus ring is drawn on the outer <li> (has-focus-visible,\n // below) so it wraps the leading control too — but the browser's own\n // default outline still targets whichever element actually has focus,\n // which is this one, so it has to be suppressed here specifically.\n 'focus-visible:outline-hidden'\n : [\n 'hover:bg-spark-a3 focus-visible:bg-spark-a3',\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n ],\n ],\n ),\n children: skeleton ? (\n <ListItemSkeleton />\n ) : hoistLeading ? (\n childArray?.filter((child) => child !== leadingChild)\n ) : (\n children\n ),\n },\n })\n\n return (\n <li\n data-slot=\"list-item\"\n className={cn(\n 'relative has-focus-visible:z-10',\n hoistLeading && [\n 'flex min-w-0 items-center gap-4 pl-4',\n !skeleton && selected && 'bg-spark-a3',\n interactive && [\n // neutral at rest → subtle accent tint on hover/focus (the affordance goes\n // accent too, in ListItemTrailing; title + leading stay neutral). The click\n // target itself is `row`, so focus-visible (unlike hover) has to be read off\n // a descendant via has() — it never lands on this <li> directly.\n 'cursor-pointer',\n 'hover:bg-spark-a3 has-focus-visible:bg-spark-a3',\n 'has-focus-visible:ring-2 has-focus-visible:ring-offset-2',\n ],\n ],\n // soft/solid rows sit in a gapped stack, not a glued panel, but still read as one\n // rounded group: only the first/last row round the outer corners. surface/\n // outline glue rows into one bordered panel instead — border SIDES are variant-\n // only (no colour axis), so they stay on data-variant; fill and border COLOUR\n // depend on variant *and* colour together, so those live on data-look instead\n // (see the comment on `look` in List, above).\n 'group-data-[variant=surface]/list:border-x group-data-[variant=surface]/list:border-t group-data-[variant=surface]/list:last:border-b',\n 'group-data-[variant=outline]/list:border-x group-data-[variant=outline]/list:border-t group-data-[variant=outline]/list:last:border-b',\n 'group-data-[look=soft]/list:bg-gray-a2 dark:group-data-[look=soft]/list:bg-gray-a3',\n // arbitrary-var form, not the bg-spark-a3 utility: identical colour, but avoids a\n // literal substring collision with the unconditional selection/hover tint below,\n // which a couple of tests distinguish with a plain className.includes check.\n 'group-data-[look=soft-accent]/list:bg-(--spark-a3)',\n 'group-data-[look=surface]/list:border-gray-a6 group-data-[look=surface]/list:bg-gray-2',\n 'group-data-[look=surface-accent]/list:border-spark-a6 group-data-[look=surface-accent]/list:bg-(--spark-surface)',\n 'group-data-[look=outline]/list:border-gray-a6',\n 'group-data-[look=outline-accent]/list:border-spark-a6',\n 'group-data-[look=solid]/list:bg-(--neutral-1)',\n 'group-data-[look=solid-accent]/list:bg-spark-9',\n Object.values(radiusRowClasses),\n className,\n )}\n {...props}\n >\n <ListItemContext.Provider value={recentCtx}>\n {leading}\n {row}\n </ListItemContext.Provider>\n </li>\n )\n}\n\nfunction ListItemSkeleton() {\n // Compose the shared Skeleton primitive so the placeholder matches every other skeleton\n // (token + radius + animation + motion-reduce).\n return (\n <>\n <Skeleton className=\"size-10 shrink-0 rounded-full\" />\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Skeleton className=\"h-3.5 w-1/3\" />\n <Skeleton className=\"h-3.5 w-2/3\" />\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col items-end gap-2\">\n <Skeleton className=\"h-3.5 w-1/4\" />\n <Skeleton className=\"h-3.5 w-1/2\" />\n </div>\n </>\n )\n}\n\ninterface ListItemLeadingProps extends React.ComponentProps<'div'> {\n /**\n * Set when this slot holds a focusable control (Checkbox, Radio, Button). ListItem\n * then hoists it outside `render`'s element — nesting a real control inside the row's\n * own <a>/<button> is invalid HTML and double-fires clicks. Leave unset for decorative\n * content (an icon): it stays inside the row, so the whole visual row is one\n * click/tap target, same as a row with no leading slot at all.\n */\n interactive?: boolean\n}\n\nfunction ListItemLeading({\n className,\n interactive: _interactive,\n ...props\n}: ListItemLeadingProps) {\n return (\n <div\n data-slot=\"list-item-leading\"\n className={cn('flex shrink-0 items-center', className)}\n {...props}\n />\n )\n}\n\ninterface ListItemContentProps extends React.ComponentProps<'div'> {\n /** `end` right-aligns the column (the value column). */\n align?: 'start' | 'end'\n}\n\nfunction ListItemContent({\n className,\n align = 'start',\n ...props\n}: ListItemContentProps) {\n const columnCtx = React.useMemo(() => ({ isEnd: align === 'end' }), [align])\n return (\n <ListItemColumnContext.Provider value={columnCtx}>\n <div\n data-slot=\"list-item-content\"\n className={cn(\n 'flex min-w-0 flex-1 flex-col gap-1',\n align === 'end' ? 'items-end text-right' : 'items-start text-left',\n className,\n )}\n {...props}\n />\n </ListItemColumnContext.Provider>\n )\n}\n\nfunction ListItemPreline({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"list-item-preline\"\n className={cn(\n 'block w-full truncate text-sm text-(--list-item-fg-muted,var(--neutral-11))',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction ListItemTitle({\n className,\n children,\n ...props\n}: React.ComponentProps<'span'>) {\n const { recent } = React.useContext(ListItemContext)\n const { isEnd } = React.useContext(ListItemColumnContext)\n // recency dot sits inline, immediately left of the title (Figma 1310-977) — only on the\n // primary (start) column, so a two-column value row's value never carries it.\n const showDot = recent && !isEnd\n\n // className/{...props} always land on THIS span (the one that truncates), so a caller's\n // override (e.g. `title`, `line-clamp-2 whitespace-normal`) behaves identically whether\n // or not the dot renders — only the wrapping structure differs below.\n const title = (\n <span\n data-slot=\"list-item-title\"\n className={cn(\n showDot ? 'min-w-0 truncate' : 'block w-full truncate',\n 'text-base font-bold text-(--list-item-fg,var(--neutral-12))',\n className,\n )}\n {...props}\n >\n {children}\n </span>\n )\n\n if (!showDot) {\n // No dot: stay a plain block so the column's text alignment (e.g. an end column's\n // text-right) governs the title directly.\n return title\n }\n\n return (\n <span className=\"flex w-full items-center gap-2\">\n <span\n aria-hidden=\"true\"\n data-slot=\"list-item-indicator\"\n className=\"size-2 shrink-0 rounded-full bg-spark-9\"\n />\n {title}\n </span>\n )\n}\n\nfunction ListItemSubline({\n className,\n ...props\n}: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"list-item-subline\"\n className={cn(\n 'block w-full truncate text-sm text-(--list-item-fg-muted,var(--neutral-11))',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction ListItemTrailing({\n className,\n ...props\n}: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"list-item-trailing\"\n className={cn(\n 'flex shrink-0 items-center text-gray-11',\n // interactive rows tint the affordance accent on hover/focus (group/row is set on\n // the interactive inner row; absent on static rows, so this simply never fires).\n // Relies on the child reading currentColor (MaterialSymbol does) — the colour-\n // independent Icon component hardcodes its own ink and won't pick this up; use\n // MaterialSymbol here, not Icon.\n 'transition-colors duration-150 motion-reduce:transition-none',\n 'group-hover/row:text-spark-a11 group-focus-visible/row:text-spark-a11',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport {\n List,\n ListItem,\n ListItemContent,\n ListItemLeading,\n ListItemPreline,\n ListItemSubline,\n ListItemTitle,\n ListItemTrailing,\n}\nexport type {\n ListProps,\n ListItemProps,\n ListItemContentProps,\n ListItemLeadingProps,\n ListVariant,\n ListRadius,\n}\n"],"mappings":"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"}
@@ -1,17 +1,30 @@
1
1
  "use client";
2
2
 
3
+ import { n as SparkCardVariant, t as SparkCardColor } from "../theme-types-1yB0d8mp.cjs";
4
+ import { ContainerRadius } from "../lib/container-chrome.cjs";
3
5
  import * as React$1 from "react";
4
6
  import { useRender } from "@base-ui/react/use-render";
5
7
 
6
8
  //#region src/components/list.d.ts
7
- type ListVariant = 'soft' | 'surface' | 'outline' | 'ghost';
9
+ type ListVariant = SparkCardVariant;
10
+ type ListRadius = ContainerRadius;
8
11
  interface ListProps extends React$1.ComponentProps<'ul'> {
9
12
  /** A prop, not the ambient `data-style` knob — that would cascade into row content. */
10
13
  variant?: ListVariant;
14
+ /** Chrome palette. `neutral` (default) tracks the app neutral; `accent` tints with the brand accent. */
15
+ color?: SparkCardColor;
16
+ /** Corner radius, as a named step. Unset → `md`, today's fixed behaviour. */
17
+ radius?: ListRadius;
18
+ /** How many `--spark-layout-gap` units apart each row sits (`soft`/`solid`/`ghost` only). */
19
+ gap?: number;
11
20
  }
12
21
  declare function List({
13
22
  className,
14
23
  variant,
24
+ color,
25
+ radius,
26
+ gap,
27
+ style,
15
28
  ...props
16
29
  }: ListProps): import("react/jsx-runtime").JSX.Element;
17
30
  interface ListItemProps extends React$1.ComponentProps<'li'> {
@@ -36,10 +49,21 @@ declare function ListItem({
36
49
  render,
37
50
  ...props
38
51
  }: ListItemProps): import("react/jsx-runtime").JSX.Element;
52
+ interface ListItemLeadingProps extends React$1.ComponentProps<'div'> {
53
+ /**
54
+ * Set when this slot holds a focusable control (Checkbox, Radio, Button). ListItem
55
+ * then hoists it outside `render`'s element — nesting a real control inside the row's
56
+ * own <a>/<button> is invalid HTML and double-fires clicks. Leave unset for decorative
57
+ * content (an icon): it stays inside the row, so the whole visual row is one
58
+ * click/tap target, same as a row with no leading slot at all.
59
+ */
60
+ interactive?: boolean;
61
+ }
39
62
  declare function ListItemLeading({
40
63
  className,
64
+ interactive: _interactive,
41
65
  ...props
42
- }: React$1.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
66
+ }: ListItemLeadingProps): import("react/jsx-runtime").JSX.Element;
43
67
  interface ListItemContentProps extends React$1.ComponentProps<'div'> {
44
68
  /** `end` right-aligns the column (the value column). */
45
69
  align?: 'start' | 'end';
@@ -67,5 +91,5 @@ declare function ListItemTrailing({
67
91
  ...props
68
92
  }: React$1.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
69
93
  //#endregion
70
- export { List, ListItem, ListItemContent, type ListItemContentProps, ListItemLeading, ListItemPreline, type ListItemProps, ListItemSubline, ListItemTitle, ListItemTrailing, type ListProps, type ListVariant };
94
+ export { List, ListItem, ListItemContent, type ListItemContentProps, ListItemLeading, type ListItemLeadingProps, ListItemPreline, type ListItemProps, ListItemSubline, ListItemTitle, ListItemTrailing, type ListProps, type ListRadius, type ListVariant };
71
95
  //# sourceMappingURL=list.d.cts.map
@@ -1,17 +1,30 @@
1
1
  "use client";
2
2
 
3
+ import { n as SparkCardVariant, t as SparkCardColor } from "../theme-types-1yB0d8mp.js";
4
+ import { ContainerRadius } from "../lib/container-chrome.js";
3
5
  import * as React$1 from "react";
4
6
  import { useRender } from "@base-ui/react/use-render";
5
7
 
6
8
  //#region src/components/list.d.ts
7
- type ListVariant = 'soft' | 'surface' | 'outline' | 'ghost';
9
+ type ListVariant = SparkCardVariant;
10
+ type ListRadius = ContainerRadius;
8
11
  interface ListProps extends React$1.ComponentProps<'ul'> {
9
12
  /** A prop, not the ambient `data-style` knob — that would cascade into row content. */
10
13
  variant?: ListVariant;
14
+ /** Chrome palette. `neutral` (default) tracks the app neutral; `accent` tints with the brand accent. */
15
+ color?: SparkCardColor;
16
+ /** Corner radius, as a named step. Unset → `md`, today's fixed behaviour. */
17
+ radius?: ListRadius;
18
+ /** How many `--spark-layout-gap` units apart each row sits (`soft`/`solid`/`ghost` only). */
19
+ gap?: number;
11
20
  }
12
21
  declare function List({
13
22
  className,
14
23
  variant,
24
+ color,
25
+ radius,
26
+ gap,
27
+ style,
15
28
  ...props
16
29
  }: ListProps): import("react/jsx-runtime").JSX.Element;
17
30
  interface ListItemProps extends React$1.ComponentProps<'li'> {
@@ -36,10 +49,21 @@ declare function ListItem({
36
49
  render,
37
50
  ...props
38
51
  }: ListItemProps): import("react/jsx-runtime").JSX.Element;
52
+ interface ListItemLeadingProps extends React$1.ComponentProps<'div'> {
53
+ /**
54
+ * Set when this slot holds a focusable control (Checkbox, Radio, Button). ListItem
55
+ * then hoists it outside `render`'s element — nesting a real control inside the row's
56
+ * own <a>/<button> is invalid HTML and double-fires clicks. Leave unset for decorative
57
+ * content (an icon): it stays inside the row, so the whole visual row is one
58
+ * click/tap target, same as a row with no leading slot at all.
59
+ */
60
+ interactive?: boolean;
61
+ }
39
62
  declare function ListItemLeading({
40
63
  className,
64
+ interactive: _interactive,
41
65
  ...props
42
- }: React$1.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
66
+ }: ListItemLeadingProps): import("react/jsx-runtime").JSX.Element;
43
67
  interface ListItemContentProps extends React$1.ComponentProps<'div'> {
44
68
  /** `end` right-aligns the column (the value column). */
45
69
  align?: 'start' | 'end';
@@ -67,5 +91,5 @@ declare function ListItemTrailing({
67
91
  ...props
68
92
  }: React$1.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
69
93
  //#endregion
70
- export { List, ListItem, ListItemContent, type ListItemContentProps, ListItemLeading, ListItemPreline, type ListItemProps, ListItemSubline, ListItemTitle, ListItemTrailing, type ListProps, type ListVariant };
94
+ export { List, ListItem, ListItemContent, type ListItemContentProps, ListItemLeading, type ListItemLeadingProps, ListItemPreline, type ListItemProps, ListItemSubline, ListItemTitle, ListItemTrailing, type ListProps, type ListRadius, type ListVariant };
71
95
  //# sourceMappingURL=list.d.ts.map