@llmnative/react 1.3.0 → 1.4.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.
package/dist/index.mjs CHANGED
@@ -11376,57 +11376,61 @@ function Td({ records: e, selectedKeys: t, onSelectionChange: n, getRecordKey: r
11376
11376
  }
11377
11377
  //#endregion
11378
11378
  //#region src/components/ui/useStableRecordKey.ts
11379
- function Ed(e) {
11380
- let t = m(/* @__PURE__ */ new WeakMap()), n = m(0);
11381
- return s((r, i) => {
11382
- if (r._key) return r[Ia];
11383
- let a = r, o = t.current.get(a);
11384
- if (o) return o;
11385
- let s = `${e}-${n.current++}`;
11386
- return t.current.set(a, s), s;
11387
- }, [e]);
11379
+ function Ed(e, t) {
11380
+ let n = m(/* @__PURE__ */ new WeakMap()), r = m(0);
11381
+ return s((i, a) => {
11382
+ if (t != null) {
11383
+ let e = typeof t == "function" ? t(i) : i[t];
11384
+ if (e != null && e !== "") return String(e);
11385
+ }
11386
+ if (i._key) return i[Ia];
11387
+ let o = i, s = n.current.get(o);
11388
+ if (s) return s;
11389
+ let c = `${e}-${r.current++}`;
11390
+ return n.current.set(o, c), c;
11391
+ }, [e, t]);
11388
11392
  }
11389
11393
  //#endregion
11390
11394
  //#region src/components/ui/Table.tsx
11391
- function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRowClick: i = void 0, onReorder: a = void 0, onSelectionChange: o = void 0, selection: c = "multiple", sortable: d = !1, pagination: f = void 0, activeKey: g = void 0, selectedKeys: _ = void 0, groupBy: v = void 0, before: y = void 0, after: b = void 0, wrapperClassName: x = void 0, className: S = void 0, headerClassName: C = void 0, bodyClassName: w = void 0, footerClassName: T = void 0, heightClassName: A = void 0, scrollClassName: j = void 0, selectedClassName: M = void 0, renderCell: N = void 0 }) {
11392
- let P = Y("table"), F = Mn("table"), I = M || P.Table.selectedClassName, [L, R] = h(n || []), ee = p(() => {
11395
+ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRowClick: i = void 0, onReorder: a = void 0, onSelectionChange: o = void 0, selection: c = "multiple", sortable: d = !1, pagination: f = void 0, activeKey: g = void 0, selectedKeys: _ = void 0, groupBy: v = void 0, recordId: y = void 0, before: b = void 0, after: x = void 0, wrapperClassName: S = void 0, className: C = void 0, headerClassName: w = void 0, bodyClassName: T = void 0, footerClassName: A = void 0, heightClassName: j = void 0, scrollClassName: M = void 0, selectedClassName: N = void 0, renderCell: P = void 0 }) {
11396
+ let F = Y("table"), I = Mn("table"), L = N || F.Table.selectedClassName, [R, ee] = h(n || []), z = p(() => {
11393
11397
  if (!(!d || typeof d == "boolean")) return d;
11394
- }, [typeof d == "object" ? d?.dir : void 0, typeof d == "object" ? d?.field : void 0]), z = d !== !1, [B, V] = h(ee), [H, U] = h(null), [te, ne] = h(null), [W, re] = h(null), [ie, G] = h(null), [ae, oe] = h(null), se = m(!1), ce = s((e) => {
11395
- e && U(e);
11396
- }, []), le = u(), ue = !!a, de = z || !!Is.normalize(ee), fe = ue && de, pe = !fe && z, K = fe ? void 0 : ee;
11398
+ }, [typeof d == "object" ? d?.dir : void 0, typeof d == "object" ? d?.field : void 0]), B = d !== !1, [V, H] = h(z), [U, te] = h(null), [ne, W] = h(null), [re, ie] = h(null), [G, ae] = h(null), [oe, se] = h(null), ce = m(!1), le = s((e) => {
11399
+ e && te(e);
11400
+ }, []), ue = u(), de = !!a, fe = B || !!Is.normalize(z), pe = de && fe, K = !pe && B, q = pe ? void 0 : z;
11397
11401
  l(() => {
11398
- R(n || []);
11402
+ ee(n || []);
11399
11403
  }, [n]), l(() => {
11400
- V(K);
11401
- }, [K?.field, K?.dir]), l(() => {
11402
- !fe || se.current || (console.warn("Table: `onReorder` cannot be combined with sortable sorting on the same view. Manual reorder takes precedence and sorting is ignored."), se.current = !0);
11403
- }, [fe]);
11404
- let q = Ed("row"), J = s((e, t) => q(e, t), [q]), { activeSelectedKeys: me, selectionState: he, showSelection: ge, updateSelection: _e } = Td({
11405
- records: L,
11404
+ H(q);
11405
+ }, [q?.field, q?.dir]), l(() => {
11406
+ !pe || ce.current || (console.warn("Table: `onReorder` cannot be combined with sortable sorting on the same view. Manual reorder takes precedence and sorting is ignored."), ce.current = !0);
11407
+ }, [pe]);
11408
+ let J = Ed("row", y), me = s((e, t) => J(e, t), [J]), { activeSelectedKeys: he, selectionState: ge, showSelection: _e, updateSelection: ve } = Td({
11409
+ records: R,
11406
11410
  selectedKeys: _,
11407
11411
  onSelectionChange: o,
11408
- getRecordKey: J
11412
+ getRecordKey: me
11409
11413
  });
11410
11414
  l(() => {
11411
- ae && (L.some((e, t) => J(e, t) === ae) || oe(null));
11415
+ oe && (R.some((e, t) => me(e, t) === oe) || se(null));
11412
11416
  }, [
11413
- ae,
11414
- J,
11415
- L
11417
+ oe,
11418
+ me,
11419
+ R
11416
11420
  ]), l(() => {
11417
- if (B || !e?.length || ue) return;
11418
- let t = e.find((e) => pe && e.sort !== !1);
11419
- t && V({
11421
+ if (V || !e?.length || de) return;
11422
+ let t = e.find((e) => K && e.sort !== !1);
11423
+ t && H({
11420
11424
  field: t.key,
11421
11425
  dir: "asc"
11422
11426
  });
11423
11427
  }, [
11424
- B,
11425
- pe,
11428
+ V,
11429
+ K,
11426
11430
  e,
11427
- ue
11431
+ de
11428
11432
  ]);
11429
- let ve = p(() => Is.records(L, B) || [], [L, B]), ye = (e, t, n) => {
11433
+ let ye = p(() => Is.records(R, V) || [], [R, V]), be = (e, t, n) => {
11430
11434
  let r = e.target;
11431
11435
  for (; r && r.tagName !== "TR";) {
11432
11436
  if ([
@@ -11437,77 +11441,77 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11437
11441
  ].includes(r.tagName)) return;
11438
11442
  r = r.parentNode;
11439
11443
  }
11440
- let a = J(t, n);
11441
- I && g === void 0 && oe((e) => e === a ? null : a), i?.(t);
11442
- }, be = (e, n, r) => {
11443
- if (N) return N(e, n, r);
11444
+ let a = me(t, n);
11445
+ L && g === void 0 && se((e) => e === a ? null : a), i?.(t);
11446
+ }, xe = (e, n, r) => {
11447
+ if (P) return P(e, n, r);
11444
11448
  let i = e[n], a = typeof i == "object" && i && !Array.isArray(i) ? i : null, o = a?.prompt && a?.value || i;
11445
11449
  return t.isValidElement(o) || typeof o != "object" || !o ? o : Array.isArray(o) && !o.some((e) => typeof e == "object" && e) ? o.join(", ") : "";
11446
- }, xe = s((e, t) => {
11447
- let n = J(e, t), r = me.includes(n) ? me.filter((e) => e !== n) : [...me, n];
11448
- _e(r);
11450
+ }, Se = s((e, t) => {
11451
+ let n = me(e, t), r = he.includes(n) ? he.filter((e) => e !== n) : [...he, n];
11452
+ ve(r);
11449
11453
  }, [
11454
+ he,
11450
11455
  me,
11451
- J,
11452
- _e
11453
- ]), Se = s((e, t) => {
11454
- let n = J(e, t);
11455
- _e(me.includes(n) ? [] : [n]);
11456
+ ve
11457
+ ]), Ce = s((e, t) => {
11458
+ let n = me(e, t);
11459
+ ve(he.includes(n) ? [] : [n]);
11456
11460
  }, [
11461
+ he,
11457
11462
  me,
11458
- J,
11459
- _e
11460
- ]), Ce = s((e, t) => {
11461
- if (!te) return;
11462
- let n = ve.findIndex((e, t) => J(e, t) === te), r = ve.findIndex((n, r) => J(n, r) === J(e, t));
11463
- re(null), ne(null);
11464
- let i = ie?.position || "after";
11465
- if (G(null), n < 0 || r < 0 || n === r) return;
11466
- let o = [...ve], [s] = o.splice(n, 1), c = n < r ? r + (i === "after" ? 0 : -1) : r + +(i === "after");
11467
- o.splice(c, 0, s), V(void 0), R(o), a?.(o, {
11463
+ ve
11464
+ ]), we = s((e, t) => {
11465
+ if (!ne) return;
11466
+ let n = ye.findIndex((e, t) => me(e, t) === ne), r = ye.findIndex((n, r) => me(n, r) === me(e, t));
11467
+ ie(null), W(null);
11468
+ let i = G?.position || "after";
11469
+ if (ae(null), n < 0 || r < 0 || n === r) return;
11470
+ let o = [...ye], [s] = o.splice(n, 1), c = n < r ? r + (i === "after" ? 0 : -1) : r + +(i === "after");
11471
+ o.splice(c, 0, s), H(void 0), ee(o), a?.(o, {
11468
11472
  fromIndex: n,
11469
11473
  toIndex: c,
11470
11474
  record: s
11471
11475
  });
11472
11476
  }, [
11473
- te,
11474
- ie?.position,
11475
- J,
11477
+ ne,
11478
+ G?.position,
11479
+ me,
11476
11480
  a,
11477
- ve
11481
+ ye
11478
11482
  ]);
11479
- if (ve.length === 0) return /* @__PURE__ */ t.createElement("p", { className: "p-4" }, F.noDataFound);
11480
- let we = e || Object.keys(ve[0]).map((e) => ({
11483
+ if (ye.length === 0) return /* @__PURE__ */ t.createElement("p", { className: "p-4" }, I.noDataFound);
11484
+ let Te = e || Object.keys(ye[0]).map((e) => ({
11481
11485
  key: e,
11482
11486
  label: e,
11483
- sort: z
11484
- })), Te = [
11487
+ sort: B
11488
+ })), Ee = [
11485
11489
  "w-full",
11486
- P.Table.scrollClassName,
11487
- A ? `${A} overflow-auto` : "",
11488
- j || ""
11489
- ].filter(Boolean).join(" "), Ee = we.length + +!!ge + +!!ue, De = (e, n, r, i) => !ie || ie.key !== e || ie.position !== n ? null : /* @__PURE__ */ t.createElement("tr", {
11490
+ F.Table.scrollClassName,
11491
+ j ? `${j} overflow-auto` : "",
11492
+ M || ""
11493
+ ].filter(Boolean).join(" "), De = Te.length + +!!_e + +!!de, Oe = (e, n, r, i) => !G || G.key !== e || G.position !== n ? null : /* @__PURE__ */ t.createElement("tr", {
11490
11494
  "aria-hidden": "true",
11491
11495
  onDragOver: (t) => {
11492
- ue && (t.preventDefault(), W !== e && re(e), G({
11496
+ de && (t.preventDefault(), re !== e && ie(e), ae({
11493
11497
  key: e,
11494
11498
  position: n
11495
11499
  }));
11496
11500
  },
11497
11501
  onDrop: (t) => {
11498
- ue && (t.preventDefault(), G({
11502
+ de && (t.preventDefault(), ae({
11499
11503
  key: e,
11500
11504
  position: n
11501
- }), Ce(r, i));
11505
+ }), we(r, i));
11502
11506
  }
11503
11507
  }, /* @__PURE__ */ t.createElement("td", {
11504
- colSpan: Ee,
11508
+ colSpan: De,
11505
11509
  className: "border-0 p-0"
11506
11510
  }, /* @__PURE__ */ t.createElement("div", { className: "relative h-5 cursor-grab" }, /* @__PURE__ */ t.createElement("div", { className: "absolute inset-x-2 top-1/2 -translate-y-1/2" }, /* @__PURE__ */ t.createElement("div", { className: "h-0 rounded-full border-t-2 border-primary/80" }), /* @__PURE__ */ t.createElement("div", { className: "absolute left-0 top-1/2 h-2 w-2 -translate-y-1/2 rounded-full bg-primary shadow-sm" })))));
11507
- return /* @__PURE__ */ t.createElement("div", { className: "flex items-stretch gap-3" }, y && /* @__PURE__ */ t.createElement("div", { className: "table-before flex shrink-0 items-center self-stretch" }, y), /* @__PURE__ */ t.createElement("div", {
11508
- ref: ce,
11509
- className: "min-w-0 flex-1 overflow-x-auto " + (x || P.Table.wrapperClassName)
11510
- }, /* @__PURE__ */ t.createElement("div", { className: Te }, /* @__PURE__ */ t.createElement("table", { className: "w-full min-w-full text-left text-sm border-collapse " + (S || P.Table.className) }, /* @__PURE__ */ t.createElement("thead", { className: "border-b " + (C || P.Table.headerClassName) }, /* @__PURE__ */ t.createElement("tr", null, ge && /* @__PURE__ */ t.createElement("th", {
11511
+ return /* @__PURE__ */ t.createElement("div", { className: "flex items-stretch gap-3" }, b && /* @__PURE__ */ t.createElement("div", { className: "table-before flex shrink-0 items-center self-stretch" }, b), /* @__PURE__ */ t.createElement("div", {
11512
+ ref: le,
11513
+ className: "min-w-0 flex-1 overflow-x-auto " + (S || F.Table.wrapperClassName)
11514
+ }, /* @__PURE__ */ t.createElement("div", { className: Ee }, /* @__PURE__ */ t.createElement("table", { className: "w-full min-w-full text-left text-sm border-collapse " + (C || F.Table.className) }, /* @__PURE__ */ t.createElement("thead", { className: "border-b " + (w || F.Table.headerClassName) }, /* @__PURE__ */ t.createElement("tr", null, _e && /* @__PURE__ */ t.createElement("th", {
11511
11515
  className: "px-3 py-2 font-semibold text-muted-foreground",
11512
11516
  style: {
11513
11517
  width: "1%",
@@ -11515,20 +11519,20 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11515
11519
  }
11516
11520
  }, c === "single" ? /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" }) : /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" }, /* @__PURE__ */ t.createElement("input", {
11517
11521
  type: "checkbox",
11518
- "aria-label": F.selectAllRows,
11519
- checked: he.records.length > 0 && he.records.length === L.length,
11522
+ "aria-label": I.selectAllRows,
11523
+ checked: ge.records.length > 0 && ge.records.length === R.length,
11520
11524
  onChange: (e) => {
11521
- let t = e.target.checked ? ve.map((e, t) => J(e, t)) : [];
11522
- _e(t);
11525
+ let t = e.target.checked ? ye.map((e, t) => me(e, t)) : [];
11526
+ ve(t);
11523
11527
  }
11524
- }))), ue && /* @__PURE__ */ t.createElement("th", {
11528
+ }))), de && /* @__PURE__ */ t.createElement("th", {
11525
11529
  className: "px-3 py-2 font-semibold text-muted-foreground",
11526
11530
  style: {
11527
11531
  width: "1%",
11528
11532
  whiteSpace: "nowrap"
11529
11533
  }
11530
- }, /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" })), we.map((e) => e.label ? (() => {
11531
- let n = pe && e.sort !== !1, r = n && B?.field === e.key, i = r ? B?.dir === "desc" ? "descending" : "ascending" : "none";
11534
+ }, /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" })), Te.map((e) => e.label ? (() => {
11535
+ let n = K && e.sort !== !1, r = n && V?.field === e.key, i = r ? V?.dir === "desc" ? "descending" : "ascending" : "none";
11532
11536
  return /* @__PURE__ */ t.createElement("th", {
11533
11537
  key: e.key,
11534
11538
  className: "px-3 py-2 font-semibold text-muted-foreground" + (e.className ? " " + e.className : ""),
@@ -11536,16 +11540,16 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11536
11540
  }, n ? /* @__PURE__ */ t.createElement("button", {
11537
11541
  type: "button",
11538
11542
  className: "th-inner group inline-flex w-full cursor-pointer items-center gap-2 rounded-sm border-0 bg-transparent px-0 py-1 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 " + (r ? "font-semibold text-foreground" : "text-muted-foreground hover:text-foreground"),
11539
- onClick: () => V((t) => Is.toggle(t, e.key)),
11540
- "aria-label": r ? wn(F.sortByCurrent, {
11543
+ onClick: () => H((t) => Is.toggle(t, e.key)),
11544
+ "aria-label": r ? wn(I.sortByCurrent, {
11541
11545
  label: e.label,
11542
- direction: B?.dir === "desc" ? "descending" : "ascending"
11543
- }) : wn(F.sortBy, { label: e.label }),
11544
- title: r ? `${e.label}: ${B?.dir === "desc" ? "descending" : "ascending"}` : wn(F.sortBy, { label: e.label })
11546
+ direction: V?.dir === "desc" ? "descending" : "ascending"
11547
+ }) : wn(I.sortBy, { label: e.label }),
11548
+ title: r ? `${e.label}: ${V?.dir === "desc" ? "descending" : "ascending"}` : wn(I.sortBy, { label: e.label })
11545
11549
  }, /* @__PURE__ */ t.createElement("span", {
11546
11550
  className: "inline-flex h-4 w-4 flex-none items-center justify-center transition-colors " + (r ? "text-primary" : "text-muted-foreground/70 group-hover:text-foreground/80"),
11547
11551
  "aria-hidden": "true"
11548
- }, r ? B?.dir === "desc" ? /* @__PURE__ */ t.createElement(E, { size: 14 }) : /* @__PURE__ */ t.createElement(D, { size: 14 }) : /* @__PURE__ */ t.createElement(O, { size: 14 })), /* @__PURE__ */ t.createElement("span", null, e.label)) : /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" }, e.label));
11552
+ }, r ? V?.dir === "desc" ? /* @__PURE__ */ t.createElement(E, { size: 14 }) : /* @__PURE__ */ t.createElement(D, { size: 14 }) : /* @__PURE__ */ t.createElement(O, { size: 14 })), /* @__PURE__ */ t.createElement("span", null, e.label)) : /* @__PURE__ */ t.createElement("div", { className: "th-inner py-1" }, e.label));
11549
11553
  })() : /* @__PURE__ */ t.createElement("th", {
11550
11554
  key: e.key,
11551
11555
  className: "px-3 py-2 font-semibold text-muted-foreground",
@@ -11553,56 +11557,56 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11553
11557
  width: "1%",
11554
11558
  whiteSpace: "nowrap"
11555
11559
  }
11556
- })))), /* @__PURE__ */ t.createElement("tbody", { className: w || P.Table.bodyClassName }, /* @__PURE__ */ t.createElement(Ep, {
11557
- records: ve,
11558
- appendTo: H,
11560
+ })))), /* @__PURE__ */ t.createElement("tbody", { className: T || F.Table.bodyClassName }, /* @__PURE__ */ t.createElement(Ep, {
11561
+ records: ye,
11562
+ appendTo: U,
11559
11563
  wrapperClassName: "px-3 pt-4 pb-2",
11560
11564
  ...f || {}
11561
11565
  }, (e, n) => {
11562
11566
  let r = v ? Array.isArray(v) ? v : [v] : null, a;
11563
11567
  return e.map((e, o) => {
11564
- let s = n + o, l = J(e, s), u = r ? r.map((t) => String(e[t] ?? "")).join(" · ") : void 0, d = u !== void 0 && u !== a;
11568
+ let s = n + o, l = me(e, s), u = r ? r.map((t) => String(e[t] ?? "")).join(" · ") : void 0, d = u !== void 0 && u !== a;
11565
11569
  a = u;
11566
- let f = me.includes(l), p = W === l, m = te === l, h = I && (g === void 0 ? ae : g) === l;
11570
+ let f = he.includes(l), p = re === l, m = ne === l, h = L && (g === void 0 ? oe : g) === l;
11567
11571
  return /* @__PURE__ */ t.createElement(t.Fragment, { key: l }, d && /* @__PURE__ */ t.createElement("tr", { "aria-hidden": "true" }, /* @__PURE__ */ t.createElement("td", {
11568
- colSpan: Ee,
11572
+ colSpan: De,
11569
11573
  className: "bg-muted/40 px-3 py-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground"
11570
- }, u)), De(l, "before", e, s), /* @__PURE__ */ t.createElement("tr", {
11571
- draggable: ue,
11574
+ }, u)), Oe(l, "before", e, s), /* @__PURE__ */ t.createElement("tr", {
11575
+ draggable: de,
11572
11576
  className: [
11573
11577
  "odd:bg-muted/30 hover:bg-muted/20 transition-colors",
11574
11578
  p ? "bg-muted/30" : "",
11575
- h ? I : ""
11579
+ h ? L : ""
11576
11580
  ].filter(Boolean).join(" ") || void 0,
11577
11581
  style: {
11578
- cursor: i ? "pointer" : ue ? "grab" : "default",
11582
+ cursor: i ? "pointer" : de ? "grab" : "default",
11579
11583
  opacity: m ? .45 : 1
11580
11584
  },
11581
11585
  onClick: (t) => {
11582
- i && ye(t, e, s);
11586
+ i && be(t, e, s);
11583
11587
  },
11584
11588
  onDragStart: () => {
11585
- ne(l);
11589
+ W(l);
11586
11590
  },
11587
11591
  onDragOver: (e) => {
11588
- if (!ue) return;
11592
+ if (!de) return;
11589
11593
  e.preventDefault();
11590
11594
  let t = e.currentTarget.getBoundingClientRect(), n = e.clientY < t.top + t.height / 2 ? "before" : "after";
11591
- W !== l && re(l), te !== l && G((e) => e?.key === l && e.position === n ? e : {
11595
+ re !== l && ie(l), ne !== l && ae((e) => e?.key === l && e.position === n ? e : {
11592
11596
  key: l,
11593
11597
  position: n
11594
11598
  });
11595
11599
  },
11596
11600
  onDragLeave: () => {
11597
- W === l && re(null);
11601
+ re === l && ie(null);
11598
11602
  },
11599
11603
  onDragEnd: () => {
11600
- ne(null), re(null), G(null);
11604
+ W(null), ie(null), ae(null);
11601
11605
  },
11602
11606
  onDrop: (t) => {
11603
- ue && (t.preventDefault(), Ce(e, s));
11607
+ de && (t.preventDefault(), we(e, s));
11604
11608
  }
11605
- }, ge && /* @__PURE__ */ t.createElement("td", {
11609
+ }, _e && /* @__PURE__ */ t.createElement("td", {
11606
11610
  className: "px-3 py-2 border-b border-border/50",
11607
11611
  style: {
11608
11612
  width: "1%",
@@ -11610,20 +11614,20 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11610
11614
  }
11611
11615
  }, /* @__PURE__ */ t.createElement("input", {
11612
11616
  type: c === "single" ? "radio" : "checkbox",
11613
- name: c === "single" ? le : void 0,
11614
- "aria-label": wn(F.selectRow, { key: l }),
11617
+ name: c === "single" ? ue : void 0,
11618
+ "aria-label": wn(I.selectRow, { key: l }),
11615
11619
  checked: f,
11616
11620
  onChange: () => {
11617
11621
  if (c === "single") {
11618
- Se(e, s);
11622
+ Ce(e, s);
11619
11623
  return;
11620
11624
  }
11621
- xe(e, s);
11625
+ Se(e, s);
11622
11626
  },
11623
11627
  onClick: (t) => {
11624
- t.stopPropagation(), c === "single" && (t.preventDefault(), Se(e, s));
11628
+ t.stopPropagation(), c === "single" && (t.preventDefault(), Ce(e, s));
11625
11629
  }
11626
- })), ue && /* @__PURE__ */ t.createElement("td", {
11630
+ })), de && /* @__PURE__ */ t.createElement("td", {
11627
11631
  className: "px-3 py-2 border-b border-border/50",
11628
11632
  style: {
11629
11633
  width: "1%",
@@ -11631,22 +11635,22 @@ function Dd({ columns: e = void 0, records: n = void 0, footer: r = void 0, onRo
11631
11635
  }
11632
11636
  }, /* @__PURE__ */ t.createElement("button", {
11633
11637
  type: "button",
11634
- draggable: ue,
11638
+ draggable: de,
11635
11639
  className: "inline-flex cursor-grab items-center justify-center rounded-sm border-0 bg-transparent p-0 text-muted-foreground",
11636
- "aria-label": wn(F.reorderRow, { key: l }),
11640
+ "aria-label": wn(I.reorderRow, { key: l }),
11637
11641
  onClick: (e) => e.preventDefault(),
11638
11642
  onDragStart: (e) => {
11639
- e.stopPropagation(), ne(l);
11643
+ e.stopPropagation(), W(l);
11640
11644
  },
11641
11645
  onDragEnd: (e) => {
11642
- e.stopPropagation(), ne(null), re(null), G(null);
11646
+ e.stopPropagation(), W(null), ie(null), ae(null);
11643
11647
  }
11644
- }, /* @__PURE__ */ t.createElement(k, { size: 14 }))), we.map((n) => /* @__PURE__ */ t.createElement("td", {
11648
+ }, /* @__PURE__ */ t.createElement(k, { size: 14 }))), Te.map((n) => /* @__PURE__ */ t.createElement("td", {
11645
11649
  key: n.key,
11646
11650
  className: "px-3 py-2 border-b border-border/50"
11647
- }, be(e, n.key, s)))), De(l, "after", e, s));
11651
+ }, xe(e, n.key, s)))), Oe(l, "after", e, s));
11648
11652
  });
11649
- })), r && /* @__PURE__ */ t.createElement("tfoot", { className: T || P.Table.footerClassName }, r)))), b && /* @__PURE__ */ t.createElement("div", { className: "table-after flex shrink-0 items-center self-stretch" }, b));
11653
+ })), r && /* @__PURE__ */ t.createElement("tfoot", { className: A || F.Table.footerClassName }, r)))), x && /* @__PURE__ */ t.createElement("div", { className: "table-after flex shrink-0 items-center self-stretch" }, x));
11650
11654
  }
11651
11655
  //#endregion
11652
11656
  //#region src/components/ui/LayoutBuilder.tsx
@@ -13461,6 +13465,7 @@ function If({ records: e, recordId: n, columns: r, runAction: i, sortable: a, pa
13461
13465
  sort: e.sortable
13462
13466
  })),
13463
13467
  records: e,
13468
+ recordId: (e) => S(e),
13464
13469
  sortable: a,
13465
13470
  pagination: o,
13466
13471
  renderCell: E,
@@ -38,6 +38,7 @@ export { default as Tab } from './ui/Tab';
38
38
  export * from './ui/Tab';
39
39
  export { default as Table } from './ui/Table';
40
40
  export type { TableProps, TableHeaderProp, TableReorderHandler, TableReorderMeta, TableSelectionChangeHandler, TableSelectionState } from './ui/Table';
41
+ export type { RecordKeyResolver } from './ui/useStableRecordKey';
41
42
  export { default as Icon } from './ui/Icon';
42
43
  export { LayoutBuilder } from './ui/LayoutBuilder';
43
44
  export * from './ui/fields/Input';
@@ -4,6 +4,7 @@ import { UIProps } from '../';
4
4
  import { PaginationParams } from './Pagination';
5
5
  import { type OrderConfig } from '../../libs/order';
6
6
  import { RecordSelectionState } from './useRecordSelection';
7
+ import { type RecordKeyResolver } from './useStableRecordKey';
7
8
  export type TableHeaderProp = {
8
9
  key: string;
9
10
  label: string;
@@ -34,6 +35,12 @@ export interface TableProps extends UIProps {
34
35
  activeKey?: string | null;
35
36
  selectedKeys?: string[];
36
37
  groupBy?: string | string[];
38
+ /** Field name (or resolver function) for a stable per-record key — see
39
+ * useStableRecordKey.ts for why this matters specifically for a Table whose `records` are
40
+ * re-supplied with new object identities on every edit (e.g. wrapped in a `Form`, one clone
41
+ * per keystroke): without it, a record with no `_key` falls back to an identity-keyed cache
42
+ * that treats every clone as a brand-new row, remounting it. Absent = unchanged behavior. */
43
+ recordId?: RecordKeyResolver<RecordProps>;
37
44
  headerClassName?: string;
38
45
  bodyClassName?: string;
39
46
  footerClassName?: string;
@@ -43,5 +50,5 @@ export interface TableProps extends UIProps {
43
50
  /** Custom cell renderer. Receives the record, column key, and absolute row index. */
44
51
  renderCell?: (record: RecordProps, key: string, absoluteIndex: number) => React.ReactNode;
45
52
  }
46
- declare function Table({ columns, records, footer, onRowClick, onReorder, onSelectionChange, selection, sortable, pagination, activeKey, selectedKeys, groupBy, before, after, wrapperClassName, className, headerClassName, bodyClassName, footerClassName, heightClassName, scrollClassName, selectedClassName, renderCell }: TableProps): React.JSX.Element;
53
+ declare function Table({ columns, records, footer, onRowClick, onReorder, onSelectionChange, selection, sortable, pagination, activeKey, selectedKeys, groupBy, recordId, before, after, wrapperClassName, className, headerClassName, bodyClassName, footerClassName, heightClassName, scrollClassName, selectedClassName, renderCell }: TableProps): React.JSX.Element;
47
54
  export default Table;
@@ -1,5 +1,18 @@
1
1
  type RecordWithOptionalKey = {
2
2
  _key?: string;
3
3
  };
4
- export declare function useStableRecordKey<TRecord extends RecordWithOptionalKey>(prefix: string): (record: TRecord, _index?: number) => string;
4
+ /** A field name (read via bracket access) or a function computing the key directly. */
5
+ export type RecordKeyResolver<TRecord> = string | ((record: TRecord) => string);
6
+ export declare function useStableRecordKey<TRecord extends RecordWithOptionalKey>(prefix: string,
7
+ /** Explicit resolver, checked BEFORE the RECORD_KEY/WeakMap fallback below — trusted even
8
+ * across the new object identities a caller's own state management may produce on every
9
+ * edit (e.g. Form.tsx's `cloneContainer`, which clones the touched record on each keystroke
10
+ * but preserves this field's VALUE unchanged). Without an explicit resolver, a record with no
11
+ * `RECORD_KEY` gets a key from a WeakMap keyed by object identity — a fresh clone is a cache
12
+ * miss and gets a brand-new key, which remounts that row (and any interactive element inside
13
+ * it, e.g. a Form-bound `<Input>`, losing focus) on every single keystroke. Passing a
14
+ * resolver for a stable id field already present on the record (e.g. `"id"`) sidesteps this
15
+ * entirely, since the resolved value never changes across a clone. Absent = unchanged
16
+ * behavior (RECORD_KEY/WeakMap fallback only). */
17
+ recordId?: RecordKeyResolver<TRecord>): (record: TRecord, _index?: number) => string;
5
18
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmnative/react",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "LLM-native React framework for deterministic UI generation. Data-driven by default, schema-driven optional. Ultra-low token consumption — built for AI agents, not just humans.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",