@ai-matrx/content-ir-react 0.22.0 → 0.24.0

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.
@@ -0,0 +1,1131 @@
1
+ "use client";
2
+
3
+ // kind-kit/SortableList.tsx
4
+ import * as React3 from "react";
5
+
6
+ // kind-kit/icons.tsx
7
+ import "react";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ function make(name, children) {
10
+ const Icon = ({ className }) => /* @__PURE__ */ jsx(
11
+ "svg",
12
+ {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ width: "24",
15
+ height: "24",
16
+ viewBox: "0 0 24 24",
17
+ fill: "none",
18
+ stroke: "currentColor",
19
+ strokeWidth: "2",
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round",
22
+ "aria-hidden": "true",
23
+ className,
24
+ children
25
+ }
26
+ );
27
+ Icon.displayName = name;
28
+ return Icon;
29
+ }
30
+ var Loader2 = make("Loader2", /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }));
31
+ var MoreHorizontal = make(
32
+ "MoreHorizontal",
33
+ /* @__PURE__ */ jsxs(Fragment, { children: [
34
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1" }),
35
+ /* @__PURE__ */ jsx("circle", { cx: "19", cy: "12", r: "1" }),
36
+ /* @__PURE__ */ jsx("circle", { cx: "5", cy: "12", r: "1" })
37
+ ] })
38
+ );
39
+ var ChevronDown = make("ChevronDown", /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }));
40
+ var ChevronUp = make("ChevronUp", /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" }));
41
+ var GripVertical = make(
42
+ "GripVertical",
43
+ /* @__PURE__ */ jsxs(Fragment, { children: [
44
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "12", r: "1" }),
45
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "5", r: "1" }),
46
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "19", r: "1" }),
47
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "12", r: "1" }),
48
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "5", r: "1" }),
49
+ /* @__PURE__ */ jsx("circle", { cx: "15", cy: "19", r: "1" })
50
+ ] })
51
+ );
52
+ var X = make(
53
+ "X",
54
+ /* @__PURE__ */ jsxs(Fragment, { children: [
55
+ /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
56
+ /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
57
+ ] })
58
+ );
59
+ var Check = make("Check", /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }));
60
+ var Pencil = make(
61
+ "Pencil",
62
+ /* @__PURE__ */ jsxs(Fragment, { children: [
63
+ /* @__PURE__ */ jsx("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" }),
64
+ /* @__PURE__ */ jsx("path", { d: "m15 5 4 4" })
65
+ ] })
66
+ );
67
+ var Plus = make(
68
+ "Plus",
69
+ /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ /* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
71
+ /* @__PURE__ */ jsx("path", { d: "M12 5v14" })
72
+ ] })
73
+ );
74
+
75
+ // kind-kit/SortableList.tsx
76
+ import { cn } from "@ai-matrx/design-system";
77
+
78
+ // kind-kit/kind-kit-host.tsx
79
+ import * as React2 from "react";
80
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
81
+ var KEY = /* @__PURE__ */ Symbol.for("ai-matrx.content-ir-react.kind-kit-host");
82
+ function resolveText(human, json) {
83
+ if (typeof human === "function") return human();
84
+ if (typeof human === "string") return human;
85
+ if (json !== void 0) return JSON.stringify(typeof json === "function" ? json() : json, null, 2);
86
+ return "";
87
+ }
88
+ function DefaultCopyButtons({ label, human, json, size, className }) {
89
+ const [state, setState] = React2.useState("idle");
90
+ const onClick = async () => {
91
+ try {
92
+ await navigator.clipboard.writeText(resolveText(human, json));
93
+ setState("copied");
94
+ } catch {
95
+ setState("failed");
96
+ }
97
+ setTimeout(() => setState("idle"), 1500);
98
+ };
99
+ return /* @__PURE__ */ jsx2(
100
+ "button",
101
+ {
102
+ type: "button",
103
+ onClick,
104
+ title: `Copy ${label}`,
105
+ "aria-label": `Copy ${label}`,
106
+ className: className ?? `inline-flex items-center rounded-md border border-border px-2 text-xs text-foreground hover:bg-muted ${size === "icon" ? "h-7" : "h-8"}`,
107
+ children: state === "copied" ? "Copied" : state === "failed" ? "Copy failed" : "Copy"
108
+ }
109
+ );
110
+ }
111
+ function RetryButton({ onRetry }) {
112
+ if (!onRetry) return null;
113
+ return /* @__PURE__ */ jsx2("button", { type: "button", onClick: onRetry, className: "ml-2 underline underline-offset-2", children: "Try again" });
114
+ }
115
+ function DefaultReadEmpty({ read, loading, children }) {
116
+ const status = read?.status ?? "ready";
117
+ const what = read?.what ?? "this list";
118
+ if (status === "loading") return /* @__PURE__ */ jsx2(Fragment2, { children: loading ?? /* @__PURE__ */ jsx2("div", { role: "status", className: "text-xs text-muted-foreground", children: `Loading ${what}\u2026` }) });
119
+ if (status === "error") {
120
+ return /* @__PURE__ */ jsxs2("div", { role: "alert", className: "text-xs text-destructive", children: [
121
+ `Could not load ${what}.`,
122
+ /* @__PURE__ */ jsx2(RetryButton, { onRetry: read?.onRetry })
123
+ ] });
124
+ }
125
+ return /* @__PURE__ */ jsx2(Fragment2, { children: children ?? null });
126
+ }
127
+ function DefaultReadStaleNotice({ read, className }) {
128
+ if (read?.status !== "error") return null;
129
+ return /* @__PURE__ */ jsxs2("div", { role: "alert", className: `text-xs text-muted-foreground ${className ?? ""}`, children: [
130
+ `Showing earlier ${read.what ?? "results"}; the latest refresh failed.`,
131
+ /* @__PURE__ */ jsx2(RetryButton, { onRetry: read.onRetry })
132
+ ] });
133
+ }
134
+ var DEFAULTS = {
135
+ CopyButtons: DefaultCopyButtons,
136
+ ReadEmpty: DefaultReadEmpty,
137
+ ReadStaleNotice: DefaultReadStaleNotice
138
+ };
139
+ function setKindKitHost(host) {
140
+ globalThis[KEY] = { ...globalThis[KEY], ...host };
141
+ }
142
+ function getKindKitHost() {
143
+ return { ...DEFAULTS, ...globalThis[KEY] };
144
+ }
145
+ function resetKindKitHost() {
146
+ delete globalThis[KEY];
147
+ }
148
+
149
+ // kind-kit/SortableList.tsx
150
+ import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
151
+ function defaultKey(item, index) {
152
+ if (typeof item === "string" || typeof item === "number") return String(item);
153
+ if (item && typeof item === "object") {
154
+ const rec = item;
155
+ if (typeof rec.id === "string" || typeof rec.id === "number")
156
+ return String(rec.id);
157
+ if (typeof rec.key === "string") return rec.key;
158
+ }
159
+ return String(index);
160
+ }
161
+ function defaultRender(item) {
162
+ if (typeof item === "string" || typeof item === "number") return String(item);
163
+ if (item && typeof item === "object") {
164
+ const rec = item;
165
+ for (const k of ["label", "title", "name", "text"]) {
166
+ if (typeof rec[k] === "string") return rec[k];
167
+ }
168
+ return JSON.stringify(item);
169
+ }
170
+ return String(item);
171
+ }
172
+ function moveItem(items, from, to) {
173
+ const next = items.slice();
174
+ const [moved] = next.splice(from, 1);
175
+ next.splice(to, 0, moved);
176
+ return next;
177
+ }
178
+ function SortableList({
179
+ items,
180
+ getKey = defaultKey,
181
+ onReorder,
182
+ renderItem,
183
+ onRemove,
184
+ disabled = false,
185
+ hideArrows = false,
186
+ emptyState,
187
+ read,
188
+ className,
189
+ itemClassName,
190
+ ariaLabel
191
+ }) {
192
+ const { ReadEmpty, ReadStaleNotice } = getKindKitHost();
193
+ const [drag, setDrag] = React3.useState(null);
194
+ const [armed, setArmed] = React3.useState(null);
195
+ const listRef = React3.useRef(null);
196
+ const rowRefs = React3.useRef([]);
197
+ const canInteract = !disabled;
198
+ const handleDragStart = (index) => (e) => {
199
+ if (!canInteract || armed !== index) {
200
+ e.preventDefault();
201
+ return;
202
+ }
203
+ e.dataTransfer.effectAllowed = "move";
204
+ e.dataTransfer.setData("text/plain", String(index));
205
+ const listTop = listRef.current?.getBoundingClientRect().top ?? 0;
206
+ const rects = rowRefs.current.slice(0, items.length).map((el) => {
207
+ const r = el ? el.getBoundingClientRect() : new DOMRect();
208
+ return { top: r.top - listTop, bottom: r.bottom - listTop, height: r.height };
209
+ });
210
+ setDrag({ from: index, over: index, rects });
211
+ };
212
+ const handleDragOver = (e) => {
213
+ if (!drag) return;
214
+ e.preventDefault();
215
+ e.dataTransfer.dropEffect = "move";
216
+ const listTop = listRef.current?.getBoundingClientRect().top ?? 0;
217
+ const y = e.clientY - listTop;
218
+ let over = drag.rects.length - 1;
219
+ for (let i = 0; i < drag.rects.length; i++) {
220
+ const r = drag.rects[i];
221
+ if (r && y < r.bottom) {
222
+ over = i;
223
+ break;
224
+ }
225
+ }
226
+ if (over !== drag.over) setDrag({ ...drag, over });
227
+ };
228
+ const finish = () => {
229
+ setDrag(null);
230
+ setArmed(null);
231
+ };
232
+ const handleDrop = (e) => {
233
+ e.preventDefault();
234
+ if (drag && drag.from !== drag.over) {
235
+ onReorder(moveItem(items, drag.from, drag.over));
236
+ }
237
+ finish();
238
+ };
239
+ const move = (from, to) => {
240
+ if (to < 0 || to >= items.length || from === to) return;
241
+ onReorder(moveItem(items, from, to));
242
+ };
243
+ const translateFor = (index) => {
244
+ if (!drag) return 0;
245
+ const { from, over, rects } = drag;
246
+ if (from === over) return 0;
247
+ const dragged = rects[from];
248
+ if (!dragged) return 0;
249
+ const neighbour = rects[from + 1] ?? rects[from - 1];
250
+ const gap = neighbour ? Math.max(
251
+ 0,
252
+ from + 1 < rects.length ? neighbour.top - dragged.bottom : dragged.top - neighbour.bottom
253
+ ) : 0;
254
+ const slot = dragged.height + gap;
255
+ if (index === from) {
256
+ const target = rects[over];
257
+ if (!target) return 0;
258
+ return over > from ? target.bottom - dragged.bottom : target.top - dragged.top;
259
+ }
260
+ if (from < over && index > from && index <= over) return -slot;
261
+ if (over < from && index >= over && index < from) return slot;
262
+ return 0;
263
+ };
264
+ if (items.length === 0) {
265
+ if (read && read.status !== "ready") return /* @__PURE__ */ jsx3(ReadEmpty, { read });
266
+ return emptyState !== void 0 ? /* @__PURE__ */ jsx3("div", { className: cn("text-xs text-muted-foreground", className), children: emptyState }) : null;
267
+ }
268
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
269
+ /* @__PURE__ */ jsx3(ReadStaleNotice, { read, className: "mb-1.5" }),
270
+ /* @__PURE__ */ jsx3(
271
+ "ul",
272
+ {
273
+ role: "list",
274
+ "aria-label": ariaLabel,
275
+ ref: listRef,
276
+ className: cn("flex flex-col gap-1.5", className),
277
+ onDragOver: handleDragOver,
278
+ onDrop: handleDrop,
279
+ children: items.map((item, index) => {
280
+ const key = getKey(item, index);
281
+ const isDragging = drag?.from === index;
282
+ const translate = translateFor(index);
283
+ return /* @__PURE__ */ jsxs3(
284
+ "li",
285
+ {
286
+ ref: (el) => {
287
+ rowRefs.current[index] = el;
288
+ },
289
+ draggable: canInteract && armed === index,
290
+ onDragStart: handleDragStart(index),
291
+ onDragEnd: finish,
292
+ style: {
293
+ transform: translate ? `translate3d(0, ${translate}px, 0)` : void 0
294
+ },
295
+ className: cn(
296
+ "flex items-center gap-1.5 rounded-md border px-2 py-1.5 text-sm text-foreground",
297
+ "transition-transform duration-150 ease-out will-change-transform",
298
+ isDragging ? "border-dashed border-primary/60 bg-primary/5 shadow-inner" : "border-border bg-card",
299
+ itemClassName
300
+ ),
301
+ children: [
302
+ /* @__PURE__ */ jsx3(
303
+ "button",
304
+ {
305
+ type: "button",
306
+ "aria-label": "Drag to reorder",
307
+ disabled: !canInteract,
308
+ onPointerDown: () => canInteract && setArmed(index),
309
+ onPointerUp: () => !drag && setArmed(null),
310
+ className: cn(
311
+ "flex h-7 w-6 shrink-0 touch-none items-center justify-center rounded text-muted-foreground",
312
+ canInteract ? "cursor-grab hover:bg-muted hover:text-foreground active:cursor-grabbing" : "opacity-40"
313
+ ),
314
+ children: /* @__PURE__ */ jsx3(GripVertical, { className: "h-4 w-4" })
315
+ }
316
+ ),
317
+ /* @__PURE__ */ jsx3(
318
+ "div",
319
+ {
320
+ className: cn(
321
+ "min-w-0 flex-1 break-words",
322
+ isDragging && "opacity-40"
323
+ ),
324
+ children: renderItem ? renderItem(item, { index, isDragging }) : defaultRender(item)
325
+ }
326
+ ),
327
+ (!hideArrows || onRemove) && /*
328
+ * Controls sit IN FLOW at the row's end — never floating.
329
+ *
330
+ * A cluster that costs no layout width must, by construction,
331
+ * land on top of something when it appears, and it wins every
332
+ * click there because it is the layer above. Rows here carry the
333
+ * host component's own trailing controls (copy, edit, menus), so
334
+ * a floating cluster covered live buttons on every consumer:
335
+ * measured on `artisan_demo_reading_list`, it sat on "Copy for
336
+ * AI" and "Edit book". The kit cannot know what a row draws in
337
+ * its corner, so it takes its own width instead of borrowing the
338
+ * row's. Ruled 2026-08-30: overlap is never worth the density.
339
+ */
340
+ /* @__PURE__ */ jsxs3(
341
+ "div",
342
+ {
343
+ className: cn(
344
+ "flex shrink-0 items-center gap-px self-start",
345
+ isDragging && "opacity-40"
346
+ ),
347
+ children: [
348
+ !hideArrows && /* Chevrons stack so the pair costs one 20px column, not two. */
349
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center pointer-coarse:flex-row", children: [
350
+ /* @__PURE__ */ jsx3(
351
+ "button",
352
+ {
353
+ type: "button",
354
+ "aria-label": "Move up",
355
+ disabled: !canInteract || index === 0,
356
+ onClick: () => move(index, index - 1),
357
+ className: "flex h-3.5 w-5 items-center justify-center rounded-sm text-muted-foreground/70 hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-30 pointer-coarse:h-7 pointer-coarse:w-7",
358
+ children: /* @__PURE__ */ jsx3(ChevronUp, { className: "h-3 w-3" })
359
+ }
360
+ ),
361
+ /* @__PURE__ */ jsx3(
362
+ "button",
363
+ {
364
+ type: "button",
365
+ "aria-label": "Move down",
366
+ disabled: !canInteract || index === items.length - 1,
367
+ onClick: () => move(index, index + 1),
368
+ className: "flex h-3.5 w-5 items-center justify-center rounded-sm text-muted-foreground/70 hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-30 pointer-coarse:h-7 pointer-coarse:w-7",
369
+ children: /* @__PURE__ */ jsx3(ChevronDown, { className: "h-3 w-3" })
370
+ }
371
+ )
372
+ ] }),
373
+ onRemove && /* @__PURE__ */ jsx3(
374
+ "button",
375
+ {
376
+ type: "button",
377
+ "aria-label": "Remove",
378
+ disabled: !canInteract,
379
+ onClick: () => onRemove(item, index),
380
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground/70 hover:bg-muted hover:text-destructive disabled:pointer-events-none disabled:opacity-30 pointer-coarse:h-7 pointer-coarse:w-7",
381
+ children: /* @__PURE__ */ jsx3(X, { className: "h-3.5 w-3.5" })
382
+ }
383
+ )
384
+ ]
385
+ }
386
+ )
387
+ ]
388
+ },
389
+ key
390
+ );
391
+ })
392
+ }
393
+ )
394
+ ] });
395
+ }
396
+
397
+ // kind-kit/KindPanelGrid.tsx
398
+ import "react";
399
+ import { cn as cn2 } from "@ai-matrx/design-system";
400
+ import { jsx as jsx4 } from "react/jsx-runtime";
401
+ var GAP_PX = { sm: 8, md: 12, lg: 16 };
402
+ var GAP_CLASS = { sm: "gap-2", md: "gap-3", lg: "gap-4" };
403
+ function KindPanelGrid({
404
+ children,
405
+ minColumnWidth = 280,
406
+ maxColumns,
407
+ gap = "md",
408
+ fill = "auto-fit",
409
+ className
410
+ }) {
411
+ const min = `min(100%, ${minColumnWidth}px)`;
412
+ const track = maxColumns && maxColumns > 0 ? `max(${min}, calc((100% - ${GAP_PX[gap] * (maxColumns - 1)}px) / ${maxColumns}))` : min;
413
+ return /* @__PURE__ */ jsx4(
414
+ "div",
415
+ {
416
+ className: cn2("grid items-stretch", GAP_CLASS[gap], className),
417
+ style: { gridTemplateColumns: `repeat(${fill}, minmax(${track}, 1fr))` },
418
+ children
419
+ }
420
+ );
421
+ }
422
+
423
+ // kind-kit/KindPanel.tsx
424
+ import * as React6 from "react";
425
+ import {
426
+ Button,
427
+ cn as cn4,
428
+ DropdownMenu,
429
+ DropdownMenuContent,
430
+ DropdownMenuItem,
431
+ DropdownMenuSeparator,
432
+ DropdownMenuTrigger
433
+ } from "@ai-matrx/design-system";
434
+
435
+ // kind-kit/icon-slot.tsx
436
+ import * as React5 from "react";
437
+ import { cn as cn3 } from "@ai-matrx/design-system";
438
+ function resolveIconType(icon) {
439
+ if (typeof icon === "function") return icon;
440
+ if (typeof icon !== "object" || icon === null) return null;
441
+ const candidate = icon;
442
+ if (typeof candidate.$$typeof === "symbol") {
443
+ return icon;
444
+ }
445
+ if ("default" in candidate && candidate.default !== icon) {
446
+ return resolveIconType(candidate.default);
447
+ }
448
+ return null;
449
+ }
450
+ function renderKindKitIcon(icon, className) {
451
+ if (!icon) return null;
452
+ if (React5.isValidElement(icon)) {
453
+ return React5.cloneElement(icon, {
454
+ className: cn3(className, icon.props.className)
455
+ });
456
+ }
457
+ const Icon = resolveIconType(icon);
458
+ return Icon ? React5.createElement(Icon, { className }) : null;
459
+ }
460
+
461
+ // kind-kit/KindPanel.tsx
462
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
463
+ function KindPanel({
464
+ title,
465
+ icon,
466
+ count,
467
+ badge,
468
+ streaming = false,
469
+ actions,
470
+ menuItems,
471
+ subline,
472
+ children,
473
+ footer,
474
+ variant = "card",
475
+ dense = false,
476
+ className,
477
+ bodyClassName
478
+ }) {
479
+ const px = dense ? "px-2.5" : "px-3";
480
+ const menu = menuItems && menuItems.length > 0 ? menuItems : null;
481
+ return /* @__PURE__ */ jsxs4(
482
+ "section",
483
+ {
484
+ className: cn4(
485
+ "flex h-full min-h-0 min-w-0 flex-col",
486
+ variant === "card" && "rounded-lg border border-border bg-card",
487
+ className
488
+ ),
489
+ children: [
490
+ /* @__PURE__ */ jsxs4(
491
+ "header",
492
+ {
493
+ className: cn4(
494
+ "flex items-start gap-2",
495
+ px,
496
+ dense ? "pt-2" : "pt-3",
497
+ variant === "bare" && "px-0"
498
+ ),
499
+ children: [
500
+ renderKindKitIcon(icon, "mt-0.5 h-3.5 w-3.5 shrink-0 text-primary"),
501
+ /* @__PURE__ */ jsx5("h3", { className: "min-w-0 flex-1 text-xs font-semibold uppercase leading-5 tracking-wide text-foreground break-words", children: title }),
502
+ count !== void 0 && /* @__PURE__ */ jsx5("span", { className: "mt-0.5 shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] tabular-nums text-muted-foreground", children: count }),
503
+ badge !== void 0 && /* @__PURE__ */ jsx5("span", { className: "mt-0.5 shrink-0", children: badge }),
504
+ streaming && /* @__PURE__ */ jsx5(
505
+ Loader2,
506
+ {
507
+ "aria-label": "Still arriving",
508
+ className: "mt-1 h-3 w-3 shrink-0 animate-spin text-muted-foreground"
509
+ }
510
+ ),
511
+ actions && /* @__PURE__ */ jsx5("div", { className: "flex shrink-0 items-center gap-1", children: actions }),
512
+ menu && /* @__PURE__ */ jsxs4(DropdownMenu, { children: [
513
+ /* @__PURE__ */ jsx5(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(
514
+ Button,
515
+ {
516
+ type: "button",
517
+ variant: "ghost",
518
+ size: "icon",
519
+ "aria-label": "More actions",
520
+ className: "-mr-1 -mt-1 h-7 w-7 shrink-0 text-muted-foreground",
521
+ children: /* @__PURE__ */ jsx5(MoreHorizontal, { className: "h-4 w-4" })
522
+ }
523
+ ) }),
524
+ /* @__PURE__ */ jsx5(DropdownMenuContent, { align: "end", className: "min-w-44", children: menu.map((item, i) => /* @__PURE__ */ jsxs4(React6.Fragment, { children: [
525
+ item.separatorBefore && i > 0 && /* @__PURE__ */ jsx5(DropdownMenuSeparator, {}),
526
+ /* @__PURE__ */ jsxs4(
527
+ DropdownMenuItem,
528
+ {
529
+ disabled: item.disabled ?? false,
530
+ onSelect: () => item.onSelect(),
531
+ className: cn4(
532
+ "text-xs",
533
+ item.destructive && "text-destructive focus:text-destructive"
534
+ ),
535
+ children: [
536
+ item.icon && /* @__PURE__ */ jsx5(item.icon, { className: "mr-2 h-3.5 w-3.5" }),
537
+ item.label
538
+ ]
539
+ }
540
+ )
541
+ ] }, `${i}-${item.label}`)) })
542
+ ] })
543
+ ]
544
+ }
545
+ ),
546
+ subline !== void 0 && subline !== null && subline !== "" && /* @__PURE__ */ jsx5(
547
+ "div",
548
+ {
549
+ className: cn4(
550
+ "pt-1 text-xs leading-snug text-muted-foreground break-words",
551
+ px,
552
+ variant === "bare" && "px-0"
553
+ ),
554
+ children: subline
555
+ }
556
+ ),
557
+ /* @__PURE__ */ jsx5(
558
+ "div",
559
+ {
560
+ className: cn4(
561
+ "min-w-0 flex-1",
562
+ px,
563
+ dense ? "py-1.5" : "py-2",
564
+ variant === "bare" && "px-0",
565
+ bodyClassName
566
+ ),
567
+ children
568
+ }
569
+ ),
570
+ footer !== void 0 && footer !== null && /* @__PURE__ */ jsx5(
571
+ "div",
572
+ {
573
+ className: cn4(
574
+ "mt-auto border-t border-border",
575
+ px,
576
+ dense ? "py-1.5" : "py-2",
577
+ variant === "bare" && "px-0"
578
+ ),
579
+ children: footer
580
+ }
581
+ )
582
+ ]
583
+ }
584
+ );
585
+ }
586
+
587
+ // kind-kit/KindHeaderBar.tsx
588
+ import "react";
589
+ import { cn as cn5 } from "@ai-matrx/design-system";
590
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
591
+ function KindHeaderBar({
592
+ title,
593
+ icon,
594
+ subtitle,
595
+ stats,
596
+ streaming = false,
597
+ streamingLabel = "Streaming",
598
+ copy,
599
+ actions,
600
+ size = "sm",
601
+ className
602
+ }) {
603
+ const { CopyButtons } = getKindKitHost();
604
+ const titleCls = size === "md" ? "text-base" : "text-sm";
605
+ const iconCls = size === "md" ? "h-5 w-5" : "h-4 w-4";
606
+ const iconNode = renderKindKitIcon(
607
+ icon,
608
+ cn5("mt-0.5 shrink-0 text-primary", iconCls)
609
+ );
610
+ return /* @__PURE__ */ jsxs5(
611
+ "div",
612
+ {
613
+ className: cn5("flex flex-wrap items-center gap-x-3 gap-y-1.5", className),
614
+ children: [
615
+ /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-1 basis-48 items-start gap-2", children: [
616
+ iconNode,
617
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1", children: [
618
+ /* @__PURE__ */ jsx6(
619
+ "div",
620
+ {
621
+ className: cn5(
622
+ "font-semibold leading-tight text-foreground break-words",
623
+ titleCls
624
+ ),
625
+ children: title
626
+ }
627
+ ),
628
+ subtitle !== void 0 && subtitle !== null && subtitle !== "" && /* @__PURE__ */ jsx6("div", { className: "mt-0.5 text-xs leading-snug text-muted-foreground break-words", children: subtitle })
629
+ ] })
630
+ ] }),
631
+ stats && stats.length > 0 && /* @__PURE__ */ jsx6("dl", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: stats.map((s, i) => /* @__PURE__ */ jsxs5(
632
+ "div",
633
+ {
634
+ title: s.title,
635
+ className: "flex items-baseline gap-1 text-xs",
636
+ children: [
637
+ renderKindKitIcon(
638
+ s.icon,
639
+ "h-3 w-3 self-center text-muted-foreground"
640
+ ),
641
+ /* @__PURE__ */ jsx6("dd", { className: "font-semibold tabular-nums text-foreground", children: s.value }),
642
+ /* @__PURE__ */ jsx6("dt", { className: "text-muted-foreground", children: s.label })
643
+ ]
644
+ },
645
+ `${i}-${s.label}`
646
+ )) }),
647
+ streaming && /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
648
+ /* @__PURE__ */ jsx6(Loader2, { className: "h-3 w-3 animate-spin" }),
649
+ streamingLabel
650
+ ] }),
651
+ (actions || copy) && /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
652
+ actions,
653
+ copy && /* @__PURE__ */ jsx6(CopyButtons, { ...copy, size: size === "md" ? "sm" : "icon" })
654
+ ] })
655
+ ]
656
+ }
657
+ );
658
+ }
659
+
660
+ // kind-kit/KindActionButton.tsx
661
+ import * as React8 from "react";
662
+ import { Button as Button2, cn as cn6 } from "@ai-matrx/design-system";
663
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
664
+ var ERROR_MAX = 60;
665
+ function KindActionButton({
666
+ runAction,
667
+ action,
668
+ input,
669
+ label,
670
+ icon,
671
+ busyLabel,
672
+ confirm,
673
+ onDone,
674
+ onError,
675
+ variant = "outline",
676
+ compact = false,
677
+ disabled = false,
678
+ className
679
+ }) {
680
+ const [busy, setBusy] = React8.useState(false);
681
+ const [asking, setAsking] = React8.useState(false);
682
+ const [error, setError] = React8.useState(null);
683
+ const inFlight = React8.useRef(false);
684
+ const mounted = React8.useRef(true);
685
+ const errorTimer = React8.useRef(null);
686
+ React8.useEffect(() => {
687
+ mounted.current = true;
688
+ return () => {
689
+ mounted.current = false;
690
+ if (errorTimer.current) clearTimeout(errorTimer.current);
691
+ };
692
+ }, []);
693
+ const run = React8.useCallback(async () => {
694
+ if (inFlight.current) return;
695
+ inFlight.current = true;
696
+ setAsking(false);
697
+ setError(null);
698
+ setBusy(true);
699
+ try {
700
+ const payload = typeof input === "function" ? input() : input;
701
+ const res = await runAction(action, payload);
702
+ if (res && res.ok) {
703
+ onDone?.(res.result);
704
+ } else {
705
+ const message = res && "error" in res && res.error || "Action failed";
706
+ if (mounted.current) {
707
+ setError(message);
708
+ if (errorTimer.current) clearTimeout(errorTimer.current);
709
+ errorTimer.current = setTimeout(() => {
710
+ if (mounted.current) setError(null);
711
+ }, 8e3);
712
+ }
713
+ onError?.(message);
714
+ }
715
+ } catch (e) {
716
+ const message = e instanceof Error ? e.message : "Action failed";
717
+ if (mounted.current) setError(message);
718
+ onError?.(message);
719
+ } finally {
720
+ inFlight.current = false;
721
+ if (mounted.current) setBusy(false);
722
+ }
723
+ }, [action, input, onDone, onError, runAction]);
724
+ const onClick = () => {
725
+ if (busy || disabled || inFlight.current) return;
726
+ if (confirm) setAsking(true);
727
+ else void run();
728
+ };
729
+ if (asking && !busy) {
730
+ return /* @__PURE__ */ jsxs6(
731
+ "span",
732
+ {
733
+ role: "group",
734
+ "aria-label": label,
735
+ className: cn6(
736
+ "inline-flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md border border-border bg-card px-2 py-1 text-xs",
737
+ className
738
+ ),
739
+ children: [
740
+ /* @__PURE__ */ jsx7("span", { className: "text-foreground", children: confirm }),
741
+ /* @__PURE__ */ jsx7(Button2, { type: "button", size: "xs", variant: variant === "outline" ? "default" : variant, onClick: () => void run(), children: label }),
742
+ /* @__PURE__ */ jsx7(Button2, { type: "button", size: "xs", variant: "ghost", onClick: () => setAsking(false), children: "Cancel" })
743
+ ]
744
+ }
745
+ );
746
+ }
747
+ const shownLabel = busy ? busyLabel ?? label : label;
748
+ const glyph = busy ? /* @__PURE__ */ jsx7(Loader2, { className: "h-4 w-4 animate-spin" }) : renderKindKitIcon(icon, "h-4 w-4");
749
+ return /* @__PURE__ */ jsxs6("span", { className: cn6("inline-flex min-w-0 items-center gap-2", className), children: [
750
+ /* @__PURE__ */ jsxs6(
751
+ Button2,
752
+ {
753
+ type: "button",
754
+ variant,
755
+ size: compact ? "icon-sm" : "sm",
756
+ disabled: disabled || busy,
757
+ "aria-busy": busy || void 0,
758
+ "aria-label": compact ? shownLabel : void 0,
759
+ title: compact ? label : void 0,
760
+ onClick,
761
+ children: [
762
+ glyph,
763
+ !compact && /* @__PURE__ */ jsx7("span", { children: shownLabel })
764
+ ]
765
+ }
766
+ ),
767
+ error && /* @__PURE__ */ jsx7(
768
+ "span",
769
+ {
770
+ role: "alert",
771
+ title: error,
772
+ className: "min-w-0 text-xs text-destructive",
773
+ children: error.length > ERROR_MAX ? `${error.slice(0, ERROR_MAX - 1)}\u2026` : error
774
+ }
775
+ )
776
+ ] });
777
+ }
778
+
779
+ // kind-kit/StreamingSkeleton.tsx
780
+ import * as React9 from "react";
781
+ import { cn as cn7, Skeleton } from "@ai-matrx/design-system";
782
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
783
+ function StreamingSkeleton({
784
+ layout = "list",
785
+ rows = 3,
786
+ columns,
787
+ header = true,
788
+ label = "Loading",
789
+ className
790
+ }) {
791
+ const n = Math.max(1, rows);
792
+ const cols = Math.max(1, columns ?? (layout === "cards" ? 2 : 3));
793
+ return /* @__PURE__ */ jsxs7(
794
+ "div",
795
+ {
796
+ role: "status",
797
+ "aria-busy": "true",
798
+ "aria-label": label,
799
+ className: cn7("space-y-2", className),
800
+ children: [
801
+ header && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
802
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-4 rounded" }),
803
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-40" }),
804
+ /* @__PURE__ */ jsx8(Skeleton, { className: "ml-auto h-6 w-16" })
805
+ ] }),
806
+ layout === "list" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 rounded-md border border-border px-2 py-2", children: [
807
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-4 rounded" }),
808
+ /* @__PURE__ */ jsx8(Skeleton, { className: cn7("h-3.5", i % 3 === 0 ? "w-2/3" : i % 3 === 1 ? "w-1/2" : "w-3/4") })
809
+ ] }, i)),
810
+ layout === "cards" && /* @__PURE__ */ jsx8(
811
+ "div",
812
+ {
813
+ className: "grid gap-3",
814
+ style: { gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, 240px), 1fr))` },
815
+ children: Array.from({ length: Math.max(n, cols) }).map((_, i) => /* @__PURE__ */ jsxs7("div", { className: "space-y-2 rounded-lg border border-border p-3", children: [
816
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-3.5 w-1/2" }),
817
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-3 w-full" }),
818
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-1.5 pt-1", children: [
819
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-16 rounded-full" }),
820
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-24 rounded-full" }),
821
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-12 rounded-full" })
822
+ ] })
823
+ ] }, i))
824
+ }
825
+ ),
826
+ layout === "table" && /* @__PURE__ */ jsxs7("div", { className: "overflow-hidden rounded-md border border-border", children: [
827
+ /* @__PURE__ */ jsx8(
828
+ "div",
829
+ {
830
+ className: "grid gap-2 border-b border-border bg-muted/40 px-2 py-1.5",
831
+ style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
832
+ children: Array.from({ length: cols }).map((_, c) => /* @__PURE__ */ jsx8(Skeleton, { className: "h-3 w-2/3" }, c))
833
+ }
834
+ ),
835
+ Array.from({ length: n }).map((_, r) => /* @__PURE__ */ jsx8(
836
+ "div",
837
+ {
838
+ className: "grid gap-2 px-2 py-2",
839
+ style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
840
+ children: Array.from({ length: cols }).map((_2, c) => /* @__PURE__ */ jsx8(Skeleton, { className: cn7("h-3", c === 0 ? "w-3/4" : "w-1/2") }, c))
841
+ },
842
+ r
843
+ ))
844
+ ] }),
845
+ layout === "text" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsx8(
846
+ Skeleton,
847
+ {
848
+ className: cn7("h-3", i === n - 1 ? "w-2/5" : i % 2 === 0 ? "w-full" : "w-11/12")
849
+ },
850
+ i
851
+ )),
852
+ /* @__PURE__ */ jsx8("span", { className: "sr-only", children: label })
853
+ ]
854
+ }
855
+ );
856
+ }
857
+ function useStreamingValue(value, fallback) {
858
+ const [last, setLast] = React9.useState({
859
+ value: fallback,
860
+ arrived: false
861
+ });
862
+ const defined = value !== null && value !== void 0;
863
+ if (defined && (!last.arrived || !Object.is(value, last.value))) {
864
+ const next = { value, arrived: true };
865
+ setLast(next);
866
+ return next;
867
+ }
868
+ return last;
869
+ }
870
+ function streamList(value) {
871
+ return Array.isArray(value) ? value : [];
872
+ }
873
+ function streamText(value, fallback = "") {
874
+ return typeof value === "string" && value.length > 0 ? value : fallback;
875
+ }
876
+
877
+ // kind-kit/TagList.tsx
878
+ import * as React10 from "react";
879
+ import { cn as cn8 } from "@ai-matrx/design-system";
880
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
881
+ var TONE = {
882
+ default: "border-border bg-background text-foreground",
883
+ primary: "border-primary/40 bg-primary/5 text-foreground",
884
+ muted: "border-border bg-muted text-muted-foreground"
885
+ };
886
+ function KeywordChip({
887
+ label,
888
+ meta,
889
+ icon,
890
+ selected = false,
891
+ onSelect,
892
+ onRemove,
893
+ onEdit,
894
+ disabled = false,
895
+ tone = "default",
896
+ size = "sm",
897
+ className
898
+ }) {
899
+ const [editing, setEditing] = React10.useState(false);
900
+ const [draft, setDraft] = React10.useState(label);
901
+ const inputRef = React10.useRef(null);
902
+ const selectable = !!onSelect && !disabled;
903
+ const editable = !!onEdit && !disabled;
904
+ const startEdit = () => {
905
+ if (!editable) return;
906
+ setDraft(label);
907
+ setEditing(true);
908
+ requestAnimationFrame(() => inputRef.current?.select());
909
+ };
910
+ const commit = () => {
911
+ setEditing(false);
912
+ const next = draft.trim();
913
+ if (next && next !== label) onEdit?.(next);
914
+ };
915
+ const cancel = () => {
916
+ setEditing(false);
917
+ setDraft(label);
918
+ };
919
+ const pad = size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs";
920
+ const inputText = size === "md" ? "text-[16px] sm:text-sm" : "text-[16px] sm:text-xs";
921
+ const ctl = size === "md" ? "h-4 w-4" : "h-3.5 w-3.5";
922
+ return /* @__PURE__ */ jsxs8(
923
+ "span",
924
+ {
925
+ className: cn8(
926
+ // max-w-full + min-w-0 + break-words: the text wraps INSIDE the chip.
927
+ "inline-flex max-w-full min-w-0 items-center gap-1 rounded-full border leading-snug",
928
+ pad,
929
+ selected ? "border-primary bg-primary/10 text-foreground" : TONE[tone],
930
+ disabled && "opacity-60",
931
+ className
932
+ ),
933
+ children: [
934
+ selectable && /* @__PURE__ */ jsx9(
935
+ "button",
936
+ {
937
+ type: "button",
938
+ role: "checkbox",
939
+ "aria-checked": selected,
940
+ "aria-label": `${selected ? "Deselect" : "Select"} ${label}`,
941
+ onClick: () => onSelect?.(!selected),
942
+ className: cn8(
943
+ "flex shrink-0 items-center justify-center rounded-sm border",
944
+ size === "md" ? "h-4 w-4" : "h-3.5 w-3.5",
945
+ selected ? "border-primary bg-primary text-primary-foreground" : "border-muted-foreground/50 bg-background"
946
+ ),
947
+ children: selected && /* @__PURE__ */ jsx9(Check, { className: "h-2.5 w-2.5" })
948
+ }
949
+ ),
950
+ renderKindKitIcon(
951
+ icon,
952
+ cn8("shrink-0 text-muted-foreground", ctl)
953
+ ),
954
+ editing ? /* @__PURE__ */ jsx9(
955
+ "input",
956
+ {
957
+ ref: inputRef,
958
+ value: draft,
959
+ onChange: (e) => setDraft(e.target.value),
960
+ onBlur: commit,
961
+ onKeyDown: (e) => {
962
+ if (e.key === "Enter") {
963
+ e.preventDefault();
964
+ commit();
965
+ } else if (e.key === "Escape") {
966
+ e.preventDefault();
967
+ cancel();
968
+ }
969
+ },
970
+ "aria-label": `Edit ${label}`,
971
+ size: Math.max(4, draft.length + 1),
972
+ className: cn8("min-w-0 bg-transparent outline-none", inputText)
973
+ }
974
+ ) : /* @__PURE__ */ jsx9(
975
+ "span",
976
+ {
977
+ className: "min-w-0 whitespace-normal break-words text-left",
978
+ onDoubleClick: startEdit,
979
+ children: label
980
+ }
981
+ ),
982
+ meta !== void 0 && meta !== null && /* @__PURE__ */ jsx9("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: meta }),
983
+ editable && !editing && /* @__PURE__ */ jsx9(
984
+ "button",
985
+ {
986
+ type: "button",
987
+ "aria-label": `Edit ${label}`,
988
+ onClick: startEdit,
989
+ className: "shrink-0 rounded-full text-muted-foreground hover:text-foreground",
990
+ children: /* @__PURE__ */ jsx9(Pencil, { className: cn8("h-3 w-3", size === "md" && "h-3.5 w-3.5") })
991
+ }
992
+ ),
993
+ onRemove && /* @__PURE__ */ jsx9(
994
+ "button",
995
+ {
996
+ type: "button",
997
+ "aria-label": `Remove ${label}`,
998
+ disabled,
999
+ onClick: onRemove,
1000
+ className: "-mr-0.5 shrink-0 rounded-full text-muted-foreground hover:text-destructive disabled:pointer-events-none",
1001
+ children: /* @__PURE__ */ jsx9(X, { className: ctl })
1002
+ }
1003
+ )
1004
+ ]
1005
+ }
1006
+ );
1007
+ }
1008
+ function normalize(item) {
1009
+ return typeof item === "string" ? { label: item } : item;
1010
+ }
1011
+ function TagList({
1012
+ items,
1013
+ selected,
1014
+ onToggle,
1015
+ onRemove,
1016
+ onEdit,
1017
+ onAdd,
1018
+ addPlaceholder = "Add\u2026",
1019
+ emptyState,
1020
+ read,
1021
+ tone,
1022
+ size = "sm",
1023
+ disabled = false,
1024
+ className
1025
+ }) {
1026
+ const { ReadEmpty, ReadStaleNotice } = getKindKitHost();
1027
+ const [adding, setAdding] = React10.useState(false);
1028
+ const [draft, setDraft] = React10.useState("");
1029
+ const inputText = size === "md" ? "text-[16px] sm:text-sm" : "text-[16px] sm:text-xs";
1030
+ const selectedSet = new Set(selected ?? []);
1031
+ const commitAdd = () => {
1032
+ const next = draft.trim();
1033
+ if (next) onAdd?.(next);
1034
+ setDraft("");
1035
+ setAdding(false);
1036
+ };
1037
+ if (items.length === 0 && read && read.status !== "ready") return /* @__PURE__ */ jsx9(ReadEmpty, { read });
1038
+ if (items.length === 0 && !onAdd) {
1039
+ return emptyState !== void 0 ? /* @__PURE__ */ jsx9("div", { className: cn8("text-xs text-muted-foreground", className), children: emptyState }) : null;
1040
+ }
1041
+ return /* @__PURE__ */ jsxs8("div", { className: cn8("flex flex-wrap items-center gap-1.5", className), children: [
1042
+ /* @__PURE__ */ jsx9(ReadStaleNotice, { read, className: "w-full" }),
1043
+ items.map((raw, index) => {
1044
+ const item = normalize(raw);
1045
+ const key = item.key ?? item.label;
1046
+ return /* @__PURE__ */ jsx9(
1047
+ KeywordChip,
1048
+ {
1049
+ label: item.label,
1050
+ meta: item.meta,
1051
+ tone,
1052
+ size,
1053
+ disabled: disabled || item.disabled,
1054
+ selected: selectedSet.has(key),
1055
+ onSelect: onToggle ? (next) => onToggle(key, next) : void 0,
1056
+ onRemove: onRemove ? () => onRemove(key, index) : void 0,
1057
+ onEdit: onEdit ? (next) => onEdit(key, index, next) : void 0
1058
+ },
1059
+ `${key}-${index}`
1060
+ );
1061
+ }),
1062
+ items.length === 0 && emptyState !== void 0 && /* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: emptyState }),
1063
+ onAdd && !disabled && (adding ? /* @__PURE__ */ jsx9(
1064
+ "span",
1065
+ {
1066
+ className: cn8(
1067
+ "inline-flex items-center gap-1 rounded-full border border-dashed border-primary/60 bg-background",
1068
+ size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs"
1069
+ ),
1070
+ children: /* @__PURE__ */ jsx9(
1071
+ "input",
1072
+ {
1073
+ autoFocus: true,
1074
+ value: draft,
1075
+ placeholder: addPlaceholder,
1076
+ onChange: (e) => setDraft(e.target.value),
1077
+ onBlur: commitAdd,
1078
+ onKeyDown: (e) => {
1079
+ if (e.key === "Enter") {
1080
+ e.preventDefault();
1081
+ commitAdd();
1082
+ } else if (e.key === "Escape") {
1083
+ e.preventDefault();
1084
+ setDraft("");
1085
+ setAdding(false);
1086
+ }
1087
+ },
1088
+ "aria-label": addPlaceholder,
1089
+ size: Math.max(6, draft.length + 1),
1090
+ className: cn8("min-w-0 bg-transparent outline-none placeholder:text-muted-foreground", inputText)
1091
+ }
1092
+ )
1093
+ }
1094
+ ) : /* @__PURE__ */ jsxs8(
1095
+ "button",
1096
+ {
1097
+ type: "button",
1098
+ onClick: () => setAdding(true),
1099
+ className: cn8(
1100
+ "inline-flex items-center gap-1 rounded-full border border-dashed border-border text-muted-foreground hover:border-primary/60 hover:text-foreground",
1101
+ size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs"
1102
+ ),
1103
+ children: [
1104
+ /* @__PURE__ */ jsx9(Plus, { className: "h-3 w-3" }),
1105
+ addPlaceholder.replace(/…$/, "")
1106
+ ]
1107
+ }
1108
+ ))
1109
+ ] });
1110
+ }
1111
+ export {
1112
+ DefaultCopyButtons,
1113
+ DefaultReadEmpty,
1114
+ DefaultReadStaleNotice,
1115
+ KeywordChip,
1116
+ KindActionButton,
1117
+ KindHeaderBar,
1118
+ KindPanel,
1119
+ KindPanelGrid,
1120
+ SortableList,
1121
+ StreamingSkeleton,
1122
+ TagList,
1123
+ getKindKitHost,
1124
+ renderKindKitIcon,
1125
+ resetKindKitHost,
1126
+ setKindKitHost,
1127
+ streamList,
1128
+ streamText,
1129
+ useStreamingValue
1130
+ };
1131
+ //# sourceMappingURL=kind-kit.js.map