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