@tangle-network/ui 11.12.0 → 11.13.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 (276) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/_virtual/_rolldown/runtime.js +13 -0
  3. package/dist/auth/auth.d.ts +53 -0
  4. package/dist/{auth-DOETfnd9.js → auth/auth.js} +7 -37
  5. package/dist/auth/login-layout.d.ts +20 -0
  6. package/dist/auth/login-layout.js +36 -0
  7. package/dist/auth.d.ts +2 -1
  8. package/dist/auth.js +2 -1
  9. package/dist/chat/agent-timeline.d.ts +83 -0
  10. package/dist/chat/agent-timeline.js +236 -0
  11. package/dist/chat/chat-container.d.ts +51 -0
  12. package/dist/chat/chat-container.js +309 -0
  13. package/dist/chat/chat-message.d.ts +22 -0
  14. package/dist/chat/chat-message.js +38 -0
  15. package/dist/chat/message-list.d.ts +32 -0
  16. package/dist/chat/message-list.js +37 -0
  17. package/dist/chat/thinking-indicator.d.ts +6 -0
  18. package/dist/chat/thinking-indicator.js +38 -0
  19. package/dist/chat/user-message.d.ts +21 -0
  20. package/dist/chat/user-message.js +42 -0
  21. package/dist/chat.d.ts +6 -1
  22. package/dist/chat.js +6 -1
  23. package/dist/editor/document-editor-pane.d.ts +37 -0
  24. package/dist/editor/document-editor-pane.js +199 -0
  25. package/dist/editor/editor-lazy.js +37 -0
  26. package/dist/editor/editor-loading.js +21 -0
  27. package/dist/editor/editor-peers.d.ts +6 -0
  28. package/dist/editor/editor-peers.js +155 -0
  29. package/dist/editor/editor-provider.d.ts +97 -0
  30. package/dist/editor/editor-provider.js +253 -0
  31. package/dist/editor/editor-toolbar.d.ts +11 -0
  32. package/dist/editor/editor-toolbar.js +106 -0
  33. package/dist/editor/markdown-conversion.js +23 -0
  34. package/dist/editor/markdown-document-editor.js +103 -0
  35. package/dist/editor/tiptap-editor.d.ts +45 -0
  36. package/dist/editor/tiptap-editor.js +271 -0
  37. package/dist/editor/use-editor.d.ts +67 -0
  38. package/dist/editor/use-editor.js +158 -0
  39. package/dist/editor.d.ts +6 -119
  40. package/dist/editor.js +5 -1
  41. package/dist/files/file-artifact-pane.d.ts +47 -0
  42. package/dist/files/file-artifact-pane.js +114 -0
  43. package/dist/files/file-format.d.ts +51 -0
  44. package/dist/{file-format-BgXbr-Ib.js → files/file-format.js} +1 -1
  45. package/dist/files/file-preview.d.ts +27 -0
  46. package/dist/files/file-preview.js +359 -0
  47. package/dist/files/file-tabs.d.ts +19 -0
  48. package/dist/files/file-tabs.js +48 -0
  49. package/dist/files/file-tree.d.ts +31 -0
  50. package/dist/files/file-tree.js +135 -0
  51. package/dist/files/rich-file-tree.d.ts +62 -0
  52. package/dist/files/rich-file-tree.js +122 -0
  53. package/dist/files.d.ts +6 -1
  54. package/dist/files.js +6 -2
  55. package/dist/hooks/use-auth.d.ts +40 -0
  56. package/dist/hooks/use-auth.js +91 -0
  57. package/dist/hooks/use-auto-scroll.d.ts +11 -0
  58. package/dist/hooks/use-auto-scroll.js +48 -0
  59. package/dist/hooks/use-dropdown-menu.d.ts +12 -0
  60. package/dist/hooks/use-dropdown-menu.js +31 -0
  61. package/dist/hooks/use-live-time.d.ts +7 -0
  62. package/dist/hooks/use-live-time.js +22 -0
  63. package/dist/hooks/use-realtime-session.d.ts +32 -0
  64. package/dist/hooks/use-realtime-session.js +235 -0
  65. package/dist/hooks/use-run-collapse-state.d.ts +13 -0
  66. package/dist/hooks/use-run-collapse-state.js +24 -0
  67. package/dist/hooks/use-run-groups.d.ts +11 -0
  68. package/dist/hooks/use-run-groups.js +85 -0
  69. package/dist/hooks/use-sdk-session.d.ts +59 -0
  70. package/dist/hooks/use-sdk-session.js +322 -0
  71. package/dist/hooks/use-sse-stream.d.ts +124 -0
  72. package/dist/hooks/use-sse-stream.js +229 -0
  73. package/dist/hooks/use-tool-call-stream.d.ts +23 -0
  74. package/dist/hooks/use-tool-call-stream.js +75 -0
  75. package/dist/hooks.d.ts +11 -49
  76. package/dist/hooks.js +10 -110
  77. package/dist/index.d.ts +99 -25
  78. package/dist/index.js +86 -36
  79. package/dist/lib/focus.d.ts +55 -0
  80. package/dist/{focus-BcE_SHqz.js → lib/focus.js} +1 -1
  81. package/dist/lib/utils.d.ts +4 -0
  82. package/dist/{utils-C_uf36nf.js → lib/utils.js} +1 -1
  83. package/dist/{code-block-B9miUPht.d.ts → markdown/code-block.d.ts} +5 -6
  84. package/dist/{code-block-B36KVUSN.js → markdown/code-block.js} +60 -55
  85. package/dist/{markdown-C0atSabr.d.ts → markdown/markdown.d.ts} +4 -5
  86. package/dist/{markdown-Db08KAYF.js → markdown/markdown.js} +3 -3
  87. package/dist/markdown.d.ts +2 -2
  88. package/dist/markdown.js +2 -2
  89. package/dist/{openui-artifact-renderer-fkBQaoLO.d.ts → openui/openui-artifact-renderer.d.ts} +20 -21
  90. package/dist/{openui-artifact-renderer-DG_i2lOR.js → openui/openui-artifact-renderer.js} +9 -7
  91. package/dist/{schema-BpW9rSSG.js → openui/schema-compiled.js} +2 -354
  92. package/dist/{schema-DAstk-J4.d.ts → openui/schema-data.d.ts} +3 -24
  93. package/dist/openui/schema-data.js +206 -0
  94. package/dist/openui-schema.d.ts +22 -3
  95. package/dist/openui-schema.js +138 -1
  96. package/dist/openui.d.ts +3 -2
  97. package/dist/openui.js +3 -2
  98. package/dist/{artifact-pane-BL_DFWNl.d.ts → primitives/artifact-pane.d.ts} +3 -4
  99. package/dist/{artifact-pane-DMXT9a8U.js → primitives/artifact-pane.js} +2 -2
  100. package/dist/primitives/avatar.d.ts +8 -0
  101. package/dist/primitives/avatar.js +25 -0
  102. package/dist/primitives/badge.d.ts +22 -0
  103. package/dist/primitives/badge.js +47 -0
  104. package/dist/{button-yoIv77e2.d.ts → primitives/button.d.ts} +2 -2
  105. package/dist/primitives/button.js +113 -0
  106. package/dist/primitives/card.d.ts +18 -0
  107. package/dist/primitives/card.js +52 -0
  108. package/dist/primitives/code-block.d.ts +6 -0
  109. package/dist/primitives/code-block.js +13 -0
  110. package/dist/primitives/dialog.d.ts +23 -0
  111. package/dist/primitives/dialog.js +59 -0
  112. package/dist/primitives/drop-zone.d.ts +23 -0
  113. package/dist/primitives/drop-zone.js +104 -0
  114. package/dist/primitives/dropdown-menu.d.ts +29 -0
  115. package/dist/{dropdown-menu-BpcLa5vF.js → primitives/dropdown-menu.js} +2 -23
  116. package/dist/primitives/empty-state.d.ts +11 -0
  117. package/dist/primitives/empty-state.js +32 -0
  118. package/dist/primitives/heading.d.ts +23 -0
  119. package/dist/primitives/heading.js +38 -0
  120. package/dist/primitives/input.d.ts +23 -0
  121. package/dist/primitives/input.js +110 -0
  122. package/dist/primitives/label.d.ts +6 -0
  123. package/dist/primitives/label.js +16 -0
  124. package/dist/primitives/metric-strip.d.ts +48 -0
  125. package/dist/primitives/metric-strip.js +52 -0
  126. package/dist/primitives/page-header.d.ts +25 -0
  127. package/dist/primitives/page-header.js +47 -0
  128. package/dist/primitives/page-shell.d.ts +14 -0
  129. package/dist/primitives/page-shell.js +17 -0
  130. package/dist/primitives/progress.d.ts +9 -0
  131. package/dist/primitives/progress.js +29 -0
  132. package/dist/primitives/segmented-control.d.ts +40 -0
  133. package/dist/primitives/segmented-control.js +57 -0
  134. package/dist/primitives/select.d.ts +15 -0
  135. package/dist/primitives/select.js +74 -0
  136. package/dist/primitives/sidebar-drop-zone.d.ts +21 -0
  137. package/dist/primitives/sidebar-drop-zone.js +88 -0
  138. package/dist/primitives/skeleton.d.ts +10 -0
  139. package/dist/primitives/skeleton.js +50 -0
  140. package/dist/primitives/stat-card.d.ts +16 -0
  141. package/dist/primitives/stat-card.js +60 -0
  142. package/dist/primitives/status-pill.d.ts +44 -0
  143. package/dist/primitives/status-pill.js +119 -0
  144. package/dist/primitives/switch.d.ts +6 -0
  145. package/dist/primitives/switch.js +16 -0
  146. package/dist/primitives/table.d.ts +22 -0
  147. package/dist/primitives/table.js +63 -0
  148. package/dist/primitives/tabs.d.ts +13 -0
  149. package/dist/{tabs-BVHR6NkO.js → primitives/tabs.js} +3 -3
  150. package/dist/primitives/terminal-display.d.ts +25 -0
  151. package/dist/primitives/terminal-display.js +109 -0
  152. package/dist/primitives/text-shimmer.d.ts +16 -0
  153. package/dist/{text-shimmer-BUUo6I-g.js → primitives/text-shimmer.js} +2 -2
  154. package/dist/primitives/theme-toggle.d.ts +11 -0
  155. package/dist/primitives/theme-toggle.js +154 -0
  156. package/dist/primitives/toast.d.ts +29 -0
  157. package/dist/primitives/toast.js +142 -0
  158. package/dist/primitives/toolbar.d.ts +55 -0
  159. package/dist/primitives/toolbar.js +37 -0
  160. package/dist/primitives/upload-progress.d.ts +23 -0
  161. package/dist/primitives/upload-progress.js +72 -0
  162. package/dist/primitives.d.ts +35 -5
  163. package/dist/primitives.js +35 -9
  164. package/dist/{index-COgqsFAQ.d.ts → redaction/redacted-document.d.ts} +6 -7
  165. package/dist/{redaction-CGGB2ENG.js → redaction/redacted-document.js} +2 -2
  166. package/dist/redaction.d.ts +1 -1
  167. package/dist/redaction.js +1 -1
  168. package/dist/run/expandable-content.js +41 -0
  169. package/dist/run/expanded-tool-detail.d.ts +12 -0
  170. package/dist/run/expanded-tool-detail.js +163 -0
  171. package/dist/run/inline-thinking-item.d.ts +11 -0
  172. package/dist/run/inline-thinking-item.js +60 -0
  173. package/dist/run/inline-tool-item.d.ts +25 -0
  174. package/dist/run/inline-tool-item.js +63 -0
  175. package/dist/run/run-group.d.ts +26 -0
  176. package/dist/{run-group-BWGeesgs.js → run/run-group.js} +9 -60
  177. package/dist/run/run-item-primitives.d.ts +5 -0
  178. package/dist/{run-ZsIKPA6J.js → run/run-item-primitives.js} +2 -2
  179. package/dist/run/run-row-shell.d.ts +53 -0
  180. package/dist/run/run-row-shell.js +114 -0
  181. package/dist/{tool-call-feed-BeB1_4pX.d.ts → run/tool-call-feed.d.ts} +7 -12
  182. package/dist/{tool-call-feed-BpmMLpPX.js → run/tool-call-feed.js} +4 -4
  183. package/dist/run/tool-call-step.d.ts +5 -0
  184. package/dist/run/tool-call-step.js +82 -0
  185. package/dist/run.d.ts +8 -2
  186. package/dist/run.js +7 -4
  187. package/dist/sdk-hooks.d.ts +8 -1
  188. package/dist/sdk-hooks.js +8 -2
  189. package/dist/stores/active-sessions-store.d.ts +83 -0
  190. package/dist/{active-sessions-store-Gt1R0rFG.js → stores/active-sessions-store.js} +1 -1
  191. package/dist/stores/chat-store.d.ts +14 -0
  192. package/dist/stores/chat-store.js +33 -0
  193. package/dist/stores.d.ts +3 -16
  194. package/dist/stores.js +2 -33
  195. package/dist/tool-previews/command-preview.d.ts +11 -0
  196. package/dist/tool-previews/command-preview.js +91 -0
  197. package/dist/tool-previews/diff-preview.d.ts +7 -0
  198. package/dist/tool-previews/diff-preview.js +76 -0
  199. package/dist/tool-previews/glob-results-preview.d.ts +7 -0
  200. package/dist/tool-previews/glob-results-preview.js +53 -0
  201. package/dist/tool-previews/grep-results-preview.d.ts +7 -0
  202. package/dist/tool-previews/grep-results-preview.js +99 -0
  203. package/dist/tool-previews/preview-primitives.js +58 -0
  204. package/dist/tool-previews/question-preview.d.ts +7 -0
  205. package/dist/tool-previews/question-preview.js +63 -0
  206. package/dist/tool-previews/web-search-preview.d.ts +7 -0
  207. package/dist/tool-previews/web-search-preview.js +78 -0
  208. package/dist/tool-previews/write-file-preview.d.ts +11 -0
  209. package/dist/tool-previews/write-file-preview.js +52 -0
  210. package/dist/tool-previews.d.ts +7 -1
  211. package/dist/tool-previews.js +7 -1
  212. package/dist/{branding-26d5ARIr.d.ts → types/branding.d.ts} +2 -3
  213. package/dist/{message-vhUI0c5G.d.ts → types/message.d.ts} +2 -3
  214. package/dist/{parts-5mhy9yJ3.d.ts → types/parts.d.ts} +8 -9
  215. package/dist/{run-OyWmIDqu.d.ts → types/run.d.ts} +9 -10
  216. package/dist/{tool-display-DgmL5rIU.d.ts → types/tool-display.d.ts} +5 -6
  217. package/dist/types.d.ts +5 -5
  218. package/dist/utils/copy-text.d.ts +7 -0
  219. package/dist/{utils-Bl_CZ0Qp.js → utils/copy-text.js} +1 -11
  220. package/dist/utils/format.d.ts +22 -0
  221. package/dist/{format-DfcLWqMa.js → utils/format.js} +1 -1
  222. package/dist/utils/time-ago.d.ts +3 -0
  223. package/dist/utils/time-ago.js +11 -0
  224. package/dist/utils/tool-display.d.ts +16 -0
  225. package/dist/{tool-display-BAuAVa43.js → utils/tool-display.js} +1 -1
  226. package/dist/utils.d.ts +6 -1
  227. package/dist/utils.js +6 -5
  228. package/package.json +2 -2
  229. package/src/files/rich-file-tree.stories.tsx +1 -1
  230. package/src/files/rich-file-tree.tsx +12 -9
  231. package/src/markdown/code-block.test.tsx +80 -2
  232. package/src/markdown/code-block.tsx +76 -80
  233. package/src/primitives/button.stories.tsx +37 -1
  234. package/src/primitives/button.test.tsx +230 -0
  235. package/src/primitives/button.tsx +62 -14
  236. package/src/primitives/card-anatomy.stories.tsx +51 -0
  237. package/src/primitives/card.test.tsx +71 -0
  238. package/src/primitives/card.tsx +25 -13
  239. package/src/primitives/heading.stories.tsx +35 -0
  240. package/src/primitives/heading.test.tsx +56 -0
  241. package/src/primitives/heading.tsx +76 -0
  242. package/src/primitives/index.ts +8 -0
  243. package/src/primitives/input.stories.tsx +28 -0
  244. package/src/primitives/input.test.tsx +161 -0
  245. package/src/primitives/input.tsx +34 -28
  246. package/src/primitives/page-header.stories.tsx +51 -0
  247. package/src/primitives/page-header.test.tsx +48 -0
  248. package/src/primitives/page-header.tsx +35 -35
  249. package/src/primitives/page-shell.stories.tsx +89 -0
  250. package/src/primitives/page-shell.test.tsx +24 -0
  251. package/src/primitives/page-shell.tsx +26 -0
  252. package/src/primitives/table-wrapper.stories.tsx +54 -0
  253. package/src/primitives/table.test.tsx +72 -0
  254. package/src/primitives/table.tsx +33 -12
  255. package/src/primitives/theme-toggle.test.tsx +167 -0
  256. package/src/primitives/theme-toggle.tsx +111 -39
  257. package/dist/active-sessions-store-nl70ZnMC.d.ts +0 -84
  258. package/dist/button-C87nEe2R.js +0 -78
  259. package/dist/chat-DDvF2oGQ.js +0 -672
  260. package/dist/diff-preview-BcK3nRXb.js +0 -533
  261. package/dist/document-editor-pane-BilJfiCo.d.ts +0 -136
  262. package/dist/document-editor-pane-POsq5Q0o.js +0 -1279
  263. package/dist/files-hywocVZz.js +0 -753
  264. package/dist/index-2UntyjBb.d.ts +0 -52
  265. package/dist/index-BgUHilZm.d.ts +0 -108
  266. package/dist/index-CJ8wRfiC.d.ts +0 -236
  267. package/dist/index-CPDET_s1.d.ts +0 -549
  268. package/dist/index-Cg6gYAqh.d.ts +0 -73
  269. package/dist/index-Cs7j8V7l.d.ts +0 -203
  270. package/dist/index-DjKxO357.d.ts +0 -128
  271. package/dist/primitives-Bx59fT-U.js +0 -1239
  272. package/dist/table-Bss73DhB.js +0 -146
  273. package/dist/tool-call-step-DNebqhmX.js +0 -434
  274. package/dist/use-auto-scroll-C5Pjeqon.js +0 -153
  275. package/dist/use-sse-stream-DjqRuDft.js +0 -884
  276. package/dist/use-sse-stream-Dm6R5YWz.d.ts +0 -282
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
3
+ //#region src/primitives/progress.d.ts
4
+ declare const Progress: React.ForwardRefExoticComponent<Omit<ProgressPrimitive.ProgressProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
5
+ variant?: "default" | "sandbox";
6
+ showValue?: boolean;
7
+ } & React.RefAttributes<HTMLDivElement>>;
8
+ //#endregion
9
+ export { Progress };
@@ -0,0 +1,29 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import * as React from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
5
+ //#region src/primitives/progress.tsx
6
+ const Progress = React.forwardRef(({ className, value, variant = "default", showValue = false, ...props }, ref) => {
7
+ const indicatorVariants = {
8
+ default: "bg-primary",
9
+ sandbox: "bg-[image:var(--accent-gradient-strong)]"
10
+ };
11
+ return /* @__PURE__ */ jsxs("div", {
12
+ className: "relative",
13
+ children: [/* @__PURE__ */ jsx(ProgressPrimitive.Root, {
14
+ ref,
15
+ className: cn("relative h-2 w-full overflow-hidden rounded-full bg-muted", className),
16
+ ...props,
17
+ children: /* @__PURE__ */ jsx(ProgressPrimitive.Indicator, {
18
+ className: cn("h-full w-full flex-1 transition-all duration-300 ease-out", indicatorVariants[variant]),
19
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
20
+ })
21
+ }), showValue && /* @__PURE__ */ jsxs("span", {
22
+ className: "absolute -top-6 right-0 text-muted-foreground text-xs",
23
+ children: [value, "%"]
24
+ })]
25
+ });
26
+ });
27
+ Progress.displayName = ProgressPrimitive.Root.displayName;
28
+ //#endregion
29
+ export { Progress };
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ //#region src/primitives/segmented-control.d.ts
3
+ /**
4
+ * Visually lightweight segmented control for single-value selection.
5
+ *
6
+ * Uses role="radiogroup" / role="radio" because this is a value-selector
7
+ * with no associated panels — not a tab interface. Arrow keys navigate
8
+ * between options (with wrapping), Home/End jump to first/last.
9
+ *
10
+ * **Accessibility:** Provide either `aria-label` or `aria-labelledby` — the
11
+ * ARIA spec requires every radiogroup to have an accessible name. A dev-mode
12
+ * console warning fires when both are omitted.
13
+ *
14
+ * Design rules baked into the default variant:
15
+ * - Only the SELECTED segment shows a surface colour + accent text.
16
+ * - Unselected segments have NO background — they're plain-text labels
17
+ * that darken on hover. This keeps the selected segment as the
18
+ * single visual anchor instead of the whole group competing with
19
+ * itself.
20
+ */
21
+ export interface SegmentedControlOption<T extends string = string> {
22
+ value: T;
23
+ label: React.ReactNode;
24
+ /** Rendered right of the label, typically a count or status pill. */
25
+ adornment?: React.ReactNode;
26
+ }
27
+ export interface SegmentedControlProps<T extends string = string> extends Pick<React.HTMLAttributes<HTMLDivElement>, "id" | "className" | "aria-label" | "aria-labelledby"> {
28
+ value: T;
29
+ onValueChange: (value: T) => void;
30
+ options: SegmentedControlOption<T>[];
31
+ /**
32
+ * Layout:
33
+ * - "row" — horizontal pill bar (default, fits in a header region)
34
+ * - "tabs" — horizontal with a bottom border so the selected pill
35
+ * reads as a classic tab (used on the Team page)
36
+ */
37
+ variant?: "row" | "tabs";
38
+ }
39
+ export declare function SegmentedControl<T extends string = string>({ value, onValueChange, options, variant, className, ...rest }: SegmentedControlProps<T>): React.JSX.Element;
40
+ //#endregion
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { focusRing, focusRingInset } from "../lib/focus.js";
3
+ import { cn } from "../lib/utils.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/primitives/segmented-control.tsx
7
+ function SegmentedControl({ value, onValueChange, options, variant = "row", className, ...rest }) {
8
+ if (typeof process !== "undefined" && process?.env?.NODE_ENV !== "production" && !rest["aria-label"] && !rest["aria-labelledby"]) console.warn("[SegmentedControl] role=\"radiogroup\" requires either aria-label or aria-labelledby for accessibility.");
9
+ const optionRefs = React.useRef(/* @__PURE__ */ new Map());
10
+ const hasMatch = options.some((o) => o.value === value);
11
+ const handleKeyDown = (e) => {
12
+ if (options.length === 0) return;
13
+ let idx = options.findIndex((o) => o.value === value);
14
+ if (idx === -1) idx = 0;
15
+ let next;
16
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") next = (idx + 1) % options.length;
17
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp") next = (idx - 1 + options.length) % options.length;
18
+ else if (e.key === "Home") next = 0;
19
+ else if (e.key === "End") next = options.length - 1;
20
+ if (next !== void 0) {
21
+ e.preventDefault();
22
+ if (options[next].value !== value) onValueChange(options[next].value);
23
+ optionRefs.current.get(options[next].value)?.focus();
24
+ }
25
+ };
26
+ return /* @__PURE__ */ jsx("div", {
27
+ role: "radiogroup",
28
+ id: rest.id,
29
+ "aria-label": rest["aria-label"],
30
+ "aria-labelledby": rest["aria-labelledby"],
31
+ onKeyDown: handleKeyDown,
32
+ className: cn("flex gap-1", variant === "row" && "flex-wrap items-center rounded-lg border border-border bg-card p-1", variant === "tabs" && "flex-nowrap items-end border-b border-border pb-0 overflow-x-auto", className),
33
+ children: options.map((option, i) => {
34
+ const active = option.value === value;
35
+ return /* @__PURE__ */ jsxs("button", {
36
+ ref: (el) => {
37
+ if (el) optionRefs.current.set(option.value, el);
38
+ else optionRefs.current.delete(option.value);
39
+ },
40
+ type: "button",
41
+ role: "radio",
42
+ "aria-checked": active,
43
+ tabIndex: active || !hasMatch && i === 0 ? 0 : -1,
44
+ onClick: () => {
45
+ if (!active) onValueChange(option.value);
46
+ },
47
+ className: cn("relative inline-flex items-center gap-2 whitespace-nowrap text-sm transition-[color,background-color,border-color,box-shadow]", variant === "row" && ["rounded-md px-3 py-1.5", focusRing], variant === "tabs" && ["rounded-none border-b-2 -mb-px px-4 py-2", focusRingInset], active ? variant === "row" ? "border border-transparent bg-[var(--accent-surface)] text-[var(--accent-text)] font-semibold" : "border-[var(--accent-text)] text-[var(--accent-text)] font-semibold" : variant === "row" ? "border border-transparent text-muted-foreground hover:text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"),
48
+ children: [/* @__PURE__ */ jsx("span", { children: option.label }), option.adornment && /* @__PURE__ */ jsx("span", {
49
+ className: cn("text-xs", active ? "text-[var(--accent-text)]/80" : "text-muted-foreground"),
50
+ children: option.adornment
51
+ })]
52
+ }, option.value);
53
+ })
54
+ });
55
+ }
56
+ //#endregion
57
+ export { SegmentedControl };
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import * as SelectPrimitive from "@radix-ui/react-select";
3
+ //#region src/primitives/select.d.ts
4
+ declare const Select: React.FC<SelectPrimitive.SelectProps>;
5
+ declare const SelectGroup: React.ForwardRefExoticComponent<SelectPrimitive.SelectGroupProps & React.RefAttributes<HTMLDivElement>>;
6
+ declare const SelectValue: React.ForwardRefExoticComponent<SelectPrimitive.SelectValueProps & React.RefAttributes<HTMLSpanElement>>;
7
+ declare const SelectTrigger: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
8
+ declare const SelectScrollUpButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollUpButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
9
+ declare const SelectScrollDownButton: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectScrollDownButtonProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
10
+ declare const SelectContent: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
11
+ declare const SelectLabel: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
12
+ declare const SelectItem: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
13
+ declare const SelectSeparator: React.ForwardRefExoticComponent<Omit<SelectPrimitive.SelectSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
14
+ //#endregion
15
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { focusField } from "../lib/focus.js";
3
+ import { cn } from "../lib/utils.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Check, ChevronDown, ChevronUp } from "lucide-react";
7
+ import * as SelectPrimitive from "@radix-ui/react-select";
8
+ //#region src/primitives/select.tsx
9
+ const Select = SelectPrimitive.Root;
10
+ const SelectGroup = SelectPrimitive.Group;
11
+ const SelectValue = SelectPrimitive.Value;
12
+ const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
13
+ ref,
14
+ className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border bg-card px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", focusField, className),
15
+ ...props,
16
+ children: [children, /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
17
+ asChild: true,
18
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 opacity-50" })
19
+ })]
20
+ }));
21
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
22
+ const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.ScrollUpButton, {
23
+ ref,
24
+ className: cn("flex cursor-default items-center justify-center py-1", className),
25
+ ...props,
26
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" })
27
+ }));
28
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
29
+ const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.ScrollDownButton, {
30
+ ref,
31
+ className: cn("flex cursor-default items-center justify-center py-1", className),
32
+ ...props,
33
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
34
+ }));
35
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
36
+ const SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
37
+ ref,
38
+ className: cn("data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-border bg-card text-foreground shadow-[var(--shadow-card)] data-[state=closed]:animate-out data-[state=open]:animate-in", position === "popper" && "data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1", className),
39
+ position,
40
+ ...props,
41
+ children: [
42
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
43
+ /* @__PURE__ */ jsx(SelectPrimitive.Viewport, {
44
+ className: cn("p-1", position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),
45
+ children
46
+ }),
47
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
48
+ ]
49
+ }) }));
50
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
51
+ const SelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Label, {
52
+ ref,
53
+ className: cn("px-2 py-1.5 font-semibold text-sm", className),
54
+ ...props
55
+ }));
56
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
57
+ const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
58
+ ref,
59
+ className: cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pr-8 pl-2 text-sm outline-none focus:bg-muted/50 focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
60
+ ...props,
61
+ children: [/* @__PURE__ */ jsx("span", {
62
+ className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center",
63
+ children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) })
64
+ }), /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })]
65
+ }));
66
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
67
+ const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Separator, {
68
+ ref,
69
+ className: cn("-mx-1 my-1 h-px bg-border", className),
70
+ ...props
71
+ }));
72
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
73
+ //#endregion
74
+ export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/primitives/sidebar-drop-zone.d.ts
3
+ export interface SidebarDropZoneProps {
4
+ /** Called with dropped files */
5
+ onDrop: (files: File[]) => void;
6
+ /** Accepted file types (e.g. ".pdf,.csv") */
7
+ accept?: string;
8
+ /** Whether drop zone is active */
9
+ disabled?: boolean;
10
+ /** Title shown in the drop zone */
11
+ title?: string;
12
+ /** Description shown below the title */
13
+ description?: string;
14
+ /** Custom icon (replaces default upload icon) */
15
+ icon?: ReactNode;
16
+ /** Always visible (not just on drag). Useful as a persistent upload area. */
17
+ persistent?: boolean;
18
+ className?: string;
19
+ }
20
+ export declare function SidebarDropZone({ onDrop, accept, disabled, title, description, icon, persistent, className }: SidebarDropZoneProps): import("react").JSX.Element;
21
+ //#endregion
@@ -0,0 +1,88 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { useCallback, useRef, useState } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Upload } from "lucide-react";
5
+ //#region src/primitives/sidebar-drop-zone.tsx
6
+ /**
7
+ * SidebarDropZone — compact scoped drop zone for sidebar panels and narrow containers.
8
+ *
9
+ * Unlike the full-window DropZone, this renders as an inline element
10
+ * that can be placed inside sidebar panels, file trees, or any container.
11
+ * Shows a subtle drop target when files are dragged over it.
12
+ *
13
+ * Usage:
14
+ * <SidebarPanelContent>
15
+ * <FileTree ... />
16
+ * <SidebarDropZone onDrop={uploadToWorkspace} title="Upload to workspace" />
17
+ * </SidebarPanelContent>
18
+ */
19
+ function SidebarDropZone({ onDrop, accept, disabled, title = "Drop files here", description, icon, persistent = false, className }) {
20
+ const [dragOver, setDragOver] = useState(false);
21
+ const counter = useRef(0);
22
+ const isAccepted = useCallback((file) => {
23
+ if (!accept) return true;
24
+ const extensions = accept.split(",").map((ext) => ext.trim().toLowerCase());
25
+ const fileName = file.name.toLowerCase();
26
+ return extensions.some((ext) => fileName.endsWith(ext));
27
+ }, [accept]);
28
+ const handleDragEnter = useCallback((e) => {
29
+ e.preventDefault();
30
+ e.stopPropagation();
31
+ if (disabled) return;
32
+ counter.current++;
33
+ if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
34
+ }, [disabled]);
35
+ const handleDragLeave = useCallback((e) => {
36
+ e.preventDefault();
37
+ e.stopPropagation();
38
+ counter.current--;
39
+ if (counter.current === 0) setDragOver(false);
40
+ }, []);
41
+ const handleDragOver = useCallback((e) => {
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+ if (!disabled) e.dataTransfer.dropEffect = "copy";
45
+ }, [disabled]);
46
+ const handleDrop = useCallback((e) => {
47
+ e.preventDefault();
48
+ e.stopPropagation();
49
+ counter.current = 0;
50
+ setDragOver(false);
51
+ if (disabled) return;
52
+ const allFiles = Array.from(e.dataTransfer?.files || []);
53
+ const accepted = accept ? allFiles.filter(isAccepted) : allFiles;
54
+ if (accepted.length > 0) onDrop(accepted);
55
+ }, [
56
+ disabled,
57
+ accept,
58
+ isAccepted,
59
+ onDrop
60
+ ]);
61
+ const isVisible = persistent || dragOver;
62
+ return /* @__PURE__ */ jsx("div", {
63
+ onDragEnter: handleDragEnter,
64
+ onDragLeave: handleDragLeave,
65
+ onDragOver: handleDragOver,
66
+ onDrop: handleDrop,
67
+ className: cn("rounded-lg border-2 border-dashed transition-all duration-150", isVisible ? "p-4" : "p-0 border-transparent", dragOver ? "border-[var(--brand-cool,hsl(var(--ring)))] bg-[var(--accent-surface-soft)]" : persistent ? "border-[var(--border-subtle,hsl(var(--border)))] bg-transparent hover:border-[var(--border-default,hsl(var(--border)))] hover:bg-[var(--bg-hover,hsl(var(--accent)))]" : "", disabled && "opacity-50 pointer-events-none", className),
68
+ children: isVisible && /* @__PURE__ */ jsxs("div", {
69
+ className: "flex flex-col items-center gap-2 text-center",
70
+ children: [
71
+ /* @__PURE__ */ jsx("div", {
72
+ className: cn("flex h-8 w-8 items-center justify-center rounded-lg transition-colors", dragOver ? "bg-[var(--brand-cool,hsl(var(--primary)))]/15 text-[var(--brand-cool,hsl(var(--primary)))]" : "text-[var(--text-muted,hsl(var(--muted-foreground)))]"),
73
+ children: icon ?? /* @__PURE__ */ jsx(Upload, { className: "h-4 w-4" })
74
+ }),
75
+ /* @__PURE__ */ jsx("p", {
76
+ className: cn("text-xs font-medium", dragOver ? "text-[var(--text-primary,hsl(var(--foreground)))]" : "text-[var(--text-muted,hsl(var(--muted-foreground)))]"),
77
+ children: title
78
+ }),
79
+ description && /* @__PURE__ */ jsx("p", {
80
+ className: "text-[10px] text-[var(--text-muted,hsl(var(--muted-foreground)))]",
81
+ children: description
82
+ })
83
+ ]
84
+ })
85
+ });
86
+ }
87
+ //#endregion
88
+ export { SidebarDropZone };
@@ -0,0 +1,10 @@
1
+ //#region src/primitives/skeleton.d.ts
2
+ declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
3
+ declare function SkeletonCard({ className }: {
4
+ className?: string;
5
+ }): import("react").JSX.Element;
6
+ declare function SkeletonTable({ rows }: {
7
+ rows?: number;
8
+ }): import("react").JSX.Element;
9
+ //#endregion
10
+ export { Skeleton, SkeletonCard, SkeletonTable };
@@ -0,0 +1,50 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/primitives/skeleton.tsx
4
+ function Skeleton({ className, ...props }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ className: cn("animate-pulse rounded-lg bg-muted/50", className),
7
+ ...props
8
+ });
9
+ }
10
+ function SkeletonCard({ className }) {
11
+ return /* @__PURE__ */ jsxs("div", {
12
+ className: cn("space-y-4 rounded-xl border border-border bg-card p-6", className),
13
+ children: [
14
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }),
15
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/2" }),
16
+ /* @__PURE__ */ jsxs("div", {
17
+ className: "space-y-2 pt-4",
18
+ children: [
19
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full" }),
20
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-5/6" }),
21
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-4/6" })
22
+ ]
23
+ })
24
+ ]
25
+ });
26
+ }
27
+ function SkeletonTable({ rows = 5 }) {
28
+ return /* @__PURE__ */ jsxs("div", {
29
+ className: "space-y-3",
30
+ children: [/* @__PURE__ */ jsxs("div", {
31
+ className: "flex gap-4 border-border border-b pb-2",
32
+ children: [
33
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
34
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
35
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
36
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" })
37
+ ]
38
+ }), Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs("div", {
39
+ className: "flex gap-4",
40
+ children: [
41
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
42
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
43
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" }),
44
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/4" })
45
+ ]
46
+ }, i))]
47
+ });
48
+ }
49
+ //#endregion
50
+ export { Skeleton, SkeletonCard, SkeletonTable };
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ //#region src/primitives/stat-card.d.ts
3
+ export interface StatCardProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ variant?: "default" | "sandbox";
5
+ title: string;
6
+ value: string | number;
7
+ subtitle?: string;
8
+ icon?: React.ReactNode;
9
+ trend?: {
10
+ value: number;
11
+ label?: string;
12
+ };
13
+ }
14
+ declare const StatCard: React.ForwardRefExoticComponent<StatCardProps & React.RefAttributes<HTMLDivElement>>;
15
+ //#endregion
16
+ export { StatCard };
@@ -0,0 +1,60 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Card } from "./card.js";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/primitives/stat-card.tsx
6
+ const StatCard = React.forwardRef(({ className, variant = "default", title, value, subtitle, icon, trend, ...props }, ref) => {
7
+ const iconColors = {
8
+ default: "text-muted-foreground",
9
+ sandbox: "text-[var(--accent-text)]"
10
+ };
11
+ const trendColors = {
12
+ positive: "text-[var(--surface-success-text)]",
13
+ negative: "text-[var(--surface-danger-text)]",
14
+ neutral: "text-muted-foreground"
15
+ };
16
+ const trendStatus = trend ? trend.value > 0 ? "positive" : trend.value < 0 ? "negative" : "neutral" : null;
17
+ return /* @__PURE__ */ jsx(Card, {
18
+ ref,
19
+ variant,
20
+ className: cn("p-6", className),
21
+ ...props,
22
+ children: /* @__PURE__ */ jsxs("div", {
23
+ className: "flex items-start justify-between",
24
+ children: [/* @__PURE__ */ jsxs("div", {
25
+ className: "space-y-1",
26
+ children: [
27
+ /* @__PURE__ */ jsx("p", {
28
+ className: "text-muted-foreground text-sm",
29
+ children: title
30
+ }),
31
+ /* @__PURE__ */ jsx("p", {
32
+ className: "font-bold text-3xl tracking-tight",
33
+ children: value
34
+ }),
35
+ subtitle && /* @__PURE__ */ jsx("p", {
36
+ className: "text-[var(--text-dim)] text-xs",
37
+ children: subtitle
38
+ }),
39
+ trend && trendStatus && /* @__PURE__ */ jsxs("div", {
40
+ className: cn("flex items-center gap-1 text-sm", trendColors[trendStatus]),
41
+ children: [
42
+ trend.value > 0 ? "↑" : trend.value < 0 ? "↓" : "→",
43
+ /* @__PURE__ */ jsxs("span", { children: [Math.abs(trend.value), "%"] }),
44
+ trend.label && /* @__PURE__ */ jsx("span", {
45
+ className: "text-muted-foreground",
46
+ children: trend.label
47
+ })
48
+ ]
49
+ })
50
+ ]
51
+ }), icon && /* @__PURE__ */ jsx("div", {
52
+ className: cn("rounded-lg bg-muted/50 p-2", variant === "sandbox" && "bg-[var(--accent-surface-soft)]", iconColors[variant]),
53
+ children: icon
54
+ })]
55
+ })
56
+ });
57
+ });
58
+ StatCard.displayName = "StatCard";
59
+ //#endregion
60
+ export { StatCard };
@@ -0,0 +1,44 @@
1
+ import * as React from "react";
2
+ //#region src/primitives/status-pill.d.ts
3
+ /**
4
+ * A run/resource state, told three ways at once.
5
+ *
6
+ * Status is the one place a console cannot afford to speak in colour alone: a
7
+ * red dot and a green dot are the same dot to roughly one man in twelve, and
8
+ * identical in a greyscale print or a screenshot pasted into a ticket. So every
9
+ * pill carries all three channels — a GLYPH whose silhouette differs per tone,
10
+ * the tone's COLOUR, and the state's own LABEL as text.
11
+ *
12
+ * The glyphs are chosen to survive at 8px and to differ in outline rather than
13
+ * in fill: a ring reads as "still open", a solid disc as "settled", a slashed
14
+ * disc as "stopped". Two states never share one silhouette.
15
+ *
16
+ * Each tone draws its fill, border and text from ONE matched token triple.
17
+ * That pairing is the whole point: a status colour is solved against its own
18
+ * background, and nothing guarantees it against an arbitrary one. A component
19
+ * that always brings its own background cannot be placed onto a plane that
20
+ * breaks it.
21
+ */
22
+ export type StatusTone = "success" | "warning" | "danger" | "info" | "neutral" | "running";
23
+ export interface StatusPillProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
24
+ tone: StatusTone;
25
+ children: React.ReactNode;
26
+ /**
27
+ * Drops the fill and border, leaving a toned GLYPH beside a label in the
28
+ * inherited body colour.
29
+ *
30
+ * The label deliberately does not keep the tone. Every status text token
31
+ * clears the 4.5:1 body floor on the page canvas — a gate holds them there —
32
+ * but in light the margin is thin (4.51:1 for warning, 4.54:1 for success),
33
+ * and the canvas is only one of the planes a caller can put a pill on. The
34
+ * glyph keeps the tone instead because a glyph is non-text content against a
35
+ * 3:1 floor, so the tone still reads with room to spare on any plane.
36
+ *
37
+ * For a control that supplies its own surface (a chip, a selected row).
38
+ */
39
+ bare?: boolean;
40
+ size?: "sm" | "md";
41
+ }
42
+ declare const StatusPill: React.ForwardRefExoticComponent<StatusPillProps & React.RefAttributes<HTMLSpanElement>>;
43
+ //#endregion
44
+ export { StatusPill };
@@ -0,0 +1,119 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import * as React from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/primitives/status-pill.tsx
5
+ const TONE_SURFACE = {
6
+ success: "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] border-[var(--surface-success-border)]",
7
+ warning: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border-[var(--surface-warning-border)]",
8
+ danger: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border-[var(--surface-danger-border)]",
9
+ info: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
10
+ running: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
11
+ neutral: "bg-[var(--surface-neutral-bg)] text-[var(--surface-neutral-text)] border-[var(--surface-neutral-border)]"
12
+ };
13
+ /**
14
+ * The text tier alone, for `bare`. Declared rather than recovered from
15
+ * `TONE_SURFACE` by string search: picking the `text-` class out of that string
16
+ * silently yields `undefined` the moment the triple gains a second `text-`
17
+ * utility, and an undefined class removes the tone from the one channel `bare`
18
+ * has left — the glyph — with nothing to signal that it happened.
19
+ */
20
+ const TONE_TEXT = {
21
+ success: "text-[var(--surface-success-text)]",
22
+ warning: "text-[var(--surface-warning-text)]",
23
+ danger: "text-[var(--surface-danger-text)]",
24
+ info: "text-[var(--surface-info-text)]",
25
+ running: "text-[var(--surface-info-text)]",
26
+ neutral: "text-[var(--surface-neutral-text)]"
27
+ };
28
+ /**
29
+ * One glyph per silhouette. `currentColor` throughout so the mark inherits the
30
+ * tone's text colour and can never drift from the label beside it.
31
+ */
32
+ function ToneGlyph({ tone }) {
33
+ const common = {
34
+ viewBox: "0 0 8 8",
35
+ className: "size-2 shrink-0"
36
+ };
37
+ switch (tone) {
38
+ case "success": return /* @__PURE__ */ jsx("svg", {
39
+ ...common,
40
+ "aria-hidden": "true",
41
+ fill: "currentColor",
42
+ children: /* @__PURE__ */ jsx("circle", {
43
+ cx: "4",
44
+ cy: "4",
45
+ r: "3.25"
46
+ })
47
+ });
48
+ case "danger": return /* @__PURE__ */ jsxs("svg", {
49
+ ...common,
50
+ "aria-hidden": "true",
51
+ fill: "none",
52
+ stroke: "currentColor",
53
+ strokeWidth: "1.5",
54
+ children: [/* @__PURE__ */ jsx("circle", {
55
+ cx: "4",
56
+ cy: "4",
57
+ r: "3.1",
58
+ fill: "currentColor",
59
+ opacity: "0.35"
60
+ }), /* @__PURE__ */ jsx("path", {
61
+ d: "M1.9 6.1 6.1 1.9",
62
+ strokeLinecap: "round"
63
+ })]
64
+ });
65
+ case "warning": return /* @__PURE__ */ jsx("svg", {
66
+ ...common,
67
+ "aria-hidden": "true",
68
+ fill: "currentColor",
69
+ children: /* @__PURE__ */ jsx("path", { d: "M4 0.6 7.7 7.1H0.3z" })
70
+ });
71
+ case "running": return /* @__PURE__ */ jsx("svg", {
72
+ ...common,
73
+ "aria-hidden": "true",
74
+ fill: "none",
75
+ stroke: "currentColor",
76
+ strokeWidth: "1.75",
77
+ children: /* @__PURE__ */ jsx("circle", {
78
+ cx: "4",
79
+ cy: "4",
80
+ r: "2.9"
81
+ })
82
+ });
83
+ case "info": return /* @__PURE__ */ jsx("svg", {
84
+ ...common,
85
+ "aria-hidden": "true",
86
+ fill: "currentColor",
87
+ children: /* @__PURE__ */ jsx("rect", {
88
+ x: "0.9",
89
+ y: "0.9",
90
+ width: "6.2",
91
+ height: "6.2",
92
+ rx: "1.2"
93
+ })
94
+ });
95
+ default: return /* @__PURE__ */ jsx("svg", {
96
+ ...common,
97
+ "aria-hidden": "true",
98
+ fill: "none",
99
+ stroke: "currentColor",
100
+ strokeWidth: "1.75",
101
+ children: /* @__PURE__ */ jsx("path", {
102
+ d: "M1 4h6",
103
+ strokeLinecap: "round"
104
+ })
105
+ });
106
+ }
107
+ }
108
+ const StatusPill = React.forwardRef(({ className, tone, children, bare = false, size = "sm", ...props }, ref) => /* @__PURE__ */ jsxs("span", {
109
+ ref,
110
+ className: cn("inline-flex items-center gap-1.5 whitespace-nowrap rounded-full font-medium", size === "sm" ? "px-2 py-0.5 text-xs" : "px-2.5 py-1 text-sm", bare ? "border border-transparent bg-transparent px-0" : cn("border", TONE_SURFACE[tone]), className),
111
+ ...props,
112
+ children: [/* @__PURE__ */ jsx("span", {
113
+ className: cn("inline-flex", bare && TONE_TEXT[tone]),
114
+ children: /* @__PURE__ */ jsx(ToneGlyph, { tone })
115
+ }), children]
116
+ }));
117
+ StatusPill.displayName = "StatusPill";
118
+ //#endregion
119
+ export { StatusPill };
@@ -0,0 +1,6 @@
1
+ import * as React from "react";
2
+ import * as SwitchPrimitives from "@radix-ui/react-switch";
3
+ //#region src/primitives/switch.d.ts
4
+ declare const Switch: React.ForwardRefExoticComponent<Omit<SwitchPrimitives.SwitchProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
5
+ //#endregion
6
+ export { Switch };