@epilot/spark-ui 1.0.0-alpha.5 → 1.0.0-alpha.6

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.
@@ -19,7 +19,7 @@ function Accordion({ className, variant = "soft", ...props }) {
19
19
  function AccordionItem({ className, ...props }) {
20
20
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_accordion.Accordion.Item, {
21
21
  "data-slot": "accordion-item",
22
- className: (0, cnfast.cn)("group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2", "group-data-[variant=surface]/accordion:bg-gray-2", "group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b", "group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b", className),
22
+ className: (0, cnfast.cn)("group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2 dark:group-data-[variant=soft]/accordion:bg-gray-a3", "group-data-[variant=surface]/accordion:bg-gray-2", "group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b", "group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b", className),
23
23
  ...props
24
24
  });
25
25
  }
@@ -28,7 +28,7 @@ function AccordionTrigger({ className, children, ...props }) {
28
28
  className: "flex",
29
29
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_base_ui_react_accordion.Accordion.Trigger, {
30
30
  "data-slot": "accordion-trigger",
31
- className: (0, cnfast.cn)("flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "disabled:pointer-events-none disabled:opacity-50", "group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4", "[&[data-panel-open]>:last-child]:rotate-180", className),
31
+ className: (0, cnfast.cn)("flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12", "rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "disabled:pointer-events-none disabled:opacity-50", "group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4", "[&[data-panel-open]>:last-child]:rotate-180", className),
32
32
  ...props,
33
33
  children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_material_symbol.MaterialSymbol, {
34
34
  className: "shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none",
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.cjs","names":["AccordionPrimitive","MaterialSymbol"],"sources":["../../src/components/accordion.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\ntype AccordionVariant = 'ghost' | 'soft' | 'surface' | 'outline'\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root> & {\n /**\n * Container chrome (neutral):\n * - `ghost` — no border/fill, just the trigger + spacing;\n * - `soft` (default) — separate soft-tinted rounded cards, 2px gap between them;\n * - `surface` — items glued into one bordered panel with an opaque fill;\n * - `outline` — the same glued bordered panel, but no fill (transparent).\n * A `variant` prop, NOT the ambient `data-style` knob — that would cascade into\n * the panel content. Spacing + scaling still come from the ambient knobs.\n */\n variant?: AccordionVariant\n}\n\nfunction Accordion({ className, variant = 'soft', ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n // group/accordion + data-variant drive every item/trigger's per-variant\n // chrome; soft stacks its separate cards with a gap (below).\n data-variant={variant}\n className={cn(\n 'group/accordion',\n // soft = separate cards → stack them with a small (2px) gap. surface/outline\n // glue their items into one bordered panel (default block, no gap).\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-0.5',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n // NEUTRAL container chrome per the accordion variant (group/accordion) — mirrors\n // ListItem's group-data-[variant=X]/list: block (list.tsx); keep both in sync if\n // this pattern changes. ghost carries no chrome. Radius = rounded-md (tracks the\n // radius knob but never goes fully round). No text underline / per-item separator\n // anymore.\n\n // soft (default): each item is its own borderless soft-tinted rounded card;\n // the root separates them with a 2px gap (the gap IS the separator).\n 'group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2',\n // surface + outline share ONE glued-panel frame: full thin border around the\n // stack (sides on all, top on each as divider/frame, bottom on the last),\n // first/last round the outer corners. surface fills it (opaque bg); outline\n // leaves it transparent.\n 'group-data-[variant=surface]/accordion:bg-gray-2',\n 'group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b',\n 'group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionTriggerProps = React.ComponentProps<\n typeof AccordionPrimitive.Trigger\n>\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n // WCAG 2.5.5: min 44px touch target — a HARD floor (min-h-[2.75rem], not\n // min-h-11, which scales below 44px under dense/scaled knobs). py/text still\n // scale with the spacing + scaling knobs, growing the target past 44px.\n // No text underline (was hover:underline).\n 'flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12',\n // default focus style (matches Button): 2px ring + 2px offset, accent colour\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'disabled:pointer-events-none disabled:opacity-50',\n // horizontal padding sits INSIDE the chrome (soft/surface/outline); ghost\n // keeps the label flush (\"just plain text and spacing\").\n 'group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n // chevron (last child) flips when open\n '[&[data-panel-open]>:last-child]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <MaterialSymbol\n className=\"shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none\"\n name=\"expand_more\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\ntype AccordionContentProps = React.ComponentProps<\n typeof AccordionPrimitive.Panel\n>\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n // Base UI sets --accordion-panel-height + starting/ending styles on the\n // panel; the height transition replaces the radix keyframe animation.\n className=\"h-(--accordion-panel-height) overflow-hidden text-sm text-gray-11 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none\"\n {...props}\n >\n {/* padding aligns with the trigger: flush for ghost, inside the chrome otherwise */}\n <div\n className={cn(\n 'pb-4 group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n className,\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger }\nexport type { AccordionProps, AccordionVariant }\n"],"mappings":";;;;;;;;;;AAoBA,SAAS,UAAU,EAAE,WAAW,UAAU,QAAQ,GAAG,SAAyB;AAC5E,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,MAApB;EACE,aAAU;EAGV,gBAAc;EACd,YAAA,GAAA,OAAA,IACE,mBAGA,qFACA,UACD;EACD,GAAI;EACJ,CAAA;;AAMN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,MAApB;EACE,aAAU;EACV,YAAA,GAAA,OAAA,IASE,iGAKA,oDACA,iUACA,iUACA,UACD;EACD,GAAI;EACJ,CAAA;;AAQN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,QAApB;EAA2B,WAAU;YACnC,iBAAA,GAAA,kBAAA,MAACA,yBAAAA,UAAmB,SAApB;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IAKE,yHAEA,iFACA,oDAGA,oIAEA,+CACA,UACD;GACD,GAAI;aAlBN,CAoBG,UACD,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;IACE,WAAU;IACV,MAAK;IACL,CAAA,CACyB;;EACH,CAAA;;AAQhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACD,yBAAAA,UAAmB,OAApB;EACE,aAAU;EAGV,WAAU;EACV,GAAI;YAGJ,iBAAA,GAAA,kBAAA,KAAC,OAAD;GACE,YAAA,GAAA,OAAA,IACE,yIACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
1
+ {"version":3,"file":"accordion.cjs","names":["AccordionPrimitive","MaterialSymbol"],"sources":["../../src/components/accordion.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\ntype AccordionVariant = 'ghost' | 'soft' | 'surface' | 'outline'\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root> & {\n /**\n * Container chrome (neutral):\n * - `ghost` — no border/fill, just the trigger + spacing;\n * - `soft` (default) — separate soft-tinted rounded cards, 2px gap between them;\n * - `surface` — items glued into one bordered panel with an opaque fill;\n * - `outline` — the same glued bordered panel, but no fill (transparent).\n * A `variant` prop, NOT the ambient `data-style` knob — that would cascade into\n * the panel content. Spacing + scaling still come from the ambient knobs.\n */\n variant?: AccordionVariant\n}\n\nfunction Accordion({ className, variant = 'soft', ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n // group/accordion + data-variant drive every item/trigger's per-variant\n // chrome; soft stacks its separate cards with a gap (below).\n data-variant={variant}\n className={cn(\n 'group/accordion',\n // soft = separate cards → stack them with a small (2px) gap. surface/outline\n // glue their items into one bordered panel (default block, no gap).\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-0.5',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n // NEUTRAL container chrome per the accordion variant (group/accordion) — mirrors\n // ListItem's group-data-[variant=X]/list: block (list.tsx); keep both in sync if\n // this pattern changes. ghost carries no chrome. Radius = rounded-md (tracks the\n // radius knob but never goes fully round). No text underline / per-item separator\n // anymore.\n\n // soft (default): each item is its own borderless soft-tinted rounded card;\n // the root separates them with a 2px gap (the gap IS the separator).\n 'group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2 dark:group-data-[variant=soft]/accordion:bg-gray-a3',\n // surface + outline share ONE glued-panel frame: full thin border around the\n // stack (sides on all, top on each as divider/frame, bottom on the last),\n // first/last round the outer corners. surface fills it (opaque bg); outline\n // leaves it transparent.\n 'group-data-[variant=surface]/accordion:bg-gray-2',\n 'group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b',\n 'group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionTriggerProps = React.ComponentProps<\n typeof AccordionPrimitive.Trigger\n>\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n // WCAG 2.5.5: min 44px touch target — a HARD floor (min-h-[2.75rem], not\n // min-h-11, which scales below 44px under dense/scaled knobs). py/text still\n // scale with the spacing + scaling knobs, growing the target past 44px.\n // No text underline (was hover:underline).\n 'flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12',\n // default focus style (matches Button): 2px ring + 2px offset, accent colour\n 'rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'disabled:pointer-events-none disabled:opacity-50',\n // horizontal padding sits INSIDE the chrome (soft/surface/outline); ghost\n // keeps the label flush (\"just plain text and spacing\").\n 'group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n // chevron (last child) flips when open\n '[&[data-panel-open]>:last-child]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <MaterialSymbol\n className=\"shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none\"\n name=\"expand_more\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\ntype AccordionContentProps = React.ComponentProps<\n typeof AccordionPrimitive.Panel\n>\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n // Base UI sets --accordion-panel-height + starting/ending styles on the\n // panel; the height transition replaces the radix keyframe animation.\n className=\"h-(--accordion-panel-height) overflow-hidden text-sm text-gray-11 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none\"\n {...props}\n >\n {/* padding aligns with the trigger: flush for ghost, inside the chrome otherwise */}\n <div\n className={cn(\n 'pb-4 group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n className,\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger }\nexport type { AccordionProps, AccordionVariant }\n"],"mappings":";;;;;;;;;;AAoBA,SAAS,UAAU,EAAE,WAAW,UAAU,QAAQ,GAAG,SAAyB;AAC5E,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,MAApB;EACE,aAAU;EAGV,gBAAc;EACd,YAAA,GAAA,OAAA,IACE,mBAGA,qFACA,UACD;EACD,GAAI;EACJ,CAAA;;AAMN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,MAApB;EACE,aAAU;EACV,YAAA,GAAA,OAAA,IASE,qJAKA,oDACA,iUACA,iUACA,UACD;EACD,GAAI;EACJ,CAAA;;AAQN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACA,yBAAAA,UAAmB,QAApB;EAA2B,WAAU;YACnC,iBAAA,GAAA,kBAAA,MAACA,yBAAAA,UAAmB,SAApB;GACE,aAAU;GACV,YAAA,GAAA,OAAA,IAKE,yHAEA,4FACA,oDAGA,oIAEA,+CACA,UACD;GACD,GAAI;aAlBN,CAoBG,UACD,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;IACE,WAAU;IACV,MAAK;IACL,CAAA,CACyB;;EACH,CAAA;;AAQhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACD,yBAAAA,UAAmB,OAApB;EACE,aAAU;EAGV,WAAU;EACV,GAAI;YAGJ,iBAAA,GAAA,kBAAA,KAAC,OAAD;GACE,YAAA,GAAA,OAAA,IACE,yIACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
@@ -16,7 +16,7 @@ function Accordion({ className, variant = "soft", ...props }) {
16
16
  function AccordionItem({ className, ...props }) {
17
17
  return /* @__PURE__ */ jsx(Accordion$1.Item, {
18
18
  "data-slot": "accordion-item",
19
- className: cn("group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2", "group-data-[variant=surface]/accordion:bg-gray-2", "group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b", "group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b", className),
19
+ className: cn("group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2 dark:group-data-[variant=soft]/accordion:bg-gray-a3", "group-data-[variant=surface]/accordion:bg-gray-2", "group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b", "group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b", className),
20
20
  ...props
21
21
  });
22
22
  }
@@ -25,7 +25,7 @@ function AccordionTrigger({ className, children, ...props }) {
25
25
  className: "flex",
26
26
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
27
27
  "data-slot": "accordion-trigger",
28
- className: cn("flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12", "focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "disabled:pointer-events-none disabled:opacity-50", "group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4", "[&[data-panel-open]>:last-child]:rotate-180", className),
28
+ className: cn("flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12", "rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", "disabled:pointer-events-none disabled:opacity-50", "group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4", "[&[data-panel-open]>:last-child]:rotate-180", className),
29
29
  ...props,
30
30
  children: [children, /* @__PURE__ */ jsx(MaterialSymbol, {
31
31
  className: "shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none",
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","names":["AccordionPrimitive"],"sources":["../../src/components/accordion.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\ntype AccordionVariant = 'ghost' | 'soft' | 'surface' | 'outline'\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root> & {\n /**\n * Container chrome (neutral):\n * - `ghost` — no border/fill, just the trigger + spacing;\n * - `soft` (default) — separate soft-tinted rounded cards, 2px gap between them;\n * - `surface` — items glued into one bordered panel with an opaque fill;\n * - `outline` — the same glued bordered panel, but no fill (transparent).\n * A `variant` prop, NOT the ambient `data-style` knob — that would cascade into\n * the panel content. Spacing + scaling still come from the ambient knobs.\n */\n variant?: AccordionVariant\n}\n\nfunction Accordion({ className, variant = 'soft', ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n // group/accordion + data-variant drive every item/trigger's per-variant\n // chrome; soft stacks its separate cards with a gap (below).\n data-variant={variant}\n className={cn(\n 'group/accordion',\n // soft = separate cards → stack them with a small (2px) gap. surface/outline\n // glue their items into one bordered panel (default block, no gap).\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-0.5',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n // NEUTRAL container chrome per the accordion variant (group/accordion) — mirrors\n // ListItem's group-data-[variant=X]/list: block (list.tsx); keep both in sync if\n // this pattern changes. ghost carries no chrome. Radius = rounded-md (tracks the\n // radius knob but never goes fully round). No text underline / per-item separator\n // anymore.\n\n // soft (default): each item is its own borderless soft-tinted rounded card;\n // the root separates them with a 2px gap (the gap IS the separator).\n 'group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2',\n // surface + outline share ONE glued-panel frame: full thin border around the\n // stack (sides on all, top on each as divider/frame, bottom on the last),\n // first/last round the outer corners. surface fills it (opaque bg); outline\n // leaves it transparent.\n 'group-data-[variant=surface]/accordion:bg-gray-2',\n 'group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b',\n 'group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionTriggerProps = React.ComponentProps<\n typeof AccordionPrimitive.Trigger\n>\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n // WCAG 2.5.5: min 44px touch target — a HARD floor (min-h-[2.75rem], not\n // min-h-11, which scales below 44px under dense/scaled knobs). py/text still\n // scale with the spacing + scaling knobs, growing the target past 44px.\n // No text underline (was hover:underline).\n 'flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12',\n // default focus style (matches Button): 2px ring + 2px offset, accent colour\n 'focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'disabled:pointer-events-none disabled:opacity-50',\n // horizontal padding sits INSIDE the chrome (soft/surface/outline); ghost\n // keeps the label flush (\"just plain text and spacing\").\n 'group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n // chevron (last child) flips when open\n '[&[data-panel-open]>:last-child]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <MaterialSymbol\n className=\"shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none\"\n name=\"expand_more\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\ntype AccordionContentProps = React.ComponentProps<\n typeof AccordionPrimitive.Panel\n>\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n // Base UI sets --accordion-panel-height + starting/ending styles on the\n // panel; the height transition replaces the radix keyframe animation.\n className=\"h-(--accordion-panel-height) overflow-hidden text-sm text-gray-11 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none\"\n {...props}\n >\n {/* padding aligns with the trigger: flush for ghost, inside the chrome otherwise */}\n <div\n className={cn(\n 'pb-4 group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n className,\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger }\nexport type { AccordionProps, AccordionVariant }\n"],"mappings":";;;;;;;AAoBA,SAAS,UAAU,EAAE,WAAW,UAAU,QAAQ,GAAG,SAAyB;AAC5E,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EAGV,gBAAc;EACd,WAAW,GACT,mBAGA,qFACA,UACD;EACD,GAAI;EACJ,CAAA;;AAMN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GAST,iGAKA,oDACA,iUACA,iUACA,UACD;EACD,GAAI;EACJ,CAAA;;AAQN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,QAApB;EAA2B,WAAU;YACnC,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GAKT,yHAEA,iFACA,oDAGA,oIAEA,+CACA,UACD;GACD,GAAI;aAlBN,CAoBG,UACD,oBAAC,gBAAD;IACE,WAAU;IACV,MAAK;IACL,CAAA,CACyB;;EACH,CAAA;;AAQhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,OAApB;EACE,aAAU;EAGV,WAAU;EACV,GAAI;YAGJ,oBAAC,OAAD;GACE,WAAW,GACT,yIACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
1
+ {"version":3,"file":"accordion.js","names":["AccordionPrimitive"],"sources":["../../src/components/accordion.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from '@base-ui/react/accordion'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\n\ntype AccordionVariant = 'ghost' | 'soft' | 'surface' | 'outline'\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root> & {\n /**\n * Container chrome (neutral):\n * - `ghost` — no border/fill, just the trigger + spacing;\n * - `soft` (default) — separate soft-tinted rounded cards, 2px gap between them;\n * - `surface` — items glued into one bordered panel with an opaque fill;\n * - `outline` — the same glued bordered panel, but no fill (transparent).\n * A `variant` prop, NOT the ambient `data-style` knob — that would cascade into\n * the panel content. Spacing + scaling still come from the ambient knobs.\n */\n variant?: AccordionVariant\n}\n\nfunction Accordion({ className, variant = 'soft', ...props }: AccordionProps) {\n return (\n <AccordionPrimitive.Root\n data-slot=\"accordion\"\n // group/accordion + data-variant drive every item/trigger's per-variant\n // chrome; soft stacks its separate cards with a gap (below).\n data-variant={variant}\n className={cn(\n 'group/accordion',\n // soft = separate cards → stack them with a small (2px) gap. surface/outline\n // glue their items into one bordered panel (default block, no gap).\n 'data-[variant=soft]:flex data-[variant=soft]:flex-col data-[variant=soft]:gap-0.5',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionItemProps = React.ComponentProps<typeof AccordionPrimitive.Item>\n\nfunction AccordionItem({ className, ...props }: AccordionItemProps) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\n // NEUTRAL container chrome per the accordion variant (group/accordion) — mirrors\n // ListItem's group-data-[variant=X]/list: block (list.tsx); keep both in sync if\n // this pattern changes. ghost carries no chrome. Radius = rounded-md (tracks the\n // radius knob but never goes fully round). No text underline / per-item separator\n // anymore.\n\n // soft (default): each item is its own borderless soft-tinted rounded card;\n // the root separates them with a 2px gap (the gap IS the separator).\n 'group-data-[variant=soft]/accordion:rounded-md group-data-[variant=soft]/accordion:bg-gray-a2 dark:group-data-[variant=soft]/accordion:bg-gray-a3',\n // surface + outline share ONE glued-panel frame: full thin border around the\n // stack (sides on all, top on each as divider/frame, bottom on the last),\n // first/last round the outer corners. surface fills it (opaque bg); outline\n // leaves it transparent.\n 'group-data-[variant=surface]/accordion:bg-gray-2',\n 'group-data-[variant=surface]/accordion:border-x group-data-[variant=surface]/accordion:border-t group-data-[variant=surface]/accordion:border-gray-a6 group-data-[variant=surface]/accordion:first:rounded-t-md group-data-[variant=surface]/accordion:last:rounded-b-md group-data-[variant=surface]/accordion:last:border-b',\n 'group-data-[variant=outline]/accordion:border-x group-data-[variant=outline]/accordion:border-t group-data-[variant=outline]/accordion:border-gray-a6 group-data-[variant=outline]/accordion:first:rounded-t-md group-data-[variant=outline]/accordion:last:rounded-b-md group-data-[variant=outline]/accordion:last:border-b',\n className,\n )}\n {...props}\n />\n )\n}\n\ntype AccordionTriggerProps = React.ComponentProps<\n typeof AccordionPrimitive.Trigger\n>\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n // WCAG 2.5.5: min 44px touch target — a HARD floor (min-h-[2.75rem], not\n // min-h-11, which scales below 44px under dense/scaled knobs). py/text still\n // scale with the spacing + scaling knobs, growing the target past 44px.\n // No text underline (was hover:underline).\n 'flex min-h-[2.75rem] flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left font-medium text-gray-12',\n // default focus style (matches Button): 2px ring + 2px offset, accent colour\n 'rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'disabled:pointer-events-none disabled:opacity-50',\n // horizontal padding sits INSIDE the chrome (soft/surface/outline); ghost\n // keeps the label flush (\"just plain text and spacing\").\n 'group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n // chevron (last child) flips when open\n '[&[data-panel-open]>:last-child]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <MaterialSymbol\n className=\"shrink-0 text-gray-11 transition-transform duration-200 motion-reduce:transition-none\"\n name=\"expand_more\"\n />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\ntype AccordionContentProps = React.ComponentProps<\n typeof AccordionPrimitive.Panel\n>\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: AccordionContentProps) {\n return (\n <AccordionPrimitive.Panel\n data-slot=\"accordion-content\"\n // Base UI sets --accordion-panel-height + starting/ending styles on the\n // panel; the height transition replaces the radix keyframe animation.\n className=\"h-(--accordion-panel-height) overflow-hidden text-sm text-gray-11 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none\"\n {...props}\n >\n {/* padding aligns with the trigger: flush for ghost, inside the chrome otherwise */}\n <div\n className={cn(\n 'pb-4 group-data-[variant=outline]/accordion:px-4 group-data-[variant=soft]/accordion:px-4 group-data-[variant=surface]/accordion:px-4',\n className,\n )}\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n )\n}\n\nexport { Accordion, AccordionContent, AccordionItem, AccordionTrigger }\nexport type { AccordionProps, AccordionVariant }\n"],"mappings":";;;;;;;AAoBA,SAAS,UAAU,EAAE,WAAW,UAAU,QAAQ,GAAG,SAAyB;AAC5E,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EAGV,gBAAc;EACd,WAAW,GACT,mBAGA,qFACA,UACD;EACD,GAAI;EACJ,CAAA;;AAMN,SAAS,cAAc,EAAE,WAAW,GAAG,SAA6B;AAClE,QACE,oBAACA,YAAmB,MAApB;EACE,aAAU;EACV,WAAW,GAST,qJAKA,oDACA,iUACA,iUACA,UACD;EACD,GAAI;EACJ,CAAA;;AAQN,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,QAApB;EAA2B,WAAU;YACnC,qBAACA,YAAmB,SAApB;GACE,aAAU;GACV,WAAW,GAKT,yHAEA,4FACA,oDAGA,oIAEA,+CACA,UACD;GACD,GAAI;aAlBN,CAoBG,UACD,oBAAC,gBAAD;IACE,WAAU;IACV,MAAK;IACL,CAAA,CACyB;;EACH,CAAA;;AAQhC,SAAS,iBAAiB,EACxB,WACA,UACA,GAAG,SACqB;AACxB,QACE,oBAACA,YAAmB,OAApB;EACE,aAAU;EAGV,WAAU;EACV,GAAI;YAGJ,oBAAC,OAAD;GACE,WAAW,GACT,yIACA,UACD;GAEA;GACG,CAAA;EACmB,CAAA"}
@@ -9,7 +9,7 @@ import { useRender } from "@base-ui/react/use-render";
9
9
 
10
10
  //#region src/components/attachment.d.ts
11
11
  declare const attachmentVariants: (props?: ({
12
- size?: "sm" | "default" | "xs" | null | undefined;
12
+ size?: "default" | "sm" | "xs" | null | undefined;
13
13
  orientation?: "horizontal" | "vertical" | null | undefined;
14
14
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
15
15
  declare function Attachment({
@@ -9,7 +9,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
9
9
 
10
10
  //#region src/components/attachment.d.ts
11
11
  declare const attachmentVariants: (props?: ({
12
- size?: "sm" | "default" | "xs" | null | undefined;
12
+ size?: "default" | "sm" | "xs" | null | undefined;
13
13
  orientation?: "horizontal" | "vertical" | null | undefined;
14
14
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
15
15
  declare function Attachment({
@@ -34,7 +34,7 @@ const BreadcrumbsLink = ({ className, render, ...rest }) => {
34
34
  return (0, _base_ui_react_use_render.useRender)({
35
35
  defaultTagName: "a",
36
36
  render,
37
- props: (0, _base_ui_react_merge_props.mergeProps)({ className: (0, cnfast.cn)("transition-colors hover:text-gray", className) }, rest)
37
+ props: (0, _base_ui_react_merge_props.mergeProps)({ className: (0, cnfast.cn)("rounded-xs transition-colors hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", className) }, rest)
38
38
  });
39
39
  };
40
40
  /** Current page marker — the trailing breadcrumb the user is on. */
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.cjs","names":[],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cn } from '../utils/cn'\n\nconst Breadcrumbs = ({\n className,\n 'aria-label': ariaLabel = 'Breadcrumb',\n ...rest\n}: React.ComponentProps<'nav'>) => {\n return <nav aria-label={ariaLabel} className={cn(className)} {...rest} />\n}\n\nconst BreadcrumbsList = ({\n className,\n ...rest\n}: React.ComponentProps<'ol'>) => {\n return (\n <ol\n className={cn(\n 'flex flex-wrap items-center gap-1.5 text-sm text-gray-light',\n className,\n )}\n {...rest}\n />\n )\n}\n\nconst BreadcrumbsItem = ({\n className,\n ...rest\n}: React.ComponentProps<'li'>) => {\n return <li className={cn('flex items-center gap-1.5', className)} {...rest} />\n}\n\n/**\n * Link inside a breadcrumb. Pass `render` to render any router-specific link\n * component (TanStack `Link`, Next `Link`, plain `<a>`, …) and inherit the\n * breadcrumb link styling. Without `render` it renders as a plain anchor.\n */\nconst BreadcrumbsLink = ({\n className,\n render,\n ...rest\n}: useRender.ComponentProps<'a'>) => {\n return useRender({\n defaultTagName: 'a',\n render,\n props: mergeProps<'a'>(\n { className: cn('transition-colors hover:text-gray', className) },\n rest,\n ),\n })\n}\n\n/** Current page marker — the trailing breadcrumb the user is on. */\nconst BreadcrumbsPage = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n aria-current=\"page\"\n className={cn('font-medium text-gray', className)}\n {...rest}\n />\n )\n}\n\n/** Visual separator between breadcrumb items. Defaults to \"/\". */\nconst BreadcrumbsSeparator = ({\n children,\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span aria-hidden=\"true\" className={cn(className)} {...rest}>\n {children ?? '/'}\n </span>\n )\n}\n\nexport {\n Breadcrumbs,\n BreadcrumbsList,\n BreadcrumbsItem,\n BreadcrumbsLink,\n BreadcrumbsPage,\n BreadcrumbsSeparator,\n}\n"],"mappings":";;;;;;;;AAIA,MAAM,eAAe,EACnB,WACA,cAAc,YAAY,cAC1B,GAAG,WAC8B;AACjC,QAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,cAAY;EAAW,YAAA,GAAA,OAAA,IAAc,UAAU;EAAE,GAAI;EAAQ,CAAA;;AAG3E,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QACE,iBAAA,GAAA,kBAAA,KAAC,MAAD;EACE,YAAA,GAAA,OAAA,IACE,+DACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QAAO,iBAAA,GAAA,kBAAA,KAAC,MAAD;EAAI,YAAA,GAAA,OAAA,IAAc,6BAA6B,UAAU;EAAE,GAAI;EAAQ,CAAA;;;;;;;AAQhF,MAAM,mBAAmB,EACvB,WACA,QACA,GAAG,WACgC;AACnC,SAAA,GAAA,0BAAA,WAAiB;EACf,gBAAgB;EAChB;EACA,QAAA,GAAA,2BAAA,YACE,EAAE,YAAA,GAAA,OAAA,IAAc,qCAAqC,UAAU,EAAE,EACjE,KACD;EACF,CAAC;;;AAIJ,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC+B;AAClC,QACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,gBAAa;EACb,YAAA,GAAA,OAAA,IAAc,yBAAyB,UAAU;EACjD,GAAI;EACJ,CAAA;;;AAKN,MAAM,wBAAwB,EAC5B,UACA,WACA,GAAG,WAC+B;AAClC,QACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EAAM,eAAY;EAAO,YAAA,GAAA,OAAA,IAAc,UAAU;EAAE,GAAI;YACpD,YAAY;EACR,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.cjs","names":[],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cn } from '../utils/cn'\n\nconst Breadcrumbs = ({\n className,\n 'aria-label': ariaLabel = 'Breadcrumb',\n ...rest\n}: React.ComponentProps<'nav'>) => {\n return <nav aria-label={ariaLabel} className={cn(className)} {...rest} />\n}\n\nconst BreadcrumbsList = ({\n className,\n ...rest\n}: React.ComponentProps<'ol'>) => {\n return (\n <ol\n className={cn(\n 'flex flex-wrap items-center gap-1.5 text-sm text-gray-light',\n className,\n )}\n {...rest}\n />\n )\n}\n\nconst BreadcrumbsItem = ({\n className,\n ...rest\n}: React.ComponentProps<'li'>) => {\n return <li className={cn('flex items-center gap-1.5', className)} {...rest} />\n}\n\n/**\n * Link inside a breadcrumb. Pass `render` to render any router-specific link\n * component (TanStack `Link`, Next `Link`, plain `<a>`, …) and inherit the\n * breadcrumb link styling. Without `render` it renders as a plain anchor.\n */\nconst BreadcrumbsLink = ({\n className,\n render,\n ...rest\n}: useRender.ComponentProps<'a'>) => {\n return useRender({\n defaultTagName: 'a',\n render,\n props: mergeProps<'a'>(\n {\n className: cn(\n 'rounded-xs transition-colors hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n className,\n ),\n },\n rest,\n ),\n })\n}\n\n/** Current page marker — the trailing breadcrumb the user is on. */\nconst BreadcrumbsPage = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n aria-current=\"page\"\n className={cn('font-medium text-gray', className)}\n {...rest}\n />\n )\n}\n\n/** Visual separator between breadcrumb items. Defaults to \"/\". */\nconst BreadcrumbsSeparator = ({\n children,\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span aria-hidden=\"true\" className={cn(className)} {...rest}>\n {children ?? '/'}\n </span>\n )\n}\n\nexport {\n Breadcrumbs,\n BreadcrumbsList,\n BreadcrumbsItem,\n BreadcrumbsLink,\n BreadcrumbsPage,\n BreadcrumbsSeparator,\n}\n"],"mappings":";;;;;;;;AAIA,MAAM,eAAe,EACnB,WACA,cAAc,YAAY,cAC1B,GAAG,WAC8B;AACjC,QAAO,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,cAAY;EAAW,YAAA,GAAA,OAAA,IAAc,UAAU;EAAE,GAAI;EAAQ,CAAA;;AAG3E,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QACE,iBAAA,GAAA,kBAAA,KAAC,MAAD;EACE,YAAA,GAAA,OAAA,IACE,+DACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QAAO,iBAAA,GAAA,kBAAA,KAAC,MAAD;EAAI,YAAA,GAAA,OAAA,IAAc,6BAA6B,UAAU;EAAE,GAAI;EAAQ,CAAA;;;;;;;AAQhF,MAAM,mBAAmB,EACvB,WACA,QACA,GAAG,WACgC;AACnC,SAAA,GAAA,0BAAA,WAAiB;EACf,gBAAgB;EAChB;EACA,QAAA,GAAA,2BAAA,YACE,EACE,YAAA,GAAA,OAAA,IACE,8HACA,UACD,EACF,EACD,KACD;EACF,CAAC;;;AAIJ,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC+B;AAClC,QACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EACE,gBAAa;EACb,YAAA,GAAA,OAAA,IAAc,yBAAyB,UAAU;EACjD,GAAI;EACJ,CAAA;;;AAKN,MAAM,wBAAwB,EAC5B,UACA,WACA,GAAG,WAC+B;AAClC,QACE,iBAAA,GAAA,kBAAA,KAAC,QAAD;EAAM,eAAY;EAAO,YAAA,GAAA,OAAA,IAAc,UAAU;EAAE,GAAI;YACpD,YAAY;EACR,CAAA"}
@@ -32,7 +32,7 @@ const BreadcrumbsLink = ({ className, render, ...rest }) => {
32
32
  return useRender({
33
33
  defaultTagName: "a",
34
34
  render,
35
- props: mergeProps({ className: cn("transition-colors hover:text-gray", className) }, rest)
35
+ props: mergeProps({ className: cn("rounded-xs transition-colors hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", className) }, rest)
36
36
  });
37
37
  };
38
38
  /** Current page marker — the trailing breadcrumb the user is on. */
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.js","names":[],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cn } from '../utils/cn'\n\nconst Breadcrumbs = ({\n className,\n 'aria-label': ariaLabel = 'Breadcrumb',\n ...rest\n}: React.ComponentProps<'nav'>) => {\n return <nav aria-label={ariaLabel} className={cn(className)} {...rest} />\n}\n\nconst BreadcrumbsList = ({\n className,\n ...rest\n}: React.ComponentProps<'ol'>) => {\n return (\n <ol\n className={cn(\n 'flex flex-wrap items-center gap-1.5 text-sm text-gray-light',\n className,\n )}\n {...rest}\n />\n )\n}\n\nconst BreadcrumbsItem = ({\n className,\n ...rest\n}: React.ComponentProps<'li'>) => {\n return <li className={cn('flex items-center gap-1.5', className)} {...rest} />\n}\n\n/**\n * Link inside a breadcrumb. Pass `render` to render any router-specific link\n * component (TanStack `Link`, Next `Link`, plain `<a>`, …) and inherit the\n * breadcrumb link styling. Without `render` it renders as a plain anchor.\n */\nconst BreadcrumbsLink = ({\n className,\n render,\n ...rest\n}: useRender.ComponentProps<'a'>) => {\n return useRender({\n defaultTagName: 'a',\n render,\n props: mergeProps<'a'>(\n { className: cn('transition-colors hover:text-gray', className) },\n rest,\n ),\n })\n}\n\n/** Current page marker — the trailing breadcrumb the user is on. */\nconst BreadcrumbsPage = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n aria-current=\"page\"\n className={cn('font-medium text-gray', className)}\n {...rest}\n />\n )\n}\n\n/** Visual separator between breadcrumb items. Defaults to \"/\". */\nconst BreadcrumbsSeparator = ({\n children,\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span aria-hidden=\"true\" className={cn(className)} {...rest}>\n {children ?? '/'}\n </span>\n )\n}\n\nexport {\n Breadcrumbs,\n BreadcrumbsList,\n BreadcrumbsItem,\n BreadcrumbsLink,\n BreadcrumbsPage,\n BreadcrumbsSeparator,\n}\n"],"mappings":";;;;;;AAIA,MAAM,eAAe,EACnB,WACA,cAAc,YAAY,cAC1B,GAAG,WAC8B;AACjC,QAAO,oBAAC,OAAD;EAAK,cAAY;EAAW,WAAW,GAAG,UAAU;EAAE,GAAI;EAAQ,CAAA;;AAG3E,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QACE,oBAAC,MAAD;EACE,WAAW,GACT,+DACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QAAO,oBAAC,MAAD;EAAI,WAAW,GAAG,6BAA6B,UAAU;EAAE,GAAI;EAAQ,CAAA;;;;;;;AAQhF,MAAM,mBAAmB,EACvB,WACA,QACA,GAAG,WACgC;AACnC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,WACL,EAAE,WAAW,GAAG,qCAAqC,UAAU,EAAE,EACjE,KACD;EACF,CAAC;;;AAIJ,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC+B;AAClC,QACE,oBAAC,QAAD;EACE,gBAAa;EACb,WAAW,GAAG,yBAAyB,UAAU;EACjD,GAAI;EACJ,CAAA;;;AAKN,MAAM,wBAAwB,EAC5B,UACA,WACA,GAAG,WAC+B;AAClC,QACE,oBAAC,QAAD;EAAM,eAAY;EAAO,WAAW,GAAG,UAAU;EAAE,GAAI;YACpD,YAAY;EACR,CAAA"}
1
+ {"version":3,"file":"breadcrumbs.js","names":[],"sources":["../../src/components/breadcrumbs.tsx"],"sourcesContent":["import { mergeProps } from '@base-ui/react/merge-props'\nimport { useRender } from '@base-ui/react/use-render'\nimport { cn } from '../utils/cn'\n\nconst Breadcrumbs = ({\n className,\n 'aria-label': ariaLabel = 'Breadcrumb',\n ...rest\n}: React.ComponentProps<'nav'>) => {\n return <nav aria-label={ariaLabel} className={cn(className)} {...rest} />\n}\n\nconst BreadcrumbsList = ({\n className,\n ...rest\n}: React.ComponentProps<'ol'>) => {\n return (\n <ol\n className={cn(\n 'flex flex-wrap items-center gap-1.5 text-sm text-gray-light',\n className,\n )}\n {...rest}\n />\n )\n}\n\nconst BreadcrumbsItem = ({\n className,\n ...rest\n}: React.ComponentProps<'li'>) => {\n return <li className={cn('flex items-center gap-1.5', className)} {...rest} />\n}\n\n/**\n * Link inside a breadcrumb. Pass `render` to render any router-specific link\n * component (TanStack `Link`, Next `Link`, plain `<a>`, …) and inherit the\n * breadcrumb link styling. Without `render` it renders as a plain anchor.\n */\nconst BreadcrumbsLink = ({\n className,\n render,\n ...rest\n}: useRender.ComponentProps<'a'>) => {\n return useRender({\n defaultTagName: 'a',\n render,\n props: mergeProps<'a'>(\n {\n className: cn(\n 'rounded-xs transition-colors hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n className,\n ),\n },\n rest,\n ),\n })\n}\n\n/** Current page marker — the trailing breadcrumb the user is on. */\nconst BreadcrumbsPage = ({\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span\n aria-current=\"page\"\n className={cn('font-medium text-gray', className)}\n {...rest}\n />\n )\n}\n\n/** Visual separator between breadcrumb items. Defaults to \"/\". */\nconst BreadcrumbsSeparator = ({\n children,\n className,\n ...rest\n}: React.ComponentProps<'span'>) => {\n return (\n <span aria-hidden=\"true\" className={cn(className)} {...rest}>\n {children ?? '/'}\n </span>\n )\n}\n\nexport {\n Breadcrumbs,\n BreadcrumbsList,\n BreadcrumbsItem,\n BreadcrumbsLink,\n BreadcrumbsPage,\n BreadcrumbsSeparator,\n}\n"],"mappings":";;;;;;AAIA,MAAM,eAAe,EACnB,WACA,cAAc,YAAY,cAC1B,GAAG,WAC8B;AACjC,QAAO,oBAAC,OAAD;EAAK,cAAY;EAAW,WAAW,GAAG,UAAU;EAAE,GAAI;EAAQ,CAAA;;AAG3E,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QACE,oBAAC,MAAD;EACE,WAAW,GACT,+DACA,UACD;EACD,GAAI;EACJ,CAAA;;AAIN,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC6B;AAChC,QAAO,oBAAC,MAAD;EAAI,WAAW,GAAG,6BAA6B,UAAU;EAAE,GAAI;EAAQ,CAAA;;;;;;;AAQhF,MAAM,mBAAmB,EACvB,WACA,QACA,GAAG,WACgC;AACnC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,WACL,EACE,WAAW,GACT,8HACA,UACD,EACF,EACD,KACD;EACF,CAAC;;;AAIJ,MAAM,mBAAmB,EACvB,WACA,GAAG,WAC+B;AAClC,QACE,oBAAC,QAAD;EACE,gBAAa;EACb,WAAW,GAAG,yBAAyB,UAAU;EACjD,GAAI;EACJ,CAAA;;;AAKN,MAAM,wBAAwB,EAC5B,UACA,WACA,GAAG,WAC+B;AAClC,QACE,oBAAC,QAAD;EAAM,eAAY;EAAO,WAAW,GAAG,UAAU;EAAE,GAAI;YACpD,YAAY;EACR,CAAA"}
@@ -12,7 +12,7 @@ declare function BubbleGroup({
12
12
  ...props
13
13
  }: React$1.ComponentProps<'div'>): _$react_jsx_runtime0.JSX.Element;
14
14
  declare const bubbleVariants: (props?: ({
15
- variant?: "default" | "secondary" | "muted" | "tinted" | "outline" | "ghost" | "destructive" | null | undefined;
15
+ variant?: "default" | "ghost" | "outline" | "secondary" | "destructive" | "muted" | "tinted" | null | undefined;
16
16
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
17
17
  declare function Bubble({
18
18
  variant,
@@ -12,7 +12,7 @@ declare function BubbleGroup({
12
12
  ...props
13
13
  }: React$1.ComponentProps<'div'>): _$react_jsx_runtime0.JSX.Element;
14
14
  declare const bubbleVariants: (props?: ({
15
- variant?: "default" | "secondary" | "muted" | "tinted" | "outline" | "ghost" | "destructive" | null | undefined;
15
+ variant?: "default" | "ghost" | "outline" | "secondary" | "destructive" | "muted" | "tinted" | null | undefined;
16
16
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
17
17
  declare function Bubble({
18
18
  variant,
@@ -9,9 +9,9 @@ import { VariantProps } from "class-variance-authority";
9
9
 
10
10
  //#region src/components/button.d.ts
11
11
  declare const buttonVariants: (props?: ({
12
- variant?: "secondary" | "destructive" | "primary" | "tertiary" | "bare" | null | undefined;
12
+ variant?: "primary" | "secondary" | "tertiary" | "bare" | "destructive" | null | undefined;
13
13
  color?: "neutral" | "accent" | "danger" | null | undefined;
14
- size?: "small" | "icon" | "default" | "medium" | "icon-small" | "icon-medium" | null | undefined;
14
+ size?: "small" | "default" | "icon" | "medium" | "icon-small" | "icon-medium" | null | undefined;
15
15
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
16
16
  type SparkButtonColor = 'accent' | 'neutral' | 'danger';
17
17
  interface ButtonProps extends React$1.ComponentProps<typeof Button$1>, Omit<VariantProps<typeof buttonVariants>, 'variant' | 'color'> {
@@ -9,9 +9,9 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
9
9
 
10
10
  //#region src/components/button.d.ts
11
11
  declare const buttonVariants: (props?: ({
12
- variant?: "secondary" | "destructive" | "primary" | "tertiary" | "bare" | null | undefined;
12
+ variant?: "primary" | "secondary" | "tertiary" | "bare" | "destructive" | null | undefined;
13
13
  color?: "neutral" | "accent" | "danger" | null | undefined;
14
- size?: "small" | "icon" | "default" | "medium" | "icon-small" | "icon-medium" | null | undefined;
14
+ size?: "small" | "default" | "icon" | "medium" | "icon-small" | "icon-medium" | null | undefined;
15
15
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
16
16
  type SparkButtonColor = 'accent' | 'neutral' | 'danger';
17
17
  interface ButtonProps extends React$1.ComponentProps<typeof Button$1>, Omit<VariantProps<typeof buttonVariants>, 'variant' | 'color'> {
@@ -9,7 +9,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
9
9
  let _daypicker_react = require("@daypicker/react");
10
10
  let cnfast = require("cnfast");
11
11
  //#region src/components/calendar.tsx
12
- function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
12
+ function Calendar({ className, classNames, showOutsideDays = true, fixedWeeks = true, showTodayDot = true, ...props }) {
13
13
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_daypicker_react.DayPicker, {
14
14
  className: (0, cnfast.cn)("p-3", className),
15
15
  classNames: {
@@ -37,7 +37,7 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
37
37
  range_start: "range-start",
38
38
  range_end: "range-end",
39
39
  selected: "rounded-full",
40
- today: "relative bg-base-gray-soft text-gray after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]",
40
+ today: (0, cnfast.cn)("relative bg-base-gray-soft text-gray", showTodayDot && "after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]"),
41
41
  outside: "outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light",
42
42
  disabled: "text-gray-light opacity-50",
43
43
  range_middle: "aria-selected:bg-base-gray-soft aria-selected:text-gray",
@@ -48,6 +48,7 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
48
48
  className: (0, cnfast.cn)("text-[20px]", orientation === "up" && "rotate-90", orientation === "down" && "-rotate-90"),
49
49
  name: orientation === "right" ? "chevron_right" : "chevron_left"
50
50
  }) },
51
+ fixedWeeks,
51
52
  showOutsideDays,
52
53
  ...props
53
54
  });
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.cjs","names":["DayPicker","buttonVariants","MaterialSymbol"],"sources":["../../src/components/calendar.tsx"],"sourcesContent":["import { DayPicker } from '@daypicker/react'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\nimport { buttonVariants } from './button'\n\ntype CalendarProps = React.ComponentProps<typeof DayPicker>\n\n// Pass `locale` (from '@daypicker/react/locale') for localized month/weekday\n// names — the library ships no language default.\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n className={cn('p-3', className)}\n classNames={{\n months: 'relative',\n month: 'flex flex-col gap-2',\n month_caption: 'flex h-10 items-center justify-center',\n caption_label: 'text-sm font-bold text-gray',\n button_previous: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 left-0 z-10 text-gray-light hover:text-gray',\n ),\n button_next: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 right-0 z-10 text-gray-light hover:text-gray',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex w-full justify-between',\n weekday:\n 'mt-0.5 flex h-10 w-10 items-center justify-center rounded-full text-sm font-bold text-gray',\n week: 'mt-1 flex w-full justify-between',\n day: cn(\n 'relative mx-0.5 flex h-10 w-10 items-center justify-center rounded-full p-0 text-center text-sm focus-within:relative focus-within:z-20',\n props.mode === 'range'\n ? '[&:has(>.range-end)]:rounded-r-full [&:has(>.range-start)]:rounded-l-full first:[&:has([aria-selected])]:rounded-l-full last:[&:has([aria-selected])]:rounded-r-full'\n : '[&:has([aria-selected])]:rounded-full',\n ),\n day_button: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n // hover:…:bg-spark-10 outranks tertiary's hover:bg-gray-a3 — selected days\n // darken like a solid button instead of washing out gray under white text\n 'size-10 shrink-0 rounded-full p-0 font-normal text-gray in-aria-selected:rounded-full in-aria-selected:bg-base-accent-solid in-aria-selected:text-accent-contrast hover:in-aria-selected:bg-spark-10 hover:in-aria-selected:text-accent-contrast',\n ),\n range_start: 'range-start',\n range_end: 'range-end',\n selected: 'rounded-full',\n today:\n 'relative bg-base-gray-soft text-gray after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]',\n outside:\n 'outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light',\n disabled: 'text-gray-light opacity-50',\n range_middle: 'aria-selected:bg-base-gray-soft aria-selected:text-gray',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => (\n <MaterialSymbol\n className={cn(\n 'text-[20px]',\n orientation === 'up' && 'rotate-90',\n orientation === 'down' && '-rotate-90',\n )}\n name={orientation === 'right' ? 'chevron_right' : 'chevron_left'}\n />\n ),\n }}\n showOutsideDays={showOutsideDays}\n {...props}\n />\n )\n}\n\nexport { Calendar }\nexport type { CalendarProps }\n"],"mappings":";;;;;;;;;;;AAUA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,GAAG,SACa;AAChB,QACE,iBAAA,GAAA,kBAAA,KAACA,iBAAAA,WAAD;EACE,YAAA,GAAA,OAAA,IAAc,OAAO,UAAU;EAC/B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,kBAAA,GAAA,OAAA,IACEC,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,6DACD;GACD,cAAA,GAAA,OAAA,IACEA,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,8DACD;GACD,YAAY;GACZ,UAAU;GACV,SACE;GACF,MAAM;GACN,MAAA,GAAA,OAAA,IACE,2IACA,MAAM,SAAS,UACX,yKACA,wCACL;GACD,aAAA,GAAA,OAAA,IACEA,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EAGrD,mPACD;GACD,aAAa;GACb,WAAW;GACX,UAAU;GACV,OACE;GACF,SACE;GACF,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;GACJ;EACD,YAAY,EACV,UAAU,EAAE,kBACV,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;GACE,YAAA,GAAA,OAAA,IACE,eACA,gBAAgB,QAAQ,aACxB,gBAAgB,UAAU,aAC3B;GACD,MAAM,gBAAgB,UAAU,kBAAkB;GAClD,CAAA,EAEL;EACgB;EACjB,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"calendar.cjs","names":["DayPicker","buttonVariants","MaterialSymbol"],"sources":["../../src/components/calendar.tsx"],"sourcesContent":["import { DayPicker } from '@daypicker/react'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\nimport { buttonVariants } from './button'\n\ntype CalendarProps = React.ComponentProps<typeof DayPicker> & {\n showTodayDot?: boolean\n}\n\n// Pass `locale` (from '@daypicker/react/locale') for localized month/weekday\n// names — the library ships no language default.\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n fixedWeeks = true,\n showTodayDot = true,\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n className={cn('p-3', className)}\n classNames={{\n months: 'relative',\n month: 'flex flex-col gap-2',\n month_caption: 'flex h-10 items-center justify-center',\n caption_label: 'text-sm font-bold text-gray',\n button_previous: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 left-0 z-10 text-gray-light hover:text-gray',\n ),\n button_next: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 right-0 z-10 text-gray-light hover:text-gray',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex w-full justify-between',\n weekday:\n 'mt-0.5 flex h-10 w-10 items-center justify-center rounded-full text-sm font-bold text-gray',\n week: 'mt-1 flex w-full justify-between',\n day: cn(\n 'relative mx-0.5 flex h-10 w-10 items-center justify-center rounded-full p-0 text-center text-sm focus-within:relative focus-within:z-20',\n props.mode === 'range'\n ? '[&:has(>.range-end)]:rounded-r-full [&:has(>.range-start)]:rounded-l-full first:[&:has([aria-selected])]:rounded-l-full last:[&:has([aria-selected])]:rounded-r-full'\n : '[&:has([aria-selected])]:rounded-full',\n ),\n day_button: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n // hover:…:bg-spark-10 outranks tertiary's hover:bg-gray-a3 — selected days\n // darken like a solid button instead of washing out gray under white text\n 'size-10 shrink-0 rounded-full p-0 font-normal text-gray in-aria-selected:rounded-full in-aria-selected:bg-base-accent-solid in-aria-selected:text-accent-contrast hover:in-aria-selected:bg-spark-10 hover:in-aria-selected:text-accent-contrast',\n ),\n range_start: 'range-start',\n range_end: 'range-end',\n selected: 'rounded-full',\n today: cn(\n 'relative bg-base-gray-soft text-gray',\n showTodayDot &&\n 'after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]',\n ),\n outside:\n 'outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light',\n disabled: 'text-gray-light opacity-50',\n range_middle: 'aria-selected:bg-base-gray-soft aria-selected:text-gray',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => (\n <MaterialSymbol\n className={cn(\n 'text-[20px]',\n orientation === 'up' && 'rotate-90',\n orientation === 'down' && '-rotate-90',\n )}\n name={orientation === 'right' ? 'chevron_right' : 'chevron_left'}\n />\n ),\n }}\n fixedWeeks={fixedWeeks}\n showOutsideDays={showOutsideDays}\n {...props}\n />\n )\n}\n\nexport { Calendar }\nexport type { CalendarProps }\n"],"mappings":";;;;;;;;;;;AAYA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,aAAa,MACb,eAAe,MACf,GAAG,SACa;AAChB,QACE,iBAAA,GAAA,kBAAA,KAACA,iBAAAA,WAAD;EACE,YAAA,GAAA,OAAA,IAAc,OAAO,UAAU;EAC/B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,kBAAA,GAAA,OAAA,IACEC,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,6DACD;GACD,cAAA,GAAA,OAAA,IACEA,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,8DACD;GACD,YAAY;GACZ,UAAU;GACV,SACE;GACF,MAAM;GACN,MAAA,GAAA,OAAA,IACE,2IACA,MAAM,SAAS,UACX,yKACA,wCACL;GACD,aAAA,GAAA,OAAA,IACEA,0BAAAA,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EAGrD,mPACD;GACD,aAAa;GACb,WAAW;GACX,UAAU;GACV,QAAA,GAAA,OAAA,IACE,wCACA,gBACE,kLACH;GACD,SACE;GACF,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;GACJ;EACD,YAAY,EACV,UAAU,EAAE,kBACV,iBAAA,GAAA,kBAAA,KAACC,8BAAAA,gBAAD;GACE,YAAA,GAAA,OAAA,IACE,eACA,gBAAgB,QAAQ,aACxB,gBAAgB,UAAU,aAC3B;GACD,MAAM,gBAAgB,UAAU,kBAAkB;GAClD,CAAA,EAEL;EACW;EACK;EACjB,GAAI;EACJ,CAAA"}
@@ -5,11 +5,15 @@ import * as React$1 from "react";
5
5
  import { DayPicker } from "@daypicker/react";
6
6
 
7
7
  //#region src/components/calendar.d.ts
8
- type CalendarProps = React$1.ComponentProps<typeof DayPicker>;
8
+ type CalendarProps = React$1.ComponentProps<typeof DayPicker> & {
9
+ showTodayDot?: boolean;
10
+ };
9
11
  declare function Calendar({
10
12
  className,
11
13
  classNames,
12
14
  showOutsideDays,
15
+ fixedWeeks,
16
+ showTodayDot,
13
17
  ...props
14
18
  }: CalendarProps): _$react_jsx_runtime0.JSX.Element;
15
19
  //#endregion
@@ -5,11 +5,15 @@ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import { DayPicker } from "@daypicker/react";
6
6
 
7
7
  //#region src/components/calendar.d.ts
8
- type CalendarProps = React$1.ComponentProps<typeof DayPicker>;
8
+ type CalendarProps = React$1.ComponentProps<typeof DayPicker> & {
9
+ showTodayDot?: boolean;
10
+ };
9
11
  declare function Calendar({
10
12
  className,
11
13
  classNames,
12
14
  showOutsideDays,
15
+ fixedWeeks,
16
+ showTodayDot,
13
17
  ...props
14
18
  }: CalendarProps): _$react_jsx_runtime0.JSX.Element;
15
19
  //#endregion
@@ -6,7 +6,7 @@ import "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { DayPicker } from "@daypicker/react";
8
8
  //#region src/components/calendar.tsx
9
- function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
9
+ function Calendar({ className, classNames, showOutsideDays = true, fixedWeeks = true, showTodayDot = true, ...props }) {
10
10
  return /* @__PURE__ */ jsx(DayPicker, {
11
11
  className: cn("p-3", className),
12
12
  classNames: {
@@ -34,7 +34,7 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
34
34
  range_start: "range-start",
35
35
  range_end: "range-end",
36
36
  selected: "rounded-full",
37
- today: "relative bg-base-gray-soft text-gray after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]",
37
+ today: cn("relative bg-base-gray-soft text-gray", showTodayDot && "after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]"),
38
38
  outside: "outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light",
39
39
  disabled: "text-gray-light opacity-50",
40
40
  range_middle: "aria-selected:bg-base-gray-soft aria-selected:text-gray",
@@ -45,6 +45,7 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
45
45
  className: cn("text-[20px]", orientation === "up" && "rotate-90", orientation === "down" && "-rotate-90"),
46
46
  name: orientation === "right" ? "chevron_right" : "chevron_left"
47
47
  }) },
48
+ fixedWeeks,
48
49
  showOutsideDays,
49
50
  ...props
50
51
  });
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.js","names":[],"sources":["../../src/components/calendar.tsx"],"sourcesContent":["import { DayPicker } from '@daypicker/react'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\nimport { buttonVariants } from './button'\n\ntype CalendarProps = React.ComponentProps<typeof DayPicker>\n\n// Pass `locale` (from '@daypicker/react/locale') for localized month/weekday\n// names — the library ships no language default.\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n className={cn('p-3', className)}\n classNames={{\n months: 'relative',\n month: 'flex flex-col gap-2',\n month_caption: 'flex h-10 items-center justify-center',\n caption_label: 'text-sm font-bold text-gray',\n button_previous: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 left-0 z-10 text-gray-light hover:text-gray',\n ),\n button_next: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 right-0 z-10 text-gray-light hover:text-gray',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex w-full justify-between',\n weekday:\n 'mt-0.5 flex h-10 w-10 items-center justify-center rounded-full text-sm font-bold text-gray',\n week: 'mt-1 flex w-full justify-between',\n day: cn(\n 'relative mx-0.5 flex h-10 w-10 items-center justify-center rounded-full p-0 text-center text-sm focus-within:relative focus-within:z-20',\n props.mode === 'range'\n ? '[&:has(>.range-end)]:rounded-r-full [&:has(>.range-start)]:rounded-l-full first:[&:has([aria-selected])]:rounded-l-full last:[&:has([aria-selected])]:rounded-r-full'\n : '[&:has([aria-selected])]:rounded-full',\n ),\n day_button: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n // hover:…:bg-spark-10 outranks tertiary's hover:bg-gray-a3 — selected days\n // darken like a solid button instead of washing out gray under white text\n 'size-10 shrink-0 rounded-full p-0 font-normal text-gray in-aria-selected:rounded-full in-aria-selected:bg-base-accent-solid in-aria-selected:text-accent-contrast hover:in-aria-selected:bg-spark-10 hover:in-aria-selected:text-accent-contrast',\n ),\n range_start: 'range-start',\n range_end: 'range-end',\n selected: 'rounded-full',\n today:\n 'relative bg-base-gray-soft text-gray after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]',\n outside:\n 'outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light',\n disabled: 'text-gray-light opacity-50',\n range_middle: 'aria-selected:bg-base-gray-soft aria-selected:text-gray',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => (\n <MaterialSymbol\n className={cn(\n 'text-[20px]',\n orientation === 'up' && 'rotate-90',\n orientation === 'down' && '-rotate-90',\n )}\n name={orientation === 'right' ? 'chevron_right' : 'chevron_left'}\n />\n ),\n }}\n showOutsideDays={showOutsideDays}\n {...props}\n />\n )\n}\n\nexport { Calendar }\nexport type { CalendarProps }\n"],"mappings":";;;;;;;;AAUA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,GAAG,SACa;AAChB,QACE,oBAAC,WAAD;EACE,WAAW,GAAG,OAAO,UAAU;EAC/B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,iBAAiB,GACf,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,6DACD;GACD,aAAa,GACX,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,8DACD;GACD,YAAY;GACZ,UAAU;GACV,SACE;GACF,MAAM;GACN,KAAK,GACH,2IACA,MAAM,SAAS,UACX,yKACA,wCACL;GACD,YAAY,GACV,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EAGrD,mPACD;GACD,aAAa;GACb,WAAW;GACX,UAAU;GACV,OACE;GACF,SACE;GACF,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;GACJ;EACD,YAAY,EACV,UAAU,EAAE,kBACV,oBAAC,gBAAD;GACE,WAAW,GACT,eACA,gBAAgB,QAAQ,aACxB,gBAAgB,UAAU,aAC3B;GACD,MAAM,gBAAgB,UAAU,kBAAkB;GAClD,CAAA,EAEL;EACgB;EACjB,GAAI;EACJ,CAAA"}
1
+ {"version":3,"file":"calendar.js","names":[],"sources":["../../src/components/calendar.tsx"],"sourcesContent":["import { DayPicker } from '@daypicker/react'\nimport * as React from 'react'\nimport { MaterialSymbol } from '../icons/material-symbol'\nimport { cn } from '../utils/cn'\nimport { buttonVariants } from './button'\n\ntype CalendarProps = React.ComponentProps<typeof DayPicker> & {\n showTodayDot?: boolean\n}\n\n// Pass `locale` (from '@daypicker/react/locale') for localized month/weekday\n// names — the library ships no language default.\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n fixedWeeks = true,\n showTodayDot = true,\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n className={cn('p-3', className)}\n classNames={{\n months: 'relative',\n month: 'flex flex-col gap-2',\n month_caption: 'flex h-10 items-center justify-center',\n caption_label: 'text-sm font-bold text-gray',\n button_previous: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 left-0 z-10 text-gray-light hover:text-gray',\n ),\n button_next: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n 'absolute top-0 right-0 z-10 text-gray-light hover:text-gray',\n ),\n month_grid: 'w-full border-collapse',\n weekdays: 'flex w-full justify-between',\n weekday:\n 'mt-0.5 flex h-10 w-10 items-center justify-center rounded-full text-sm font-bold text-gray',\n week: 'mt-1 flex w-full justify-between',\n day: cn(\n 'relative mx-0.5 flex h-10 w-10 items-center justify-center rounded-full p-0 text-center text-sm focus-within:relative focus-within:z-20',\n props.mode === 'range'\n ? '[&:has(>.range-end)]:rounded-r-full [&:has(>.range-start)]:rounded-l-full first:[&:has([aria-selected])]:rounded-l-full last:[&:has([aria-selected])]:rounded-r-full'\n : '[&:has([aria-selected])]:rounded-full',\n ),\n day_button: cn(\n buttonVariants({ size: 'icon', variant: 'tertiary' }),\n // hover:…:bg-spark-10 outranks tertiary's hover:bg-gray-a3 — selected days\n // darken like a solid button instead of washing out gray under white text\n 'size-10 shrink-0 rounded-full p-0 font-normal text-gray in-aria-selected:rounded-full in-aria-selected:bg-base-accent-solid in-aria-selected:text-accent-contrast hover:in-aria-selected:bg-spark-10 hover:in-aria-selected:text-accent-contrast',\n ),\n range_start: 'range-start',\n range_end: 'range-end',\n selected: 'rounded-full',\n today: cn(\n 'relative bg-base-gray-soft text-gray',\n showTodayDot &&\n 'after:absolute after:right-0 after:-bottom-1 after:left-0 after:m-auto after:inline-flex after:h-1 after:w-1 after:rounded-full after:bg-base-accent-solid after:content-[\"\"]',\n ),\n outside:\n 'outside text-gray-light opacity-50 aria-selected:bg-base-gray-soft aria-selected:text-gray-light',\n disabled: 'text-gray-light opacity-50',\n range_middle: 'aria-selected:bg-base-gray-soft aria-selected:text-gray',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation }) => (\n <MaterialSymbol\n className={cn(\n 'text-[20px]',\n orientation === 'up' && 'rotate-90',\n orientation === 'down' && '-rotate-90',\n )}\n name={orientation === 'right' ? 'chevron_right' : 'chevron_left'}\n />\n ),\n }}\n fixedWeeks={fixedWeeks}\n showOutsideDays={showOutsideDays}\n {...props}\n />\n )\n}\n\nexport { Calendar }\nexport type { CalendarProps }\n"],"mappings":";;;;;;;;AAYA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,aAAa,MACb,eAAe,MACf,GAAG,SACa;AAChB,QACE,oBAAC,WAAD;EACE,WAAW,GAAG,OAAO,UAAU;EAC/B,YAAY;GACV,QAAQ;GACR,OAAO;GACP,eAAe;GACf,eAAe;GACf,iBAAiB,GACf,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,6DACD;GACD,aAAa,GACX,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EACrD,8DACD;GACD,YAAY;GACZ,UAAU;GACV,SACE;GACF,MAAM;GACN,KAAK,GACH,2IACA,MAAM,SAAS,UACX,yKACA,wCACL;GACD,YAAY,GACV,eAAe;IAAE,MAAM;IAAQ,SAAS;IAAY,CAAC,EAGrD,mPACD;GACD,aAAa;GACb,WAAW;GACX,UAAU;GACV,OAAO,GACL,wCACA,gBACE,kLACH;GACD,SACE;GACF,UAAU;GACV,cAAc;GACd,QAAQ;GACR,GAAG;GACJ;EACD,YAAY,EACV,UAAU,EAAE,kBACV,oBAAC,gBAAD;GACE,WAAW,GACT,eACA,gBAAgB,QAAQ,aACxB,gBAAgB,UAAU,aAC3B;GACD,MAAM,gBAAgB,UAAU,kBAAkB;GAClD,CAAA,EAEL;EACW;EACK;EACjB,GAAI;EACJ,CAAA"}
@@ -9,7 +9,7 @@ import { VariantProps } from "class-variance-authority";
9
9
  //#region src/components/callout.d.ts
10
10
  type CalloutVariant = 'error' | 'info' | 'success' | 'warning';
11
11
  declare const calloutVariants: (props?: ({
12
- variant?: "info" | "warning" | "success" | "error" | null | undefined;
12
+ variant?: "success" | "warning" | "error" | "info" | null | undefined;
13
13
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
14
14
  interface CalloutProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof calloutVariants> {}
15
15
  declare const CalloutTitle: ({
@@ -9,7 +9,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
9
9
  //#region src/components/callout.d.ts
10
10
  type CalloutVariant = 'error' | 'info' | 'success' | 'warning';
11
11
  declare const calloutVariants: (props?: ({
12
- variant?: "info" | "warning" | "success" | "error" | null | undefined;
12
+ variant?: "success" | "warning" | "error" | "info" | null | undefined;
13
13
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
14
14
  interface CalloutProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof calloutVariants> {}
15
15
  declare const CalloutTitle: ({
@@ -39,7 +39,7 @@ function ListItem({ className, children, recent, selected, skeleton, render, ...
39
39
  });
40
40
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
41
41
  "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", "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),
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),
43
43
  ...props,
44
44
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListItemContext.Provider, {
45
45
  value: recentCtx,
@@ -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-0.5',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]: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 so has-[:focus-visible]:z-10 lifts the focused row's ring-offset above\n // the stacked siblings instead of being clipped by the next item.\n 'relative has-[:focus-visible]:z-10',\n // NEUTRAL container chrome per the list variant (group/list) — mirrors\n // AccordionItem's group-data-[variant=X]/accordion: block (accordion.tsx); keep\n // both in sync if this pattern changes. Radius = rounded-md (tracks the radius\n // knob but never goes fully round). ghost matches none of these selectors on\n // purpose — no fill/border, just the List root's gap (above) for spacing.\n // soft: each row is its own borderless soft-tinted rounded card (root gap = divider).\n 'group-data-[variant=soft]/list:rounded-md group-data-[variant=soft]/list:bg-gray-a2',\n // surface + outline share ONE glued-panel frame: sides on all, top on each (divider),\n // first/last round the outer corners, last closes with border-b. surface fills it.\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 { 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-0.5',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]: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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"}
@@ -36,7 +36,7 @@ function ListItem({ className, children, recent, selected, skeleton, render, ...
36
36
  });
37
37
  return /* @__PURE__ */ jsx("li", {
38
38
  "data-slot": "list-item",
39
- className: cn("relative has-[:focus-visible]:z-10", "group-data-[variant=soft]/list:rounded-md group-data-[variant=soft]/list:bg-gray-a2", "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),
39
+ className: 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),
40
40
  ...props,
41
41
  children: /* @__PURE__ */ jsx(ListItemContext.Provider, {
42
42
  value: recentCtx,
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","names":["React"],"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-0.5',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]: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 so has-[:focus-visible]:z-10 lifts the focused row's ring-offset above\n // the stacked siblings instead of being clipped by the next item.\n 'relative has-[:focus-visible]:z-10',\n // NEUTRAL container chrome per the list variant (group/list) — mirrors\n // AccordionItem's group-data-[variant=X]/accordion: block (accordion.tsx); keep\n // both in sync if this pattern changes. Radius = rounded-md (tracks the radius\n // knob but never goes fully round). ghost matches none of these selectors on\n // purpose — no fill/border, just the List root's gap (above) for spacing.\n // soft: each row is its own borderless soft-tinted rounded card (root gap = divider).\n 'group-data-[variant=soft]/list:rounded-md group-data-[variant=soft]/list:bg-gray-a2',\n // surface + outline share ONE glued-panel frame: sides on all, top on each (divider),\n // first/last round the outer corners, last closes with border-b. surface fills it.\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.js","names":["React"],"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-0.5',\n 'data-[variant=ghost]:flex data-[variant=ghost]:flex-col data-[variant=ghost]: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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"}
@@ -23,7 +23,7 @@ function SegmentedControl({ className, styleVariant = "solid", size = "default",
23
23
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_tabs.Tabs.Indicator, {
24
24
  "data-slot": "segmented-control-indicator",
25
25
  renderBeforeHydration: true,
26
- className: (0, cnfast.cn)("pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "[&[data-starting-style]]:transition-none")
26
+ className: (0, cnfast.cn)("pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "data-starting-style:transition-none")
27
27
  }), children]
28
28
  })
29
29
  });
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.cjs","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n '[&[data-starting-style]]:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // ring-offset-1 floats the ring off the segment (a flush ring vanishes\n // on the solid indicator; a full inset box reads heavy)\n 'focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,iBAAA,GAAA,kBAAA,MAACA,oBAAAA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,YAAA,GAAA,OAAA,IAEE,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,YAAA,GAAA,OAAA,IACE,uJACA,oEACA,6BACA,2EACA,8HACA,0FAEA,2CACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,KAAf;EACE,aAAU;EACL;EACL,YAAA,GAAA,OAAA,IACE,gJACA,oEACA,iEACA,sCACA,6DAGA,iFACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
1
+ {"version":3,"file":"segmented-control.cjs","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n 'data-starting-style:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // ring-offset-1 floats the ring off the segment (a flush ring vanishes\n // on the solid indicator; a full inset box reads heavy)\n 'focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,iBAAA,GAAA,kBAAA,MAACA,oBAAAA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,YAAA,GAAA,OAAA,IAEE,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,YAAA,GAAA,OAAA,IACE,mIACA,oEACA,6BACA,2EACA,8HACA,0FAEA,sCACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,iBAAA,GAAA,kBAAA,KAACA,oBAAAA,KAAc,KAAf;EACE,aAAU;EACL;EACL,YAAA,GAAA,OAAA,IACE,gJACA,oEACA,iEACA,sCACA,6DAGA,iFACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
@@ -20,7 +20,7 @@ function SegmentedControl({ className, styleVariant = "solid", size = "default",
20
20
  children: [/* @__PURE__ */ jsx(Tabs.Indicator, {
21
21
  "data-slot": "segmented-control-indicator",
22
22
  renderBeforeHydration: true,
23
- className: cn("pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "[&[data-starting-style]]:transition-none")
23
+ className: cn("pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "data-starting-style:transition-none")
24
24
  }), children]
25
25
  })
26
26
  });
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.js","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n '[&[data-starting-style]]:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // ring-offset-1 floats the ring off the segment (a flush ring vanishes\n // on the solid indicator; a full inset box reads heavy)\n 'focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,oBAACA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,qBAACA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,WAAW,GAET,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,oBAACA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,WAAW,GACT,uJACA,oEACA,6BACA,2EACA,8HACA,0FAEA,2CACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,oBAACA,KAAc,KAAf;EACE,aAAU;EACL;EACL,WAAW,GACT,gJACA,oEACA,iEACA,sCACA,6DAGA,iFACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
1
+ {"version":3,"file":"segmented-control.js","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n 'data-starting-style:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // ring-offset-1 floats the ring off the segment (a flush ring vanishes\n // on the solid indicator; a full inset box reads heavy)\n 'focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,oBAACA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,qBAACA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,WAAW,GAET,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,oBAACA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,WAAW,GACT,mIACA,oEACA,6BACA,2EACA,8HACA,0FAEA,sCACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,oBAACA,KAAc,KAAf;EACE,aAAU;EACL;EACL,WAAW,GACT,gJACA,oEACA,iEACA,sCACA,6DAGA,iFACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epilot/spark-ui",
3
- "version": "1.0.0-alpha.5",
3
+ "version": "1.0.0-alpha.6",
4
4
  "description": "React UI component library from Spark SDK",
5
5
  "license": "Apache-2.0",
6
6
  "author": "epilot",