@nocoo/basalt 2.1.2 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/ai/INTEGRATION.md +17 -1
  2. package/ai/USAGE.md +1 -1
  3. package/ai/registry.json +75 -75
  4. package/dist/charts/charts.d.ts +1 -1
  5. package/dist/charts/charts.js +3 -16
  6. package/dist/charts/charts.js.map +1 -1
  7. package/dist/charts/custom-chart.d.ts +1 -1
  8. package/dist/charts/custom-chart.js +3 -16
  9. package/dist/charts/custom-chart.js.map +1 -1
  10. package/dist/charts/grouped-bar.d.ts +1 -1
  11. package/dist/charts/grouped-bar.js +11 -48
  12. package/dist/charts/grouped-bar.js.map +1 -1
  13. package/dist/charts/heatmap-calendar.js +80 -136
  14. package/dist/charts/heatmap-calendar.js.map +1 -1
  15. package/dist/charts/slot-bar.js +2 -12
  16. package/dist/charts/slot-bar.js.map +1 -1
  17. package/dist/charts/stat-card.js +2 -7
  18. package/dist/charts/stat-card.js.map +1 -1
  19. package/dist/charts/timeseries.d.ts +1 -1
  20. package/dist/charts/timeseries.js +3 -16
  21. package/dist/charts/timeseries.js.map +1 -1
  22. package/dist/charts/tooltip.js +13 -51
  23. package/dist/charts/tooltip.js.map +1 -1
  24. package/dist/components/autocomplete.d.ts +1 -1
  25. package/dist/components/autocomplete.js +3 -16
  26. package/dist/components/autocomplete.js.map +1 -1
  27. package/dist/components/banner.js +28 -28
  28. package/dist/components/banner.js.map +1 -1
  29. package/dist/components/button.js +6 -7
  30. package/dist/components/button.js.map +1 -1
  31. package/dist/components/chat-composer.js +1 -2
  32. package/dist/components/chat-composer.js.map +1 -1
  33. package/dist/components/checkbox.js +50 -82
  34. package/dist/components/checkbox.js.map +1 -1
  35. package/dist/components/code.js +1 -1
  36. package/dist/components/code.js.map +1 -1
  37. package/dist/components/combobox.d.ts +1 -1
  38. package/dist/components/combobox.js +3 -16
  39. package/dist/components/combobox.js.map +1 -1
  40. package/dist/components/context-menu.d.ts +1 -67
  41. package/dist/components/context-menu.js.map +1 -1
  42. package/dist/components/data-table.js +111 -123
  43. package/dist/components/data-table.js.map +1 -1
  44. package/dist/components/date-picker.js +236 -245
  45. package/dist/components/date-picker.js.map +1 -1
  46. package/dist/components/dock.js +15 -16
  47. package/dist/components/dock.js.map +1 -1
  48. package/dist/components/field.js +20 -23
  49. package/dist/components/field.js.map +1 -1
  50. package/dist/components/layer-card.d.ts +1 -1
  51. package/dist/components/layer-card.js +44 -51
  52. package/dist/components/layer-card.js.map +1 -1
  53. package/dist/components/skeleton-line.d.ts +2 -2
  54. package/dist/components/skeleton-line.js +1 -1
  55. package/dist/components/skeleton-line.js.map +1 -1
  56. package/dist/components/switch.js +46 -78
  57. package/dist/components/switch.js.map +1 -1
  58. package/dist/providers/accent.js +89 -198
  59. package/dist/providers/accent.js.map +1 -1
  60. package/dist/providers/theme.js +46 -144
  61. package/dist/providers/theme.js.map +1 -1
  62. package/dist/utils/preference-store.d.ts +16 -0
  63. package/dist/utils/preference-store.js +106 -0
  64. package/dist/utils/preference-store.js.map +1 -0
  65. package/dist/utils/use-checkable-group.d.ts +19 -0
  66. package/dist/utils/use-checkable-group.js +61 -0
  67. package/dist/utils/use-checkable-group.js.map +1 -0
  68. package/package.json +1 -2
@@ -2,11 +2,11 @@
2
2
  import { cn as e } from "../utils/cn.js";
3
3
  import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
4
4
  import { Button as n } from "./button.js";
5
- import { Children as r, createContext as i, useContext as a } from "react";
6
- import { cva as o } from "class-variance-authority";
7
- import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { Children as r, createContext as i, isValidElement as a, useContext as o } from "react";
6
+ import { cva as s } from "class-variance-authority";
7
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
8
8
  //#region src/components/banner.tsx
9
- var u = o("flex w-full items-start gap-3 rounded-basalt-md text-sm", {
9
+ var d = s("flex w-full items-start gap-3 rounded-basalt-md text-sm", {
10
10
  variants: {
11
11
  variant: {
12
12
  default: "bg-basalt-info-tint text-basalt-info",
@@ -23,46 +23,46 @@ var u = o("flex w-full items-start gap-3 rounded-basalt-md text-sm", {
23
23
  variant: "default",
24
24
  size: "base"
25
25
  }
26
- }), d = i({
26
+ }), f = i({
27
27
  variant: "default",
28
28
  size: "base"
29
29
  });
30
- function f(e) {
31
- return typeof e == "object" && !!e && "type" in e && e.type === m;
30
+ function p(e) {
31
+ return a(e) && e.type === h;
32
32
  }
33
- function p({ className: n, variant: i = "default", size: a = "base", title: o, description: p, icon: m, action: h, children: g, ..._ }) {
34
- let v = i ?? "default", y = a ?? "base", b = o != null || p != null, x = r.toArray(h), S = x.filter(f), C = x.filter((e) => !f(e)), w = y === "sm" ? S : [...C, ...S], T = y === "sm" ? C : [];
35
- return /* @__PURE__ */ c(d.Provider, {
33
+ function m({ className: n, variant: i = "default", size: a = "base", title: o, description: s, icon: m, action: h, children: g, ..._ }) {
34
+ let v = i ?? "default", y = a ?? "base", b = o != null || s != null, x = r.toArray(h), S = x.filter(p), C = x.filter((e) => !p(e)), w = y === "sm" ? S : [...C, ...S], T = y === "sm" ? C : [];
35
+ return /* @__PURE__ */ l(f.Provider, {
36
36
  value: {
37
37
  variant: v,
38
38
  size: y
39
39
  },
40
- children: /* @__PURE__ */ l("div", {
41
- className: e(t, u({
40
+ children: /* @__PURE__ */ u("div", {
41
+ className: e(t, d({
42
42
  variant: v,
43
43
  size: y
44
44
  }), n),
45
45
  ..._,
46
46
  children: [
47
- m ? /* @__PURE__ */ c("span", {
47
+ m ? /* @__PURE__ */ l("span", {
48
48
  className: "mt-0.5 inline-flex shrink-0 [&_svg]:size-5",
49
49
  children: m
50
50
  }) : null,
51
- /* @__PURE__ */ l("div", {
51
+ /* @__PURE__ */ u("div", {
52
52
  className: "min-w-0 flex-1 space-y-0.5",
53
53
  children: [
54
- o ? /* @__PURE__ */ c("p", {
54
+ o ? /* @__PURE__ */ l("p", {
55
55
  className: "font-medium",
56
56
  children: o
57
57
  }) : null,
58
- p ? /* @__PURE__ */ l("div", {
58
+ s ? /* @__PURE__ */ u("div", {
59
59
  className: e(v === "secondary" ? "text-basalt-muted-foreground" : "text-current"),
60
- children: [p, T.length > 0 ? /* @__PURE__ */ l(s, { children: [" ", T] }) : null]
61
- }) : T.length > 0 ? /* @__PURE__ */ c("div", { children: T }) : null,
60
+ children: [s, T.length > 0 ? /* @__PURE__ */ u(c, { children: [" ", T] }) : null]
61
+ }) : T.length > 0 ? /* @__PURE__ */ l("div", { children: T }) : null,
62
62
  b ? null : g
63
63
  ]
64
64
  }),
65
- w.length > 0 ? /* @__PURE__ */ c("div", {
65
+ w.length > 0 ? /* @__PURE__ */ l("div", {
66
66
  className: "flex shrink-0 items-center gap-2",
67
67
  children: w
68
68
  }) : null
@@ -70,20 +70,20 @@ function p({ className: n, variant: i = "default", size: a = "base", title: o, d
70
70
  })
71
71
  });
72
72
  }
73
- function m({ className: t, variant: r = "default", size: i, icon: o, children: s, ...l }) {
74
- let u = a(d), f = r === "ghost" ? "ghost" : r === "secondary" ? "secondary" : u.variant === "error" ? "destructive" : "default", p = s == null || s === "";
75
- return /* @__PURE__ */ c(n, {
76
- variant: f,
73
+ function h({ className: t, variant: r = "default", size: i, icon: a, children: s, ...c }) {
74
+ let u = o(f), d = r === "ghost" ? "ghost" : r === "secondary" ? "secondary" : u.variant === "error" ? "destructive" : "default", p = s == null || s === "";
75
+ return /* @__PURE__ */ l(n, {
76
+ variant: d,
77
77
  size: i ?? (p ? "icon" : u.size === "sm" ? "sm" : "default"),
78
- icon: o,
78
+ icon: a,
79
79
  className: e(p && "size-8", t),
80
- ...l,
80
+ ...c,
81
81
  children: s
82
82
  });
83
83
  }
84
- m.displayName = "Banner.Action";
85
- var h = Object.assign(p, { Action: m });
84
+ h.displayName = "Banner.Action";
85
+ var g = Object.assign(m, { Action: h });
86
86
  //#endregion
87
- export { h as Banner, m as BannerAction };
87
+ export { g as Banner, h as BannerAction };
88
88
 
89
89
  //# sourceMappingURL=banner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"banner.js","names":[],"sources":["../../src/components/banner.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport { Children, createContext, type HTMLAttributes, type ReactNode, useContext } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\n\nconst bannerVariants = cva(\"flex w-full items-start gap-3 rounded-basalt-md text-sm\", {\n\tvariants: {\n\t\tvariant: {\n\t\t\tdefault: \"bg-basalt-info-tint text-basalt-info\",\n\t\t\talert: \"bg-basalt-warning-tint text-basalt-warning\",\n\t\t\terror: \"bg-basalt-danger-tint text-basalt-danger\",\n\t\t\tsecondary: \"bg-basalt-muted text-basalt-foreground\",\n\t\t},\n\t\tsize: {\n\t\t\tbase: \"px-4 py-3\",\n\t\t\tsm: \"px-3 py-2\",\n\t\t},\n\t},\n\tdefaultVariants: { variant: \"default\", size: \"base\" },\n});\n\ntype BannerVariant = NonNullable<VariantProps<typeof bannerVariants>[\"variant\"]>;\ntype BannerSize = NonNullable<VariantProps<typeof bannerVariants>[\"size\"]>;\n\nconst BannerContext = createContext<{ variant: BannerVariant; size: BannerSize }>({\n\tvariant: \"default\",\n\tsize: \"base\",\n});\n\nexport interface BannerProps\n\textends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\">,\n\t\tOmit<VariantProps<typeof bannerVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual tone variant of the banner.\n\t *\n\t * Note: Defaults to \"default\" (informational). Passing null falls back to \"default\".\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof bannerVariants>[\"variant\"];\n\n\t/**\n\t * Sizing preset controlling padding geometry and action placement.\n\t *\n\t * Note: Defaults to \"base\". In compact mode (\"sm\"), only direct `<Banner.Action>` elements\n\t * are placed in the trailing slot, while other action content renders inline next to the description.\n\t * Passing null falls back to \"base\".\n\t *\n\t * @default \"base\"\n\t */\n\tsize?: VariantProps<typeof bannerVariants>[\"size\"];\n\n\t/**\n\t * Primary heading text.\n\t *\n\t * Note: When present (or when description is present), structured mode is enabled\n\t * and standard children are not rendered.\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Secondary copy rendered below the title.\n\t */\n\tdescription?: ReactNode;\n\n\t/**\n\t * Visual icon rendered before the banner content.\n\t */\n\ticon?: ReactNode;\n\n\t/**\n\t * Trailing or inline call-to-action slot.\n\t * Pass `<Banner.Action>` elements for contextual styling.\n\t * In compact mode (\"sm\"), only direct `<Banner.Action>` elements are placed in the trailing slot,\n\t * while other action content renders inline next to the description.\n\t */\n\taction?: ReactNode;\n\n\t/**\n\t * Unstructured child content rendered only when both title and description are null or undefined.\n\t * When title or description is non-null/non-undefined (including empty string or false),\n\t * structured mode is active and children are ignored.\n\t */\n\tchildren?: HTMLAttributes<HTMLDivElement>[\"children\"];\n}\n\nexport interface BannerActionProps\n\textends Omit<\n\t\tButtonProps,\n\t\t\"variant\" | \"size\" | \"asChild\" | \"type\" | \"loading\" | \"icon\" | \"children\"\n\t> {\n\t/**\n\t * Visual style variant. Preserves \"ghost\" and \"secondary\"; all other values\n\t * are mapped contextually to \"destructive\" (when parent Banner variant is \"error\")\n\t * or \"default\".\n\t *\n\t * Note: Ordinary function component without forwarded ref.\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: ButtonProps[\"variant\"];\n\n\t/**\n\t * Sizing preset. When unspecified or null, resolves to \"icon\" if children are omitted,\n\t * null, or an empty string, \"sm\" when parent Banner is compact (\"sm\"), or \"default\" otherwise.\n\t * When iconOnly mode is resolved, an additional \"size-8\" class is attached.\n\t */\n\tsize?: ButtonProps[\"size\"];\n\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * @default false\n\t */\n\tasChild?: ButtonProps[\"asChild\"];\n\n\t/**\n\t * Button type attribute.\n\t *\n\t * @default \"button\"\n\t */\n\ttype?: ButtonProps[\"type\"];\n\n\t/**\n\t * Display loading spinner and disable interactions.\n\t *\n\t * @default false\n\t */\n\tloading?: ButtonProps[\"loading\"];\n\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: ButtonProps[\"icon\"];\n\n\t/**\n\t * Action label content. When null, undefined, or empty string, enables iconOnly sizing mode.\n\t */\n\tchildren?: ButtonProps[\"children\"];\n}\n\nfunction isBannerAction(node: ReactNode): boolean {\n\treturn (\n\t\ttypeof node === \"object\" &&\n\t\tnode !== null &&\n\t\t\"type\" in node &&\n\t\t(node as { type: unknown }).type === BannerAction\n\t);\n}\n\nfunction BannerRoot({\n\tclassName,\n\tvariant = \"default\",\n\tsize = \"base\",\n\ttitle,\n\tdescription,\n\ticon,\n\taction,\n\tchildren,\n\t...props\n}: BannerProps) {\n\tconst resolvedVariant = variant ?? \"default\";\n\tconst resolvedSize = size ?? \"base\";\n\tconst structured = title != null || description != null;\n\tconst nodes = Children.toArray(action);\n\tconst ctas = nodes.filter(isBannerAction);\n\tconst other = nodes.filter((node) => !isBannerAction(node));\n\tconst trailing = resolvedSize === \"sm\" ? ctas : [...other, ...ctas];\n\tconst inlineActions = resolvedSize === \"sm\" ? other : [];\n\n\treturn (\n\t\t<BannerContext.Provider value={{ variant: resolvedVariant, size: resolvedSize }}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\tbannerVariants({ variant: resolvedVariant, size: resolvedSize }),\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{icon ? <span className=\"mt-0.5 inline-flex shrink-0 [&_svg]:size-5\">{icon}</span> : null}\n\t\t\t\t<div className=\"min-w-0 flex-1 space-y-0.5\">\n\t\t\t\t\t{title ? <p className=\"font-medium\">{title}</p> : null}\n\t\t\t\t\t{description ? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\tresolvedVariant === \"secondary\" ? \"text-basalt-muted-foreground\" : \"text-current\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t{inlineActions.length > 0 ? <> {inlineActions}</> : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : inlineActions.length > 0 ? (\n\t\t\t\t\t\t<div>{inlineActions}</div>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{structured ? null : children}\n\t\t\t\t</div>\n\t\t\t\t{trailing.length > 0 ? (\n\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-2\">{trailing}</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</BannerContext.Provider>\n\t);\n}\n\nexport function BannerAction({\n\tclassName,\n\tvariant = \"default\",\n\tsize,\n\ticon,\n\tchildren,\n\t...props\n}: BannerActionProps) {\n\tconst banner = useContext(BannerContext);\n\tconst mapped =\n\t\tvariant === \"ghost\"\n\t\t\t? \"ghost\"\n\t\t\t: variant === \"secondary\"\n\t\t\t\t? \"secondary\"\n\t\t\t\t: banner.variant === \"error\"\n\t\t\t\t\t? \"destructive\"\n\t\t\t\t\t: \"default\";\n\tconst iconOnly = children == null || children === \"\";\n\treturn (\n\t\t<Button\n\t\t\tvariant={mapped}\n\t\t\tsize={size ?? (iconOnly ? \"icon\" : banner.size === \"sm\" ? \"sm\" : \"default\")}\n\t\t\ticon={icon}\n\t\t\tclassName={cn(iconOnly && \"size-8\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t);\n}\nBannerAction.displayName = \"Banner.Action\";\n\nexport const Banner = Object.assign(BannerRoot, { Action: BannerAction });\n"],"mappings":";;;;;;;;AAMA,IAAM,IAAiB,EAAI,2DAA2D;CACrF,UAAU;EACT,SAAS;GACR,SAAS;GACT,OAAO;GACP,OAAO;GACP,WAAW;EACZ;EACA,MAAM;GACL,MAAM;GACN,IAAI;EACL;CACD;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAO;AACrD,CAAC,GAKK,IAAgB,EAA4D;CACjF,SAAS;CACT,MAAM;AACP,CAAC;AAkHD,SAAS,EAAe,GAA0B;CACjD,OACC,OAAO,KAAS,cAChB,KACA,UAAU,KACT,EAA2B,SAAS;AAEvC;AAEA,SAAS,EAAW,EACnB,cACA,aAAU,WACV,UAAO,QACP,UACA,gBACA,SACA,WACA,aACA,GAAG,KACY;CACf,IAAM,IAAkB,KAAW,WAC7B,IAAe,KAAQ,QACvB,IAAa,KAAS,QAAQ,KAAe,MAC7C,IAAQ,EAAS,QAAQ,CAAM,GAC/B,IAAO,EAAM,OAAO,CAAc,GAClC,IAAQ,EAAM,QAAQ,MAAS,CAAC,EAAe,CAAI,CAAC,GACpD,IAAW,MAAiB,OAAO,IAAO,CAAC,GAAG,GAAO,GAAG,CAAI,GAC5D,IAAgB,MAAiB,OAAO,IAAQ,CAAC;CAEvD,OACC,kBAAC,EAAc,UAAf;EAAwB,OAAO;GAAE,SAAS;GAAiB,MAAM;EAAa;EAC7E,UAAA,kBAAC,OAAD;GACC,WAAW,EACV,GACA,EAAe;IAAE,SAAS;IAAiB,MAAM;GAAa,CAAC,GAC/D,CACD;GACA,GAAI;GANL,UAAA;IAQE,IAAO,kBAAC,QAAD;KAAM,WAAU;KAA8C,UAAA;IAAW,CAAA,IAAI;IACrF,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,IAAQ,kBAAC,KAAD;OAAG,WAAU;OAAe,UAAA;MAAS,CAAA,IAAI;MACjD,IACA,kBAAC,OAAD;OACC,WAAW,EACV,MAAoB,cAAc,iCAAiC,cACpE;OAHD,UAAA,CAKE,GACA,EAAc,SAAS,IAAI,kBAAA,GAAA,EAAA,UAAA,CAAE,KAAE,CAAgB,EAAA,CAAA,IAAI,IAChD;MACF,CAAA,IAAA,EAAc,SAAS,IAC1B,kBAAC,OAAD,EAAA,UAAM,EAAmB,CAAA,IACtB;MACH,IAAa,OAAO;KACjB;;IACJ,EAAS,SAAS,IAClB,kBAAC,OAAD;KAAK,WAAU;KAAoC,UAAA;IAAc,CAAA,IAC9D;GACA;;CACkB,CAAA;AAE1B;AAEA,SAAgB,EAAa,EAC5B,cACA,aAAU,WACV,SACA,SACA,aACA,GAAG,KACkB;CACrB,IAAM,IAAS,EAAW,CAAa,GACjC,IACL,MAAY,UACT,UACA,MAAY,cACX,cACA,EAAO,YAAY,UAClB,gBACA,WACA,IAAW,KAAY,QAAQ,MAAa;CAClD,OACC,kBAAC,GAAD;EACC,SAAS;EACT,MAAM,MAAS,IAAW,SAAS,EAAO,SAAS,OAAO,OAAO;EAC3D;EACN,WAAW,EAAG,KAAY,UAAU,CAAS;EAC7C,GAAI;EAEH;CACM,CAAA;AAEV;AACA,EAAa,cAAc;AAE3B,IAAa,IAAS,OAAO,OAAO,GAAY,EAAE,QAAQ,EAAa,CAAC"}
1
+ {"version":3,"file":"banner.js","names":[],"sources":["../../src/components/banner.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\nimport {\n\tChildren,\n\tcreateContext,\n\ttype HTMLAttributes,\n\tisValidElement,\n\ttype ReactNode,\n\tuseContext,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\n\nconst bannerVariants = cva(\"flex w-full items-start gap-3 rounded-basalt-md text-sm\", {\n\tvariants: {\n\t\tvariant: {\n\t\t\tdefault: \"bg-basalt-info-tint text-basalt-info\",\n\t\t\talert: \"bg-basalt-warning-tint text-basalt-warning\",\n\t\t\terror: \"bg-basalt-danger-tint text-basalt-danger\",\n\t\t\tsecondary: \"bg-basalt-muted text-basalt-foreground\",\n\t\t},\n\t\tsize: {\n\t\t\tbase: \"px-4 py-3\",\n\t\t\tsm: \"px-3 py-2\",\n\t\t},\n\t},\n\tdefaultVariants: { variant: \"default\", size: \"base\" },\n});\n\ntype BannerVariant = NonNullable<VariantProps<typeof bannerVariants>[\"variant\"]>;\ntype BannerSize = NonNullable<VariantProps<typeof bannerVariants>[\"size\"]>;\n\nconst BannerContext = createContext<{ variant: BannerVariant; size: BannerSize }>({\n\tvariant: \"default\",\n\tsize: \"base\",\n});\n\nexport interface BannerProps\n\textends Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\">,\n\t\tOmit<VariantProps<typeof bannerVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual tone variant of the banner.\n\t *\n\t * Note: Defaults to \"default\" (informational). Passing null falls back to \"default\".\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof bannerVariants>[\"variant\"];\n\n\t/**\n\t * Sizing preset controlling padding geometry and action placement.\n\t *\n\t * Note: Defaults to \"base\". In compact mode (\"sm\"), only direct `<Banner.Action>` elements\n\t * are placed in the trailing slot, while other action content renders inline next to the description.\n\t * Passing null falls back to \"base\".\n\t *\n\t * @default \"base\"\n\t */\n\tsize?: VariantProps<typeof bannerVariants>[\"size\"];\n\n\t/**\n\t * Primary heading text.\n\t *\n\t * Note: When present (or when description is present), structured mode is enabled\n\t * and standard children are not rendered.\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Secondary copy rendered below the title.\n\t */\n\tdescription?: ReactNode;\n\n\t/**\n\t * Visual icon rendered before the banner content.\n\t */\n\ticon?: ReactNode;\n\n\t/**\n\t * Trailing or inline call-to-action slot.\n\t * Pass `<Banner.Action>` elements for contextual styling.\n\t * In compact mode (\"sm\"), only direct `<Banner.Action>` elements are placed in the trailing slot,\n\t * while other action content renders inline next to the description.\n\t */\n\taction?: ReactNode;\n\n\t/**\n\t * Unstructured child content rendered only when both title and description are null or undefined.\n\t * When title or description is non-null/non-undefined (including empty string or false),\n\t * structured mode is active and children are ignored.\n\t */\n\tchildren?: HTMLAttributes<HTMLDivElement>[\"children\"];\n}\n\nexport interface BannerActionProps\n\textends Omit<\n\t\tButtonProps,\n\t\t\"variant\" | \"size\" | \"asChild\" | \"type\" | \"loading\" | \"icon\" | \"children\"\n\t> {\n\t/**\n\t * Visual style variant. Preserves \"ghost\" and \"secondary\"; all other values\n\t * are mapped contextually to \"destructive\" (when parent Banner variant is \"error\")\n\t * or \"default\".\n\t *\n\t * Note: Ordinary function component without forwarded ref.\n\t *\n\t * @default \"default\"\n\t */\n\tvariant?: ButtonProps[\"variant\"];\n\n\t/**\n\t * Sizing preset. When unspecified or null, resolves to \"icon\" if children are omitted,\n\t * null, or an empty string, \"sm\" when parent Banner is compact (\"sm\"), or \"default\" otherwise.\n\t * When iconOnly mode is resolved, an additional \"size-8\" class is attached.\n\t */\n\tsize?: ButtonProps[\"size\"];\n\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * @default false\n\t */\n\tasChild?: ButtonProps[\"asChild\"];\n\n\t/**\n\t * Button type attribute.\n\t *\n\t * @default \"button\"\n\t */\n\ttype?: ButtonProps[\"type\"];\n\n\t/**\n\t * Display loading spinner and disable interactions.\n\t *\n\t * @default false\n\t */\n\tloading?: ButtonProps[\"loading\"];\n\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: ButtonProps[\"icon\"];\n\n\t/**\n\t * Action label content. When null, undefined, or empty string, enables iconOnly sizing mode.\n\t */\n\tchildren?: ButtonProps[\"children\"];\n}\n\nfunction isBannerAction(node: ReactNode): boolean {\n\treturn isValidElement(node) && node.type === BannerAction;\n}\n\nfunction BannerRoot({\n\tclassName,\n\tvariant = \"default\",\n\tsize = \"base\",\n\ttitle,\n\tdescription,\n\ticon,\n\taction,\n\tchildren,\n\t...props\n}: BannerProps) {\n\tconst resolvedVariant = variant ?? \"default\";\n\tconst resolvedSize = size ?? \"base\";\n\tconst structured = title != null || description != null;\n\tconst nodes = Children.toArray(action);\n\tconst ctas = nodes.filter(isBannerAction);\n\tconst other = nodes.filter((node) => !isBannerAction(node));\n\tconst trailing = resolvedSize === \"sm\" ? ctas : [...other, ...ctas];\n\tconst inlineActions = resolvedSize === \"sm\" ? other : [];\n\n\treturn (\n\t\t<BannerContext.Provider value={{ variant: resolvedVariant, size: resolvedSize }}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\tbannerVariants({ variant: resolvedVariant, size: resolvedSize }),\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{icon ? <span className=\"mt-0.5 inline-flex shrink-0 [&_svg]:size-5\">{icon}</span> : null}\n\t\t\t\t<div className=\"min-w-0 flex-1 space-y-0.5\">\n\t\t\t\t\t{title ? <p className=\"font-medium\">{title}</p> : null}\n\t\t\t\t\t{description ? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\tresolvedVariant === \"secondary\" ? \"text-basalt-muted-foreground\" : \"text-current\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t{inlineActions.length > 0 ? <> {inlineActions}</> : null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : inlineActions.length > 0 ? (\n\t\t\t\t\t\t<div>{inlineActions}</div>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{structured ? null : children}\n\t\t\t\t</div>\n\t\t\t\t{trailing.length > 0 ? (\n\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-2\">{trailing}</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</BannerContext.Provider>\n\t);\n}\n\nexport function BannerAction({\n\tclassName,\n\tvariant = \"default\",\n\tsize,\n\ticon,\n\tchildren,\n\t...props\n}: BannerActionProps) {\n\tconst banner = useContext(BannerContext);\n\tconst mapped =\n\t\tvariant === \"ghost\"\n\t\t\t? \"ghost\"\n\t\t\t: variant === \"secondary\"\n\t\t\t\t? \"secondary\"\n\t\t\t\t: banner.variant === \"error\"\n\t\t\t\t\t? \"destructive\"\n\t\t\t\t\t: \"default\";\n\tconst iconOnly = children == null || children === \"\";\n\treturn (\n\t\t<Button\n\t\t\tvariant={mapped}\n\t\t\tsize={size ?? (iconOnly ? \"icon\" : banner.size === \"sm\" ? \"sm\" : \"default\")}\n\t\t\ticon={icon}\n\t\t\tclassName={cn(iconOnly && \"size-8\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t);\n}\nBannerAction.displayName = \"Banner.Action\";\n\nexport const Banner = Object.assign(BannerRoot, { Action: BannerAction });\n"],"mappings":";;;;;;;;AAaA,IAAM,IAAiB,EAAI,2DAA2D;CACrF,UAAU;EACT,SAAS;GACR,SAAS;GACT,OAAO;GACP,OAAO;GACP,WAAW;EACZ;EACA,MAAM;GACL,MAAM;GACN,IAAI;EACL;CACD;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAO;AACrD,CAAC,GAKK,IAAgB,EAA4D;CACjF,SAAS;CACT,MAAM;AACP,CAAC;AAkHD,SAAS,EAAe,GAA0B;CACjD,OAAO,EAAe,CAAI,KAAK,EAAK,SAAS;AAC9C;AAEA,SAAS,EAAW,EACnB,cACA,aAAU,WACV,UAAO,QACP,UACA,gBACA,SACA,WACA,aACA,GAAG,KACY;CACf,IAAM,IAAkB,KAAW,WAC7B,IAAe,KAAQ,QACvB,IAAa,KAAS,QAAQ,KAAe,MAC7C,IAAQ,EAAS,QAAQ,CAAM,GAC/B,IAAO,EAAM,OAAO,CAAc,GAClC,IAAQ,EAAM,QAAQ,MAAS,CAAC,EAAe,CAAI,CAAC,GACpD,IAAW,MAAiB,OAAO,IAAO,CAAC,GAAG,GAAO,GAAG,CAAI,GAC5D,IAAgB,MAAiB,OAAO,IAAQ,CAAC;CAEvD,OACC,kBAAC,EAAc,UAAf;EAAwB,OAAO;GAAE,SAAS;GAAiB,MAAM;EAAa;EAC7E,UAAA,kBAAC,OAAD;GACC,WAAW,EACV,GACA,EAAe;IAAE,SAAS;IAAiB,MAAM;GAAa,CAAC,GAC/D,CACD;GACA,GAAI;GANL,UAAA;IAQE,IAAO,kBAAC,QAAD;KAAM,WAAU;KAA8C,UAAA;IAAW,CAAA,IAAI;IACrF,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,IAAQ,kBAAC,KAAD;OAAG,WAAU;OAAe,UAAA;MAAS,CAAA,IAAI;MACjD,IACA,kBAAC,OAAD;OACC,WAAW,EACV,MAAoB,cAAc,iCAAiC,cACpE;OAHD,UAAA,CAKE,GACA,EAAc,SAAS,IAAI,kBAAA,GAAA,EAAA,UAAA,CAAE,KAAE,CAAgB,EAAA,CAAA,IAAI,IAChD;MACF,CAAA,IAAA,EAAc,SAAS,IAC1B,kBAAC,OAAD,EAAA,UAAM,EAAmB,CAAA,IACtB;MACH,IAAa,OAAO;KACjB;;IACJ,EAAS,SAAS,IAClB,kBAAC,OAAD;KAAK,WAAU;KAAoC,UAAA;IAAc,CAAA,IAC9D;GACA;;CACkB,CAAA;AAE1B;AAEA,SAAgB,EAAa,EAC5B,cACA,aAAU,WACV,SACA,SACA,aACA,GAAG,KACkB;CACrB,IAAM,IAAS,EAAW,CAAa,GACjC,IACL,MAAY,UACT,UACA,MAAY,cACX,cACA,EAAO,YAAY,UAClB,gBACA,WACA,IAAW,KAAY,QAAQ,MAAa;CAClD,OACC,kBAAC,GAAD;EACC,SAAS;EACT,MAAM,MAAS,IAAW,SAAS,EAAO,SAAS,OAAO,OAAO;EAC3D;EACN,WAAW,EAAG,KAAY,UAAU,CAAS;EAC7C,GAAI;EAEH;CACM,CAAA;AAEV;AACA,EAAa,cAAc;AAE3B,IAAa,IAAS,OAAO,OAAO,GAAY,EAAE,QAAQ,EAAa,CAAC"}
@@ -36,7 +36,7 @@ var l = a(`${t} inline-flex items-center justify-center gap-2 rounded-basalt-md
36
36
  let o = m, c = typeof o.type == "string" && o.type.toLowerCase() === "button", u = (e) => {
37
37
  e.preventDefault(), e.stopPropagation(), "stopImmediatePropagation" in e && typeof e.stopImmediatePropagation == "function" && e.stopImmediatePropagation();
38
38
  }, d = (e) => {
39
- e.key === "Enter" || e.key === " " || e.key === "Spacebar" ? (e.preventDefault(), e.stopPropagation(), typeof e.nativeEvent?.stopImmediatePropagation == "function" && e.nativeEvent.stopImmediatePropagation()) : (e.stopPropagation(), typeof e.nativeEvent?.stopImmediatePropagation == "function" && e.nativeEvent.stopImmediatePropagation());
39
+ (e.key === "Enter" || e.key === " " || e.key === "Spacebar") && e.preventDefault(), e.stopPropagation(), typeof e.nativeEvent?.stopImmediatePropagation == "function" && e.nativeEvent.stopImmediatePropagation();
40
40
  }, p = {
41
41
  onClick: u,
42
42
  onClickCapture: u,
@@ -56,28 +56,27 @@ var l = a(`${t} inline-flex items-center justify-center gap-2 rounded-basalt-md
56
56
  onPointerUpCapture: u,
57
57
  onAuxClick: u,
58
58
  onAuxClickCapture: u
59
- }, { disabled: h, ...v } = o.props, y = r.cloneElement(o, {
60
- ...v,
59
+ }, h = r.cloneElement(o, {
61
60
  ...p,
62
61
  ...c ? { disabled: !0 } : {},
63
62
  "aria-disabled": !0,
64
63
  "aria-busy": f ? !0 : void 0,
65
64
  tabIndex: -1
66
- }), b = {
65
+ }), v = {
67
66
  ...g,
68
67
  ...p,
69
68
  "aria-disabled": !0,
70
69
  "aria-busy": f ? "true" : void 0,
71
70
  tabIndex: -1
72
71
  };
73
- return c && (b.disabled = !0), /* @__PURE__ */ s(i, {
72
+ return c && (v.disabled = !0), /* @__PURE__ */ s(i, {
74
73
  className: e(l({
75
74
  variant: n,
76
75
  size: a
77
76
  }), t),
78
77
  ref: _,
79
- ...b,
80
- children: y
78
+ ...v,
79
+ children: h
81
80
  });
82
81
  }
83
82
  return /* @__PURE__ */ s(i, {
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} inline-flex items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90\",\n\t\t\t\tsecondary: \"bg-basalt-control text-basalt-foreground hover:bg-basalt-accent\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive/90\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border border-basalt-border bg-basalt-control hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-9 px-4 py-2\",\n\t\t\t\tsm: \"h-8 rounded-basalt-md px-3 text-xs\",\n\t\t\t\tlg: \"h-10 rounded-basalt-md px-6\",\n\t\t\t\ticon: \"h-9 w-9\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// For non-activation keys like Tab, suppress user handlers from running while preserving browser default navigation\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst { disabled: _ignoredChildDisabled, ...sanitizedProps } = childElement.props;\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...sanitizedProps,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":"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"}
1
+ {"version":3,"file":"button.js","names":[],"sources":["../../src/components/button.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nconst buttonVariants = cva(\n\t`${BASALT_UI_CLASS} inline-flex items-center justify-center gap-2 rounded-basalt-md text-sm font-medium transition-colors ${FOCUS_RING} disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0`,\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-basalt-primary text-basalt-primary-foreground hover:bg-basalt-primary/90\",\n\t\t\t\tsecondary: \"bg-basalt-control text-basalt-foreground hover:bg-basalt-accent\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-basalt-destructive text-basalt-destructive-foreground hover:bg-basalt-destructive/90\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border border-basalt-border bg-basalt-control hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tghost: \"hover:bg-basalt-accent hover:text-basalt-accent-foreground\",\n\t\t\t\tlink: \"text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-9 px-4 py-2\",\n\t\t\t\tsm: \"h-8 rounded-basalt-md px-3 text-xs\",\n\t\t\t\tlg: \"h-10 rounded-basalt-md px-6\",\n\t\t\t\ticon: \"h-9 w-9\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"type\">,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Pass control to child element slot.\n\t *\n\t * Note: Child element must forward props and ref in all states. When disabled or loading,\n\t * asChild suppresses click, keyboard activation (Enter/Space), and pointer handlers on both\n\t * child and parent while retaining browser default Tab navigation without trapping focus.\n\t * To preserve single DOM node layout and avoid unexpected child layout shifts, no internal\n\t * spinner is inserted in asChild loading mode; visual disabled state is expressed via aria-disabled.\n\t *\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Button type attribute.\n\t * @default \"button\"\n\t */\n\ttype?: React.ButtonHTMLAttributes<HTMLButtonElement>[\"type\"];\n\t/**\n\t * Display loading spinner and disable interactions.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvariant,\n\t\t\tsize,\n\t\t\tasChild = false,\n\t\t\ttype = \"button\",\n\t\t\tloading = false,\n\t\t\ticon,\n\t\t\tchildren,\n\t\t\tdisabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst isDisabled = Boolean(disabled || loading);\n\n\t\tif (asChild) {\n\t\t\tif (isDisabled && React.isValidElement(children)) {\n\t\t\t\tconst childElement = children as React.ReactElement<Record<string, unknown>>;\n\t\t\t\tconst isNativeButton =\n\t\t\t\t\ttypeof childElement.type === \"string\" && childElement.type.toLowerCase() === \"button\";\n\n\t\t\t\tconst blockActivationEvent = (event: React.SyntheticEvent | Event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (\n\t\t\t\t\t\t\"stopImmediatePropagation\" in event &&\n\t\t\t\t\t\ttypeof event.stopImmediatePropagation === \"function\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst handleKeyEvent = (event: React.KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \" || event.key === \"Spacebar\") {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tif (typeof event.nativeEvent?.stopImmediatePropagation === \"function\") {\n\t\t\t\t\t\tevent.nativeEvent.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst blockedHandlers = {\n\t\t\t\t\tonClick: blockActivationEvent,\n\t\t\t\t\tonClickCapture: blockActivationEvent,\n\t\t\t\t\tonKeyDown: handleKeyEvent,\n\t\t\t\t\tonKeyDownCapture: handleKeyEvent,\n\t\t\t\t\tonKeyUp: handleKeyEvent,\n\t\t\t\t\tonKeyUpCapture: handleKeyEvent,\n\t\t\t\t\tonKeyPress: handleKeyEvent,\n\t\t\t\t\tonKeyPressCapture: handleKeyEvent,\n\t\t\t\t\tonMouseDown: blockActivationEvent,\n\t\t\t\t\tonMouseDownCapture: blockActivationEvent,\n\t\t\t\t\tonMouseUp: blockActivationEvent,\n\t\t\t\t\tonMouseUpCapture: blockActivationEvent,\n\t\t\t\t\tonPointerDown: blockActivationEvent,\n\t\t\t\t\tonPointerDownCapture: blockActivationEvent,\n\t\t\t\t\tonPointerUp: blockActivationEvent,\n\t\t\t\t\tonPointerUpCapture: blockActivationEvent,\n\t\t\t\t\tonAuxClick: blockActivationEvent,\n\t\t\t\t\tonAuxClickCapture: blockActivationEvent,\n\t\t\t\t};\n\n\t\t\t\tconst sanitizedChild = React.cloneElement(childElement, {\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t...(isNativeButton ? { disabled: true } : {}),\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? true : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t});\n\n\t\t\t\tconst slotProps: Record<string, unknown> = {\n\t\t\t\t\t...props,\n\t\t\t\t\t...blockedHandlers,\n\t\t\t\t\t\"aria-disabled\": true,\n\t\t\t\t\t\"aria-busy\": loading ? \"true\" : undefined,\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t};\n\t\t\t\tif (isNativeButton) {\n\t\t\t\t\tslotProps.disabled = true;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Slot\n\t\t\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t{...slotProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t{sanitizedChild}\n\t\t\t\t\t</Slot>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<Slot className={cn(buttonVariants({ variant, size }), className)} ref={ref} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</Slot>\n\t\t\t);\n\t\t}\n\n\t\tconst iconNode = loading ? (\n\t\t\t<Loader2 className=\"animate-basalt-spin motion-reduce:animate-none\" aria-hidden=\"true\" />\n\t\t) : (\n\t\t\ticon\n\t\t);\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size }), className)}\n\t\t\t\tref={ref}\n\t\t\t\ttype={type}\n\t\t\t\tdisabled={isDisabled}\n\t\t\t\taria-busy={loading || undefined}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{iconNode}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t},\n);\nButton.displayName = \"Button\";\n\nexport interface LinkButtonProps\n\textends React.AnchorHTMLAttributes<HTMLAnchorElement>,\n\t\tOmit<VariantProps<typeof buttonVariants>, \"variant\" | \"size\"> {\n\t/**\n\t * Visual style variant.\n\t * @default \"default\"\n\t */\n\tvariant?: VariantProps<typeof buttonVariants>[\"variant\"];\n\t/**\n\t * Sizing preset.\n\t * @default \"default\"\n\t */\n\tsize?: VariantProps<typeof buttonVariants>[\"size\"];\n\t/**\n\t * Optional leading icon slot.\n\t */\n\ticon?: React.ReactNode;\n}\n\nexport const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>(\n\t({ className, variant, size, icon, children, ...props }, ref) => (\n\t\t<a ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props}>\n\t\t\t{icon}\n\t\t\t{children}\n\t\t</a>\n\t),\n);\nLinkButton.displayName = \"LinkButton\";\n\nexport { buttonVariants };\n"],"mappings":";;;;;;;;;;AAQA,IAAM,IAAiB,EACtB,GAAG,EAAgB,yGAAyG,EAAW,yIACvI;CACC,UAAU;EACT,SAAS;GACR,SAAS;GACT,WAAW;GACX,aACC;GACD,SACC;GACD,OAAO;GACP,MAAM;EACP;EACA,MAAM;GACL,SAAS;GACT,IAAI;GACJ,IAAI;GACJ,MAAM;EACP;CACD;CACA,iBAAiB;EAChB,SAAS;EACT,MAAM;CACP;AACD,CACD,GA2Ca,IAAS,EAAM,YAE1B,EACC,cACA,YACA,SACA,aAAU,IACV,UAAO,UACP,aAAU,IACV,SACA,aACA,aACA,GAAG,KAEJ,MACI;CACJ,IAAM,IAAa,GAAQ,KAAY;CAEvC,IAAI,GAAS;EACZ,IAAI,KAAc,EAAM,eAAe,CAAQ,GAAG;GACjD,IAAM,IAAe,GACf,IACL,OAAO,EAAa,QAAS,YAAY,EAAa,KAAK,YAAY,MAAM,UAExE,KAAwB,MAAwC;IAGrE,AAFA,EAAM,eAAe,GACrB,EAAM,gBAAgB,GAErB,8BAA8B,KAC9B,OAAO,EAAM,4BAA6B,cAE1C,EAAM,yBAAyB;GAEjC,GAEM,KAAkB,MAA+B;IAKtD,CAJI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OAAO,EAAM,QAAQ,eAC/D,EAAM,eAAe,GAEtB,EAAM,gBAAgB,GAClB,OAAO,EAAM,aAAa,4BAA6B,cAC1D,EAAM,YAAY,yBAAyB;GAE7C,GAEM,IAAkB;IACvB,SAAS;IACT,gBAAgB;IAChB,WAAW;IACX,kBAAkB;IAClB,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,mBAAmB;IACnB,aAAa;IACb,oBAAoB;IACpB,WAAW;IACX,kBAAkB;IAClB,eAAe;IACf,sBAAsB;IACtB,aAAa;IACb,oBAAoB;IACpB,YAAY;IACZ,mBAAmB;GACpB,GAEM,IAAiB,EAAM,aAAa,GAAc;IACvD,GAAG;IACH,GAAI,IAAiB,EAAE,UAAU,GAAK,IAAI,CAAC;IAC3C,iBAAiB;IACjB,aAAa,IAAU,KAAO,KAAA;IAC9B,UAAU;GACX,CAAC,GAEK,IAAqC;IAC1C,GAAG;IACH,GAAG;IACH,iBAAiB;IACjB,aAAa,IAAU,SAAS,KAAA;IAChC,UAAU;GACX;GAKA,OAJI,MACH,EAAU,WAAW,KAIrB,kBAAC,GAAD;IACC,WAAW,EAAG,EAAe;KAAE;KAAS;IAAK,CAAC,GAAG,CAAS;IACrD;IACL,GAAI;IAEH,UAAA;GACI,CAAA;EAER;EAEA,OACC,kBAAC,GAAD;GAAM,WAAW,EAAG,EAAe;IAAE;IAAS;GAAK,CAAC,GAAG,CAAS;GAAQ;GAAK,GAAI;GAC/E;EACI,CAAA;CAER;CAEA,IAAM,IAAW,IAChB,kBAAC,GAAD;EAAS,WAAU;EAAiD,eAAY;CAAQ,CAAA,IAExF;CAED,OACC,kBAAC,UAAD;EACC,WAAW,EAAG,EAAe;GAAE;GAAS;EAAK,CAAC,GAAG,CAAS;EACrD;EACC;EACN,UAAU;EACV,aAAW,KAAW,KAAA;EACtB,GAAI;EANL,UAAA,CAQE,GACA,CACM;;AAEV,CACD;AACA,EAAO,cAAc;AAqBrB,IAAa,IAAa,EAAM,YAC9B,EAAE,cAAW,YAAS,SAAM,SAAM,aAAU,GAAG,KAAS,MACxD,kBAAC,KAAD;CAAQ;CAAK,WAAW,EAAG,EAAe;EAAE;EAAS;CAAK,CAAC,GAAG,CAAS;CAAG,GAAI;CAA9E,UAAA,CACE,GACA,CACC;AAEL,CAAA,CAAA;AACA,EAAW,cAAc"}
@@ -13,8 +13,7 @@ function l({ disabled: l = !1, streaming: u = !1, label: d = "Message", placehol
13
13
  }, C = () => {
14
14
  let e = v.trim();
15
15
  !e || l || u || (p(e), y(""), requestAnimationFrame(() => {
16
- let e = b.current;
17
- e && (e.style.height = "0px", e.style.height = `${Math.min(e.scrollHeight, 160)}px`, e.focus());
16
+ S(), b.current?.focus();
18
17
  }));
19
18
  };
20
19
  return /* @__PURE__ */ s("form", {
@@ -1 +1 @@
1
- {"version":3,"file":"chat-composer.js","names":[],"sources":["../../src/components/chat-composer.tsx"],"sourcesContent":["import { ArrowUp, Square } from \"lucide-react\";\nimport { type FormEvent, type KeyboardEvent, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { InputArea } from \"./input-area\";\n\nexport interface ChatComposerProps {\n\t/**\n\t * Disable the field and send.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n\t/**\n\t * Replace send with stop. When streaming is true, the stop button renders and triggers onCancel.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Field accessible name.\n\t * @default \"Message\"\n\t */\n\tlabel?: string;\n\t/**\n\t * Placeholder when empty.\n\t */\n\tplaceholder?: string;\n\t/**\n\t * Called with trimmed text on send. Operates on internal draft state and does not wait for a Promise (caller manages asynchronous errors).\n\t */\n\tonSend: (text: string) => void;\n\t/**\n\t * Called when the stop control is pressed while streaming is active.\n\t */\n\tonCancel?: () => void;\n\t/**\n\t * Send control accessible name.\n\t * @default \"Send message\"\n\t */\n\tsendLabel?: string;\n\t/**\n\t * Stop control accessible name.\n\t * @default \"Stop generating\"\n\t */\n\tcancelLabel?: string;\n\t/**\n\t * Optional class name applied to the form container.\n\t * Component manages internal draft/height state and does not forward native form rest attributes or ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatComposer({\n\tdisabled = false,\n\tstreaming = false,\n\tlabel = \"Message\",\n\tplaceholder,\n\tonSend,\n\tonCancel,\n\tsendLabel = \"Send message\",\n\tcancelLabel = \"Stop generating\",\n\tclassName,\n}: ChatComposerProps) {\n\tconst [value, setValue] = useState(\"\");\n\tconst ref = useRef<HTMLTextAreaElement>(null);\n\tconst composingRef = useRef(false);\n\n\tconst resize = () => {\n\t\tconst el = ref.current;\n\t\tif (!el) {\n\t\t\treturn;\n\t\t}\n\t\tel.style.height = \"0px\";\n\t\tel.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n\t};\n\n\tconst submit = () => {\n\t\tconst text = value.trim();\n\t\tif (!text || disabled || streaming) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(text);\n\t\tsetValue(\"\");\n\t\trequestAnimationFrame(() => {\n\t\t\tconst el = ref.current;\n\t\t\tif (el) {\n\t\t\t\tel.style.height = \"0px\";\n\t\t\t\tel.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n\t\t\t\tel.focus();\n\t\t\t}\n\t\t});\n\t};\n\n\tconst onSubmit = (event: FormEvent) => {\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\tconst onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (composingRef.current || event.nativeEvent.isComposing) {\n\t\t\treturn;\n\t\t}\n\t\tif (event.key !== \"Enter\" || event.shiftKey) {\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\treturn (\n\t\t<form\n\t\t\tclassName={cn(\"border-t border-basalt-border/50 bg-basalt-card p-3\", className)}\n\t\t\tonSubmit={onSubmit}\n\t\t>\n\t\t\t<div className=\"flex items-end gap-2 rounded-2xl bg-basalt-secondary p-2 ring-1 ring-basalt-border/50\">\n\t\t\t\t<InputArea\n\t\t\t\t\tref={ref}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tsetValue(event.target.value);\n\t\t\t\t\t\trequestAnimationFrame(resize);\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionStart={() => {\n\t\t\t\t\t\tcomposingRef.current = true;\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionEnd={() => {\n\t\t\t\t\t\tcomposingRef.current = false;\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t\t\trows={1}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-label={label}\n\t\t\t\t\tclassName=\"max-h-40 min-h-[40px] flex-1 resize-none border-0 bg-transparent p-2 shadow-none ring-0\"\n\t\t\t\t/>\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\t\tdisabled={!onCancel}\n\t\t\t\t\t\taria-label={cancelLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Square className=\"h-3.5 w-3.5 fill-current\" strokeWidth={0} />\n\t\t\t\t\t</Button>\n\t\t\t\t) : (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tdisabled={disabled || !value.trim()}\n\t\t\t\t\t\taria-label={sendLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowUp className=\"h-4 w-4\" strokeWidth={2.25} />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n"],"mappings":";;;;;;;;AAmDA,SAAgB,EAAa,EAC5B,cAAW,IACX,eAAY,IACZ,WAAQ,WACR,gBACA,WACA,aACA,eAAY,gBACZ,iBAAc,mBACd,gBACqB;CACrB,IAAM,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,IAAM,EAA4B,IAAI,GACtC,IAAe,EAAO,EAAK,GAE3B,UAAe;EACpB,IAAM,IAAK,EAAI;EACV,MAGL,EAAG,MAAM,SAAS,OAClB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,GAAG,EAAE;CACrD,GAEM,UAAe;EACpB,IAAM,IAAO,EAAM,KAAK;EACpB,CAAC,KAAQ,KAAY,MAGzB,EAAO,CAAI,GACX,EAAS,EAAE,GACX,4BAA4B;GAC3B,IAAM,IAAK,EAAI;GACf,AAAI,MACH,EAAG,MAAM,SAAS,OAClB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,GAAG,EAAE,KACpD,EAAG,MAAM;EAEX,CAAC;CACF;CAkBA,OACC,kBAAC,QAAD;EACC,WAAW,EAAG,uDAAuD,CAAS;EACpE,WAnBM,MAAqB;GAEtC,AADA,EAAM,eAAe,GACrB,EAAO;EACR;EAkBE,UAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACC,kBAAC,GAAD;IACM;IACE;IACP,WAAW,MAAU;KAEpB,AADA,EAAS,EAAM,OAAO,KAAK,GAC3B,sBAAsB,CAAM;IAC7B;IACA,0BAA0B;KACzB,EAAa,UAAU;IACxB;IACA,wBAAwB;KACvB,EAAa,UAAU;IACxB;IACW,YA9BI,MAA8C;KAC5D,EAAa,WAAW,EAAM,YAAY,eAG1C,EAAM,QAAQ,WAAW,EAAM,aAGnC,EAAM,eAAe,GACrB,EAAO;IACR;IAsBI,MAAM;IACO;IACH;IACV,cAAY;IACZ,WAAU;GACV,CAAA,GACA,IACA,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,SAAQ;IACR,SAAS;IACT,UAAU,CAAC;IACX,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAQ,WAAU;KAA2B,aAAa;IAAI,CAAA;GACvD,CAAA,IAER,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,UAAU,KAAY,CAAC,EAAM,KAAK;IAClC,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAS,WAAU;KAAU,aAAa;IAAO,CAAA;GAC1C,CAAA,CAEL;;CACA,CAAA;AAER"}
1
+ {"version":3,"file":"chat-composer.js","names":[],"sources":["../../src/components/chat-composer.tsx"],"sourcesContent":["import { ArrowUp, Square } from \"lucide-react\";\nimport { type FormEvent, type KeyboardEvent, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { InputArea } from \"./input-area\";\n\nexport interface ChatComposerProps {\n\t/**\n\t * Disable the field and send.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n\t/**\n\t * Replace send with stop. When streaming is true, the stop button renders and triggers onCancel.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Field accessible name.\n\t * @default \"Message\"\n\t */\n\tlabel?: string;\n\t/**\n\t * Placeholder when empty.\n\t */\n\tplaceholder?: string;\n\t/**\n\t * Called with trimmed text on send. Operates on internal draft state and does not wait for a Promise (caller manages asynchronous errors).\n\t */\n\tonSend: (text: string) => void;\n\t/**\n\t * Called when the stop control is pressed while streaming is active.\n\t */\n\tonCancel?: () => void;\n\t/**\n\t * Send control accessible name.\n\t * @default \"Send message\"\n\t */\n\tsendLabel?: string;\n\t/**\n\t * Stop control accessible name.\n\t * @default \"Stop generating\"\n\t */\n\tcancelLabel?: string;\n\t/**\n\t * Optional class name applied to the form container.\n\t * Component manages internal draft/height state and does not forward native form rest attributes or ref.\n\t */\n\tclassName?: string;\n}\n\nexport function ChatComposer({\n\tdisabled = false,\n\tstreaming = false,\n\tlabel = \"Message\",\n\tplaceholder,\n\tonSend,\n\tonCancel,\n\tsendLabel = \"Send message\",\n\tcancelLabel = \"Stop generating\",\n\tclassName,\n}: ChatComposerProps) {\n\tconst [value, setValue] = useState(\"\");\n\tconst ref = useRef<HTMLTextAreaElement>(null);\n\tconst composingRef = useRef(false);\n\n\tconst resize = () => {\n\t\tconst el = ref.current;\n\t\tif (!el) {\n\t\t\treturn;\n\t\t}\n\t\tel.style.height = \"0px\";\n\t\tel.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n\t};\n\n\tconst submit = () => {\n\t\tconst text = value.trim();\n\t\tif (!text || disabled || streaming) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(text);\n\t\tsetValue(\"\");\n\t\trequestAnimationFrame(() => {\n\t\t\tresize();\n\t\t\tref.current?.focus();\n\t\t});\n\t};\n\n\tconst onSubmit = (event: FormEvent) => {\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\tconst onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (composingRef.current || event.nativeEvent.isComposing) {\n\t\t\treturn;\n\t\t}\n\t\tif (event.key !== \"Enter\" || event.shiftKey) {\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\treturn (\n\t\t<form\n\t\t\tclassName={cn(\"border-t border-basalt-border/50 bg-basalt-card p-3\", className)}\n\t\t\tonSubmit={onSubmit}\n\t\t>\n\t\t\t<div className=\"flex items-end gap-2 rounded-2xl bg-basalt-secondary p-2 ring-1 ring-basalt-border/50\">\n\t\t\t\t<InputArea\n\t\t\t\t\tref={ref}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tsetValue(event.target.value);\n\t\t\t\t\t\trequestAnimationFrame(resize);\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionStart={() => {\n\t\t\t\t\t\tcomposingRef.current = true;\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionEnd={() => {\n\t\t\t\t\t\tcomposingRef.current = false;\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t\t\trows={1}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-label={label}\n\t\t\t\t\tclassName=\"max-h-40 min-h-[40px] flex-1 resize-none border-0 bg-transparent p-2 shadow-none ring-0\"\n\t\t\t\t/>\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\t\tdisabled={!onCancel}\n\t\t\t\t\t\taria-label={cancelLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Square className=\"h-3.5 w-3.5 fill-current\" strokeWidth={0} />\n\t\t\t\t\t</Button>\n\t\t\t\t) : (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tdisabled={disabled || !value.trim()}\n\t\t\t\t\t\taria-label={sendLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowUp className=\"h-4 w-4\" strokeWidth={2.25} />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n"],"mappings":";;;;;;;;AAmDA,SAAgB,EAAa,EAC5B,cAAW,IACX,eAAY,IACZ,WAAQ,WACR,gBACA,WACA,aACA,eAAY,gBACZ,iBAAc,mBACd,gBACqB;CACrB,IAAM,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,IAAM,EAA4B,IAAI,GACtC,IAAe,EAAO,EAAK,GAE3B,UAAe;EACpB,IAAM,IAAK,EAAI;EACV,MAGL,EAAG,MAAM,SAAS,OAClB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,GAAG,EAAE;CACrD,GAEM,UAAe;EACpB,IAAM,IAAO,EAAM,KAAK;EACpB,CAAC,KAAQ,KAAY,MAGzB,EAAO,CAAI,GACX,EAAS,EAAE,GACX,4BAA4B;GAE3B,AADA,EAAO,GACP,EAAI,SAAS,MAAM;EACpB,CAAC;CACF;CAkBA,OACC,kBAAC,QAAD;EACC,WAAW,EAAG,uDAAuD,CAAS;EACpE,WAnBM,MAAqB;GAEtC,AADA,EAAM,eAAe,GACrB,EAAO;EACR;EAkBE,UAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACC,kBAAC,GAAD;IACM;IACE;IACP,WAAW,MAAU;KAEpB,AADA,EAAS,EAAM,OAAO,KAAK,GAC3B,sBAAsB,CAAM;IAC7B;IACA,0BAA0B;KACzB,EAAa,UAAU;IACxB;IACA,wBAAwB;KACvB,EAAa,UAAU;IACxB;IACW,YA9BI,MAA8C;KAC5D,EAAa,WAAW,EAAM,YAAY,eAG1C,EAAM,QAAQ,WAAW,EAAM,aAGnC,EAAM,eAAe,GACrB,EAAO;IACR;IAsBI,MAAM;IACO;IACH;IACV,cAAY;IACZ,WAAU;GACV,CAAA,GACA,IACA,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,SAAQ;IACR,SAAS;IACT,UAAU,CAAC;IACX,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAQ,WAAU;KAA2B,aAAa;IAAI,CAAA;GACvD,CAAA,IAER,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,UAAU,KAAY,CAAC,EAAM,KAAK;IAClC,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAS,WAAU;KAAU,aAAa;IAAO,CAAA;GAC1C,CAAA,CAEL;;CACA,CAAA;AAER"}
@@ -2,137 +2,105 @@
2
2
  import { cn as e } from "../utils/cn.js";
3
3
  import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
4
4
  import { FOCUS_RING as n } from "./overlay.js";
5
- import * as r from "react";
6
- import { Check as i, Minus as a } from "lucide-react";
7
- import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
- import * as c from "@radix-ui/react-checkbox";
5
+ import { useCheckableGroup as r } from "../utils/use-checkable-group.js";
6
+ import * as i from "react";
7
+ import { Check as a, Minus as o } from "lucide-react";
8
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
9
+ import * as l from "@radix-ui/react-checkbox";
9
10
  //#region src/components/checkbox.tsx
10
- var l = {
11
+ var u = {
11
12
  sm: "h-3 w-3",
12
13
  default: "h-4 w-4"
13
- }, u = {
14
+ }, d = {
14
15
  sm: "hidden h-3 w-3 group-data-[state=checked]:block",
15
16
  default: "hidden h-4 w-4 group-data-[state=checked]:block"
16
- }, d = {
17
+ }, f = {
17
18
  sm: "hidden h-2.5 w-2.5 group-data-[state=indeterminate]:block",
18
19
  default: "hidden h-3 w-3 group-data-[state=indeterminate]:block"
19
- }, f = r.createContext(null);
20
- function p(e, t, n) {
20
+ }, p = i.createContext(null);
21
+ function m(e, t, n) {
21
22
  return n ? e.includes(t) ? e : [...e, t] : e.filter((e) => e !== t);
22
23
  }
23
- var m = r.forwardRef(({ className: r, size: f = "default", ...p }, m) => /* @__PURE__ */ o(c.Root, {
24
+ var h = i.forwardRef(({ className: r, size: i = "default", ...p }, m) => /* @__PURE__ */ s(l.Root, {
24
25
  ref: m,
25
- className: e(t, "group peer shrink-0 rounded-[4px] border border-basalt-primary data-[state=checked]:bg-basalt-primary data-[state=checked]:text-basalt-primary-foreground data-[state=indeterminate]:bg-basalt-primary data-[state=indeterminate]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-50", l[f], n, r),
26
+ className: e(t, "group peer shrink-0 rounded-[4px] border border-basalt-primary data-[state=checked]:bg-basalt-primary data-[state=checked]:text-basalt-primary-foreground data-[state=indeterminate]:bg-basalt-primary data-[state=indeterminate]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-50", u[i], n, r),
26
27
  ...p,
27
- children: /* @__PURE__ */ s(c.Indicator, {
28
+ children: /* @__PURE__ */ c(l.Indicator, {
28
29
  className: "flex items-center justify-center text-current",
29
- children: [/* @__PURE__ */ o(i, { className: u[f] }), /* @__PURE__ */ o(a, { className: d[f] })]
30
+ children: [/* @__PURE__ */ s(a, { className: d[i] }), /* @__PURE__ */ s(o, { className: f[i] })]
30
31
  })
31
32
  }));
32
- m.displayName = c.Root.displayName;
33
- var h = r.forwardRef(({ className: t, value: n, defaultValue: i, onValueChange: a, error: c, disabled: l = !1, children: u, "aria-describedby": d, "aria-invalid": p, ...m }, h) => {
34
- let g = r.useId(), _ = r.useRef(null), [v, y] = r.useState(i ?? []), b = n ?? v, x = !!c, S = `${g}-error`, C = [x ? S : null, d].filter(Boolean).join(" ") || void 0, w = r.useRef(null), T = r.useCallback((e) => {
35
- let t = w.current;
36
- t && t.eventPhase !== Event.NONE || (n === void 0 && y(e), a?.(e));
37
- }, [a, n]), E = r.useCallback((e) => {
38
- if (_.current = e, h) {
39
- if (typeof h == "function") {
40
- let t = h(e);
41
- return typeof t == "function" ? () => {
42
- _.current = null, t();
43
- } : () => {
44
- _.current = null, h(null);
45
- };
46
- }
47
- return h.current = e, () => {
48
- _.current = null, h.current = null;
49
- };
50
- }
51
- }, [h]), D = m.form, O = r.useRef({
33
+ h.displayName = l.Root.displayName;
34
+ var g = i.forwardRef(({ className: t, value: n, defaultValue: i, onValueChange: a, error: o, disabled: l = !1, children: u, "aria-describedby": d, "aria-invalid": f, ...m }, h) => {
35
+ let g = r({
36
+ value: n,
52
37
  defaultValue: i,
53
- value: n
38
+ onValueChange: a,
39
+ error: o,
40
+ describedBy: d,
41
+ ariaInvalid: f,
42
+ form: m.form,
43
+ ref: h
54
44
  });
55
- return r.useEffect(() => {
56
- O.current = {
57
- defaultValue: i,
58
- value: n
59
- };
60
- }), r.useEffect(() => {
61
- let e = _.current?.form;
62
- if (!e || D && e.id !== D) return;
63
- let t = !1, n = /* @__PURE__ */ new Set(), r = (e) => {
64
- w.current = e;
65
- let r = setTimeout(() => {
66
- if (n.delete(r), t || e.defaultPrevented) return;
67
- let i = O.current;
68
- i.value === void 0 && y(i.defaultValue ?? []);
69
- }, 0);
70
- n.add(r);
71
- };
72
- return e.addEventListener("reset", r, !0), () => {
73
- t = !0, w.current = null;
74
- for (let e of n) clearTimeout(e);
75
- n.clear(), e.removeEventListener("reset", r, !0);
76
- };
77
- }, [D]), /* @__PURE__ */ o(f.Provider, {
45
+ return /* @__PURE__ */ s(p.Provider, {
78
46
  value: {
79
- value: b,
80
- setValue: T,
47
+ value: g.current,
48
+ setValue: g.setValue,
81
49
  disabled: l,
82
- invalid: x
50
+ invalid: g.invalid
83
51
  },
84
- children: /* @__PURE__ */ s("fieldset", {
85
- ref: E,
52
+ children: /* @__PURE__ */ c("fieldset", {
53
+ ref: g.setRefs,
86
54
  ...m,
87
55
  disabled: l,
88
- "aria-invalid": x ? !0 : p,
89
- "aria-describedby": C,
56
+ "aria-invalid": g.ariaInvalid,
57
+ "aria-describedby": g.mergedDescribedBy,
90
58
  className: e("flex flex-col gap-2", t),
91
- children: [u, x ? /* @__PURE__ */ o("p", {
92
- id: S,
59
+ children: [u, g.invalid ? /* @__PURE__ */ s("p", {
60
+ id: g.errorId,
93
61
  className: "text-xs text-basalt-destructive",
94
62
  role: "alert",
95
- children: c
63
+ children: o
96
64
  }) : null]
97
65
  })
98
66
  });
99
67
  });
100
- h.displayName = "Checkbox.Group";
101
- var g = r.forwardRef(({ className: t, ...n }, r) => /* @__PURE__ */ o("legend", {
68
+ g.displayName = "Checkbox.Group";
69
+ var _ = i.forwardRef(({ className: t, ...n }, r) => /* @__PURE__ */ s("legend", {
102
70
  ref: r,
103
71
  className: e("text-sm font-medium text-basalt-foreground", t),
104
72
  ...n
105
73
  }));
106
- g.displayName = "Checkbox.Legend";
107
- var _ = r.forwardRef(({ className: e, value: t, children: n, disabled: i, size: a, id: c, ...l }, u) => {
108
- let d = r.useContext(f), h = d != null, g = r.useId(), _ = c ?? g, v = h ? d.value.includes(t) : void 0, y = /* @__PURE__ */ o(m, {
74
+ _.displayName = "Checkbox.Legend";
75
+ var v = i.forwardRef(({ className: e, value: t, children: n, disabled: r, size: a, id: o, ...l }, u) => {
76
+ let d = i.useContext(p), f = d != null, g = i.useId(), _ = o ?? g, v = f ? d.value.includes(t) : void 0, y = /* @__PURE__ */ s(h, {
109
77
  ref: u,
110
78
  ...l,
111
79
  id: _,
112
80
  value: t,
113
81
  size: a,
114
82
  checked: v,
115
- defaultChecked: h ? v : void 0,
116
- disabled: i || d?.disabled,
83
+ defaultChecked: f ? v : void 0,
84
+ disabled: r || d?.disabled,
117
85
  "aria-invalid": d?.invalid || void 0,
118
86
  className: e,
119
87
  onCheckedChange: (e) => {
120
- h && typeof e == "boolean" && d.setValue(p(d.value, t, e));
88
+ f && typeof e == "boolean" && d.setValue(m(d.value, t, e));
121
89
  }
122
90
  });
123
- return n == null ? y : /* @__PURE__ */ s("label", {
91
+ return n == null ? y : /* @__PURE__ */ c("label", {
124
92
  htmlFor: _,
125
93
  className: "flex items-center gap-2 text-sm text-basalt-foreground",
126
94
  children: [y, n]
127
95
  });
128
96
  });
129
- _.displayName = "Checkbox.Item";
130
- var v = Object.assign(m, {
131
- Group: h,
132
- Legend: g,
133
- Item: _
97
+ v.displayName = "Checkbox.Item";
98
+ var y = Object.assign(h, {
99
+ Group: g,
100
+ Legend: _,
101
+ Item: v
134
102
  });
135
103
  //#endregion
136
- export { v as Checkbox };
104
+ export { y as Checkbox };
137
105
 
138
106
  //# sourceMappingURL=checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/components/checkbox.tsx"],"sourcesContent":["import * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { Check, Minus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { FOCUS_RING } from \"./overlay\";\n\nexport type CheckboxSize = \"sm\" | \"default\";\n\nconst CHECKBOX_SIZE_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"h-3 w-3\",\n\tdefault: \"h-4 w-4\",\n};\n\nconst CHECK_ICON_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"hidden h-3 w-3 group-data-[state=checked]:block\",\n\tdefault: \"hidden h-4 w-4 group-data-[state=checked]:block\",\n};\n\nconst MINUS_ICON_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"hidden h-2.5 w-2.5 group-data-[state=indeterminate]:block\",\n\tdefault: \"hidden h-3 w-3 group-data-[state=indeterminate]:block\",\n};\n\ntype CheckboxGroupContextValue = {\n\tvalue: string[];\n\tsetValue: (next: string[]) => void;\n\tdisabled: boolean;\n\tinvalid: boolean;\n};\n\nconst CheckboxGroupContext = React.createContext<CheckboxGroupContextValue | null>(null);\n\nfunction nextCheckboxGroupValue(current: string[], itemValue: string, checked: boolean): string[] {\n\tif (checked) {\n\t\treturn current.includes(itemValue) ? current : [...current, itemValue];\n\t}\n\treturn current.filter((entry) => entry !== itemValue);\n}\n\nexport type CheckboxProps = Omit<\n\tReact.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,\n\t\"checked\"\n> & {\n\t/**\n\t * The controlled checked state of the checkbox.\n\t */\n\tchecked?: boolean | \"indeterminate\";\n\t/**\n\t * The visual size of the checkbox.\n\t * @default default\n\t */\n\tsize?: CheckboxSize;\n};\n\nexport type CheckboxGroupProps = Omit<\n\tReact.ComponentPropsWithoutRef<\"fieldset\">,\n\t\"onChange\" | \"defaultValue\" | \"disabled\"\n> & {\n\t/**\n\t * The controlled selected values.\n\t */\n\tvalue?: string[];\n\t/**\n\t * The initially selected values.\n\t */\n\tdefaultValue?: string[];\n\t/**\n\t * Called when the selected values change.\n\t */\n\tonValueChange?: (value: string[]) => void;\n\t/**\n\t * Marks the group invalid and shows alert copy.\n\t */\n\terror?: React.ReactNode;\n\t/**\n\t * Disable every item in the group.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n};\n\nexport type CheckboxLegendProps = React.ComponentPropsWithoutRef<\"legend\">;\n\nexport type CheckboxItemProps = Omit<\n\tCheckboxProps,\n\t\"checked\" | \"defaultChecked\" | \"onCheckedChange\" | \"value\"\n> & {\n\t/**\n\t * The value stored in the group when this item is checked.\n\t */\n\tvalue: string;\n};\n\nconst CheckboxRoot = React.forwardRef<\n\tReact.ElementRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxProps\n>(({ className, size = \"default\", ...props }, ref) => (\n\t<CheckboxPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\tBASALT_UI_CLASS,\n\t\t\t\"group peer shrink-0 rounded-[4px] border border-basalt-primary data-[state=checked]:bg-basalt-primary data-[state=checked]:text-basalt-primary-foreground data-[state=indeterminate]:bg-basalt-primary data-[state=indeterminate]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tCHECKBOX_SIZE_CLASS[size],\n\t\t\tFOCUS_RING,\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<CheckboxPrimitive.Indicator className=\"flex items-center justify-center text-current\">\n\t\t\t<Check className={CHECK_ICON_CLASS[size]} />\n\t\t\t<Minus className={MINUS_ICON_CLASS[size]} />\n\t\t</CheckboxPrimitive.Indicator>\n\t</CheckboxPrimitive.Root>\n));\nCheckboxRoot.displayName = CheckboxPrimitive.Root.displayName;\n\nconst CheckboxGroup = React.forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tonValueChange,\n\t\t\terror,\n\t\t\tdisabled = false,\n\t\t\tchildren,\n\t\t\t\"aria-describedby\": describedBy,\n\t\t\t\"aria-invalid\": ariaInvalid,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst generatedId = React.useId();\n\t\tconst nodeRef = React.useRef<HTMLFieldSetElement | null>(null);\n\t\tconst [uncontrolled, setUncontrolled] = React.useState(defaultValue ?? []);\n\t\tconst current = value ?? uncontrolled;\n\t\tconst invalid = Boolean(error);\n\t\tconst errorId = `${generatedId}-error`;\n\t\tconst mergedDescribedBy =\n\t\t\t[invalid ? errorId : null, describedBy].filter(Boolean).join(\" \") || undefined;\n\t\tconst resetEventRef = React.useRef<Event | null>(null);\n\t\tconst setValue = React.useCallback(\n\t\t\t(next: string[]) => {\n\t\t\t\tconst activeReset = resetEventRef.current;\n\t\t\t\tif (activeReset && activeReset.eventPhase !== Event.NONE) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tsetUncontrolled(next);\n\t\t\t\t}\n\t\t\t\tonValueChange?.(next);\n\t\t\t},\n\t\t\t[onValueChange, value],\n\t\t);\n\t\tconst setRefs = React.useCallback(\n\t\t\t(node: HTMLFieldSetElement | null) => {\n\t\t\t\tnodeRef.current = node;\n\t\t\t\tif (!ref) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (typeof ref === \"function\") {\n\t\t\t\t\tconst cleanup = (ref as React.RefCallback<HTMLFieldSetElement>)(node);\n\t\t\t\t\tif (typeof cleanup === \"function\") {\n\t\t\t\t\t\treturn () => {\n\t\t\t\t\t\t\tnodeRef.current = null;\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tnodeRef.current = null;\n\t\t\t\t\t\tref(null);\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t(ref as React.RefObject<HTMLFieldSetElement | null>).current = node;\n\t\t\t\treturn () => {\n\t\t\t\t\tnodeRef.current = null;\n\t\t\t\t\t(ref as React.RefObject<HTMLFieldSetElement | null>).current = null;\n\t\t\t\t};\n\t\t\t},\n\t\t\t[ref],\n\t\t);\n\t\tconst formAttr = props.form;\n\t\tconst latestConfigRef = React.useRef({\n\t\t\tdefaultValue,\n\t\t\tvalue,\n\t\t});\n\t\tReact.useEffect(() => {\n\t\t\tlatestConfigRef.current = {\n\t\t\t\tdefaultValue,\n\t\t\t\tvalue,\n\t\t\t};\n\t\t});\n\n\t\tReact.useEffect(() => {\n\t\t\tconst form = nodeRef.current?.form;\n\t\t\tif (!form || (formAttr && form.id !== formAttr)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet disposed = false;\n\t\t\tconst timers = new Set<ReturnType<typeof setTimeout>>();\n\t\t\tconst onReset = (event: Event) => {\n\t\t\t\tresetEventRef.current = event;\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\ttimers.delete(timer);\n\t\t\t\t\tif (disposed || event.defaultPrevented) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst cfg = latestConfigRef.current;\n\t\t\t\t\tif (cfg.value === undefined) {\n\t\t\t\t\t\tsetUncontrolled(cfg.defaultValue ?? []);\n\t\t\t\t\t}\n\t\t\t\t}, 0);\n\t\t\t\ttimers.add(timer);\n\t\t\t};\n\t\t\tform.addEventListener(\"reset\", onReset, true);\n\t\t\treturn () => {\n\t\t\t\tdisposed = true;\n\t\t\t\tresetEventRef.current = null;\n\t\t\t\tfor (const timer of timers) {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t}\n\t\t\t\ttimers.clear();\n\t\t\t\tform.removeEventListener(\"reset\", onReset, true);\n\t\t\t};\n\t\t}, [formAttr]);\n\t\treturn (\n\t\t\t<CheckboxGroupContext.Provider value={{ value: current, setValue, disabled, invalid }}>\n\t\t\t\t<fieldset\n\t\t\t\t\tref={setRefs}\n\t\t\t\t\t{...props}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-invalid={invalid ? true : ariaInvalid}\n\t\t\t\t\taria-describedby={mergedDescribedBy}\n\t\t\t\t\tclassName={cn(\"flex flex-col gap-2\", className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t\t{invalid ? (\n\t\t\t\t\t\t<p id={errorId} className=\"text-xs text-basalt-destructive\" role=\"alert\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t</fieldset>\n\t\t\t</CheckboxGroupContext.Provider>\n\t\t);\n\t},\n);\nCheckboxGroup.displayName = \"Checkbox.Group\";\n\nconst CheckboxLegend = React.forwardRef<HTMLLegendElement, CheckboxLegendProps>(\n\t({ className, ...props }, ref) => (\n\t\t<legend\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"text-sm font-medium text-basalt-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCheckboxLegend.displayName = \"Checkbox.Legend\";\n\nconst CheckboxItem = React.forwardRef<\n\tReact.ElementRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxItemProps\n>(({ className, value, children, disabled, size, id, ...props }, ref) => {\n\tconst group = React.useContext(CheckboxGroupContext);\n\tconst grouped = group != null;\n\tconst generatedId = React.useId();\n\tconst controlId = id ?? generatedId;\n\tconst isChecked = grouped ? group.value.includes(value) : undefined;\n\tconst box = (\n\t\t<CheckboxRoot\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t\tid={controlId}\n\t\t\tvalue={value}\n\t\t\tsize={size}\n\t\t\tchecked={isChecked}\n\t\t\tdefaultChecked={grouped ? isChecked : undefined}\n\t\t\tdisabled={disabled || group?.disabled}\n\t\t\taria-invalid={group?.invalid || undefined}\n\t\t\tclassName={className}\n\t\t\tonCheckedChange={(next) => {\n\t\t\t\tif (grouped && typeof next === \"boolean\") {\n\t\t\t\t\tgroup.setValue(nextCheckboxGroupValue(group.value, value, next));\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n\tif (children == null) {\n\t\treturn box;\n\t}\n\treturn (\n\t\t<label htmlFor={controlId} className=\"flex items-center gap-2 text-sm text-basalt-foreground\">\n\t\t\t{box}\n\t\t\t{children}\n\t\t</label>\n\t);\n});\nCheckboxItem.displayName = \"Checkbox.Item\";\n\nexport const Checkbox = Object.assign(CheckboxRoot, {\n\tGroup: CheckboxGroup,\n\tLegend: CheckboxLegend,\n\tItem: CheckboxItem,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/components/checkbox.tsx"],"sourcesContent":["import * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { Check, Minus } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { useCheckableGroup } from \"../utils/use-checkable-group\";\nimport { FOCUS_RING } from \"./overlay\";\n\nexport type CheckboxSize = \"sm\" | \"default\";\n\nconst CHECKBOX_SIZE_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"h-3 w-3\",\n\tdefault: \"h-4 w-4\",\n};\n\nconst CHECK_ICON_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"hidden h-3 w-3 group-data-[state=checked]:block\",\n\tdefault: \"hidden h-4 w-4 group-data-[state=checked]:block\",\n};\n\nconst MINUS_ICON_CLASS: Record<CheckboxSize, string> = {\n\tsm: \"hidden h-2.5 w-2.5 group-data-[state=indeterminate]:block\",\n\tdefault: \"hidden h-3 w-3 group-data-[state=indeterminate]:block\",\n};\n\ntype CheckboxGroupContextValue = {\n\tvalue: string[];\n\tsetValue: (next: string[]) => void;\n\tdisabled: boolean;\n\tinvalid: boolean;\n};\n\nconst CheckboxGroupContext = React.createContext<CheckboxGroupContextValue | null>(null);\n\nfunction nextCheckboxGroupValue(current: string[], itemValue: string, checked: boolean): string[] {\n\tif (checked) {\n\t\treturn current.includes(itemValue) ? current : [...current, itemValue];\n\t}\n\treturn current.filter((entry) => entry !== itemValue);\n}\n\nexport type CheckboxProps = Omit<\n\tReact.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,\n\t\"checked\"\n> & {\n\t/**\n\t * The controlled checked state of the checkbox.\n\t */\n\tchecked?: boolean | \"indeterminate\";\n\t/**\n\t * The visual size of the checkbox.\n\t * @default default\n\t */\n\tsize?: CheckboxSize;\n};\n\nexport type CheckboxGroupProps = Omit<\n\tReact.ComponentPropsWithoutRef<\"fieldset\">,\n\t\"onChange\" | \"defaultValue\" | \"disabled\"\n> & {\n\t/**\n\t * The controlled selected values.\n\t */\n\tvalue?: string[];\n\t/**\n\t * The initially selected values.\n\t */\n\tdefaultValue?: string[];\n\t/**\n\t * Called when the selected values change.\n\t */\n\tonValueChange?: (value: string[]) => void;\n\t/**\n\t * Marks the group invalid and shows alert copy.\n\t */\n\terror?: React.ReactNode;\n\t/**\n\t * Disable every item in the group.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n};\n\nexport type CheckboxLegendProps = React.ComponentPropsWithoutRef<\"legend\">;\n\nexport type CheckboxItemProps = Omit<\n\tCheckboxProps,\n\t\"checked\" | \"defaultChecked\" | \"onCheckedChange\" | \"value\"\n> & {\n\t/**\n\t * The value stored in the group when this item is checked.\n\t */\n\tvalue: string;\n};\n\nconst CheckboxRoot = React.forwardRef<\n\tReact.ElementRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxProps\n>(({ className, size = \"default\", ...props }, ref) => (\n\t<CheckboxPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\tBASALT_UI_CLASS,\n\t\t\t\"group peer shrink-0 rounded-[4px] border border-basalt-primary data-[state=checked]:bg-basalt-primary data-[state=checked]:text-basalt-primary-foreground data-[state=indeterminate]:bg-basalt-primary data-[state=indeterminate]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tCHECKBOX_SIZE_CLASS[size],\n\t\t\tFOCUS_RING,\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<CheckboxPrimitive.Indicator className=\"flex items-center justify-center text-current\">\n\t\t\t<Check className={CHECK_ICON_CLASS[size]} />\n\t\t\t<Minus className={MINUS_ICON_CLASS[size]} />\n\t\t</CheckboxPrimitive.Indicator>\n\t</CheckboxPrimitive.Root>\n));\nCheckboxRoot.displayName = CheckboxPrimitive.Root.displayName;\n\nconst CheckboxGroup = React.forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tonValueChange,\n\t\t\terror,\n\t\t\tdisabled = false,\n\t\t\tchildren,\n\t\t\t\"aria-describedby\": describedBy,\n\t\t\t\"aria-invalid\": ariaInvalid,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst group = useCheckableGroup({\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tonValueChange,\n\t\t\terror,\n\t\t\tdescribedBy,\n\t\t\tariaInvalid,\n\t\t\tform: props.form,\n\t\t\tref,\n\t\t});\n\t\treturn (\n\t\t\t<CheckboxGroupContext.Provider\n\t\t\t\tvalue={{ value: group.current, setValue: group.setValue, disabled, invalid: group.invalid }}\n\t\t\t>\n\t\t\t\t<fieldset\n\t\t\t\t\tref={group.setRefs}\n\t\t\t\t\t{...props}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-invalid={group.ariaInvalid}\n\t\t\t\t\taria-describedby={group.mergedDescribedBy}\n\t\t\t\t\tclassName={cn(\"flex flex-col gap-2\", className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t\t{group.invalid ? (\n\t\t\t\t\t\t<p id={group.errorId} className=\"text-xs text-basalt-destructive\" role=\"alert\">\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t) : null}\n\t\t\t\t</fieldset>\n\t\t\t</CheckboxGroupContext.Provider>\n\t\t);\n\t},\n);\nCheckboxGroup.displayName = \"Checkbox.Group\";\n\nconst CheckboxLegend = React.forwardRef<HTMLLegendElement, CheckboxLegendProps>(\n\t({ className, ...props }, ref) => (\n\t\t<legend\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"text-sm font-medium text-basalt-foreground\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCheckboxLegend.displayName = \"Checkbox.Legend\";\n\nconst CheckboxItem = React.forwardRef<\n\tReact.ElementRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxItemProps\n>(({ className, value, children, disabled, size, id, ...props }, ref) => {\n\tconst group = React.useContext(CheckboxGroupContext);\n\tconst grouped = group != null;\n\tconst generatedId = React.useId();\n\tconst controlId = id ?? generatedId;\n\tconst isChecked = grouped ? group.value.includes(value) : undefined;\n\tconst box = (\n\t\t<CheckboxRoot\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t\tid={controlId}\n\t\t\tvalue={value}\n\t\t\tsize={size}\n\t\t\tchecked={isChecked}\n\t\t\tdefaultChecked={grouped ? isChecked : undefined}\n\t\t\tdisabled={disabled || group?.disabled}\n\t\t\taria-invalid={group?.invalid || undefined}\n\t\t\tclassName={className}\n\t\t\tonCheckedChange={(next) => {\n\t\t\t\tif (grouped && typeof next === \"boolean\") {\n\t\t\t\t\tgroup.setValue(nextCheckboxGroupValue(group.value, value, next));\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n\tif (children == null) {\n\t\treturn box;\n\t}\n\treturn (\n\t\t<label htmlFor={controlId} className=\"flex items-center gap-2 text-sm text-basalt-foreground\">\n\t\t\t{box}\n\t\t\t{children}\n\t\t</label>\n\t);\n});\nCheckboxItem.displayName = \"Checkbox.Item\";\n\nexport const Checkbox = Object.assign(CheckboxRoot, {\n\tGroup: CheckboxGroup,\n\tLegend: CheckboxLegend,\n\tItem: CheckboxItem,\n});\n"],"mappings":";;;;;;;;;;AAUA,IAAM,IAAoD;CACzD,IAAI;CACJ,SAAS;AACV,GAEM,IAAiD;CACtD,IAAI;CACJ,SAAS;AACV,GAEM,IAAiD;CACtD,IAAI;CACJ,SAAS;AACV,GASM,IAAuB,EAAM,cAAgD,IAAI;AAEvF,SAAS,EAAuB,GAAmB,GAAmB,GAA4B;CAIjG,OAHI,IACI,EAAQ,SAAS,CAAS,IAAI,IAAU,CAAC,GAAG,GAAS,CAAS,IAE/D,EAAQ,QAAQ,MAAU,MAAU,CAAS;AACrD;AAwDA,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,UAAO,WAAW,GAAG,KAAS,MAC7C,kBAAC,EAAkB,MAAnB;CACM;CACL,WAAW,EACV,GACA,oTACA,EAAoB,IACpB,GACA,CACD;CACA,GAAI;CAEJ,UAAA,kBAAC,EAAkB,WAAnB;EAA6B,WAAU;EAAvC,UAAA,CACC,kBAAC,GAAD,EAAO,WAAW,EAAiB,GAAQ,CAAA,GAC3C,kBAAC,GAAD,EAAO,WAAW,EAAiB,GAAQ,CAAA,CACf;;AACN,CAAA,CACxB;AACD,EAAa,cAAc,EAAkB,KAAK;AAElD,IAAM,IAAgB,EAAM,YAE1B,EACC,cACA,UACA,iBACA,kBACA,UACA,cAAW,IACX,aACA,oBAAoB,GACpB,gBAAgB,GAChB,GAAG,KAEJ,MACI;CACJ,IAAM,IAAQ,EAAkB;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,EAAM;EACZ;CACD,CAAC;CACD,OACC,kBAAC,EAAqB,UAAtB;EACC,OAAO;GAAE,OAAO,EAAM;GAAS,UAAU,EAAM;GAAU;GAAU,SAAS,EAAM;EAAQ;EAE1F,UAAA,kBAAC,YAAD;GACC,KAAK,EAAM;GACX,GAAI;GACM;GACV,gBAAc,EAAM;GACpB,oBAAkB,EAAM;GACxB,WAAW,EAAG,uBAAuB,CAAS;GAN/C,UAAA,CAQE,GACA,EAAM,UACN,kBAAC,KAAD;IAAG,IAAI,EAAM;IAAS,WAAU;IAAkC,MAAK;IACrE,UAAA;GACC,CAAA,IACA,IACK;;CACoB,CAAA;AAEjC,CACD;AACA,EAAc,cAAc;AAE5B,IAAM,IAAiB,EAAM,YAC3B,EAAE,cAAW,GAAG,KAAS,MACzB,kBAAC,UAAD;CACM;CACL,WAAW,EAAG,8CAA8C,CAAS;CACrE,GAAI;AACJ,CAAA,CAEH;AACA,EAAe,cAAc;AAE7B,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,UAAO,aAAU,aAAU,SAAM,OAAI,GAAG,KAAS,MAAQ;CACxE,IAAM,IAAQ,EAAM,WAAW,CAAoB,GAC7C,IAAU,KAAS,MACnB,IAAc,EAAM,MAAM,GAC1B,IAAY,KAAM,GAClB,IAAY,IAAU,EAAM,MAAM,SAAS,CAAK,IAAI,KAAA,GACpD,IACL,kBAAC,GAAD;EACM;EACL,GAAI;EACJ,IAAI;EACG;EACD;EACN,SAAS;EACT,gBAAgB,IAAU,IAAY,KAAA;EACtC,UAAU,KAAY,GAAO;EAC7B,gBAAc,GAAO,WAAW,KAAA;EACrB;EACX,kBAAkB,MAAS;GAC1B,AAAI,KAAW,OAAO,KAAS,aAC9B,EAAM,SAAS,EAAuB,EAAM,OAAO,GAAO,CAAI,CAAC;EAEjE;CACA,CAAA;CAKF,OAHI,KAAY,OACR,IAGP,kBAAC,SAAD;EAAO,SAAS;EAAW,WAAU;EAArC,UAAA,CACE,GACA,CACK;;AAET,CAAC;AACD,EAAa,cAAc;AAE3B,IAAa,IAAW,OAAO,OAAO,GAAc;CACnD,OAAO;CACP,QAAQ;CACR,MAAM;AACP,CAAC"}
@@ -9,7 +9,7 @@ function i(e) {
9
9
  for (let o of e.matchAll(r)) {
10
10
  let r = o.index ?? 0;
11
11
  r > i && t.push(e.slice(i, r));
12
- let s = o[1] ? "text-basalt-muted-foreground" : o[2] ? "text-basalt-chart-5" : o[3] ? "text-basalt-primary" : o[4] ? "text-basalt-chart-4" : "text-basalt-primary";
12
+ let s = o[1] ? "text-basalt-muted-foreground" : o[2] ? "text-basalt-chart-5" : o[4] ? "text-basalt-chart-4" : "text-basalt-primary";
13
13
  t.push(/* @__PURE__ */ n("span", {
14
14
  className: s,
15
15
  children: o[0]
@@ -1 +1 @@
1
- {"version":3,"file":"code.js","names":[],"sources":["../../src/components/code.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\n\nconst TOKEN =\n\t/(\\/\\/[^\\n]*)|(\"[^\"]*\"|'[^']*'|`[^`]*`)|\\b(import|from|export|default|async|await|function|return|const|let|var|type|interface|as|if|else|throw|new|typeof)\\b|(\\b\\d+\\b)|(<\\/?[A-Za-z][\\w.-]*)/g;\n\nfunction highlight(code: string): ReactNode[] {\n\tconst nodes: ReactNode[] = [];\n\tlet last = 0;\n\tlet key = 0;\n\tfor (const match of code.matchAll(TOKEN)) {\n\t\tconst index = match.index ?? 0;\n\t\tif (index > last) {\n\t\t\tnodes.push(code.slice(last, index));\n\t\t}\n\t\tconst className = match[1]\n\t\t\t? \"text-basalt-muted-foreground\"\n\t\t\t: match[2]\n\t\t\t\t? \"text-basalt-chart-5\"\n\t\t\t\t: match[3]\n\t\t\t\t\t? \"text-basalt-primary\"\n\t\t\t\t\t: match[4]\n\t\t\t\t\t\t? \"text-basalt-chart-4\"\n\t\t\t\t\t\t: \"text-basalt-primary\";\n\t\tnodes.push(\n\t\t\t<span key={key} className={className}>\n\t\t\t\t{match[0]}\n\t\t\t</span>,\n\t\t);\n\t\tkey += 1;\n\t\tlast = index + match[0].length;\n\t}\n\tif (last < code.length) {\n\t\tnodes.push(code.slice(last));\n\t}\n\treturn nodes;\n}\n\nexport type CodeProps = {\n\t/**\n\t * Additional classes for the inline code.\n\t */\n\tclassName?: string;\n};\n\nexport function Code({ className, ...props }: CodeProps & HTMLAttributes<HTMLElement>) {\n\treturn (\n\t\t<code\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-basalt-sm bg-basalt-secondary px-1.5 py-0.5 font-mono text-[13px] text-basalt-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type CodeBlockProps = {\n\t/**\n\t * Additional classes for the block.\n\t */\n\tclassName?: string;\n};\n\nexport function CodeBlock({\n\tclassName,\n\t...props\n}: CodeBlockProps & HTMLAttributes<HTMLPreElement>) {\n\treturn (\n\t\t<pre\n\t\t\tclassName={controlSurfaceClass(\n\t\t\t\tcn(\"overflow-x-auto p-4 font-mono text-basalt-foreground\", className),\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type CodeHighlightedProps = {\n\t/**\n\t * Source text to highlight.\n\t */\n\tcode: string;\n\t/**\n\t * Additional classes for the block.\n\t */\n\tclassName?: string;\n};\n\nexport function CodeHighlighted({\n\tcode,\n\tclassName,\n\t...props\n}: CodeHighlightedProps & HTMLAttributes<HTMLPreElement>) {\n\treturn (\n\t\t<pre\n\t\t\tclassName={controlSurfaceClass(cn(\"overflow-x-auto p-4 text-basalt-foreground\", className))}\n\t\t\t{...props}\n\t\t>\n\t\t\t<code className=\"font-mono leading-6\">{highlight(code)}</code>\n\t\t</pre>\n\t);\n}\n"],"mappings":";;;;;AAIA,IAAM,IACL;AAED,SAAS,EAAU,GAA2B;CAC7C,IAAM,IAAqB,CAAC,GACxB,IAAO,GACP,IAAM;CACV,KAAK,IAAM,KAAS,EAAK,SAAS,CAAK,GAAG;EACzC,IAAM,IAAQ,EAAM,SAAS;EAC7B,AAAI,IAAQ,KACX,EAAM,KAAK,EAAK,MAAM,GAAM,CAAK,CAAC;EAEnC,IAAM,IAAY,EAAM,KACrB,iCACA,EAAM,KACL,wBACA,EAAM,KACL,wBACA,EAAM,KACL,wBACA;EAON,AANA,EAAM,KACL,kBAAC,QAAD;GAA2B;GACzB,UAAA,EAAM;EACF,GAFK,CAEL,CACP,GACA,KAAO,GACP,IAAO,IAAQ,EAAM,EAAE,CAAC;CACzB;CAIA,OAHI,IAAO,EAAK,UACf,EAAM,KAAK,EAAK,MAAM,CAAI,CAAC,GAErB;AACR;AASA,SAAgB,EAAK,EAAE,cAAW,GAAG,KAAkD;CACtF,OACC,kBAAC,QAAD;EACC,WAAW,EACV,oGACA,CACD;EACA,GAAI;CACJ,CAAA;AAEH;AASA,SAAgB,EAAU,EACzB,cACA,GAAG,KACgD;CACnD,OACC,kBAAC,OAAD;EACC,WAAW,EACV,EAAG,wDAAwD,CAAS,CACrE;EACA,GAAI;CACJ,CAAA;AAEH;AAaA,SAAgB,EAAgB,EAC/B,SACA,cACA,GAAG,KACsD;CACzD,OACC,kBAAC,OAAD;EACC,WAAW,EAAoB,EAAG,8CAA8C,CAAS,CAAC;EAC1F,GAAI;EAEJ,UAAA,kBAAC,QAAD;GAAM,WAAU;GAAuB,UAAA,EAAU,CAAI;EAAQ,CAAA;CACzD,CAAA;AAEP"}
1
+ {"version":3,"file":"code.js","names":[],"sources":["../../src/components/code.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\n\nconst TOKEN =\n\t/(\\/\\/[^\\n]*)|(\"[^\"]*\"|'[^']*'|`[^`]*`)|\\b(import|from|export|default|async|await|function|return|const|let|var|type|interface|as|if|else|throw|new|typeof)\\b|(\\b\\d+\\b)|(<\\/?[A-Za-z][\\w.-]*)/g;\n\nfunction highlight(code: string): ReactNode[] {\n\tconst nodes: ReactNode[] = [];\n\tlet last = 0;\n\tlet key = 0;\n\tfor (const match of code.matchAll(TOKEN)) {\n\t\tconst index = match.index ?? 0;\n\t\tif (index > last) {\n\t\t\tnodes.push(code.slice(last, index));\n\t\t}\n\t\tconst className = match[1]\n\t\t\t? \"text-basalt-muted-foreground\"\n\t\t\t: match[2]\n\t\t\t\t? \"text-basalt-chart-5\"\n\t\t\t\t: match[4]\n\t\t\t\t\t? \"text-basalt-chart-4\"\n\t\t\t\t\t: \"text-basalt-primary\";\n\t\tnodes.push(\n\t\t\t<span key={key} className={className}>\n\t\t\t\t{match[0]}\n\t\t\t</span>,\n\t\t);\n\t\tkey += 1;\n\t\tlast = index + match[0].length;\n\t}\n\tif (last < code.length) {\n\t\tnodes.push(code.slice(last));\n\t}\n\treturn nodes;\n}\n\nexport type CodeProps = {\n\t/**\n\t * Additional classes for the inline code.\n\t */\n\tclassName?: string;\n};\n\nexport function Code({ className, ...props }: CodeProps & HTMLAttributes<HTMLElement>) {\n\treturn (\n\t\t<code\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-basalt-sm bg-basalt-secondary px-1.5 py-0.5 font-mono text-[13px] text-basalt-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type CodeBlockProps = {\n\t/**\n\t * Additional classes for the block.\n\t */\n\tclassName?: string;\n};\n\nexport function CodeBlock({\n\tclassName,\n\t...props\n}: CodeBlockProps & HTMLAttributes<HTMLPreElement>) {\n\treturn (\n\t\t<pre\n\t\t\tclassName={controlSurfaceClass(\n\t\t\t\tcn(\"overflow-x-auto p-4 font-mono text-basalt-foreground\", className),\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport type CodeHighlightedProps = {\n\t/**\n\t * Source text to highlight.\n\t */\n\tcode: string;\n\t/**\n\t * Additional classes for the block.\n\t */\n\tclassName?: string;\n};\n\nexport function CodeHighlighted({\n\tcode,\n\tclassName,\n\t...props\n}: CodeHighlightedProps & HTMLAttributes<HTMLPreElement>) {\n\treturn (\n\t\t<pre\n\t\t\tclassName={controlSurfaceClass(cn(\"overflow-x-auto p-4 text-basalt-foreground\", className))}\n\t\t\t{...props}\n\t\t>\n\t\t\t<code className=\"font-mono leading-6\">{highlight(code)}</code>\n\t\t</pre>\n\t);\n}\n"],"mappings":";;;;;AAIA,IAAM,IACL;AAED,SAAS,EAAU,GAA2B;CAC7C,IAAM,IAAqB,CAAC,GACxB,IAAO,GACP,IAAM;CACV,KAAK,IAAM,KAAS,EAAK,SAAS,CAAK,GAAG;EACzC,IAAM,IAAQ,EAAM,SAAS;EAC7B,AAAI,IAAQ,KACX,EAAM,KAAK,EAAK,MAAM,GAAM,CAAK,CAAC;EAEnC,IAAM,IAAY,EAAM,KACrB,iCACA,EAAM,KACL,wBACA,EAAM,KACL,wBACA;EAOL,AANA,EAAM,KACL,kBAAC,QAAD;GAA2B;GACzB,UAAA,EAAM;EACF,GAFK,CAEL,CACP,GACA,KAAO,GACP,IAAO,IAAQ,EAAM,EAAE,CAAC;CACzB;CAIA,OAHI,IAAO,EAAK,UACf,EAAM,KAAK,EAAK,MAAM,CAAI,CAAC,GAErB;AACR;AASA,SAAgB,EAAK,EAAE,cAAW,GAAG,KAAkD;CACtF,OACC,kBAAC,QAAD;EACC,WAAW,EACV,oGACA,CACD;EACA,GAAI;CACJ,CAAA;AAEH;AASA,SAAgB,EAAU,EACzB,cACA,GAAG,KACgD;CACnD,OACC,kBAAC,OAAD;EACC,WAAW,EACV,EAAG,wDAAwD,CAAS,CACrE;EACA,GAAI;CACJ,CAAA;AAEH;AAaA,SAAgB,EAAgB,EAC/B,SACA,cACA,GAAG,KACsD;CACzD,OACC,kBAAC,OAAD;EACC,WAAW,EAAoB,EAAG,8CAA8C,CAAS,CAAC;EAC1F,GAAI;EAEJ,UAAA,kBAAC,QAAD;GAAM,WAAU;GAAuB,UAAA,EAAU,CAAI;EAAQ,CAAA;CACzD,CAAA;AAEP"}
@@ -44,4 +44,4 @@ export type ComboboxProps = Omit<ComponentPropsWithoutRef<"div">, "children" | "
44
44
  */
45
45
  size?: InputSize;
46
46
  };
47
- export declare function Combobox({ items, value, defaultValue, onValueChange, name, placeholder, disabled, loading, size, className, id, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, ...rest }: ComboboxProps): import("react").JSX.Element;
47
+ export declare function Combobox({ placeholder, ...rest }: ComboboxProps): import("react").JSX.Element;
@@ -2,24 +2,11 @@
2
2
  import { TypeaheadField as e } from "./typeahead-field.js";
3
3
  import { jsx as t } from "react/jsx-runtime";
4
4
  //#region src/components/combobox.tsx
5
- function n({ items: n, value: r, defaultValue: i, onValueChange: a, name: o, placeholder: s = "Select…", disabled: c, loading: l, size: u, className: d, id: f, "aria-label": p, "aria-describedby": m, "aria-invalid": h, ...g }) {
5
+ function n({ placeholder: n = "Select…", ...r }) {
6
6
  return /* @__PURE__ */ t(e, {
7
- items: n,
8
- value: r,
9
- defaultValue: i,
10
- onValueChange: a,
11
- name: o,
12
- placeholder: s,
13
- disabled: c,
14
- loading: l,
15
- size: u,
16
- className: d,
17
- id: f,
7
+ placeholder: n,
18
8
  allowFreeform: !1,
19
- "aria-label": p,
20
- "aria-describedby": m,
21
- "aria-invalid": h,
22
- ...g
9
+ ...r
23
10
  });
24
11
  }
25
12
  //#endregion