@burtson-labs/ui 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/components/alert-dialog.js +1 -1
  2. package/dist/components/alert-dialog.js.map +1 -1
  3. package/dist/components/alert.js +2 -2
  4. package/dist/components/alert.js.map +1 -1
  5. package/dist/components/button.d.ts +1 -1
  6. package/dist/components/button.js +26 -6
  7. package/dist/components/button.js.map +1 -1
  8. package/dist/components/checkbox.js +11 -6
  9. package/dist/components/checkbox.js.map +1 -1
  10. package/dist/components/combobox.d.ts +6 -1
  11. package/dist/components/combobox.js +25 -6
  12. package/dist/components/combobox.js.map +1 -1
  13. package/dist/components/composer.d.ts +5 -3
  14. package/dist/components/composer.js +46 -9
  15. package/dist/components/composer.js.map +1 -1
  16. package/dist/components/conversation.js +2 -2
  17. package/dist/components/conversation.js.map +1 -1
  18. package/dist/components/copy-button.d.ts +3 -1
  19. package/dist/components/copy-button.js +14 -5
  20. package/dist/components/copy-button.js.map +1 -1
  21. package/dist/components/dialog.js +1 -1
  22. package/dist/components/dialog.js.map +1 -1
  23. package/dist/components/input.d.ts +2 -2
  24. package/dist/components/input.js +5 -4
  25. package/dist/components/input.js.map +1 -1
  26. package/dist/components/markdown.js +5 -14
  27. package/dist/components/markdown.js.map +1 -1
  28. package/dist/components/message.js +1 -1
  29. package/dist/components/message.js.map +1 -1
  30. package/dist/components/pagination.d.ts +1 -1
  31. package/dist/components/pagination.js +8 -2
  32. package/dist/components/pagination.js.map +1 -1
  33. package/dist/components/popover.js +1 -1
  34. package/dist/components/popover.js.map +1 -1
  35. package/dist/components/progress.d.ts +1 -1
  36. package/dist/components/progress.js +7 -4
  37. package/dist/components/progress.js.map +1 -1
  38. package/dist/components/sheet.js +1 -1
  39. package/dist/components/sheet.js.map +1 -1
  40. package/dist/components/slider.js +1 -1
  41. package/dist/components/slider.js.map +1 -1
  42. package/dist/components/steps.js +2 -2
  43. package/dist/components/steps.js.map +1 -1
  44. package/dist/components/textarea.d.ts +1 -1
  45. package/dist/components/textarea.js +4 -3
  46. package/dist/components/textarea.js.map +1 -1
  47. package/dist/components/tool-call.d.ts +3 -1
  48. package/dist/components/tool-call.js +20 -2
  49. package/dist/components/tool-call.js.map +1 -1
  50. package/dist/components/toolbar.js +1 -1
  51. package/dist/components/toolbar.js.map +1 -1
  52. package/dist/components/tooltip.js +13 -5
  53. package/dist/components/tooltip.js.map +1 -1
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.js +2 -1
  56. package/dist/lib/platform.d.ts +10 -0
  57. package/dist/lib/platform.js +24 -0
  58. package/dist/lib/platform.js.map +1 -0
  59. package/dist/styles.css +1 -1
  60. package/dist/theme.css +28 -1
  61. package/dist/tokens.js +1 -1
  62. package/dist/tokens.js.map +1 -1
  63. package/package.json +2 -2
@@ -22,11 +22,13 @@ export interface ToolApprovalProps extends Omit<React.ComponentProps<'div'>, 'ti
22
22
  args?: unknown;
23
23
  /** `pending` shows the buttons; the others record the decision. */
24
24
  state?: 'pending' | 'approved' | 'denied';
25
+ /** Disable decision controls while the application records the choice. */
26
+ busy?: boolean;
25
27
  onApprove?: () => void;
26
28
  onDeny?: () => void;
27
29
  approveLabel?: string;
28
30
  denyLabel?: string;
29
31
  }
30
32
  /** A gate before an agent runs a tool with side effects: the person approves or denies it. */
31
- declare function ToolApproval({ name, description, args, state, onApprove, onDeny, approveLabel, denyLabel, className, ...props }: ToolApprovalProps): React.JSX.Element;
33
+ declare function ToolApproval({ name, description, args, state, busy, onApprove, onDeny, approveLabel, denyLabel, className, ...props }: ToolApprovalProps): React.JSX.Element;
32
34
  export { ToolApproval, ToolCall };
@@ -19,7 +19,22 @@ var statusDot = {
19
19
  success: "success",
20
20
  error: "danger"
21
21
  };
22
- var json = (v) => typeof v === "string" ? v : JSON.stringify(v, null, 2);
22
+ var json = (value) => {
23
+ if (typeof value === "string") return value;
24
+ const seen = /* @__PURE__ */ new WeakSet();
25
+ try {
26
+ return JSON.stringify(value, (_key, item) => {
27
+ if (typeof item === "bigint") return item.toString();
28
+ if (item && typeof item === "object") {
29
+ if (seen.has(item)) return "[Repeated reference]";
30
+ seen.add(item);
31
+ }
32
+ return item;
33
+ }, 2) ?? String(value);
34
+ } catch {
35
+ return "[Value could not be displayed]";
36
+ }
37
+ };
23
38
  /** A tool call an agent made: name, live status, and collapsible arguments and result. */
24
39
  function ToolCall({ name, status, args, result, error, durationMs, defaultOpen = false, className, ...props }) {
25
40
  const hasDetail = args !== void 0 || result !== void 0 || Boolean(error);
@@ -98,9 +113,10 @@ function ToolCall({ name, status, args, result, error, durationMs, defaultOpen =
98
113
  });
99
114
  }
100
115
  /** A gate before an agent runs a tool with side effects: the person approves or denies it. */
101
- function ToolApproval({ name, description, args, state = "pending", onApprove, onDeny, approveLabel = "Approve", denyLabel = "Deny", className, ...props }) {
116
+ function ToolApproval({ name, description, args, state = "pending", busy = false, onApprove, onDeny, approveLabel = "Approve", denyLabel = "Deny", className, ...props }) {
102
117
  return /* @__PURE__ */ jsxs("div", {
103
118
  "data-slot": "tool-approval",
119
+ "aria-busy": busy || void 0,
104
120
  "data-state": state,
105
121
  className: cn("grid animate-in gap-3 rounded-md border p-3 text-[13px]", state === "pending" ? "border-warning/40 bg-warning/5" : "bg-surface", className),
106
122
  ...props,
@@ -136,10 +152,12 @@ function ToolApproval({ name, description, args, state = "pending", onApprove, o
136
152
  size: "sm",
137
153
  variant: "outline",
138
154
  onClick: onDeny,
155
+ disabled: busy || !onDeny,
139
156
  children: denyLabel
140
157
  }), /* @__PURE__ */ jsx(Button, {
141
158
  size: "sm",
142
159
  onClick: onApprove,
160
+ disabled: busy || !onApprove,
143
161
  children: approveLabel
144
162
  })]
145
163
  })
@@ -1 +1 @@
1
- {"version":3,"file":"tool-call.js","names":["CollapsiblePrimitive"],"sources":["../../src/components/tool-call.tsx"],"sourcesContent":["import ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport Wrench from '@burtson-labs/icons/react/wrench';\nimport { Collapsible as CollapsiblePrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\nimport { StatusDot } from './status';\n\nexport type ToolCallStatus = 'pending' | 'running' | 'success' | 'error';\n\nconst statusText: Record<ToolCallStatus, string> = {\n pending: 'Queued',\n running: 'Running',\n success: 'Done',\n error: 'Failed',\n};\nconst statusDot = {\n pending: 'neutral',\n running: 'brand',\n success: 'success',\n error: 'danger',\n} as const;\n\nconst json = (v: unknown) => (typeof v === 'string' ? v : JSON.stringify(v, null, 2));\n\nexport interface ToolCallProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n /** The tool's name, e.g. `get_load`. */\n name: string;\n status: ToolCallStatus;\n /** Arguments the agent passed; shown as formatted JSON. */\n args?: unknown;\n /** What the tool returned; shown as formatted JSON. */\n result?: unknown;\n /** Error message when the call failed. */\n error?: string;\n durationMs?: number;\n defaultOpen?: boolean;\n}\n\n/** A tool call an agent made: name, live status, and collapsible arguments and result. */\nfunction ToolCall({\n name,\n status,\n args,\n result,\n error,\n durationMs,\n defaultOpen = false,\n className,\n ...props\n}: ToolCallProps) {\n const hasDetail = args !== undefined || result !== undefined || Boolean(error);\n return (\n <CollapsiblePrimitive.Root defaultOpen={defaultOpen} disabled={!hasDetail}>\n <div\n data-slot=\"tool-call\"\n data-status={status}\n className={cn(\n 'animate-in overflow-hidden rounded-md border bg-surface text-[13px]',\n status === 'error' && 'border-destructive/30',\n className,\n )}\n {...props}\n >\n <CollapsiblePrimitive.Trigger className=\"group/tool flex h-9 w-full items-center gap-2 px-3 text-left outline-none hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:cursor-default disabled:hover:bg-transparent\">\n <Wrench className=\"size-3.5 shrink-0 text-muted-foreground\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate font-mono text-[12.5px]\">{name}</span>\n <span className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground\">\n <StatusDot status={statusDot[status]} pulse={status === 'running'} />\n {statusText[status]}\n {durationMs !== undefined && status !== 'running' && (\n <span className=\"tabular-nums\">· {(durationMs / 1000).toFixed(1)}s</span>\n )}\n </span>\n {hasDetail && (\n <ChevronRight\n aria-hidden\n className=\"size-3.5 text-muted-foreground transition-transform group-data-[state=open]/tool:rotate-90\"\n />\n )}\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content className=\"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down\">\n <div className=\"grid gap-2 border-t p-3\">\n {args !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Arguments\n </h4>\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n </section>\n )}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-medium text-destructive\">\n {error}\n </p>\n ) : (\n result !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Result\n </h4>\n <pre className=\"max-h-64 overflow-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(result)}\n </pre>\n </section>\n )\n )}\n </div>\n </CollapsiblePrimitive.Content>\n </div>\n </CollapsiblePrimitive.Root>\n );\n}\n\nexport interface ToolApprovalProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n name: string;\n /** What will happen, in plain words, e.g. \"Approve L-1042 and send it to Gravitate\". */\n description: React.ReactNode;\n args?: unknown;\n /** `pending` shows the buttons; the others record the decision. */\n state?: 'pending' | 'approved' | 'denied';\n onApprove?: () => void;\n onDeny?: () => void;\n approveLabel?: string;\n denyLabel?: string;\n}\n\n/** A gate before an agent runs a tool with side effects: the person approves or denies it. */\nfunction ToolApproval({\n name,\n description,\n args,\n state = 'pending',\n onApprove,\n onDeny,\n approveLabel = 'Approve',\n denyLabel = 'Deny',\n className,\n ...props\n}: ToolApprovalProps) {\n return (\n <div\n data-slot=\"tool-approval\"\n data-state={state}\n className={cn(\n 'grid animate-in gap-3 rounded-md border p-3 text-[13px]',\n state === 'pending' ? 'border-warning/40 bg-warning/5' : 'bg-surface',\n className,\n )}\n {...props}\n >\n <div className=\"flex items-center gap-2\">\n <Wrench className=\"size-3.5 text-muted-foreground\" aria-hidden />\n <span className=\"font-mono text-[12.5px]\">{name}</span>\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {state === 'pending'\n ? 'Needs your approval'\n : state === 'approved'\n ? 'Approved'\n : 'Denied'}\n </span>\n </div>\n <p className=\"text-sm\">{description}</p>\n {args !== undefined && (\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n )}\n {state === 'pending' && (\n <div className=\"flex justify-end gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={onDeny}>\n {denyLabel}\n </Button>\n <Button size=\"sm\" onClick={onApprove}>\n {approveLabel}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport { ToolApproval, ToolCall };\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-call.js","names":["CollapsiblePrimitive"],"sources":["../../src/components/tool-call.tsx"],"sourcesContent":["import ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport Wrench from '@burtson-labs/icons/react/wrench';\nimport { Collapsible as CollapsiblePrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\nimport { StatusDot } from './status';\n\nexport type ToolCallStatus = 'pending' | 'running' | 'success' | 'error';\n\nconst statusText: Record<ToolCallStatus, string> = {\n pending: 'Queued',\n running: 'Running',\n success: 'Done',\n error: 'Failed',\n};\nconst statusDot = {\n pending: 'neutral',\n running: 'brand',\n success: 'success',\n error: 'danger',\n} as const;\n\nconst json = (value: unknown) => {\n if (typeof value === 'string') return value;\n const seen = new WeakSet<object>();\n try {\n return (\n JSON.stringify(\n value,\n (_key, item: unknown) => {\n if (typeof item === 'bigint') return item.toString();\n if (item && typeof item === 'object') {\n if (seen.has(item)) return '[Repeated reference]';\n seen.add(item);\n }\n return item;\n },\n 2,\n ) ?? String(value)\n );\n } catch {\n return '[Value could not be displayed]';\n }\n};\n\nexport interface ToolCallProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n /** The tool's name, e.g. `get_load`. */\n name: string;\n status: ToolCallStatus;\n /** Arguments the agent passed; shown as formatted JSON. */\n args?: unknown;\n /** What the tool returned; shown as formatted JSON. */\n result?: unknown;\n /** Error message when the call failed. */\n error?: string;\n durationMs?: number;\n defaultOpen?: boolean;\n}\n\n/** A tool call an agent made: name, live status, and collapsible arguments and result. */\nfunction ToolCall({\n name,\n status,\n args,\n result,\n error,\n durationMs,\n defaultOpen = false,\n className,\n ...props\n}: ToolCallProps) {\n const hasDetail = args !== undefined || result !== undefined || Boolean(error);\n return (\n <CollapsiblePrimitive.Root defaultOpen={defaultOpen} disabled={!hasDetail}>\n <div\n data-slot=\"tool-call\"\n data-status={status}\n className={cn(\n 'animate-in overflow-hidden rounded-md border bg-surface text-[13px]',\n status === 'error' && 'border-destructive/30',\n className,\n )}\n {...props}\n >\n <CollapsiblePrimitive.Trigger className=\"group/tool flex h-9 w-full items-center gap-2 px-3 text-left outline-none hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:cursor-default disabled:hover:bg-transparent\">\n <Wrench className=\"size-3.5 shrink-0 text-muted-foreground\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate font-mono text-[12.5px]\">{name}</span>\n <span className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground\">\n <StatusDot status={statusDot[status]} pulse={status === 'running'} />\n {statusText[status]}\n {durationMs !== undefined && status !== 'running' && (\n <span className=\"tabular-nums\">· {(durationMs / 1000).toFixed(1)}s</span>\n )}\n </span>\n {hasDetail && (\n <ChevronRight\n aria-hidden\n className=\"size-3.5 text-muted-foreground transition-transform group-data-[state=open]/tool:rotate-90\"\n />\n )}\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content className=\"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down\">\n <div className=\"grid gap-2 border-t p-3\">\n {args !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Arguments\n </h4>\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n </section>\n )}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-medium text-destructive\">\n {error}\n </p>\n ) : (\n result !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Result\n </h4>\n <pre className=\"max-h-64 overflow-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(result)}\n </pre>\n </section>\n )\n )}\n </div>\n </CollapsiblePrimitive.Content>\n </div>\n </CollapsiblePrimitive.Root>\n );\n}\n\nexport interface ToolApprovalProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n name: string;\n /** What will happen, in plain words, e.g. \"Approve L-1042 and send it to Gravitate\". */\n description: React.ReactNode;\n args?: unknown;\n /** `pending` shows the buttons; the others record the decision. */\n state?: 'pending' | 'approved' | 'denied';\n /** Disable decision controls while the application records the choice. */\n busy?: boolean;\n onApprove?: () => void;\n onDeny?: () => void;\n approveLabel?: string;\n denyLabel?: string;\n}\n\n/** A gate before an agent runs a tool with side effects: the person approves or denies it. */\nfunction ToolApproval({\n name,\n description,\n args,\n state = 'pending',\n busy = false,\n onApprove,\n onDeny,\n approveLabel = 'Approve',\n denyLabel = 'Deny',\n className,\n ...props\n}: ToolApprovalProps) {\n return (\n <div\n data-slot=\"tool-approval\"\n aria-busy={busy || undefined}\n data-state={state}\n className={cn(\n 'grid animate-in gap-3 rounded-md border p-3 text-[13px]',\n state === 'pending' ? 'border-warning/40 bg-warning/5' : 'bg-surface',\n className,\n )}\n {...props}\n >\n <div className=\"flex items-center gap-2\">\n <Wrench className=\"size-3.5 text-muted-foreground\" aria-hidden />\n <span className=\"font-mono text-[12.5px]\">{name}</span>\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {state === 'pending'\n ? 'Needs your approval'\n : state === 'approved'\n ? 'Approved'\n : 'Denied'}\n </span>\n </div>\n <p className=\"text-sm\">{description}</p>\n {args !== undefined && (\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n )}\n {state === 'pending' && (\n <div className=\"flex justify-end gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={onDeny} disabled={busy || !onDeny}>\n {denyLabel}\n </Button>\n <Button size=\"sm\" onClick={onApprove} disabled={busy || !onApprove}>\n {approveLabel}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport { ToolApproval, ToolCall };\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { jsx } from "react/jsx-runtime";
5
5
  function Toolbar({ className, ...props }) {
6
6
  return /* @__PURE__ */ jsx("div", {
7
7
  "data-slot": "toolbar",
8
- role: "toolbar",
8
+ role: "group",
9
9
  className: cn("flex min-h-10 flex-wrap items-center gap-1 rounded-lg border border-border bg-surface p-1.5 shadow-xs", className),
10
10
  ...props
11
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.js","names":[],"sources":["../../src/components/toolbar.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nfunction Toolbar({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar\"\n role=\"toolbar\"\n className={cn(\n 'flex min-h-10 flex-wrap items-center gap-1 rounded-lg border border-border bg-surface p-1.5 shadow-xs',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ToolbarGroup({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-group\"\n className={cn('flex items-center gap-1', className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarSeparator({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-separator\"\n aria-hidden=\"true\"\n className={cn('mx-1 h-5 w-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarSpacer({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-spacer\"\n aria-hidden=\"true\"\n className={cn('min-w-2 flex-1', className)}\n {...props}\n />\n );\n}\n\nexport { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer };\n"],"mappings":";;;;AAIA,SAAS,QAAQ,EAAE,WAAW,GAAG,SAAsC;CACrE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,WAAW,GACT,yGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAsC;CAC9E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,eAAY;EACZ,WAAW,GAAG,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cAAc,EAAE,WAAW,GAAG,SAAsC;CAC3E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,eAAY;EACZ,WAAW,GAAG,kBAAkB,SAAS;EACzC,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"toolbar.js","names":[],"sources":["../../src/components/toolbar.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nfunction Toolbar({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar\"\n role=\"group\"\n className={cn(\n 'flex min-h-10 flex-wrap items-center gap-1 rounded-lg border border-border bg-surface p-1.5 shadow-xs',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ToolbarGroup({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-group\"\n className={cn('flex items-center gap-1', className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarSeparator({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-separator\"\n aria-hidden=\"true\"\n className={cn('mx-1 h-5 w-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction ToolbarSpacer({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"toolbar-spacer\"\n aria-hidden=\"true\"\n className={cn('min-w-2 flex-1', className)}\n {...props}\n />\n );\n}\n\nexport { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer };\n"],"mappings":";;;;AAIA,SAAS,QAAQ,EAAE,WAAW,GAAG,SAAsC;CACrE,OACE,oBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,WAAW,GACT,yGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAsC;CAC9E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,eAAY;EACZ,WAAW,GAAG,2BAA2B,SAAS;EAClD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cAAc,EAAE,WAAW,GAAG,SAAsC;CAC3E,OACE,oBAAC,OAAD;EACE,aAAU;EACV,eAAY;EACZ,WAAW,GAAG,kBAAkB,SAAS;EACzC,GAAI;CACL,CAAA;AAEL"}
@@ -1,17 +1,25 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { Tooltip } from "radix-ui";
3
- import "react";
3
+ import * as React from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/components/tooltip.tsx
6
+ var HasTooltipProvider = React.createContext(false);
6
7
  function TooltipProvider({ delayDuration = 200, ...props }) {
7
- return /* @__PURE__ */ jsx(Tooltip.Provider, {
8
- "data-slot": "tooltip-provider",
9
- delayDuration,
10
- ...props
8
+ return /* @__PURE__ */ jsx(HasTooltipProvider.Provider, {
9
+ value: true,
10
+ children: /* @__PURE__ */ jsx(Tooltip.Provider, {
11
+ "data-slot": "tooltip-provider",
12
+ delayDuration,
13
+ ...props
14
+ })
11
15
  });
12
16
  }
13
17
  /** Wraps its own provider, so a lone tooltip works without app-level setup. */
14
18
  function Tooltip$1(props) {
19
+ if (React.useContext(HasTooltipProvider)) return /* @__PURE__ */ jsx(Tooltip.Root, {
20
+ "data-slot": "tooltip",
21
+ ...props
22
+ });
15
23
  return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(Tooltip.Root, {
16
24
  "data-slot": "tooltip",
17
25
  ...props
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":["TooltipPrimitive","Tooltip"],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import { Tooltip as TooltipPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nfunction TooltipProvider({\n delayDuration = 200,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n );\n}\n\n/** Wraps its own provider, so a lone tooltip works without app-level setup. */\nfunction Tooltip(props: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n );\n}\n\nfunction TooltipTrigger(props: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 6,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'z-50 w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) animate-in [--bl-scale:0.98] data-[side=bottom]:[--bl-ty:-4px] data-[side=top]:[--bl-ty:4px] data-[side=left]:[--bl-tx:4px] data-[side=right]:[--bl-tx:-4px] rounded-sm border border-white/10 bg-code px-2 py-1 text-[11.5px] leading-4 font-medium text-balance text-code-foreground shadow-md data-[state=closed]:animate-out',\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"fill-code\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n"],"mappings":";;;;;AAKA,SAAS,gBAAgB,EACvB,gBAAgB,KAChB,GAAG,SACsD;CACzD,OACE,oBAACA,QAAiB,UAAlB;EACE,aAAU;EACK;EACf,GAAI;CACL,CAAA;AAEL;;AAGA,SAASC,UAAQ,OAA2D;CAC1E,OACE,oBAAC,iBAAD,EAAA,UACE,oBAACD,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA,EACxC,CAAA;AAErB;AAEA,SAAS,eAAe,OAA8D;CACpF,OAAO,oBAACA,QAAiB,SAAlB;EAA0B,aAAU;EAAkB,GAAI;CAAQ,CAAA;AAC3E;AAEA,SAAS,eAAe,EACtB,WACA,aAAa,GACb,UACA,GAAG,SACqD;CACxD,OACE,oBAACA,QAAiB,QAAlB,EAAA,UACE,qBAACA,QAAiB,SAAlB;EACE,aAAU;EACE;EACZ,WAAW,GACT,0YACA,SACF;EACA,GAAI;EAPN,UAAA,CASG,UACD,oBAACA,QAAiB,OAAlB,EAAwB,WAAU,YAAa,CAAA,CACvB;CACH,CAAA,EAAA,CAAA;AAE7B"}
1
+ {"version":3,"file":"tooltip.js","names":["TooltipPrimitive","Tooltip"],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import { Tooltip as TooltipPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nconst HasTooltipProvider = React.createContext(false);\n\nfunction TooltipProvider({\n delayDuration = 200,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <HasTooltipProvider.Provider value={true}>\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n </HasTooltipProvider.Provider>\n );\n}\n\n/** Wraps its own provider, so a lone tooltip works without app-level setup. */\nfunction Tooltip(props: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n const hasProvider = React.useContext(HasTooltipProvider);\n if (hasProvider) return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n );\n}\n\nfunction TooltipTrigger(props: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 6,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'z-50 w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) animate-in [--bl-scale:0.98] data-[side=bottom]:[--bl-ty:-4px] data-[side=top]:[--bl-ty:4px] data-[side=left]:[--bl-tx:4px] data-[side=right]:[--bl-tx:-4px] rounded-sm border border-white/10 bg-code px-2 py-1 text-[11.5px] leading-4 font-medium text-balance text-code-foreground shadow-md data-[state=closed]:animate-out',\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"fill-code\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n"],"mappings":";;;;;AAKA,IAAM,qBAAqB,MAAM,cAAc,KAAK;AAEpD,SAAS,gBAAgB,EACvB,gBAAgB,KAChB,GAAG,SACsD;CACzD,OACE,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAClC,UAAA,oBAACA,QAAiB,UAAlB;GACE,aAAU;GACK;GACf,GAAI;EACL,CAAA;CAC0B,CAAA;AAEjC;;AAGA,SAASC,UAAQ,OAA2D;CAE1E,IADoB,MAAM,WAAW,kBACjC,GAAa,OAAO,oBAACD,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA;CAC/E,OACE,oBAAC,iBAAD,EAAA,UACE,oBAACA,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA,EACxC,CAAA;AAErB;AAEA,SAAS,eAAe,OAA8D;CACpF,OAAO,oBAACA,QAAiB,SAAlB;EAA0B,aAAU;EAAkB,GAAI;CAAQ,CAAA;AAC3E;AAEA,SAAS,eAAe,EACtB,WACA,aAAa,GACb,UACA,GAAG,SACqD;CACxD,OACE,oBAACA,QAAiB,QAAlB,EAAA,UACE,qBAACA,QAAiB,SAAlB;EACE,aAAU;EACE;EACZ,WAAW,GACT,0YACA,SACF;EACA,GAAI;EAPN,UAAA,CASG,UACD,oBAACA,QAAiB,OAAlB,EAAwB,WAAU,YAAa,CAAA,CACvB;CACH,CAAA,EAAA,CAAA;AAE7B"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { cn } from './lib/utils';
2
+ export { isApplePlatform, modKeyLabel, shortcutLabel } from './lib/platform';
2
3
  export * from './tokens';
3
4
  export * from './components/accordion';
4
5
  export * from './components/alert';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { cn } from "./lib/utils.js";
2
+ import { isApplePlatform, modKeyLabel, shortcutLabel } from "./lib/platform.js";
2
3
  import tokens, { brand, dark, fontMono, fontSans, light, motion, radius, shadow } from "./tokens.js";
3
4
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./components/accordion.js";
4
5
  import { Alert, AlertDescription, AlertTitle, alertVariants } from "./components/alert.js";
@@ -53,4 +54,4 @@ import { Textarea } from "./components/textarea.js";
53
54
  import { ToolApproval, ToolCall } from "./components/tool-call.js";
54
55
  import { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer } from "./components/toolbar.js";
55
56
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/tooltip.js";
56
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, Conversation, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, Markdown, Message, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ScrollArea, ScrollBar, SecretInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, Spinner, StatCard, Status, StatusDot, Steps, StreamingIndicator, Suggestions, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, ToolApproval, ToolCall, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, dark, fieldClasses, fontMono, fontSans, light, motion, navigationMenuTriggerStyle, paginationRange, parseMarkdown, radius, shadow, statusDotVariants, surfaceClasses, toast, toastVariants, tokens };
57
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, Conversation, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, Markdown, Message, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ScrollArea, ScrollBar, SecretInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, Spinner, StatCard, Status, StatusDot, Steps, StreamingIndicator, Suggestions, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, ToolApproval, ToolCall, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, dark, fieldClasses, fontMono, fontSans, isApplePlatform, light, modKeyLabel, motion, navigationMenuTriggerStyle, paginationRange, parseMarkdown, radius, shadow, shortcutLabel, statusDotVariants, surfaceClasses, toast, toastVariants, tokens };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Keyboard-shortcut labels that match the user's platform: ⌘ on Apple
3
+ * devices, Ctrl elsewhere. Handlers should accept both (metaKey || ctrlKey);
4
+ * this only decides what to show.
5
+ */
6
+ export declare function isApplePlatform(): boolean;
7
+ /** "⌘" or "Ctrl". */
8
+ export declare function modKeyLabel(): string;
9
+ /** A shortcut such as "⌘K" / "Ctrl K" for a key pressed with the platform modifier. */
10
+ export declare function shortcutLabel(key: string): string;
@@ -0,0 +1,24 @@
1
+ //#region src/lib/platform.ts
2
+ /**
3
+ * Keyboard-shortcut labels that match the user's platform: ⌘ on Apple
4
+ * devices, Ctrl elsewhere. Handlers should accept both (metaKey || ctrlKey);
5
+ * this only decides what to show.
6
+ */
7
+ function isApplePlatform() {
8
+ if (typeof navigator === "undefined") return false;
9
+ const nav = navigator;
10
+ const platform = nav.userAgentData?.platform ?? nav.platform ?? "";
11
+ return /mac|iphone|ipad|ipod/i.test(platform) || /Mac OS X|iPhone|iPad/.test(nav.userAgent);
12
+ }
13
+ /** "⌘" or "Ctrl". */
14
+ function modKeyLabel() {
15
+ return isApplePlatform() ? "⌘" : "Ctrl";
16
+ }
17
+ /** A shortcut such as "⌘K" / "Ctrl K" for a key pressed with the platform modifier. */
18
+ function shortcutLabel(key) {
19
+ return isApplePlatform() ? `⌘${key.toUpperCase()}` : `Ctrl ${key.toUpperCase()}`;
20
+ }
21
+ //#endregion
22
+ export { isApplePlatform, modKeyLabel, shortcutLabel };
23
+
24
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","names":[],"sources":["../../src/lib/platform.ts"],"sourcesContent":["/**\n * Keyboard-shortcut labels that match the user's platform: ⌘ on Apple\n * devices, Ctrl elsewhere. Handlers should accept both (metaKey || ctrlKey);\n * this only decides what to show.\n */\nexport function isApplePlatform(): boolean {\n if (typeof navigator === 'undefined') return false;\n const nav = navigator as Navigator & { userAgentData?: { platform?: string } };\n const platform = nav.userAgentData?.platform ?? nav.platform ?? '';\n return /mac|iphone|ipad|ipod/i.test(platform) || /Mac OS X|iPhone|iPad/.test(nav.userAgent);\n}\n\n/** \"⌘\" or \"Ctrl\". */\nexport function modKeyLabel(): string {\n return isApplePlatform() ? '⌘' : 'Ctrl';\n}\n\n/** A shortcut such as \"⌘K\" / \"Ctrl K\" for a key pressed with the platform modifier. */\nexport function shortcutLabel(key: string): string {\n return isApplePlatform() ? `⌘${key.toUpperCase()}` : `Ctrl ${key.toUpperCase()}`;\n}\n"],"mappings":";;;;;;AAKA,SAAgB,kBAA2B;CACzC,IAAI,OAAO,cAAc,aAAa,OAAO;CAC7C,MAAM,MAAM;CACZ,MAAM,WAAW,IAAI,eAAe,YAAY,IAAI,YAAY;CAChE,OAAO,wBAAwB,KAAK,QAAQ,KAAK,uBAAuB,KAAK,IAAI,SAAS;AAC5F;;AAGA,SAAgB,cAAsB;CACpC,OAAO,gBAAgB,IAAI,MAAM;AACnC;;AAGA,SAAgB,cAAc,KAAqB;CACjD,OAAO,gBAAgB,IAAI,IAAI,IAAI,YAAY,MAAM,QAAQ,IAAI,YAAY;AAC/E"}