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