@tangle-network/ui 11.10.0 → 11.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +4 -1
  3. package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
  4. package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
  5. package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
  6. package/dist/artifact-pane-DMXT9a8U.js +70 -0
  7. package/dist/auth-DOETfnd9.js +154 -0
  8. package/dist/auth.d.ts +2 -74
  9. package/dist/auth.js +2 -16
  10. package/dist/branding-26d5ARIr.d.ts +14 -0
  11. package/dist/button-C87nEe2R.js +78 -0
  12. package/dist/button-yoIv77e2.d.ts +16 -0
  13. package/dist/chat-D4jAfEmj.js +667 -0
  14. package/dist/chat.d.ts +2 -201
  15. package/dist/chat.js +2 -31
  16. package/dist/code-block-B36KVUSN.js +165 -0
  17. package/dist/code-block-B9miUPht.d.ts +23 -0
  18. package/dist/diff-preview-BcK3nRXb.js +533 -0
  19. package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
  20. package/dist/document-editor-pane-BxlPjaTP.js +1287 -0
  21. package/dist/dropdown-menu-BpcLa5vF.js +101 -0
  22. package/dist/editor.d.ts +76 -78
  23. package/dist/editor.js +2 -34
  24. package/dist/file-format-BgXbr-Ib.js +160 -0
  25. package/dist/files-Bug33qCl.js +743 -0
  26. package/dist/files.d.ts +2 -243
  27. package/dist/files.js +3 -41
  28. package/dist/focus-BcE_SHqz.js +57 -0
  29. package/dist/format-DfcLWqMa.js +54 -0
  30. package/dist/hooks.d.ts +30 -37
  31. package/dist/hooks.js +111 -46
  32. package/dist/index-2UntyjBb.d.ts +52 -0
  33. package/dist/index-BgUHilZm.d.ts +108 -0
  34. package/dist/index-COgqsFAQ.d.ts +42 -0
  35. package/dist/index-CPDET_s1.d.ts +549 -0
  36. package/dist/index-CUhfHT_V.d.ts +204 -0
  37. package/dist/index-Cg6gYAqh.d.ts +73 -0
  38. package/dist/index-Cq-EJzqW.d.ts +16 -0
  39. package/dist/index-DhYmSaLF.d.ts +245 -0
  40. package/dist/index-DjKxO357.d.ts +128 -0
  41. package/dist/index.d.ts +26 -43
  42. package/dist/index.js +35 -472
  43. package/dist/markdown-BGqicV82.js +45 -0
  44. package/dist/markdown.d.ts +3 -18
  45. package/dist/markdown.js +3 -15
  46. package/dist/message-vhUI0c5G.d.ts +16 -0
  47. package/dist/nav.d.ts +6 -8
  48. package/dist/nav.js +29 -11
  49. package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
  50. package/dist/openui-artifact-renderer-DrU1AdVk.js +266 -0
  51. package/dist/openui.d.ts +2 -115
  52. package/dist/openui.js +2 -13
  53. package/dist/parts-5mhy9yJ3.d.ts +37 -0
  54. package/dist/primitives-Cb8GGVKr.js +1239 -0
  55. package/dist/primitives.d.ts +5 -525
  56. package/dist/primitives.js +9 -212
  57. package/dist/redaction-CGGB2ENG.js +74 -0
  58. package/dist/redaction.d.ts +2 -42
  59. package/dist/redaction.js +2 -7
  60. package/dist/run-OyWmIDqu.d.ts +41 -0
  61. package/dist/run-ZsIKPA6J.js +17 -0
  62. package/dist/run-group-BACLbCFl.js +410 -0
  63. package/dist/run.d.ts +3 -126
  64. package/dist/run.js +5 -40
  65. package/dist/sdk-hooks.d.ts +2 -285
  66. package/dist/sdk-hooks.js +3 -36
  67. package/dist/stores.d.ts +13 -14
  68. package/dist/stores.js +34 -76
  69. package/dist/table-Bss73DhB.js +146 -0
  70. package/dist/tabs-BVHR6NkO.js +40 -0
  71. package/dist/text-shimmer-BUUo6I-g.js +64 -0
  72. package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
  73. package/dist/tool-call-feed-Djt2q11V.js +109 -0
  74. package/dist/tool-call-step-DNebqhmX.js +434 -0
  75. package/dist/tool-display-BAuAVa43.js +158 -0
  76. package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
  77. package/dist/tool-previews.d.ts +2 -48
  78. package/dist/tool-previews.js +2 -23
  79. package/dist/types.d.ts +6 -19
  80. package/dist/types.js +0 -1
  81. package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
  82. package/dist/use-sse-stream-BVgO1QBN.js +884 -0
  83. package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
  84. package/dist/utils-Bl_CZ0Qp.js +37 -0
  85. package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
  86. package/dist/utils.d.ts +2 -104
  87. package/dist/utils.js +6 -44
  88. package/package.json +39 -41
  89. package/src/lib/focus.ts +2 -1
  90. package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
  91. package/dist/button-CMQuQEW_.d.ts +0 -17
  92. package/dist/chunk-34A66VBG.js +0 -214
  93. package/dist/chunk-3OI2QKFD.js +0 -0
  94. package/dist/chunk-3XXBZL53.js +0 -174
  95. package/dist/chunk-42PAH5D2.js +0 -112
  96. package/dist/chunk-4CLN43XT.js +0 -45
  97. package/dist/chunk-55WHV7SS.js +0 -1604
  98. package/dist/chunk-565EATZZ.js +0 -156
  99. package/dist/chunk-5Z5ZYMOJ.js +0 -0
  100. package/dist/chunk-6BGQA4BQ.js +0 -0
  101. package/dist/chunk-BEBXZPHW.js +0 -299
  102. package/dist/chunk-C5WF4WMV.js +0 -734
  103. package/dist/chunk-HFL6R6IF.js +0 -37
  104. package/dist/chunk-HGML45QH.js +0 -104
  105. package/dist/chunk-HMAPIH7L.js +0 -595
  106. package/dist/chunk-K5XFRUS4.js +0 -1401
  107. package/dist/chunk-KFQGHD73.js +0 -198
  108. package/dist/chunk-L57WRIND.js +0 -59
  109. package/dist/chunk-LTEKI7YJ.js +0 -59
  110. package/dist/chunk-M3QZK62R.js +0 -233
  111. package/dist/chunk-ND3ZFXQK.js +0 -179
  112. package/dist/chunk-OEX7NZE3.js +0 -321
  113. package/dist/chunk-OL5GYLHV.js +0 -60
  114. package/dist/chunk-QGFYBNSO.js +0 -133
  115. package/dist/chunk-R7B3UWPF.js +0 -550
  116. package/dist/chunk-R7SUY4E3.js +0 -65
  117. package/dist/chunk-REJESC5U.js +0 -117
  118. package/dist/chunk-RQGKSCEZ.js +0 -0
  119. package/dist/chunk-SNLR2AEA.js +0 -40
  120. package/dist/chunk-WKWBTL2V.js +0 -15
  121. package/dist/chunk-X7CU776B.js +0 -1048
  122. package/dist/chunk-XU3HB5QL.js +0 -127
  123. package/dist/chunk-YTO5V6QS.js +0 -19
  124. package/dist/chunk-YU4E5J2N.js +0 -437
  125. package/dist/chunk-YZ6AK25N.js +0 -886
  126. package/dist/code-block-0kSpWMnf.d.ts +0 -25
  127. package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
  128. package/dist/document-editor-pane-QHDOBA43.js +0 -13
  129. package/dist/message-BHWbxBtT.d.ts +0 -15
  130. package/dist/parts-dj7AcUg0.d.ts +0 -36
  131. package/dist/run-PfLmDAox.d.ts +0 -41
  132. package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
@@ -1,1604 +0,0 @@
1
- import {
2
- Card
3
- } from "./chunk-M3QZK62R.js";
4
- import {
5
- focusField,
6
- focusFieldInvalid,
7
- focusFieldWithin,
8
- focusRing,
9
- focusRingInset
10
- } from "./chunk-WKWBTL2V.js";
11
- import {
12
- cn
13
- } from "./chunk-RQHJBTEU.js";
14
-
15
- // src/primitives/dialog.tsx
16
- import * as DialogPrimitive from "@radix-ui/react-dialog";
17
- import { X } from "lucide-react";
18
- import * as React from "react";
19
- import { jsx, jsxs } from "react/jsx-runtime";
20
- var Dialog = DialogPrimitive.Root;
21
- var DialogTrigger = DialogPrimitive.Trigger;
22
- var DialogPortal = DialogPrimitive.Portal;
23
- var DialogClose = DialogPrimitive.Close;
24
- var DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
25
- DialogPrimitive.Overlay,
26
- {
27
- ref,
28
- className: cn(
29
- "fixed inset-0 z-50 bg-black/40",
30
- "data-[state=closed]:animate-out data-[state=open]:animate-in",
31
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
32
- className
33
- ),
34
- ...props
35
- }
36
- ));
37
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
38
- var DialogContent = React.forwardRef(({ className, children, variant = "default", ...props }, ref) => {
39
- const variants = {
40
- default: "border-border",
41
- sandbox: "border-[var(--border-accent)] shadow-[var(--shadow-accent)]"
42
- };
43
- return /* @__PURE__ */ jsxs(DialogPortal, { children: [
44
- /* @__PURE__ */ jsx(DialogOverlay, {}),
45
- /* @__PURE__ */ jsxs(
46
- DialogPrimitive.Content,
47
- {
48
- ref,
49
- className: cn(
50
- "fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%]",
51
- "gap-4 rounded-lg border bg-card p-6 shadow-lg duration-200",
52
- "data-[state=closed]:animate-out data-[state=open]:animate-in",
53
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
54
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
55
- "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
56
- "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
57
- variants[variant],
58
- className
59
- ),
60
- ...props,
61
- children: [
62
- children,
63
- /* @__PURE__ */ jsxs(
64
- DialogPrimitive.Close,
65
- {
66
- className: cn(
67
- "absolute top-4 right-4 rounded-sm opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
68
- focusRing
69
- ),
70
- children: [
71
- /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
72
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
73
- ]
74
- }
75
- )
76
- ]
77
- }
78
- )
79
- ] });
80
- });
81
- DialogContent.displayName = DialogPrimitive.Content.displayName;
82
- var DialogHeader = ({
83
- className,
84
- ...props
85
- }) => /* @__PURE__ */ jsx(
86
- "div",
87
- {
88
- className: cn(
89
- "flex flex-col space-y-1.5 text-center sm:text-left",
90
- className
91
- ),
92
- ...props
93
- }
94
- );
95
- DialogHeader.displayName = "DialogHeader";
96
- var DialogFooter = ({
97
- className,
98
- ...props
99
- }) => /* @__PURE__ */ jsx(
100
- "div",
101
- {
102
- className: cn(
103
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
104
- className
105
- ),
106
- ...props
107
- }
108
- );
109
- DialogFooter.displayName = "DialogFooter";
110
- var DialogTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
111
- DialogPrimitive.Title,
112
- {
113
- ref,
114
- className: cn(
115
- "font-semibold text-lg leading-none tracking-tight",
116
- className
117
- ),
118
- ...props
119
- }
120
- ));
121
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
122
- var DialogDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
123
- DialogPrimitive.Description,
124
- {
125
- ref,
126
- className: cn("text-muted-foreground text-sm", className),
127
- ...props
128
- }
129
- ));
130
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
131
-
132
- // src/primitives/input.tsx
133
- import * as React2 from "react";
134
- import { cva } from "class-variance-authority";
135
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
136
- var inputVariants = cva(
137
- cn(
138
- "flex w-full rounded-lg border bg-card px-4 py-2 text-sm placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 file:border-0 file:bg-transparent file:font-medium file:text-sm",
139
- focusField
140
- ),
141
- {
142
- variants: {
143
- // `default` and `sandbox` render the same field; both names stay valid.
144
- variant: {
145
- default: "",
146
- sandbox: "",
147
- error: focusFieldInvalid
148
- },
149
- size: {
150
- default: "h-11",
151
- sm: "h-9 px-3",
152
- lg: "h-12 px-5"
153
- }
154
- },
155
- defaultVariants: {
156
- variant: "default",
157
- size: "default"
158
- }
159
- }
160
- );
161
- var Input = React2.forwardRef(
162
- ({ className, type, variant, size, label, error, hint, id, ...props }, ref) => {
163
- const inputId = id ?? label?.toLowerCase().replace(/\s+/g, "-");
164
- const input = /* @__PURE__ */ jsx2(
165
- "input",
166
- {
167
- type,
168
- id: inputId,
169
- className: cn(inputVariants({ variant: error ? "error" : variant, size, className })),
170
- ref,
171
- ...props
172
- }
173
- );
174
- if (!label && !error && !hint) return input;
175
- return /* @__PURE__ */ jsxs2("div", { className: "w-full space-y-1.5", children: [
176
- label && /* @__PURE__ */ jsx2(
177
- "label",
178
- {
179
- htmlFor: inputId,
180
- className: "block font-medium text-foreground text-sm",
181
- children: label
182
- }
183
- ),
184
- input,
185
- error && /* @__PURE__ */ jsx2("p", { className: "text-[var(--surface-danger-text)] text-sm font-medium", children: error }),
186
- hint && !error && /* @__PURE__ */ jsx2("p", { className: "text-[var(--text-dim)] text-sm", children: hint })
187
- ] });
188
- }
189
- );
190
- Input.displayName = "Input";
191
- var Textarea = React2.forwardRef(
192
- ({ className, variant: _variant, label, error, hint, id, ...props }, ref) => {
193
- const textareaId = id ?? label?.toLowerCase().replace(/\s+/g, "-");
194
- const textarea = /* @__PURE__ */ jsx2(
195
- "textarea",
196
- {
197
- id: textareaId,
198
- className: cn(
199
- "flex min-h-[120px] w-full resize-y rounded-lg border bg-card px-4 py-3 text-sm",
200
- "placeholder:text-muted-foreground",
201
- "disabled:cursor-not-allowed disabled:opacity-50",
202
- focusField,
203
- error && focusFieldInvalid,
204
- className
205
- ),
206
- ref,
207
- ...props
208
- }
209
- );
210
- if (!label && !error && !hint) return textarea;
211
- return /* @__PURE__ */ jsxs2("div", { className: "w-full space-y-1.5", children: [
212
- label && /* @__PURE__ */ jsx2(
213
- "label",
214
- {
215
- htmlFor: textareaId,
216
- className: "block font-medium text-muted-foreground text-sm",
217
- children: label
218
- }
219
- ),
220
- textarea,
221
- error && /* @__PURE__ */ jsx2("p", { className: "text-[var(--surface-danger-text)] text-sm", children: error }),
222
- hint && !error && /* @__PURE__ */ jsx2("p", { className: "text-[var(--text-dim)] text-sm", children: hint })
223
- ] });
224
- }
225
- );
226
- Textarea.displayName = "Textarea";
227
-
228
- // src/primitives/select.tsx
229
- import * as SelectPrimitive from "@radix-ui/react-select";
230
- import { Check, ChevronDown, ChevronUp } from "lucide-react";
231
- import * as React3 from "react";
232
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
233
- var Select = SelectPrimitive.Root;
234
- var SelectGroup = SelectPrimitive.Group;
235
- var SelectValue = SelectPrimitive.Value;
236
- var SelectTrigger = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
237
- SelectPrimitive.Trigger,
238
- {
239
- ref,
240
- className: cn(
241
- "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",
242
- focusField,
243
- className
244
- ),
245
- ...props,
246
- children: [
247
- children,
248
- /* @__PURE__ */ jsx3(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx3(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
249
- ]
250
- }
251
- ));
252
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
253
- var SelectScrollUpButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
254
- SelectPrimitive.ScrollUpButton,
255
- {
256
- ref,
257
- className: cn(
258
- "flex cursor-default items-center justify-center py-1",
259
- className
260
- ),
261
- ...props,
262
- children: /* @__PURE__ */ jsx3(ChevronUp, { className: "h-4 w-4" })
263
- }
264
- ));
265
- SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
266
- var SelectScrollDownButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
267
- SelectPrimitive.ScrollDownButton,
268
- {
269
- ref,
270
- className: cn(
271
- "flex cursor-default items-center justify-center py-1",
272
- className
273
- ),
274
- ...props,
275
- children: /* @__PURE__ */ jsx3(ChevronDown, { className: "h-4 w-4" })
276
- }
277
- ));
278
- SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
279
- var SelectContent = React3.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx3(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs3(
280
- SelectPrimitive.Content,
281
- {
282
- ref,
283
- className: cn(
284
- "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",
285
- 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",
286
- className
287
- ),
288
- position,
289
- ...props,
290
- children: [
291
- /* @__PURE__ */ jsx3(SelectScrollUpButton, {}),
292
- /* @__PURE__ */ jsx3(
293
- SelectPrimitive.Viewport,
294
- {
295
- className: cn(
296
- "p-1",
297
- position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
298
- ),
299
- children
300
- }
301
- ),
302
- /* @__PURE__ */ jsx3(SelectScrollDownButton, {})
303
- ]
304
- }
305
- ) }));
306
- SelectContent.displayName = SelectPrimitive.Content.displayName;
307
- var SelectLabel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
308
- SelectPrimitive.Label,
309
- {
310
- ref,
311
- className: cn("px-2 py-1.5 font-semibold text-sm", className),
312
- ...props
313
- }
314
- ));
315
- SelectLabel.displayName = SelectPrimitive.Label.displayName;
316
- var SelectItem = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
317
- SelectPrimitive.Item,
318
- {
319
- ref,
320
- className: cn(
321
- "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",
322
- className
323
- ),
324
- ...props,
325
- children: [
326
- /* @__PURE__ */ jsx3("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx3(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx3(Check, { className: "h-4 w-4" }) }) }),
327
- /* @__PURE__ */ jsx3(SelectPrimitive.ItemText, { children })
328
- ]
329
- }
330
- ));
331
- SelectItem.displayName = SelectPrimitive.Item.displayName;
332
- var SelectSeparator = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
333
- SelectPrimitive.Separator,
334
- {
335
- ref,
336
- className: cn("-mx-1 my-1 h-px bg-border", className),
337
- ...props
338
- }
339
- ));
340
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
341
-
342
- // src/primitives/segmented-control.tsx
343
- import * as React4 from "react";
344
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
345
- function SegmentedControl({
346
- value,
347
- onValueChange,
348
- options,
349
- variant = "row",
350
- className,
351
- ...rest
352
- }) {
353
- if (typeof process !== "undefined" && process?.env?.NODE_ENV !== "production" && !rest["aria-label"] && !rest["aria-labelledby"]) {
354
- console.warn(
355
- '[SegmentedControl] role="radiogroup" requires either aria-label or aria-labelledby for accessibility.'
356
- );
357
- }
358
- const optionRefs = React4.useRef(/* @__PURE__ */ new Map());
359
- const hasMatch = options.some((o) => o.value === value);
360
- const handleKeyDown = (e) => {
361
- if (options.length === 0) return;
362
- let idx = options.findIndex((o) => o.value === value);
363
- if (idx === -1) idx = 0;
364
- let next;
365
- if (e.key === "ArrowRight" || e.key === "ArrowDown") next = (idx + 1) % options.length;
366
- else if (e.key === "ArrowLeft" || e.key === "ArrowUp") next = (idx - 1 + options.length) % options.length;
367
- else if (e.key === "Home") next = 0;
368
- else if (e.key === "End") next = options.length - 1;
369
- if (next !== void 0) {
370
- e.preventDefault();
371
- if (options[next].value !== value) {
372
- onValueChange(options[next].value);
373
- }
374
- optionRefs.current.get(options[next].value)?.focus();
375
- }
376
- };
377
- return /* @__PURE__ */ jsx4(
378
- "div",
379
- {
380
- role: "radiogroup",
381
- id: rest.id,
382
- "aria-label": rest["aria-label"],
383
- "aria-labelledby": rest["aria-labelledby"],
384
- onKeyDown: handleKeyDown,
385
- className: cn(
386
- "flex gap-1",
387
- variant === "row" && "flex-wrap items-center rounded-lg border border-border bg-card p-1",
388
- variant === "tabs" && "flex-nowrap items-end border-b border-border pb-0 overflow-x-auto",
389
- className
390
- ),
391
- children: options.map((option, i) => {
392
- const active = option.value === value;
393
- const focusable = active || !hasMatch && i === 0;
394
- return /* @__PURE__ */ jsxs4(
395
- "button",
396
- {
397
- ref: (el) => {
398
- if (el) optionRefs.current.set(option.value, el);
399
- else optionRefs.current.delete(option.value);
400
- },
401
- type: "button",
402
- role: "radio",
403
- "aria-checked": active,
404
- tabIndex: focusable ? 0 : -1,
405
- onClick: () => {
406
- if (!active) onValueChange(option.value);
407
- },
408
- className: cn(
409
- "relative inline-flex items-center gap-2 whitespace-nowrap text-sm transition-[color,background-color,border-color,box-shadow]",
410
- variant === "row" && ["rounded-md px-3 py-1.5", focusRing],
411
- // The strip scrolls horizontally, which would clip an outer ring.
412
- variant === "tabs" && ["rounded-none border-b-2 -mb-px px-4 py-2", focusRingInset],
413
- // Active styling is the ONLY styled state — unselected
414
- // segments stay transparent on purpose so they don't
415
- // compete visually with the selection.
416
- 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"
417
- ),
418
- children: [
419
- /* @__PURE__ */ jsx4("span", { children: option.label }),
420
- option.adornment && /* @__PURE__ */ jsx4(
421
- "span",
422
- {
423
- className: cn(
424
- "text-xs",
425
- active ? "text-[var(--accent-text)]/80" : "text-muted-foreground"
426
- ),
427
- children: option.adornment
428
- }
429
- )
430
- ]
431
- },
432
- option.value
433
- );
434
- })
435
- }
436
- );
437
- }
438
-
439
- // src/primitives/progress.tsx
440
- import * as ProgressPrimitive from "@radix-ui/react-progress";
441
- import * as React5 from "react";
442
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
443
- var Progress = React5.forwardRef(
444
- ({ className, value, variant = "default", showValue = false, ...props }, ref) => {
445
- const indicatorVariants = {
446
- default: "bg-primary",
447
- sandbox: "bg-[image:var(--accent-gradient-strong)]"
448
- };
449
- return /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
450
- /* @__PURE__ */ jsx5(
451
- ProgressPrimitive.Root,
452
- {
453
- ref,
454
- className: cn(
455
- "relative h-2 w-full overflow-hidden rounded-full bg-muted",
456
- className
457
- ),
458
- ...props,
459
- children: /* @__PURE__ */ jsx5(
460
- ProgressPrimitive.Indicator,
461
- {
462
- className: cn(
463
- "h-full w-full flex-1 transition-all duration-300 ease-out",
464
- indicatorVariants[variant]
465
- ),
466
- style: { transform: `translateX(-${100 - (value || 0)}%)` }
467
- }
468
- )
469
- }
470
- ),
471
- showValue && /* @__PURE__ */ jsxs5("span", { className: "absolute -top-6 right-0 text-muted-foreground text-xs", children: [
472
- value,
473
- "%"
474
- ] })
475
- ] });
476
- }
477
- );
478
- Progress.displayName = ProgressPrimitive.Root.displayName;
479
-
480
- // src/primitives/switch.tsx
481
- import * as SwitchPrimitives from "@radix-ui/react-switch";
482
- import * as React6 from "react";
483
- import { jsx as jsx6 } from "react/jsx-runtime";
484
- var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
485
- SwitchPrimitives.Root,
486
- {
487
- className: cn(
488
- "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-[background-color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
489
- focusRing,
490
- className
491
- ),
492
- ...props,
493
- ref,
494
- children: /* @__PURE__ */ jsx6(
495
- SwitchPrimitives.Thumb,
496
- {
497
- className: cn(
498
- "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
499
- )
500
- }
501
- )
502
- }
503
- ));
504
- Switch.displayName = SwitchPrimitives.Root.displayName;
505
-
506
- // src/primitives/skeleton.tsx
507
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
508
- function Skeleton({
509
- className,
510
- ...props
511
- }) {
512
- return /* @__PURE__ */ jsx7(
513
- "div",
514
- {
515
- className: cn("animate-pulse rounded-lg bg-muted/50", className),
516
- ...props
517
- }
518
- );
519
- }
520
- function SkeletonCard({ className }) {
521
- return /* @__PURE__ */ jsxs6(
522
- "div",
523
- {
524
- className: cn(
525
- "space-y-4 rounded-xl border border-border bg-card p-6",
526
- className
527
- ),
528
- children: [
529
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-3/4" }),
530
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/2" }),
531
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2 pt-4", children: [
532
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-full" }),
533
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-5/6" }),
534
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-4/6" })
535
- ] })
536
- ]
537
- }
538
- );
539
- }
540
- function SkeletonTable({ rows = 5 }) {
541
- return /* @__PURE__ */ jsxs6("div", { className: "space-y-3", children: [
542
- /* @__PURE__ */ jsxs6("div", { className: "flex gap-4 border-border border-b pb-2", children: [
543
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
544
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
545
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
546
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" })
547
- ] }),
548
- Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs6("div", { className: "flex gap-4", children: [
549
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
550
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
551
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" }),
552
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-1/4" })
553
- ] }, i))
554
- ] });
555
- }
556
-
557
- // src/primitives/toast.tsx
558
- import { cva as cva2 } from "class-variance-authority";
559
- import {
560
- AlertCircle,
561
- AlertTriangle,
562
- CheckCircle2,
563
- Info,
564
- X as X2
565
- } from "lucide-react";
566
- import * as React7 from "react";
567
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
568
- var toastVariants = cva2(
569
- "pointer-events-auto relative flex w-full items-center justify-between gap-3 overflow-hidden rounded-lg border p-4 shadow-lg transition-all",
570
- {
571
- variants: {
572
- variant: {
573
- default: "border-border bg-background text-foreground",
574
- success: "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]",
575
- error: "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]",
576
- warning: "border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]",
577
- info: "border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)]"
578
- }
579
- },
580
- defaultVariants: {
581
- variant: "default"
582
- }
583
- }
584
- );
585
- var icons = {
586
- success: CheckCircle2,
587
- error: AlertCircle,
588
- warning: AlertTriangle,
589
- info: Info,
590
- default: Info
591
- };
592
- function ToastComponent({
593
- id,
594
- title,
595
- description,
596
- variant = "default",
597
- onDismiss
598
- }) {
599
- const Icon2 = icons[variant];
600
- return /* @__PURE__ */ jsxs7(
601
- "div",
602
- {
603
- className: cn(toastVariants({ variant })),
604
- role: "alert",
605
- "aria-live": "polite",
606
- children: [
607
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-3", children: [
608
- /* @__PURE__ */ jsx8(Icon2, { className: "h-5 w-5 shrink-0", "aria-hidden": "true" }),
609
- /* @__PURE__ */ jsxs7("div", { className: "flex-1", children: [
610
- /* @__PURE__ */ jsx8("p", { className: "font-medium text-sm", children: title }),
611
- description && /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm opacity-80", children: description })
612
- ] })
613
- ] }),
614
- /* @__PURE__ */ jsx8(
615
- "button",
616
- {
617
- type: "button",
618
- onClick: () => onDismiss(id),
619
- className: cn(
620
- "shrink-0 rounded-md p-1 opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100",
621
- focusRing
622
- ),
623
- "aria-label": "Dismiss notification",
624
- children: /* @__PURE__ */ jsx8(X2, { className: "h-4 w-4" })
625
- }
626
- )
627
- ]
628
- }
629
- );
630
- }
631
- function ToastContainer({ toasts, onDismiss }) {
632
- return /* @__PURE__ */ jsx8(
633
- "div",
634
- {
635
- role: "region",
636
- className: "fixed right-4 bottom-4 z-50 flex max-w-md flex-col gap-2",
637
- "aria-label": "Notifications",
638
- children: toasts.map((toast) => /* @__PURE__ */ jsx8(ToastComponent, { ...toast, onDismiss }, toast.id))
639
- }
640
- );
641
- }
642
- var ToastContext = React7.createContext(null);
643
- function ToastProvider({ children }) {
644
- const [toasts, setToasts] = React7.useState([]);
645
- const dismiss = React7.useCallback((id) => {
646
- setToasts((prev) => prev.filter((t) => t.id !== id));
647
- }, []);
648
- const toast = React7.useCallback(
649
- (input) => {
650
- const id = Math.random().toString(36).slice(2);
651
- const newToast = { id, ...input };
652
- setToasts((prev) => [...prev, newToast]);
653
- const duration = input.duration ?? 5e3;
654
- if (duration > 0) {
655
- setTimeout(() => dismiss(id), duration);
656
- }
657
- },
658
- [dismiss]
659
- );
660
- const success = React7.useCallback(
661
- (title, description) => {
662
- toast({ title, description, variant: "success" });
663
- },
664
- [toast]
665
- );
666
- const error = React7.useCallback(
667
- (title, description) => {
668
- toast({ title, description, variant: "error" });
669
- },
670
- [toast]
671
- );
672
- const warning = React7.useCallback(
673
- (title, description) => {
674
- toast({ title, description, variant: "warning" });
675
- },
676
- [toast]
677
- );
678
- const info = React7.useCallback(
679
- (title, description) => {
680
- toast({ title, description, variant: "info" });
681
- },
682
- [toast]
683
- );
684
- const value = React7.useMemo(
685
- () => ({ toasts, toast, success, error, warning, info, dismiss }),
686
- [toasts, toast, success, error, warning, info, dismiss]
687
- );
688
- return /* @__PURE__ */ jsxs7(ToastContext.Provider, { value, children: [
689
- children,
690
- /* @__PURE__ */ jsx8(ToastContainer, { toasts, onDismiss: dismiss })
691
- ] });
692
- }
693
- function useToast() {
694
- const context = React7.useContext(ToastContext);
695
- if (!context) {
696
- throw new Error("useToast must be used within a ToastProvider");
697
- }
698
- return context;
699
- }
700
-
701
- // src/primitives/label.tsx
702
- import * as LabelPrimitive from "@radix-ui/react-label";
703
- import { cva as cva3 } from "class-variance-authority";
704
- import * as React8 from "react";
705
- import { jsx as jsx9 } from "react/jsx-runtime";
706
- var labelVariants = cva3(
707
- "font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
708
- );
709
- var Label2 = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
710
- LabelPrimitive.Root,
711
- {
712
- ref,
713
- className: cn(labelVariants(), className),
714
- ...props
715
- }
716
- ));
717
- Label2.displayName = LabelPrimitive.Root.displayName;
718
-
719
- // src/primitives/empty-state.tsx
720
- import * as React9 from "react";
721
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
722
- var EmptyState = React9.forwardRef(
723
- ({ className, icon, title, description, action, ...props }, ref) => {
724
- return /* @__PURE__ */ jsxs8(
725
- "div",
726
- {
727
- ref,
728
- className: cn(
729
- "flex flex-col items-center justify-center px-4 py-16 text-center",
730
- className
731
- ),
732
- ...props,
733
- children: [
734
- icon && /* @__PURE__ */ jsx10("div", { className: "mb-4 rounded-full bg-muted p-4 text-muted-foreground", children: icon }),
735
- /* @__PURE__ */ jsx10("h3", { className: "font-semibold text-lg", children: title }),
736
- description && /* @__PURE__ */ jsx10("p", { className: "mt-2 max-w-sm text-muted-foreground text-sm", children: description }),
737
- action && /* @__PURE__ */ jsx10("div", { className: "mt-6", children: action })
738
- ]
739
- }
740
- );
741
- }
742
- );
743
- EmptyState.displayName = "EmptyState";
744
-
745
- // src/primitives/stat-card.tsx
746
- import * as React10 from "react";
747
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
748
- var StatCard = React10.forwardRef(
749
- ({
750
- className,
751
- variant = "default",
752
- title,
753
- value,
754
- subtitle,
755
- icon,
756
- trend,
757
- ...props
758
- }, ref) => {
759
- const iconColors = {
760
- default: "text-muted-foreground",
761
- sandbox: "text-[var(--accent-text)]"
762
- };
763
- const trendColors = {
764
- positive: "text-[var(--surface-success-text)]",
765
- negative: "text-[var(--surface-danger-text)]",
766
- neutral: "text-muted-foreground"
767
- };
768
- const trendStatus = trend ? trend.value > 0 ? "positive" : trend.value < 0 ? "negative" : "neutral" : null;
769
- return /* @__PURE__ */ jsx11(
770
- Card,
771
- {
772
- ref,
773
- variant,
774
- className: cn("p-6", className),
775
- ...props,
776
- children: /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between", children: [
777
- /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
778
- /* @__PURE__ */ jsx11("p", { className: "text-muted-foreground text-sm", children: title }),
779
- /* @__PURE__ */ jsx11("p", { className: "font-bold text-3xl tracking-tight", children: value }),
780
- subtitle && /* @__PURE__ */ jsx11("p", { className: "text-[var(--text-dim)] text-xs", children: subtitle }),
781
- trend && trendStatus && /* @__PURE__ */ jsxs9(
782
- "div",
783
- {
784
- className: cn(
785
- "flex items-center gap-1 text-sm",
786
- trendColors[trendStatus]
787
- ),
788
- children: [
789
- trend.value > 0 ? "\u2191" : trend.value < 0 ? "\u2193" : "\u2192",
790
- /* @__PURE__ */ jsxs9("span", { children: [
791
- Math.abs(trend.value),
792
- "%"
793
- ] }),
794
- trend.label && /* @__PURE__ */ jsx11("span", { className: "text-muted-foreground", children: trend.label })
795
- ]
796
- }
797
- )
798
- ] }),
799
- icon && /* @__PURE__ */ jsx11(
800
- "div",
801
- {
802
- className: cn(
803
- "rounded-lg bg-muted/50 p-2",
804
- variant === "sandbox" && "bg-[var(--accent-surface-soft)]",
805
- iconColors[variant]
806
- ),
807
- children: icon
808
- }
809
- )
810
- ] })
811
- }
812
- );
813
- }
814
- );
815
- StatCard.displayName = "StatCard";
816
-
817
- // src/primitives/index.ts
818
- import { Logo, TangleKnot } from "@tangle-network/brand";
819
-
820
- // src/primitives/terminal-display.tsx
821
- import * as React11 from "react";
822
- import { useEffect, useRef as useRef2 } from "react";
823
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
824
- var TerminalDisplay = React11.forwardRef(
825
- ({
826
- className,
827
- variant = "default",
828
- title = "Terminal",
829
- showHeader = true,
830
- autoScroll = true,
831
- maxHeight = "400px",
832
- children,
833
- ...props
834
- }, ref) => {
835
- const containerRef = useRef2(null);
836
- useEffect(() => {
837
- if (autoScroll && containerRef.current) {
838
- containerRef.current.scrollTop = containerRef.current.scrollHeight;
839
- }
840
- }, [autoScroll]);
841
- const variants = {
842
- default: "border-border",
843
- sandbox: "border-border shadow-[var(--shadow-accent)]"
844
- };
845
- return /* @__PURE__ */ jsxs10(
846
- "div",
847
- {
848
- ref,
849
- className: cn(
850
- "overflow-hidden rounded-xl border bg-background font-mono text-sm",
851
- variants[variant],
852
- className
853
- ),
854
- ...props,
855
- children: [
856
- showHeader && /* @__PURE__ */ jsx12("div", { className: "flex items-center border-b border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx12("span", { className: "text-muted-foreground text-xs", children: title }) }),
857
- /* @__PURE__ */ jsx12(
858
- "div",
859
- {
860
- ref: containerRef,
861
- className: "overflow-auto p-4",
862
- style: { maxHeight },
863
- children
864
- }
865
- )
866
- ]
867
- }
868
- );
869
- }
870
- );
871
- TerminalDisplay.displayName = "TerminalDisplay";
872
- var TerminalLine = React11.forwardRef(
873
- ({ className, type = "output", prompt = "$", timestamp, children, ...props }, ref) => {
874
- const typeStyles = {
875
- input: "text-foreground",
876
- output: "text-foreground",
877
- error: "text-[var(--surface-danger-text)]",
878
- success: "text-[var(--surface-success-text)]",
879
- info: "text-[var(--surface-info-text)]",
880
- thinking: "text-[var(--surface-warning-text)] animate-pulse",
881
- command: "text-foreground",
882
- warning: "text-[var(--surface-warning-text)]"
883
- };
884
- return /* @__PURE__ */ jsxs10(
885
- "div",
886
- {
887
- ref,
888
- className: cn(
889
- "flex items-start gap-2 py-0.5 leading-relaxed",
890
- typeStyles[type],
891
- className
892
- ),
893
- ...props,
894
- children: [
895
- (type === "input" || type === "command") && /* @__PURE__ */ jsx12("span", { className: "shrink-0 select-none text-[var(--surface-success-text)]", children: prompt }),
896
- type === "thinking" && /* @__PURE__ */ jsx12("span", { className: "shrink-0 select-none", children: "..." }),
897
- timestamp && /* @__PURE__ */ jsxs10("span", { className: "shrink-0 select-none text-[var(--text-dim)]", children: [
898
- "[",
899
- timestamp,
900
- "]"
901
- ] }),
902
- /* @__PURE__ */ jsx12("span", { className: "whitespace-pre-wrap break-all", children })
903
- ]
904
- }
905
- );
906
- }
907
- );
908
- TerminalLine.displayName = "TerminalLine";
909
- var TerminalCursor = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
910
- "span",
911
- {
912
- ref,
913
- className: cn(
914
- "ml-0.5 inline-block h-4 w-2 animate-pulse bg-foreground",
915
- className
916
- ),
917
- ...props
918
- }
919
- ));
920
- TerminalCursor.displayName = "TerminalCursor";
921
- var TerminalInput = React11.forwardRef(
922
- // `variant` is taken out so it never reaches the DOM element.
923
- ({ className, onSubmit, variant: _variant, ...props }, ref) => {
924
- const [value, setValue] = React11.useState("");
925
- const handleKeyDown = (e) => {
926
- if (e.key === "Enter" && value.trim() && onSubmit) {
927
- onSubmit(value.trim());
928
- setValue("");
929
- }
930
- };
931
- return /* @__PURE__ */ jsxs10(
932
- "div",
933
- {
934
- className: cn(
935
- "flex items-center rounded-lg border bg-background px-4 py-2.5 font-mono text-sm",
936
- focusFieldWithin,
937
- className
938
- ),
939
- children: [
940
- /* @__PURE__ */ jsx12("span", { className: "mr-2 select-none text-[var(--surface-success-text)]", children: "$" }),
941
- /* @__PURE__ */ jsx12(
942
- "input",
943
- {
944
- ref,
945
- type: "text",
946
- value,
947
- onChange: (e) => setValue(e.target.value),
948
- onKeyDown: handleKeyDown,
949
- className: "flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground",
950
- ...props
951
- }
952
- ),
953
- /* @__PURE__ */ jsx12(TerminalCursor, {})
954
- ]
955
- }
956
- );
957
- }
958
- );
959
- TerminalInput.displayName = "TerminalInput";
960
-
961
- // src/primitives/drop-zone.tsx
962
- import { useCallback as useCallback2, useRef as useRef3, useState as useState3 } from "react";
963
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
964
- function DropZone({
965
- onDrop,
966
- accept,
967
- disabled,
968
- overlay,
969
- title = "Drop files to upload",
970
- description = "Your files will be securely stored in the workspace.",
971
- icon = "cloud_upload",
972
- children,
973
- className
974
- }) {
975
- const [dragOver, setDragOver] = useState3(false);
976
- const counter = useRef3(0);
977
- const isAccepted = useCallback2(
978
- (file) => {
979
- if (!accept) return true;
980
- const extensions = accept.split(",").map((ext) => ext.trim().toLowerCase());
981
- const fileName = file.name.toLowerCase();
982
- return extensions.some((ext) => fileName.endsWith(ext));
983
- },
984
- [accept]
985
- );
986
- const handleDragEnter = useCallback2(
987
- (e) => {
988
- e.preventDefault();
989
- if (disabled) return;
990
- counter.current++;
991
- if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
992
- },
993
- [disabled]
994
- );
995
- const handleDragLeave = useCallback2((e) => {
996
- e.preventDefault();
997
- counter.current--;
998
- if (counter.current === 0) setDragOver(false);
999
- }, []);
1000
- const handleDragOver = useCallback2(
1001
- (e) => {
1002
- e.preventDefault();
1003
- if (!disabled) e.dataTransfer.dropEffect = "copy";
1004
- },
1005
- [disabled]
1006
- );
1007
- const handleDrop = useCallback2(
1008
- (e) => {
1009
- e.preventDefault();
1010
- counter.current = 0;
1011
- setDragOver(false);
1012
- if (disabled) return;
1013
- const allFiles = Array.from(e.dataTransfer?.files || []);
1014
- const accepted = accept ? allFiles.filter(isAccepted) : allFiles;
1015
- if (accepted.length > 0) onDrop(accepted);
1016
- },
1017
- [disabled, accept, isAccepted, onDrop]
1018
- );
1019
- return /* @__PURE__ */ jsxs11(
1020
- "div",
1021
- {
1022
- onDragEnter: handleDragEnter,
1023
- onDragLeave: handleDragLeave,
1024
- onDragOver: handleDragOver,
1025
- onDrop: handleDrop,
1026
- className: cn("relative", className),
1027
- children: [
1028
- dragOver && (overlay || /* @__PURE__ */ jsx13("div", { className: "fixed inset-0 z-[100] flex items-center justify-center pointer-events-none bg-background", children: /* @__PURE__ */ jsxs11("div", { className: "rounded-2xl border-2 border-dashed border-border bg-card p-16 text-center shadow-[var(--shadow-dropdown)] max-w-lg mx-auto", children: [
1029
- /* @__PURE__ */ jsx13("div", { className: "mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-2xl border border-border bg-[var(--accent-surface-soft)]", children: typeof icon === "string" ? /* @__PURE__ */ jsxs11("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "h-10 w-10 text-[var(--accent-text)]", children: [
1030
- /* @__PURE__ */ jsx13("title", { children: "Upload" }),
1031
- /* @__PURE__ */ jsx13("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1032
- /* @__PURE__ */ jsx13("polyline", { points: "17 8 12 3 7 8" }),
1033
- /* @__PURE__ */ jsx13("line", { x1: "12", x2: "12", y1: "3", y2: "15" })
1034
- ] }) : icon }),
1035
- /* @__PURE__ */ jsx13("h2", { className: "text-2xl font-bold text-foreground", children: title }),
1036
- /* @__PURE__ */ jsx13("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
1037
- ] }) })),
1038
- children
1039
- ]
1040
- }
1041
- );
1042
- }
1043
-
1044
- // src/primitives/upload-progress.tsx
1045
- import { AlertCircle as AlertCircle2, CheckCircle2 as CheckCircle22, FileText, Loader2, RefreshCw, X as X3 } from "lucide-react";
1046
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1047
- function formatSize(bytes) {
1048
- if (bytes < 1024) return `${bytes}B`;
1049
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`;
1050
- return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
1051
- }
1052
- function UploadProgress({ files, onRemove, onRetry, className }) {
1053
- if (files.length === 0) return null;
1054
- return /* @__PURE__ */ jsx14("div", { className: cn("space-y-2", className), children: files.map((file) => /* @__PURE__ */ jsxs12(
1055
- "div",
1056
- {
1057
- className: cn(
1058
- "flex items-center gap-3 rounded-lg border px-3 py-2 text-sm",
1059
- file.status === "error" ? "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)]" : file.status === "complete" ? "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)]" : "border-border bg-card"
1060
- ),
1061
- children: [
1062
- file.status === "complete" && /* @__PURE__ */ jsx14(CheckCircle22, { className: "h-4 w-4 shrink-0 text-[var(--surface-success-text)]" }),
1063
- file.status === "error" && /* @__PURE__ */ jsx14(AlertCircle2, { className: "h-4 w-4 shrink-0 text-[var(--surface-danger-text)]" }),
1064
- file.status === "uploading" && /* @__PURE__ */ jsx14(Loader2, { className: "h-4 w-4 shrink-0 animate-spin text-primary" }),
1065
- file.status === "pending" && /* @__PURE__ */ jsx14(FileText, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
1066
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
1067
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1068
- /* @__PURE__ */ jsx14("span", { className: "truncate font-medium text-foreground", children: file.name }),
1069
- /* @__PURE__ */ jsx14("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatSize(file.size) })
1070
- ] }),
1071
- file.status === "uploading" && file.progress !== void 0 && /* @__PURE__ */ jsx14("div", { className: "mt-1 h-1 w-full overflow-hidden rounded-full bg-muted/50", children: /* @__PURE__ */ jsx14(
1072
- "div",
1073
- {
1074
- className: "h-full rounded-full bg-primary transition-all",
1075
- style: { width: `${file.progress}%` }
1076
- }
1077
- ) }),
1078
- file.status === "error" && file.error && /* @__PURE__ */ jsx14("p", { className: "mt-0.5 text-xs text-[var(--surface-danger-text)]", children: file.error })
1079
- ] }),
1080
- /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 items-center gap-1", children: [
1081
- file.status === "error" && onRetry && /* @__PURE__ */ jsx14(
1082
- "button",
1083
- {
1084
- type: "button",
1085
- onClick: () => onRetry(file.id),
1086
- className: "rounded p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
1087
- children: /* @__PURE__ */ jsx14(RefreshCw, { className: "h-3.5 w-3.5" })
1088
- }
1089
- ),
1090
- onRemove && /* @__PURE__ */ jsx14(
1091
- "button",
1092
- {
1093
- type: "button",
1094
- onClick: () => onRemove(file.id),
1095
- className: "rounded p-1 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
1096
- children: /* @__PURE__ */ jsx14(X3, { className: "h-3.5 w-3.5" })
1097
- }
1098
- )
1099
- ] })
1100
- ]
1101
- },
1102
- file.id
1103
- )) });
1104
- }
1105
-
1106
- // src/primitives/sidebar-drop-zone.tsx
1107
- import { useCallback as useCallback3, useRef as useRef4, useState as useState4 } from "react";
1108
- import { Upload } from "lucide-react";
1109
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1110
- function SidebarDropZone({
1111
- onDrop,
1112
- accept,
1113
- disabled,
1114
- title = "Drop files here",
1115
- description,
1116
- icon,
1117
- persistent = false,
1118
- className
1119
- }) {
1120
- const [dragOver, setDragOver] = useState4(false);
1121
- const counter = useRef4(0);
1122
- const isAccepted = useCallback3(
1123
- (file) => {
1124
- if (!accept) return true;
1125
- const extensions = accept.split(",").map((ext) => ext.trim().toLowerCase());
1126
- const fileName = file.name.toLowerCase();
1127
- return extensions.some((ext) => fileName.endsWith(ext));
1128
- },
1129
- [accept]
1130
- );
1131
- const handleDragEnter = useCallback3(
1132
- (e) => {
1133
- e.preventDefault();
1134
- e.stopPropagation();
1135
- if (disabled) return;
1136
- counter.current++;
1137
- if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
1138
- },
1139
- [disabled]
1140
- );
1141
- const handleDragLeave = useCallback3((e) => {
1142
- e.preventDefault();
1143
- e.stopPropagation();
1144
- counter.current--;
1145
- if (counter.current === 0) setDragOver(false);
1146
- }, []);
1147
- const handleDragOver = useCallback3(
1148
- (e) => {
1149
- e.preventDefault();
1150
- e.stopPropagation();
1151
- if (!disabled) e.dataTransfer.dropEffect = "copy";
1152
- },
1153
- [disabled]
1154
- );
1155
- const handleDrop = useCallback3(
1156
- (e) => {
1157
- e.preventDefault();
1158
- e.stopPropagation();
1159
- counter.current = 0;
1160
- setDragOver(false);
1161
- if (disabled) return;
1162
- const allFiles = Array.from(e.dataTransfer?.files || []);
1163
- const accepted = accept ? allFiles.filter(isAccepted) : allFiles;
1164
- if (accepted.length > 0) onDrop(accepted);
1165
- },
1166
- [disabled, accept, isAccepted, onDrop]
1167
- );
1168
- const isVisible = persistent || dragOver;
1169
- return /* @__PURE__ */ jsx15(
1170
- "div",
1171
- {
1172
- onDragEnter: handleDragEnter,
1173
- onDragLeave: handleDragLeave,
1174
- onDragOver: handleDragOver,
1175
- onDrop: handleDrop,
1176
- className: cn(
1177
- "rounded-lg border-2 border-dashed transition-all duration-150",
1178
- isVisible ? "p-4" : "p-0 border-transparent",
1179
- 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)))]" : "",
1180
- disabled && "opacity-50 pointer-events-none",
1181
- className
1182
- ),
1183
- children: isVisible && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col items-center gap-2 text-center", children: [
1184
- /* @__PURE__ */ jsx15("div", { className: cn(
1185
- "flex h-8 w-8 items-center justify-center rounded-lg transition-colors",
1186
- dragOver ? "bg-[var(--brand-cool,hsl(var(--primary)))]/15 text-[var(--brand-cool,hsl(var(--primary)))]" : "text-[var(--text-muted,hsl(var(--muted-foreground)))]"
1187
- ), children: icon ?? /* @__PURE__ */ jsx15(Upload, { className: "h-4 w-4" }) }),
1188
- /* @__PURE__ */ jsx15("p", { className: cn(
1189
- "text-xs font-medium",
1190
- dragOver ? "text-[var(--text-primary,hsl(var(--foreground)))]" : "text-[var(--text-muted,hsl(var(--muted-foreground)))]"
1191
- ), children: title }),
1192
- description && /* @__PURE__ */ jsx15("p", { className: "text-[10px] text-[var(--text-muted,hsl(var(--muted-foreground)))]", children: description })
1193
- ] })
1194
- }
1195
- );
1196
- }
1197
-
1198
- // src/primitives/theme-toggle.tsx
1199
- import { useCallback as useCallback4, useEffect as useEffect2, useState as useState5 } from "react";
1200
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1201
- function getSystemTheme() {
1202
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1203
- }
1204
- function applyTheme(theme) {
1205
- const resolved = theme === "system" ? getSystemTheme() : theme;
1206
- document.documentElement.classList.toggle("dark", resolved === "dark");
1207
- }
1208
- function useTheme() {
1209
- const [theme, setThemeState] = useState5(() => {
1210
- if (typeof window === "undefined") return "system";
1211
- return localStorage.getItem("theme") ?? "system";
1212
- });
1213
- const setTheme = useCallback4((next) => {
1214
- setThemeState(next);
1215
- if (next === "system") {
1216
- localStorage.removeItem("theme");
1217
- } else {
1218
- localStorage.setItem("theme", next);
1219
- }
1220
- applyTheme(next);
1221
- }, []);
1222
- useEffect2(() => {
1223
- applyTheme(theme);
1224
- if (theme !== "system") return;
1225
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
1226
- const handler = () => applyTheme("system");
1227
- mq.addEventListener("change", handler);
1228
- return () => mq.removeEventListener("change", handler);
1229
- }, [theme]);
1230
- return { theme, setTheme };
1231
- }
1232
- var iconClass = "h-4 w-4";
1233
- function SunIcon() {
1234
- return /* @__PURE__ */ jsxs14(
1235
- "svg",
1236
- {
1237
- xmlns: "http://www.w3.org/2000/svg",
1238
- viewBox: "0 0 24 24",
1239
- fill: "none",
1240
- stroke: "currentColor",
1241
- strokeWidth: 2,
1242
- strokeLinecap: "round",
1243
- strokeLinejoin: "round",
1244
- className: iconClass,
1245
- children: [
1246
- /* @__PURE__ */ jsx16("circle", { cx: 12, cy: 12, r: 5 }),
1247
- /* @__PURE__ */ jsx16("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
1248
- ]
1249
- }
1250
- );
1251
- }
1252
- function MoonIcon() {
1253
- return /* @__PURE__ */ jsx16(
1254
- "svg",
1255
- {
1256
- xmlns: "http://www.w3.org/2000/svg",
1257
- viewBox: "0 0 24 24",
1258
- fill: "none",
1259
- stroke: "currentColor",
1260
- strokeWidth: 2,
1261
- strokeLinecap: "round",
1262
- strokeLinejoin: "round",
1263
- className: iconClass,
1264
- children: /* @__PURE__ */ jsx16("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" })
1265
- }
1266
- );
1267
- }
1268
- function ThemeToggle() {
1269
- const { theme, setTheme } = useTheme();
1270
- const resolved = theme === "system" ? getSystemTheme() : theme;
1271
- return /* @__PURE__ */ jsx16(
1272
- "button",
1273
- {
1274
- type: "button",
1275
- onClick: () => setTheme(resolved === "dark" ? "light" : "dark"),
1276
- className: "inline-flex items-center justify-center rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors",
1277
- "aria-label": `Switch to ${resolved === "dark" ? "light" : "dark"} mode`,
1278
- children: resolved === "dark" ? /* @__PURE__ */ jsx16(SunIcon, {}) : /* @__PURE__ */ jsx16(MoonIcon, {})
1279
- }
1280
- );
1281
- }
1282
-
1283
- // src/primitives/page-header.tsx
1284
- import * as React12 from "react";
1285
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1286
- var PageHeader = React12.forwardRef(
1287
- ({
1288
- className,
1289
- title,
1290
- description,
1291
- actions,
1292
- meta,
1293
- titleId,
1294
- level = 1,
1295
- ...props
1296
- }, ref) => {
1297
- const Heading = level === 1 ? "h1" : "h2";
1298
- return /* @__PURE__ */ jsxs15("header", { ref, className: cn("mb-6", className), ...props, children: [
1299
- /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-start justify-between gap-x-6 gap-y-3", children: [
1300
- /* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
1301
- /* @__PURE__ */ jsx17(
1302
- Heading,
1303
- {
1304
- id: titleId,
1305
- className: cn(
1306
- "text-balance font-semibold tracking-tight",
1307
- level === 1 ? "text-2xl" : "text-lg"
1308
- ),
1309
- children: title
1310
- }
1311
- ),
1312
- description && /* @__PURE__ */ jsx17("p", { className: "mt-1 max-w-prose text-muted-foreground text-sm", children: description })
1313
- ] }),
1314
- actions && /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap items-center gap-2", children: actions })
1315
- ] }),
1316
- meta && /* @__PURE__ */ jsx17("div", { className: "mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-[var(--text-dim)] text-xs", children: meta })
1317
- ] });
1318
- }
1319
- );
1320
- PageHeader.displayName = "PageHeader";
1321
-
1322
- // src/primitives/status-pill.tsx
1323
- import * as React13 from "react";
1324
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1325
- var TONE_SURFACE = {
1326
- success: "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] border-[var(--surface-success-border)]",
1327
- warning: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border-[var(--surface-warning-border)]",
1328
- danger: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border-[var(--surface-danger-border)]",
1329
- info: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
1330
- // `running` shares the info triple on purpose. `--status-running` exists but
1331
- // is the green dot on a sandbox — a machine's power state, not a run's
1332
- // outcome — and it ships as one colour with no paired background or text
1333
- // tier, which is the pairing this component is built to guarantee. Green also
1334
- // already means SUCCEEDED here, so a green "running" pill would say a run had
1335
- // finished well while it was still going.
1336
- running: "bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] border-[var(--surface-info-border)]",
1337
- neutral: "bg-[var(--surface-neutral-bg)] text-[var(--surface-neutral-text)] border-[var(--surface-neutral-border)]"
1338
- };
1339
- var TONE_TEXT = {
1340
- success: "text-[var(--surface-success-text)]",
1341
- warning: "text-[var(--surface-warning-text)]",
1342
- danger: "text-[var(--surface-danger-text)]",
1343
- info: "text-[var(--surface-info-text)]",
1344
- running: "text-[var(--surface-info-text)]",
1345
- neutral: "text-[var(--surface-neutral-text)]"
1346
- };
1347
- function ToneGlyph({ tone }) {
1348
- const common = {
1349
- viewBox: "0 0 8 8",
1350
- className: "size-2 shrink-0"
1351
- };
1352
- switch (tone) {
1353
- // Settled and good: a solid disc.
1354
- case "success":
1355
- return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "3.25" }) });
1356
- // Settled and bad: a disc with a bar through it, so it differs from
1357
- // success in OUTLINE and not only in hue.
1358
- case "danger":
1359
- return /* @__PURE__ */ jsxs16(
1360
- "svg",
1361
- {
1362
- ...common,
1363
- "aria-hidden": "true",
1364
- fill: "none",
1365
- stroke: "currentColor",
1366
- strokeWidth: "1.5",
1367
- children: [
1368
- /* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "3.1", fill: "currentColor", opacity: "0.35" }),
1369
- /* @__PURE__ */ jsx18("path", { d: "M1.9 6.1 6.1 1.9", strokeLinecap: "round" })
1370
- ]
1371
- }
1372
- );
1373
- // Needs a person: a triangle.
1374
- case "warning":
1375
- return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("path", { d: "M4 0.6 7.7 7.1H0.3z" }) });
1376
- // Still moving: an open ring, visibly hollow at 8px.
1377
- case "running":
1378
- return /* @__PURE__ */ jsx18(
1379
- "svg",
1380
- {
1381
- ...common,
1382
- "aria-hidden": "true",
1383
- fill: "none",
1384
- stroke: "currentColor",
1385
- strokeWidth: "1.75",
1386
- children: /* @__PURE__ */ jsx18("circle", { cx: "4", cy: "4", r: "2.9" })
1387
- }
1388
- );
1389
- // Informational: a square, the only right-angled mark in the set.
1390
- case "info":
1391
- return /* @__PURE__ */ jsx18("svg", { ...common, "aria-hidden": "true", fill: "currentColor", children: /* @__PURE__ */ jsx18("rect", { x: "0.9", y: "0.9", width: "6.2", height: "6.2", rx: "1.2" }) });
1392
- // Nothing has happened: a dash. No enclosed area at all.
1393
- default:
1394
- return /* @__PURE__ */ jsx18(
1395
- "svg",
1396
- {
1397
- ...common,
1398
- "aria-hidden": "true",
1399
- fill: "none",
1400
- stroke: "currentColor",
1401
- strokeWidth: "1.75",
1402
- children: /* @__PURE__ */ jsx18("path", { d: "M1 4h6", strokeLinecap: "round" })
1403
- }
1404
- );
1405
- }
1406
- }
1407
- var StatusPill = React13.forwardRef(
1408
- ({ className, tone, children, bare = false, size = "sm", ...props }, ref) => /* @__PURE__ */ jsxs16(
1409
- "span",
1410
- {
1411
- ref,
1412
- className: cn(
1413
- "inline-flex items-center gap-1.5 whitespace-nowrap rounded-full font-medium",
1414
- size === "sm" ? "px-2 py-0.5 text-xs" : "px-2.5 py-1 text-sm",
1415
- bare ? "border border-transparent bg-transparent px-0" : cn("border", TONE_SURFACE[tone]),
1416
- className
1417
- ),
1418
- ...props,
1419
- children: [
1420
- /* @__PURE__ */ jsx18("span", { className: cn("inline-flex", bare && TONE_TEXT[tone]), children: /* @__PURE__ */ jsx18(ToneGlyph, { tone }) }),
1421
- children
1422
- ]
1423
- }
1424
- )
1425
- );
1426
- StatusPill.displayName = "StatusPill";
1427
-
1428
- // src/primitives/metric-strip.tsx
1429
- import * as React14 from "react";
1430
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
1431
- var MetricStrip = React14.forwardRef(
1432
- ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx19(
1433
- "dl",
1434
- {
1435
- ref,
1436
- className: cn(
1437
- "grid grid-cols-2 rounded-[var(--radius-lg)] border border-border bg-card shadow-[var(--shadow-card)] sm:grid-cols-4",
1438
- className
1439
- ),
1440
- ...props,
1441
- children
1442
- }
1443
- )
1444
- );
1445
- MetricStrip.displayName = "MetricStrip";
1446
- var Metric = React14.forwardRef(
1447
- ({ className, label, value, hint, attention, ...props }, ref) => /* @__PURE__ */ jsxs17(
1448
- "div",
1449
- {
1450
- ref,
1451
- className: cn(
1452
- // Leading hairline, DRAWN only where a divider belongs — never drawn
1453
- // and then suppressed. Stating it as `border-l` plus `border-l-0`
1454
- // variants puts both in one conflict group, where the winner is decided
1455
- // by emitted-rule order rather than by intent; that resolved the wrong
1456
- // way at every breakpoint and left a rule down the start of each row.
1457
- // `:not(:nth-child(Nn+1))` is the row-start test for the column count
1458
- // at that breakpoint, so no rule ever contradicts another.
1459
- //
1460
- // N is COUPLED to the grid template on `MetricStrip`: 2 columns below
1461
- // `sm`, 4 from `sm`. A new breakpoint there — `md:grid-cols-3`, say —
1462
- // needs its `md:[&:not(:nth-child(3n+1))]:border-l` here in the same
1463
- // change, or the dividers land mid-row at that width.
1464
- "border-border p-4 sm:p-5",
1465
- "max-sm:[&:not(:nth-child(2n+1))]:border-l",
1466
- "sm:[&:not(:nth-child(4n+1))]:border-l",
1467
- className
1468
- ),
1469
- ...props,
1470
- children: [
1471
- /* @__PURE__ */ jsxs17("dt", { className: "flex items-center gap-2 text-muted-foreground text-sm", children: [
1472
- /* @__PURE__ */ jsx19("span", { className: "truncate", children: label }),
1473
- attention && /* @__PURE__ */ jsx19(StatusPill, { tone: attention.tone, children: attention.label })
1474
- ] }),
1475
- /* @__PURE__ */ jsx19(
1476
- "dd",
1477
- {
1478
- className: cn(
1479
- "mt-1 truncate font-semibold text-xl tabular-nums tracking-tight lg:text-2xl",
1480
- attention?.tone === "danger" && "text-[var(--surface-danger-text)]"
1481
- ),
1482
- title: typeof value === "string" ? value : void 0,
1483
- children: value
1484
- }
1485
- ),
1486
- hint && // Titled for the same reason the value is: the line truncates, and a
1487
- // hint is where the qualifying detail lives — which wallet, which
1488
- // window — so a clipped one is the case most worth recovering.
1489
- /* @__PURE__ */ jsx19(
1490
- "dd",
1491
- {
1492
- className: "mt-0.5 truncate text-[var(--text-dim)] text-xs",
1493
- title: typeof hint === "string" ? hint : void 0,
1494
- children: hint
1495
- }
1496
- )
1497
- ]
1498
- }
1499
- )
1500
- );
1501
- Metric.displayName = "Metric";
1502
-
1503
- // src/primitives/toolbar.tsx
1504
- import * as React15 from "react";
1505
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
1506
- var Toolbar = React15.forwardRef(
1507
- ({ className, search, filters, actions, ...props }, ref) => /* @__PURE__ */ jsxs18(
1508
- "div",
1509
- {
1510
- ref,
1511
- className: cn(
1512
- "mb-4 flex flex-col gap-3 lg:flex-row lg:items-center",
1513
- className
1514
- ),
1515
- ...props,
1516
- children: [
1517
- search && /* @__PURE__ */ jsx20("div", { className: "min-w-0 lg:max-w-sm lg:flex-1", children: search }),
1518
- filters && // `py-1` leaves room for a focus ring above and below; horizontally the
1519
- // scroll container clips it, which is the trade a single-line filter row
1520
- // makes. No negative margin — pulling the row wider than its parent is
1521
- // what made every page report 4px of horizontal overflow.
1522
- /* @__PURE__ */ jsx20("div", { className: "flex min-w-0 items-center gap-2 overflow-x-auto py-1 lg:flex-1", children: filters }),
1523
- actions && /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 items-center gap-2 lg:ml-auto", children: actions })
1524
- ]
1525
- }
1526
- )
1527
- );
1528
- Toolbar.displayName = "Toolbar";
1529
- var FilterField = React15.forwardRef(
1530
- ({ className, label, htmlFor, children, ...props }, ref) => /* @__PURE__ */ jsxs18(
1531
- "div",
1532
- {
1533
- ref,
1534
- className: cn("flex shrink-0 items-center gap-2", className),
1535
- ...props,
1536
- children: [
1537
- /* @__PURE__ */ jsx20(
1538
- "label",
1539
- {
1540
- htmlFor,
1541
- className: "whitespace-nowrap text-muted-foreground text-xs",
1542
- children: label
1543
- }
1544
- ),
1545
- children
1546
- ]
1547
- }
1548
- )
1549
- );
1550
- FilterField.displayName = "FilterField";
1551
-
1552
- export {
1553
- Dialog,
1554
- DialogTrigger,
1555
- DialogPortal,
1556
- DialogClose,
1557
- DialogOverlay,
1558
- DialogContent,
1559
- DialogHeader,
1560
- DialogFooter,
1561
- DialogTitle,
1562
- DialogDescription,
1563
- Input,
1564
- Textarea,
1565
- Select,
1566
- SelectGroup,
1567
- SelectValue,
1568
- SelectTrigger,
1569
- SelectScrollUpButton,
1570
- SelectScrollDownButton,
1571
- SelectContent,
1572
- SelectLabel,
1573
- SelectItem,
1574
- SelectSeparator,
1575
- SegmentedControl,
1576
- Progress,
1577
- Switch,
1578
- Skeleton,
1579
- SkeletonCard,
1580
- SkeletonTable,
1581
- ToastContainer,
1582
- ToastProvider,
1583
- useToast,
1584
- Label2 as Label,
1585
- EmptyState,
1586
- StatCard,
1587
- TerminalDisplay,
1588
- TerminalLine,
1589
- TerminalCursor,
1590
- TerminalInput,
1591
- DropZone,
1592
- UploadProgress,
1593
- SidebarDropZone,
1594
- useTheme,
1595
- ThemeToggle,
1596
- PageHeader,
1597
- StatusPill,
1598
- MetricStrip,
1599
- Metric,
1600
- Toolbar,
1601
- FilterField,
1602
- Logo,
1603
- TangleKnot
1604
- };