@ai-matrx/records-ui 0.93.3 → 0.93.6

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.js CHANGED
@@ -7712,6 +7712,10 @@ function useMergedGridControls(args) {
7712
7712
  (columnKey) => enabled && fieldOf2(columnKey) ? headerMenuItems(columnKey, ctx) : void 0,
7713
7713
  [enabled, ctx, fieldOf2]
7714
7714
  );
7715
+ const columnsControl = useMemo14(
7716
+ () => enabled ? { order, hidden, onChange: keepColumns } : void 0,
7717
+ [enabled, order, hidden, keepColumns]
7718
+ );
7715
7719
  const close = () => setDialog(null);
7716
7720
  const dialogs = !enabled ? null : /* @__PURE__ */ jsxs24(Fragment8, { children: [
7717
7721
  colours.dialogs,
@@ -7843,7 +7847,7 @@ function useMergedGridControls(args) {
7843
7847
  headerMenuFor,
7844
7848
  filterFor,
7845
7849
  contextMenu,
7846
- columns: enabled ? { order, hidden, onChange: keepColumns } : void 0,
7850
+ columns: columnsControl,
7847
7851
  dialogs,
7848
7852
  addColumn: () => setDialog({ kind: "insert", anchor: null, side: "right" }),
7849
7853
  sheetTools: enabled ? /* @__PURE__ */ jsxs24(Fragment8, { children: [
@@ -9293,7 +9297,7 @@ function GridLayoutMenu({
9293
9297
  }
9294
9298
 
9295
9299
  // src/gridUndo.tsx
9296
- import { useCallback as useCallback13, useEffect as useEffect21, useMemo as useMemo18, useRef as useRef11, useState as useState26 } from "react";
9300
+ import { useCallback as useCallback13, useEffect as useEffect21, useLayoutEffect, useMemo as useMemo18, useRef as useRef11, useState as useState26, useSyncExternalStore } from "react";
9297
9301
  import { useRecordsClient as useRecordsClient16 } from "@ai-matrx/records/react";
9298
9302
  import { announceRecordChanged } from "@ai-matrx/records/core";
9299
9303
  import { Button as Button23 } from "@ai-matrx/design-system";
@@ -9399,7 +9403,43 @@ function useGridUndo(args) {
9399
9403
  [push, undo, redo, held, busy, notice, dismiss]
9400
9404
  );
9401
9405
  }
9402
- function UndoRedoButtons({ undo }) {
9406
+ function useUndoSource(undo) {
9407
+ const box = useRef11({
9408
+ undo,
9409
+ face: { back: undo.depth.back, forward: undo.depth.forward, busy: undo.busy },
9410
+ listeners: /* @__PURE__ */ new Set()
9411
+ });
9412
+ box.current.undo = undo;
9413
+ const source = useMemo18(
9414
+ () => ({
9415
+ face: () => box.current.face,
9416
+ subscribe: (listener) => {
9417
+ box.current.listeners.add(listener);
9418
+ return () => {
9419
+ box.current.listeners.delete(listener);
9420
+ };
9421
+ },
9422
+ undo: () => void box.current.undo.undo(),
9423
+ redo: () => void box.current.undo.redo()
9424
+ }),
9425
+ []
9426
+ );
9427
+ const { back, forward } = undo.depth;
9428
+ const busy = undo.busy;
9429
+ useLayoutEffect(() => {
9430
+ const held = box.current.face;
9431
+ if (held.back === back && held.forward === forward && held.busy === busy) return;
9432
+ box.current.face = { back, forward, busy };
9433
+ for (const listener of box.current.listeners) listener();
9434
+ }, [back, forward, busy]);
9435
+ return source;
9436
+ }
9437
+ function UndoRedoLive({ source }) {
9438
+ const face = useSyncExternalStore(source.subscribe, source.face, source.face);
9439
+ return /* @__PURE__ */ jsx37(UndoRedoPair, { face, onUndo: source.undo, onRedo: source.redo });
9440
+ }
9441
+ function UndoRedoPair({ face, onUndo, onRedo }) {
9442
+ const undo = { depth: { back: face.back, forward: face.forward }, busy: face.busy };
9403
9443
  if (undo.depth.back === 0 && undo.depth.forward === 0) return null;
9404
9444
  return /* @__PURE__ */ jsxs32(Fragment13, { children: [
9405
9445
  /* @__PURE__ */ jsxs32(
@@ -9411,7 +9451,7 @@ function UndoRedoButtons({ undo }) {
9411
9451
  title: undo.depth.back > 0 ? `Undo (Cmd-Z) \xB7 ${undo.depth.back} ${undo.depth.back === 1 ? "step" : "steps"} back` : "Nothing to undo",
9412
9452
  "aria-label": `Undo, ${undo.depth.back} ${undo.depth.back === 1 ? "step" : "steps"}`,
9413
9453
  disabled: undo.busy || undo.depth.back === 0,
9414
- onClick: () => void undo.undo(),
9454
+ onClick: onUndo,
9415
9455
  children: [
9416
9456
  "Undo ",
9417
9457
  /* @__PURE__ */ jsx37("span", { className: "ml-1 tabular-nums text-muted-foreground", "data-records-undo-count": "", children: undo.depth.back })
@@ -9427,7 +9467,7 @@ function UndoRedoButtons({ undo }) {
9427
9467
  title: undo.depth.forward > 0 ? `Redo (Shift-Cmd-Z) \xB7 ${undo.depth.forward} ${undo.depth.forward === 1 ? "step" : "steps"} forward` : "Nothing to redo",
9428
9468
  "aria-label": `Redo, ${undo.depth.forward} ${undo.depth.forward === 1 ? "step" : "steps"}`,
9429
9469
  disabled: undo.busy || undo.depth.forward === 0,
9430
- onClick: () => void undo.redo(),
9470
+ onClick: onRedo,
9431
9471
  children: [
9432
9472
  "Redo ",
9433
9473
  /* @__PURE__ */ jsx37("span", { className: "ml-1 tabular-nums text-muted-foreground", "data-records-redo-count": "", children: undo.depth.forward })
@@ -10792,6 +10832,7 @@ function Grid({
10792
10832
  );
10793
10833
  const rowVersion = useCallback16((row) => editingNow.current.rowSignature(row.id), []);
10794
10834
  const undo = useGridUndo({ tableId, reload: records.reload, forget: editing.forget });
10835
+ const undoSource = useUndoSource(undo);
10795
10836
  pushWritten.current = (write) => {
10796
10837
  const field2 = (fields.data ?? []).find((f) => f.key === write.key);
10797
10838
  const name = changedRecordName(table.data, rows.find((r) => r.id === write.rowId)?.document ?? {}, write.key, write.after);
@@ -11343,9 +11384,14 @@ function Grid({
11343
11384
  );
11344
11385
  const footerNow = useRef14({
11345
11386
  summaryCell: () => null,
11346
- addLine: () => null
11387
+ addLine: () => null,
11388
+ choose: () => void 0,
11389
+ add: () => void 0
11347
11390
  });
11348
11391
  footerNow.current = {
11392
+ // The footer is memoised on what it shows (`footerRows` below), so its buttons act through here.
11393
+ choose: chooseSummary,
11394
+ add: () => void addRowHere(),
11349
11395
  summaryCell: (columnId) => {
11350
11396
  const field2 = ordered.find((f) => f.key === columnId);
11351
11397
  if (!field2) return null;
@@ -11358,11 +11404,11 @@ function Grid({
11358
11404
  value: summaries.values[columnId],
11359
11405
  rowCount: summaries.rowCount,
11360
11406
  summaries,
11361
- onChoose: (op2) => chooseSummary(columnId, op2)
11407
+ onChoose: (op2) => footerNow.current.choose(columnId, op2)
11362
11408
  }
11363
11409
  );
11364
11410
  },
11365
- addLine: () => /* @__PURE__ */ jsx42(AddRowLine, { onAdd: () => void addRowHere(), busy: added.busy })
11411
+ addLine: () => /* @__PURE__ */ jsx42(AddRowLine, { onAdd: () => footerNow.current.add(), busy: added.busy })
11366
11412
  };
11367
11413
  const addColumnNow = useRef14(controls.addColumn);
11368
11414
  addColumnNow.current = controls.addColumn;
@@ -11477,13 +11523,24 @@ function Grid({
11477
11523
  // eslint-disable-next-line react-hooks/exhaustive-deps -- `hasTalk`/`hasAgent` stand for the host ports the JSX reads; handlers run through `rowActionsNow`.
11478
11524
  [canWrite, mayWriteRow, tableActions.runnable, tableActions.agent, runner.busy, hasTalk, hasAgent, editable, rights.write]
11479
11525
  );
11480
- const columns = useMemo22(
11526
+ const headerHeld = useRef14(/* @__PURE__ */ new Map());
11527
+ const menuLatest = useRef14(/* @__PURE__ */ new Map());
11528
+ const addColumnDef = useMemo22(() => addColumnColumn(() => addColumnNow.current()), []);
11529
+ const drawnColumns = useMemo22(
11481
11530
  () => {
11482
- const drawn = withHeaderMenus(bodyColumns, controls.headerMenuFor, controls.filterFor);
11483
- return merged && rights.structure && editable ? [...drawn, addColumnColumn(() => addColumnNow.current())] : drawn;
11531
+ const filterFor = controls.filterFor;
11532
+ const drawn = withHeaderMenus(
11533
+ bodyColumns,
11534
+ (key) => holdHeaderMenu(headerHeld.current, menuLatest.current, key, controls.headerMenuFor(key)),
11535
+ (key) => holdByContent(headerHeld.current, `filter:${key}`, filterFor(key))
11536
+ );
11537
+ return merged && rights.structure && editable ? [...drawn, addColumnDef] : drawn;
11484
11538
  },
11485
- [bodyColumns, controls.headerMenuFor, controls.filterFor, merged, rights.structure, editable]
11539
+ [bodyColumns, controls.headerMenuFor, controls.filterFor, merged, rights.structure, editable, addColumnDef]
11486
11540
  );
11541
+ const columnsHeld = useRef14(null);
11542
+ const columns = columnsHeld.current !== null && sameColumns(columnsHeld.current, drawnColumns) ? columnsHeld.current : drawnColumns;
11543
+ columnsHeld.current = columns;
11487
11544
  const [localColumns, setLocalColumns] = useState31(
11488
11545
  null
11489
11546
  );
@@ -11556,6 +11613,274 @@ function Grid({
11556
11613
  } : {}
11557
11614
  };
11558
11615
  }, [presentation, onPresentationChange, writeLook, merged, phone]);
11616
+ const queryTotal = records.data?.total ?? rows.length;
11617
+ const tableQuery = useMemo22(
11618
+ () => merged ? {
11619
+ // THE STORE ANSWERS THE QUERY (tranche 6k): `data` is already the page.
11620
+ mode: "controlled",
11621
+ state: query,
11622
+ totalItems: queryTotal,
11623
+ onStateChange: setQuery,
11624
+ sourceProcessing: { search: "source", columnFilters: "source", sort: "source" }
11625
+ } : { mode: "controlled-local", state: query, onStateChange: setQuery },
11626
+ [merged, query, queryTotal]
11627
+ );
11628
+ const showAddLine = mayAddRow && rows.length > 0;
11629
+ const showSummaryLine = rows.length > 0 && (!merged || Object.keys(chosenSummaries).length > 0);
11630
+ const footerFace = JSON.stringify([
11631
+ showAddLine ? added.busy : null,
11632
+ showSummaryLine ? [chosenSummaries, summaries.values, summaries.rowCount, summaries.loading] : null
11633
+ ]);
11634
+ const footerRows = useMemo22(
11635
+ () => [...showAddLine ? [ADD_ROW] : [], ...showSummaryLine ? [SUMMARY_ROW] : []],
11636
+ // `footerFace`, `ordered` and the summaries' operations are what the footer's cells draw.
11637
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11638
+ [showAddLine, showSummaryLine, footerFace, ordered, summaries.operations, summaries.askOperations]
11639
+ );
11640
+ const coverageTotal = typeof records.data?.total === "number" ? records.data.total : null;
11641
+ const tableCoverage = useMemo22(
11642
+ () => ({
11643
+ answeredBy: merged ? "source" : "client",
11644
+ ...merged && coverageTotal !== null ? { matched: coverageTotal } : {},
11645
+ noun: "record",
11646
+ ...coverageTotal !== null ? { total: coverageTotal } : {}
11647
+ }),
11648
+ [merged, coverageTotal]
11649
+ );
11650
+ const sheetNow = useRef14({ merged, writeRange, editing, fields: fields.data ?? [], mayWriteRow, notify: host.notify });
11651
+ sheetNow.current = { merged, writeRange, editing, fields: fields.data ?? [], mayWriteRow, notify: host.notify };
11652
+ const hasNotify = Boolean(host.notify);
11653
+ const readOnlyReason = !editable || !rights.known || rights.write ? "Editing is off here, so this table can be copied but not changed." : rights.why("write");
11654
+ const spreadsheetConfig = useMemo22(
11655
+ () => canWrite && editable ? {
11656
+ enabled: true,
11657
+ writableColumnIds: pasteableKeys,
11658
+ onPatch: (patches, intent) => {
11659
+ const now = sheetNow.current;
11660
+ if (now.merged) {
11661
+ void now.writeRange(patches, intent);
11662
+ return;
11663
+ }
11664
+ for (const patch of patches) {
11665
+ now.editing.setCell(patch.rowId, patch.columnId, patch.value);
11666
+ }
11667
+ },
11668
+ ...merged ? { undoDepth: 0, onSelectionChange: followSelection, controllerRef: sheetController } : {},
11669
+ columnRefusal: (columnId) => {
11670
+ const field2 = sheetNow.current.fields.find((f) => f.key === columnId);
11671
+ if (!field2) return `This table has no column called ${columnId}.`;
11672
+ return `${fieldName(field2)} cannot take a pasted value \u2014 ${fieldTypeLabel(field2)} is worked out or chosen, not typed.`;
11673
+ },
11674
+ validateCell: ({ columnId, value }) => {
11675
+ const field2 = sheetNow.current.fields.find((f) => f.key === columnId);
11676
+ if (!field2) return `This table has no column called ${columnId}.`;
11677
+ const judged = valueFromPastedText(field2, value === null ? "" : String(value));
11678
+ return "refusal" in judged ? judged.refusal : void 0;
11679
+ },
11680
+ onPastePlan: receivePastePlan,
11681
+ /*
11682
+ * TYPE-TO-EDIT (design-system 0.43 `onEditRequest`): the cell a person is on
11683
+ * opens ITS OWN editor — the Field's — holding what they typed (a letter, an
11684
+ * IME composition, an Option/AltGr character, dictation). A worked-out column
11685
+ * or a row this person may not write answers false, so nothing is swallowed.
11686
+ */
11687
+ onEditRequest: (address, seed) => {
11688
+ const now = sheetNow.current;
11689
+ const field2 = now.fields.find((f) => f.key === address.columnId);
11690
+ if (!field2 || !fieldIsEditable(field2) || !now.mayWriteRow(address.rowId)) return false;
11691
+ if (seed !== null && seed !== "" && typingOpens(field2) === "none") return false;
11692
+ now.editing.begin({ rowId: address.rowId, key: field2.key }, seed);
11693
+ return true;
11694
+ },
11695
+ ...hasNotify ? { notify: (message) => sheetNow.current.notify?.success(message) } : {}
11696
+ } : {
11697
+ /*
11698
+ * RANGE SELECTION AND COPY FOR A READER (merge step 3, 0.42 `readOnly`). A person
11699
+ * who may not change this table may still drag out a range, select all and press
11700
+ * Cmd-C for a real Excel/Sheets block — the UX walk graded range selection BROKEN
11701
+ * on a table whose writes were refused. Every write gesture (cut, paste, clear,
11702
+ * fill, undo) says why it cannot, in the store's own words.
11703
+ */
11704
+ enabled: true,
11705
+ readOnly: true,
11706
+ ...merged ? { onSelectionChange: followSelection, controllerRef: sheetController } : {},
11707
+ readOnlyReason
11708
+ },
11709
+ [canWrite, editable, pasteableKeys, merged, followSelection, receivePastePlan, hasNotify, readOnlyReason]
11710
+ );
11711
+ const toolbarFields = fields.data;
11712
+ const hasSeveralRows = rows.length > 1;
11713
+ const editingBusy = editing.busy;
11714
+ const addRecord = editing.addRecord;
11715
+ const phoneSheetTools = merged && phone ? controls.sheetTools : null;
11716
+ const tableToolbar = useMemo22(
11717
+ () => ({
11718
+ search: true,
11719
+ searchPlaceholder: "Search records",
11720
+ /*
11721
+ * A PHONE (tranche 6o): search and the one Tools button sit side by side at the START of
11722
+ * the row, so Tools is never scrolled out of reach; the search is the same query.
11723
+ */
11724
+ ...merged && phone ? {
11725
+ customSearch: /* @__PURE__ */ jsx42("div", { className: "flex min-w-0 flex-1 items-center gap-1.5", "data-records-grid-phone-search": "", children: /* @__PURE__ */ jsx42(
11726
+ "input",
11727
+ {
11728
+ type: "search",
11729
+ value: query.search,
11730
+ placeholder: "Search",
11731
+ "aria-label": "Search records",
11732
+ onChange: (event) => {
11733
+ const search = event.target.value;
11734
+ setQuery((held) => ({ ...held, search, page: 1 }));
11735
+ },
11736
+ className: "h-8 w-full min-w-0 rounded-md border border-input bg-background px-2 text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
11737
+ style: { fontSize: "16px" }
11738
+ }
11739
+ ) })
11740
+ } : {},
11741
+ /* ONE ROW (lane TABLE-PAGE-CHROME): on a table page the grid's search, columns and
11742
+ sort are drawn INTO the page's toolbar row, never a second bar under it. */
11743
+ ...toolbarSlot !== void 0 ? { portalInto: toolbarSlot, singleRow: true } : {},
11744
+ // SCR-2 / SCR-4: PRESENT for an admin, ABSENT for everyone else.
11745
+ // There is no third state: this package ships no disabled variant of
11746
+ // these controls, so a member cannot be shown a dead one by mistake.
11747
+ /*
11748
+ * WHERE THE GRID'S CONTROLS GO (lane C, review 2026-09-26 D6). Inline when the row has
11749
+ * room; behind the row's "…" once the page row is folded that far (Undo / Redo and New
11750
+ * record stay beside it — the primary action is never folded); on a phone EVERY control
11751
+ * — the table's own (clear, copy/export, group, columns), these, the search, the sort and
11752
+ * the page's filter, layout and share — in ONE "Tools" sheet. Never dropped.
11753
+ */
11754
+ actions: /* @__PURE__ */ jsxs36(Fragment15, { children: [
11755
+ manual ? /* @__PURE__ */ jsx42(
11756
+ SortStateControl,
11757
+ {
11758
+ ...handOrderSortState({
11759
+ sortName: columnSort ? columnLabel(toolbarFields ?? [], columnSort.id) : null,
11760
+ direction: columnSort?.direction ?? null,
11761
+ onBack: () => setQuery((held) => ({ ...held, sort: null, page: 1 })),
11762
+ ...viewOrder?.onUseSort && columnSort ? {
11763
+ onUseSort: () => {
11764
+ const sort = columnSort;
11765
+ const chosen = { field: sort.id, direction: sort.direction };
11766
+ setHeldOrder({ order: "sorted", sorts: [chosen] });
11767
+ viewOrder.onUseSort?.(chosen);
11768
+ host.notify?.success(
11769
+ `Sorted by ${columnLabel(toolbarFields ?? [], sort.id)} ${sortArrow(sort.direction)}. ${MANUAL_SORT.replacedToast}`
11770
+ );
11771
+ }
11772
+ } : {}
11773
+ })
11774
+ }
11775
+ ) : null,
11776
+ viewId && viewOrder?.onPlaced && hasSeveralRows ? /* @__PURE__ */ jsx42(Button27, { size: "sm", variant: "ghost", onClick: () => setReordering(true), "data-records-reorder-open": "", children: "Reorder" }) : null,
11777
+ !merged && Boolean(editable) && rights.write ? /* @__PURE__ */ jsx42(Button27, { size: "sm", disabled: editingBusy, onClick: () => void addRecord(), children: editingBusy ? "Adding\u2026" : "New record" }) : null,
11778
+ rights.structure && onAddField ? /* @__PURE__ */ jsx42(AddFieldButton, { onClick: onAddField }) : null,
11779
+ /* @__PURE__ */ jsx42(
11780
+ GridLayoutMenu,
11781
+ {
11782
+ look,
11783
+ firstColumn: sortedKeys[0] ? {
11784
+ key: sortedKeys[0],
11785
+ name: (() => {
11786
+ const first = (toolbarFields ?? []).find((f) => f.key === sortedKeys[0]);
11787
+ return first ? fieldName(first) : humanize(sortedKeys[0]);
11788
+ })()
11789
+ } : null,
11790
+ onChange: changeLayout,
11791
+ kept: Boolean(onPresentationChange)
11792
+ }
11793
+ )
11794
+ ] }),
11795
+ ...merged ? {
11796
+ overflow: {
11797
+ mode: phone ? "sheet" : toolbarFold2 >= 3 ? "menu" : "inline",
11798
+ pinned: /* @__PURE__ */ jsxs36(Fragment15, { children: [
11799
+ /* @__PURE__ */ jsx42(UndoRedoLive, { source: undoSource }),
11800
+ Boolean(editable) && rights.write ? /* @__PURE__ */ jsx42(Button27, { size: "sm", className: "shrink-0", disabled: added.busy, onClick: () => addRowRef.current(), children: added.busy ? "Adding\u2026" : "New record" }) : null
11801
+ ] }),
11802
+ ...phone ? {
11803
+ sheetTop: /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-1.5 pb-1", "data-records-grid-sheet-top": "", "data-matrx-table-tools-keep-open": "", children: [
11804
+ /* @__PURE__ */ jsx42(
11805
+ "input",
11806
+ {
11807
+ type: "search",
11808
+ value: query.search,
11809
+ placeholder: "Search",
11810
+ "aria-label": "Search records",
11811
+ onChange: (event) => {
11812
+ const search = event.target.value;
11813
+ setQuery((held) => ({ ...held, search, page: 1 }));
11814
+ },
11815
+ className: "h-10 w-full min-w-0 rounded-md border border-input bg-background px-2 text-foreground placeholder:text-muted-foreground",
11816
+ style: { fontSize: "16px" }
11817
+ }
11818
+ ),
11819
+ /* @__PURE__ */ jsxs36("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", "data-records-grid-sheet-sort": "", children: [
11820
+ /* @__PURE__ */ jsx42("span", { className: "shrink-0", children: "Sort by" }),
11821
+ /* @__PURE__ */ jsxs36(
11822
+ "select",
11823
+ {
11824
+ "aria-label": "Sort by",
11825
+ value: query.sort ? `${query.sort.id}:${query.sort.direction}` : "",
11826
+ onChange: (event) => {
11827
+ const [id, direction] = event.target.value.split(":");
11828
+ setQuery((held) => ({
11829
+ ...held,
11830
+ page: 1,
11831
+ sort: id ? { id, direction: direction === "desc" ? "desc" : "asc" } : null
11832
+ }));
11833
+ },
11834
+ className: "h-10 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-foreground",
11835
+ style: { fontSize: "16px" },
11836
+ children: [
11837
+ /* @__PURE__ */ jsx42("option", { value: "", children: "No sort" }),
11838
+ ordered.flatMap((field2) => [
11839
+ /* @__PURE__ */ jsx42("option", { value: `${field2.key}:asc`, children: `${fieldName(field2)} \u2191` }, `${field2.key}:asc`),
11840
+ /* @__PURE__ */ jsx42("option", { value: `${field2.key}:desc`, children: `${fieldName(field2)} \u2193` }, `${field2.key}:desc`)
11841
+ ])
11842
+ ]
11843
+ }
11844
+ )
11845
+ ] }),
11846
+ phoneSheetTools
11847
+ ] }),
11848
+ ...sheetExtras ? { sheetExtras } : {}
11849
+ } : {}
11850
+ }
11851
+ } : {}
11852
+ }),
11853
+ [
11854
+ merged,
11855
+ phone,
11856
+ query.search,
11857
+ query.sort,
11858
+ toolbarSlot,
11859
+ manual,
11860
+ columnSort,
11861
+ toolbarFields,
11862
+ viewOrder,
11863
+ host,
11864
+ viewId,
11865
+ hasSeveralRows,
11866
+ editable,
11867
+ rights.write,
11868
+ rights.structure,
11869
+ editingBusy,
11870
+ addRecord,
11871
+ onAddField,
11872
+ look,
11873
+ sortedKeys,
11874
+ changeLayout,
11875
+ onPresentationChange,
11876
+ toolbarFold2,
11877
+ undoSource,
11878
+ added.busy,
11879
+ ordered,
11880
+ phoneSheetTools,
11881
+ sheetExtras
11882
+ ]
11883
+ );
11559
11884
  const labelOfField = useCallback16(
11560
11885
  (key) => {
11561
11886
  const held = (fields.data ?? []).find((f) => f.key === key);
@@ -11724,25 +12049,12 @@ function Grid({
11724
12049
  viewTabs: false,
11725
12050
  stickyHeader: true,
11726
12051
  pageSize,
11727
- query: merged ? {
11728
- // THE STORE ANSWERS THE QUERY (tranche 6k): `data` is already the page.
11729
- mode: "controlled",
11730
- state: query,
11731
- totalItems: records.data?.total ?? rows.length,
11732
- onStateChange: setQuery,
11733
- sourceProcessing: { search: "source", columnFilters: "source", sort: "source" }
11734
- } : { mode: "controlled-local", state: query, onStateChange: setQuery },
12052
+ query: tableQuery,
11735
12053
  tableClassName: cn20(
11736
12054
  !look.wrap && "[&_tbody_td]:max-w-[28rem] [&_tbody_td]:overflow-hidden [&_tbody_td]:text-ellipsis [&_tbody_td]:whitespace-nowrap! [&_tbody_td_*]:whitespace-nowrap!",
11737
12055
  look.fit === "scroll" && "sm:[&>table]:w-max! sm:[&>table]:max-w-none! sm:[&>table]:min-w-full!"
11738
12056
  ),
11739
- ...(() => {
11740
- const footerRows = [
11741
- ...mayAddRow && rows.length > 0 ? [ADD_ROW] : [],
11742
- ...rows.length > 0 && (!merged || Object.keys(chosenSummaries).length > 0) ? [SUMMARY_ROW] : []
11743
- ];
11744
- return footerRows.length > 0 ? { footerRows } : {};
11745
- })(),
12057
+ footerRows,
11746
12058
  ...copyConfig ? { copy: copyConfig } : {},
11747
12059
  ...offerSelection ? {
11748
12060
  selection: {
@@ -11776,75 +12088,15 @@ function Grid({
11776
12088
  ] })
11777
12089
  }
11778
12090
  } : {},
11779
- detail: { enabled: false },
11780
- window: { enabled: false },
12091
+ detail: DETAIL_OFF,
12092
+ window: WINDOW_OFF,
11781
12093
  ...controls.contextMenu ? { contextMenu: controls.contextMenu } : {},
11782
- ...canWrite && editable ? {
11783
- spreadsheet: {
11784
- enabled: true,
11785
- writableColumnIds: pasteableKeys,
11786
- onPatch: (patches, intent) => {
11787
- if (merged) {
11788
- void writeRange(patches, intent);
11789
- return;
11790
- }
11791
- for (const patch of patches) {
11792
- editing.setCell(patch.rowId, patch.columnId, patch.value);
11793
- }
11794
- },
11795
- ...merged ? { undoDepth: 0, onSelectionChange: followSelection, controllerRef: sheetController } : {},
11796
- columnRefusal: (columnId) => {
11797
- const field2 = (fields.data ?? []).find((f) => f.key === columnId);
11798
- if (!field2) return `This table has no column called ${columnId}.`;
11799
- return `${fieldName(field2)} cannot take a pasted value \u2014 ${fieldTypeLabel(field2)} is worked out or chosen, not typed.`;
11800
- },
11801
- validateCell: ({ columnId, value }) => {
11802
- const field2 = (fields.data ?? []).find((f) => f.key === columnId);
11803
- if (!field2) return `This table has no column called ${columnId}.`;
11804
- const judged = valueFromPastedText(field2, value === null ? "" : String(value));
11805
- return "refusal" in judged ? judged.refusal : void 0;
11806
- },
11807
- onPastePlan: receivePastePlan,
11808
- /*
11809
- * TYPE-TO-EDIT (design-system 0.43 `onEditRequest`): the cell a person is on
11810
- * opens ITS OWN editor — the Field's — holding what they typed (a letter, an
11811
- * IME composition, an Option/AltGr character, dictation). A worked-out column
11812
- * or a row this person may not write answers false, so nothing is swallowed.
11813
- */
11814
- onEditRequest: (address, seed) => {
11815
- const field2 = (fields.data ?? []).find((f) => f.key === address.columnId);
11816
- if (!field2 || !fieldIsEditable(field2) || !mayWriteRow(address.rowId)) return false;
11817
- if (seed !== null && seed !== "" && typingOpens(field2) === "none") return false;
11818
- editing.begin({ rowId: address.rowId, key: field2.key }, seed);
11819
- return true;
11820
- },
11821
- ...host.notify ? { notify: (message) => host.notify?.success(message) } : {}
11822
- }
11823
- } : {
11824
- /*
11825
- * RANGE SELECTION AND COPY FOR A READER (merge step 3, 0.42 `readOnly`). A person
11826
- * who may not change this table may still drag out a range, select all and press
11827
- * Cmd-C for a real Excel/Sheets block — the UX walk graded range selection BROKEN
11828
- * on a table whose writes were refused. Every write gesture (cut, paste, clear,
11829
- * fill, undo) says why it cannot, in the store's own words.
11830
- */
11831
- spreadsheet: {
11832
- enabled: true,
11833
- readOnly: true,
11834
- ...merged ? { onSelectionChange: followSelection, controllerRef: sheetController } : {},
11835
- readOnlyReason: !editable || !rights.known || rights.write ? "Editing is off here, so this table can be copied but not changed." : rights.why("write")
11836
- }
11837
- },
12094
+ spreadsheet: spreadsheetConfig,
11838
12095
  ...groupingConfig ? { grouping: groupingConfig } : {},
11839
12096
  columnState,
11840
12097
  ...look.rowHeight ? { rowHeight: look.rowHeight } : {},
11841
- virtualize: fills ? { threshold: 40 } : true,
11842
- coverage: {
11843
- answeredBy: merged ? "source" : "client",
11844
- ...merged && typeof records.data?.total === "number" ? { matched: records.data.total } : {},
11845
- noun: "record",
11846
- ...typeof records.data?.total === "number" ? { total: records.data.total } : {}
11847
- },
12098
+ virtualize: fills ? VIRTUALIZE_FILLED : true,
12099
+ coverage: tableCoverage,
11848
12100
  ...tableStyleProp ? { tableStyle: tableStyleProp } : {},
11849
12101
  ...onOpenRecord ? { onRowOpen: (row) => onOpenRecord(row.id) } : {},
11850
12102
  ...offersRowActions ? { rowActions } : {},
@@ -11856,142 +12108,7 @@ function Grid({
11856
12108
  ...mayAddRow ? { addFirst: /* @__PURE__ */ jsx42(AddFirstRowButton, { onAdd: () => void addRowHere(), busy: added.busy }) } : {},
11857
12109
  emptyDescription: rights.write ? "Add the first one and it appears here." : rights.known ? `Nothing has been written to this table. ${rights.why("write")}` : "Nothing has been written to this table."
11858
12110
  }),
11859
- toolbar: {
11860
- search: true,
11861
- searchPlaceholder: "Search records",
11862
- /*
11863
- * A PHONE (tranche 6o): search and the one Tools button sit side by side at the START of
11864
- * the row, so Tools is never scrolled out of reach; the search is the same query.
11865
- */
11866
- ...merged && phone ? {
11867
- customSearch: /* @__PURE__ */ jsx42("div", { className: "flex min-w-0 flex-1 items-center gap-1.5", "data-records-grid-phone-search": "", children: /* @__PURE__ */ jsx42(
11868
- "input",
11869
- {
11870
- type: "search",
11871
- value: query.search,
11872
- placeholder: "Search",
11873
- "aria-label": "Search records",
11874
- onChange: (event) => {
11875
- const search = event.target.value;
11876
- setQuery((held) => ({ ...held, search, page: 1 }));
11877
- },
11878
- className: "h-8 w-full min-w-0 rounded-md border border-input bg-background px-2 text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
11879
- style: { fontSize: "16px" }
11880
- }
11881
- ) })
11882
- } : {},
11883
- /* ONE ROW (lane TABLE-PAGE-CHROME): on a table page the grid's search, columns and
11884
- sort are drawn INTO the page's toolbar row, never a second bar under it. */
11885
- ...toolbarSlot !== void 0 ? { portalInto: toolbarSlot, singleRow: true } : {},
11886
- // SCR-2 / SCR-4: PRESENT for an admin, ABSENT for everyone else.
11887
- // There is no third state: this package ships no disabled variant of
11888
- // these controls, so a member cannot be shown a dead one by mistake.
11889
- /*
11890
- * WHERE THE GRID'S CONTROLS GO (lane C, review 2026-09-26 D6). Inline when the row has
11891
- * room; behind the row's "…" once the page row is folded that far (Undo / Redo and New
11892
- * record stay beside it — the primary action is never folded); on a phone EVERY control
11893
- * — the table's own (clear, copy/export, group, columns), these, the search, the sort and
11894
- * the page's filter, layout and share — in ONE "Tools" sheet. Never dropped.
11895
- */
11896
- actions: /* @__PURE__ */ jsxs36(Fragment15, { children: [
11897
- manual ? /* @__PURE__ */ jsx42(
11898
- SortStateControl,
11899
- {
11900
- ...handOrderSortState({
11901
- sortName: columnSort ? columnLabel(fields.data ?? [], columnSort.id) : null,
11902
- direction: columnSort?.direction ?? null,
11903
- onBack: () => setQuery((held) => ({ ...held, sort: null, page: 1 })),
11904
- ...viewOrder?.onUseSort && columnSort ? {
11905
- onUseSort: () => {
11906
- const sort = columnSort;
11907
- const chosen = { field: sort.id, direction: sort.direction };
11908
- setHeldOrder({ order: "sorted", sorts: [chosen] });
11909
- viewOrder.onUseSort?.(chosen);
11910
- host.notify?.success(
11911
- `Sorted by ${columnLabel(fields.data ?? [], sort.id)} ${sortArrow(sort.direction)}. ${MANUAL_SORT.replacedToast}`
11912
- );
11913
- }
11914
- } : {}
11915
- })
11916
- }
11917
- ) : null,
11918
- viewId && viewOrder?.onPlaced && rows.length > 1 ? /* @__PURE__ */ jsx42(Button27, { size: "sm", variant: "ghost", onClick: () => setReordering(true), "data-records-reorder-open": "", children: "Reorder" }) : null,
11919
- !merged && Boolean(editable) && rights.write ? /* @__PURE__ */ jsx42(Button27, { size: "sm", disabled: editing.busy, onClick: () => void editing.addRecord(), children: editing.busy ? "Adding\u2026" : "New record" }) : null,
11920
- rights.structure && onAddField ? /* @__PURE__ */ jsx42(AddFieldButton, { onClick: onAddField }) : null,
11921
- /* @__PURE__ */ jsx42(
11922
- GridLayoutMenu,
11923
- {
11924
- look,
11925
- firstColumn: sortedKeys[0] ? {
11926
- key: sortedKeys[0],
11927
- name: (() => {
11928
- const first = (fields.data ?? []).find((f) => f.key === sortedKeys[0]);
11929
- return first ? fieldName(first) : humanize(sortedKeys[0]);
11930
- })()
11931
- } : null,
11932
- onChange: changeLayout,
11933
- kept: Boolean(onPresentationChange)
11934
- }
11935
- )
11936
- ] }),
11937
- ...merged ? {
11938
- overflow: {
11939
- mode: phone ? "sheet" : toolbarFold2 >= 3 ? "menu" : "inline",
11940
- pinned: /* @__PURE__ */ jsxs36(Fragment15, { children: [
11941
- /* @__PURE__ */ jsx42(UndoRedoButtons, { undo }),
11942
- Boolean(editable) && rights.write ? /* @__PURE__ */ jsx42(Button27, { size: "sm", className: "shrink-0", disabled: added.busy, onClick: () => void addRowHere(), children: added.busy ? "Adding\u2026" : "New record" }) : null
11943
- ] }),
11944
- ...phone ? {
11945
- sheetTop: /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-1.5 pb-1", "data-records-grid-sheet-top": "", "data-matrx-table-tools-keep-open": "", children: [
11946
- /* @__PURE__ */ jsx42(
11947
- "input",
11948
- {
11949
- type: "search",
11950
- value: query.search,
11951
- placeholder: "Search",
11952
- "aria-label": "Search records",
11953
- onChange: (event) => {
11954
- const search = event.target.value;
11955
- setQuery((held) => ({ ...held, search, page: 1 }));
11956
- },
11957
- className: "h-10 w-full min-w-0 rounded-md border border-input bg-background px-2 text-foreground placeholder:text-muted-foreground",
11958
- style: { fontSize: "16px" }
11959
- }
11960
- ),
11961
- /* @__PURE__ */ jsxs36("label", { className: "flex items-center gap-2 text-xs text-muted-foreground", "data-records-grid-sheet-sort": "", children: [
11962
- /* @__PURE__ */ jsx42("span", { className: "shrink-0", children: "Sort by" }),
11963
- /* @__PURE__ */ jsxs36(
11964
- "select",
11965
- {
11966
- "aria-label": "Sort by",
11967
- value: query.sort ? `${query.sort.id}:${query.sort.direction}` : "",
11968
- onChange: (event) => {
11969
- const [id, direction] = event.target.value.split(":");
11970
- setQuery((held) => ({
11971
- ...held,
11972
- page: 1,
11973
- sort: id ? { id, direction: direction === "desc" ? "desc" : "asc" } : null
11974
- }));
11975
- },
11976
- className: "h-10 min-w-0 flex-1 rounded-md border border-input bg-background px-2 text-foreground",
11977
- style: { fontSize: "16px" },
11978
- children: [
11979
- /* @__PURE__ */ jsx42("option", { value: "", children: "No sort" }),
11980
- ordered.flatMap((field2) => [
11981
- /* @__PURE__ */ jsx42("option", { value: `${field2.key}:asc`, children: `${fieldName(field2)} \u2191` }, `${field2.key}:asc`),
11982
- /* @__PURE__ */ jsx42("option", { value: `${field2.key}:desc`, children: `${fieldName(field2)} \u2193` }, `${field2.key}:desc`)
11983
- ])
11984
- ]
11985
- }
11986
- )
11987
- ] }),
11988
- controls.sheetTools
11989
- ] }),
11990
- ...sheetExtras ? { sheetExtras } : {}
11991
- } : {}
11992
- }
11993
- } : {}
11994
- }
12111
+ toolbar: tableToolbar
11995
12112
  },
11996
12113
  `records-grid-${tableId}:${openingKey}`
11997
12114
  )
@@ -12093,6 +12210,58 @@ function Grid({
12093
12210
  }
12094
12211
  ) });
12095
12212
  }
12213
+ var DETAIL_OFF = { enabled: false };
12214
+ var WINDOW_OFF = { enabled: false };
12215
+ var VIRTUALIZE_FILLED = { threshold: 40 };
12216
+ function menuFace(items) {
12217
+ return JSON.stringify(items, (_key, value) => typeof value === "function" ? "\u0192" : value);
12218
+ }
12219
+ function menuThroughLatest(items, at, latest) {
12220
+ return items.map((item) => {
12221
+ const path = `${at}/${item.id}`;
12222
+ return {
12223
+ ...item,
12224
+ ...item.onSelect ? { onSelect: () => latest.get(path)?.() } : {},
12225
+ ...item.submenu ? { submenu: menuThroughLatest(item.submenu, path, latest) } : {}
12226
+ };
12227
+ });
12228
+ }
12229
+ function bindLatest(items, at, latest) {
12230
+ for (const item of items) {
12231
+ const path = `${at}/${item.id}`;
12232
+ if (item.onSelect) latest.set(path, item.onSelect);
12233
+ if (item.submenu) bindLatest(item.submenu, path, latest);
12234
+ }
12235
+ }
12236
+ function holdHeaderMenu(held, latest, key, items) {
12237
+ if (!items) return items;
12238
+ const at = `menu:${key}`;
12239
+ bindLatest(items, at, latest);
12240
+ const sig = menuFace(items);
12241
+ const was = held.get(at);
12242
+ if (was && was.sig === sig) return was.value;
12243
+ const value = menuThroughLatest(items, at, latest);
12244
+ held.set(at, { sig, value });
12245
+ return value;
12246
+ }
12247
+ function holdByContent(held, at, value) {
12248
+ if (value === void 0) return value;
12249
+ const sig = JSON.stringify(value);
12250
+ const was = held.get(at);
12251
+ if (was && was.sig === sig) return was.value;
12252
+ held.set(at, { sig, value });
12253
+ return value;
12254
+ }
12255
+ function sameColumns(a, b) {
12256
+ if (a === b) return true;
12257
+ if (a.length !== b.length) return false;
12258
+ return a.every((column, i) => {
12259
+ const other = b[i];
12260
+ if (column === other) return true;
12261
+ const keys = Object.keys(column);
12262
+ return keys.length === Object.keys(other).length && keys.every((key) => Object.is(column[key], other[key]));
12263
+ });
12264
+ }
12096
12265
  function withHeaderMenus(columns, menuFor, filterFor) {
12097
12266
  return columns.map((column) => {
12098
12267
  const items = menuFor(String(column.id));
@@ -12949,13 +13118,24 @@ function ImportWizard({ tableId, onDone, onWrote, className }) {
12949
13118
  }
12950
13119
 
12951
13120
  // src/CustomFieldsSection.tsx
12952
- import { useMemo as useMemo24, useState as useState34 } from "react";
13121
+ import { useEffect as useEffect27, useMemo as useMemo24, useRef as useRef15, useState as useState34 } from "react";
12953
13122
  import {
12954
13123
  useEntityFieldMutation,
12955
13124
  useEntityFieldRights,
12956
- useEntityRecord
13125
+ useEntityRecord,
13126
+ useRecordsClient as useRecordsClient22
12957
13127
  } from "@ai-matrx/records/react";
12958
- import { Button as Button30, Separator as Separator4, cn as cn23 } from "@ai-matrx/design-system";
13128
+ import {
13129
+ BasicInput as BasicInput10,
13130
+ Button as Button30,
13131
+ Select as Select5,
13132
+ SelectContent as SelectContent5,
13133
+ SelectItem as SelectItem5,
13134
+ SelectTrigger as SelectTrigger5,
13135
+ SelectValue as SelectValue5,
13136
+ Separator as Separator4,
13137
+ cn as cn23
13138
+ } from "@ai-matrx/design-system";
12959
13139
  import { jsx as jsx45, jsxs as jsxs39 } from "react/jsx-runtime";
12960
13140
  var ADDABLE_TYPE_IDS = [
12961
13141
  "text",
@@ -12974,6 +13154,32 @@ var ADDABLE_TYPES = ADDABLE_TYPE_IDS.map((value) => ({
12974
13154
  value,
12975
13155
  label: fieldTypeChoice(value)?.label ?? value
12976
13156
  }));
13157
+ var ADDABLE_TYPE_SET = new Set(ADDABLE_TYPE_IDS);
13158
+ function customFieldRequestProblems(requests, existingLabels) {
13159
+ const problems = [];
13160
+ const taken = new Set(existingLabels.map((l) => l.trim().toLowerCase()));
13161
+ const asked = /* @__PURE__ */ new Set();
13162
+ if (requests.length === 0) problems.push("Name at least one field to add.");
13163
+ requests.forEach((request, index) => {
13164
+ const at = requests.length > 1 ? `Field ${index + 1}: ` : "";
13165
+ const label = typeof request?.label === "string" ? request.label.trim() : "";
13166
+ if (!label) {
13167
+ problems.push(`${at}a field needs a name.`);
13168
+ return;
13169
+ }
13170
+ const type = request.type ?? "text";
13171
+ if (!ADDABLE_TYPE_SET.has(type)) {
13172
+ problems.push(
13173
+ `${at}"${label}" cannot hold "${String(type)}". Choose one of: ${ADDABLE_TYPE_IDS.join(", ")}.`
13174
+ );
13175
+ }
13176
+ const key = label.toLowerCase();
13177
+ if (taken.has(key)) problems.push(`${at}there is already a field named "${label}".`);
13178
+ else if (asked.has(key)) problems.push(`${at}"${label}" is asked for twice.`);
13179
+ asked.add(key);
13180
+ });
13181
+ return problems;
13182
+ }
12977
13183
  function asField(f) {
12978
13184
  return {
12979
13185
  id: f.id,
@@ -12994,8 +13200,10 @@ function CustomFieldsSection({
12994
13200
  entityToken,
12995
13201
  recordId,
12996
13202
  title = "Custom fields",
12997
- className
13203
+ className,
13204
+ agentDoor
12998
13205
  }) {
13206
+ const client = useRecordsClient22();
12999
13207
  const read = useEntityRecord(entityToken, recordId);
13000
13208
  const rights = useEntityFieldRights(entityToken);
13001
13209
  const mutation = useEntityFieldMutation();
@@ -13006,14 +13214,70 @@ function CustomFieldsSection({
13006
13214
  const [draft, setDraft] = useState34({});
13007
13215
  const fields = useMemo24(() => read.data?.fields ?? [], [read.data]);
13008
13216
  const mayAdd = rights.data?.may_declare === true;
13217
+ const live = useRef15({ fields, rights: rights.data, loading: rights.loading, reload: read.reload });
13218
+ useEffect27(() => {
13219
+ live.current = { fields, rights: rights.data, loading: rights.loading, reload: read.reload };
13220
+ });
13221
+ useEffect27(() => {
13222
+ if (!agentDoor) return;
13223
+ const state = () => {
13224
+ const now = live.current;
13225
+ return {
13226
+ entityToken,
13227
+ recordId,
13228
+ entityLabel: now.rights?.label ?? null,
13229
+ mayAdd: now.rights ? now.rights.may_declare === true : now.loading ? null : false,
13230
+ refusal: now.rights && !now.rights.may_declare ? now.rights.reason ?? null : null,
13231
+ fields: now.fields.map((f) => ({ key: f.key, label: f.label, type: f.type })),
13232
+ types: ADDABLE_TYPES
13233
+ };
13234
+ };
13235
+ const check = (requests) => {
13236
+ const now = state();
13237
+ if (now.mayAdd === false) {
13238
+ return [now.refusal ?? "This person may not add a field here."];
13239
+ }
13240
+ if (now.mayAdd === null) return ["The section is still reading who may add a field. Try again in a moment."];
13241
+ return customFieldRequestProblems(requests, now.fields.map((f) => f.label));
13242
+ };
13243
+ const addField = async (request) => {
13244
+ const problems = check([request]);
13245
+ if (problems.length > 0) return { ok: false, message: problems.join(" ") };
13246
+ const label = request.label.trim();
13247
+ const type = request.type ?? "text";
13248
+ const declared2 = await client.entityFieldDeclare({ token: entityToken, spec: { label, type } });
13249
+ if (!declared2.ok) {
13250
+ const hint = hintForAPerson(declared2.error.hint);
13251
+ return { ok: false, message: hint ? `${declared2.error.message} ${hint}` : declared2.error.message };
13252
+ }
13253
+ const back = await client.entityRecordRead({ token: entityToken, record_id: recordId });
13254
+ live.current.reload();
13255
+ if (!back.ok || !(back.data?.fields ?? []).some((f) => f.id === declared2.data)) {
13256
+ return {
13257
+ ok: false,
13258
+ message: `The store took "${label}" but this record does not show it yet. Nothing was lost \u2014 read the page again before adding it a second time.`
13259
+ };
13260
+ }
13261
+ return { ok: true, field_id: declared2.data, label, type };
13262
+ };
13263
+ return agentDoor({ entityToken, recordId, state, check, addField });
13264
+ }, [agentDoor, client, entityToken, recordId]);
13009
13265
  if (!read.loading && !read.error && fields.length === 0 && !mayAdd) return null;
13010
13266
  if (read.error) return /* @__PURE__ */ jsx45(RefusalLine, { error: read.error, className });
13011
13267
  const values = read.data?.custom ?? {};
13012
13268
  const written = read.data?.custom_written ?? {};
13269
+ const empty = fields.length === 0;
13270
+ if (empty && !adding) {
13271
+ return /* @__PURE__ */ jsxs39("section", { className: cn23("flex min-w-0 items-center gap-2 text-xs", className), children: [
13272
+ /* @__PURE__ */ jsx45("h3", { className: "text-sm font-medium", children: title }),
13273
+ !read.loading ? /* @__PURE__ */ jsx45("span", { className: "text-muted-foreground", children: "None yet" }) : null,
13274
+ mayAdd ? /* @__PURE__ */ jsx45(Button30, { size: "sm", variant: "ghost", className: "ml-auto", onClick: () => setAdding(true), children: "Add field" }) : null
13275
+ ] });
13276
+ }
13013
13277
  return /* @__PURE__ */ jsxs39("section", { className: cn23("flex min-w-0 flex-col gap-2 text-xs", className), children: [
13014
13278
  /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2", children: [
13015
13279
  /* @__PURE__ */ jsx45("h3", { className: "text-sm font-medium", children: title }),
13016
- /* @__PURE__ */ jsx45("span", { className: "text-muted-foreground", children: fields.length }),
13280
+ !empty ? /* @__PURE__ */ jsx45("span", { className: "text-muted-foreground", children: fields.length }) : null,
13017
13281
  fields.length > 0 ? /* @__PURE__ */ jsx45(
13018
13282
  Button30,
13019
13283
  {
@@ -13082,9 +13346,9 @@ function CustomFieldsSection({
13082
13346
  /* @__PURE__ */ jsxs39("label", { className: "flex flex-col gap-1", children: [
13083
13347
  /* @__PURE__ */ jsx45("span", { className: "text-muted-foreground", children: "Name" }),
13084
13348
  /* @__PURE__ */ jsx45(
13085
- "input",
13349
+ BasicInput10,
13086
13350
  {
13087
- className: "h-8 rounded-md border bg-background px-2",
13351
+ className: "h-8",
13088
13352
  value: newLabel,
13089
13353
  onChange: (e) => setNewLabel(e.target.value),
13090
13354
  placeholder: "Account tier",
@@ -13092,17 +13356,12 @@ function CustomFieldsSection({
13092
13356
  }
13093
13357
  )
13094
13358
  ] }),
13095
- /* @__PURE__ */ jsxs39("label", { className: "flex flex-col gap-1", children: [
13359
+ /* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1", children: [
13096
13360
  /* @__PURE__ */ jsx45("span", { className: "text-muted-foreground", children: "Holds" }),
13097
- /* @__PURE__ */ jsx45(
13098
- "select",
13099
- {
13100
- className: "h-8 rounded-md border bg-background px-2",
13101
- value: newType,
13102
- onChange: (e) => setNewType(e.target.value),
13103
- children: ADDABLE_TYPES.map((t) => /* @__PURE__ */ jsx45("option", { value: t.value, children: t.label }, t.value))
13104
- }
13105
- )
13361
+ /* @__PURE__ */ jsxs39(Select5, { value: newType, onValueChange: setNewType, children: [
13362
+ /* @__PURE__ */ jsx45(SelectTrigger5, { size: "sm", "aria-label": "What this field holds", children: /* @__PURE__ */ jsx45(SelectValue5, {}) }),
13363
+ /* @__PURE__ */ jsx45(SelectContent5, { children: ADDABLE_TYPES.map((t) => /* @__PURE__ */ jsx45(SelectItem5, { value: t.value, children: t.label }, t.value)) })
13364
+ ] })
13106
13365
  ] }),
13107
13366
  /* @__PURE__ */ jsx45(Button30, { size: "sm", type: "submit", disabled: mutation.saving || newLabel.trim() === "", children: mutation.saving ? "Adding\u2026" : "Add" })
13108
13367
  ]
@@ -13134,13 +13393,13 @@ function CustomFieldsSection({
13134
13393
  }
13135
13394
 
13136
13395
  // src/StageRules.tsx
13137
- import { useCallback as useCallback18, useEffect as useEffect27, useMemo as useMemo25, useState as useState36 } from "react";
13138
- import { useFields as useFields7, useRecordsClient as useRecordsClient22, useTable as useTable5 } from "@ai-matrx/records/react";
13139
- import { BasicInput as BasicInput11, BasicTextarea as BasicTextarea7, Button as Button32, Separator as Separator5, Skeleton as Skeleton3, cn as cn24 } from "@ai-matrx/design-system";
13396
+ import { useCallback as useCallback18, useEffect as useEffect28, useMemo as useMemo25, useState as useState36 } from "react";
13397
+ import { useFields as useFields7, useRecordsClient as useRecordsClient23, useTable as useTable5 } from "@ai-matrx/records/react";
13398
+ import { BasicInput as BasicInput12, BasicTextarea as BasicTextarea7, Button as Button32, Separator as Separator5, Skeleton as Skeleton3, cn as cn24 } from "@ai-matrx/design-system";
13140
13399
 
13141
13400
  // src/Condition.tsx
13142
13401
  import { useState as useState35 } from "react";
13143
- import { BasicInput as BasicInput10, Button as Button31 } from "@ai-matrx/design-system";
13402
+ import { BasicInput as BasicInput11, Button as Button31 } from "@ai-matrx/design-system";
13144
13403
  import { Fragment as Fragment17, jsx as jsx46, jsxs as jsxs40 } from "react/jsx-runtime";
13145
13404
  var CONDITION_OPS = [
13146
13405
  { op: "eq", label: "is" },
@@ -13282,7 +13541,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
13282
13541
  }
13283
13542
  )
13284
13543
  ) : /* @__PURE__ */ jsx46(
13285
- BasicInput10,
13544
+ BasicInput11,
13286
13545
  {
13287
13546
  className: "h-8 w-28 text-xs",
13288
13547
  "aria-label": "Condition value",
@@ -13513,7 +13772,7 @@ function draftOf(rule) {
13513
13772
  };
13514
13773
  }
13515
13774
  function StageRulesSection({ tableId, stage, className }) {
13516
- const client = useRecordsClient22();
13775
+ const client = useRecordsClient23();
13517
13776
  const table = useTable5(tableId);
13518
13777
  const rights = useTableRights(table.data);
13519
13778
  const fields = useFields7(tableId);
@@ -13533,7 +13792,7 @@ function StageRulesSection({ tableId, stage, className }) {
13533
13792
  if (mode.ok) setEnforcement(mode.data);
13534
13793
  setAsked(true);
13535
13794
  }, [client, tableId]);
13536
- useEffect27(() => {
13795
+ useEffect28(() => {
13537
13796
  void load();
13538
13797
  }, [load]);
13539
13798
  const stages = pipeline?.stages ?? [];
@@ -13544,7 +13803,7 @@ function StageRulesSection({ tableId, stage, className }) {
13544
13803
  () => (fields.data ?? []).map((f) => ({ id: String(f.id), key: f.key, label: fieldName(f), field: f })),
13545
13804
  [fields.data]
13546
13805
  );
13547
- useEffect27(() => {
13806
+ useEffect28(() => {
13548
13807
  if (!draft || !stageKey || !draft.demands || Object.keys(draft.demands).length === 0) {
13549
13808
  setPreview(null);
13550
13809
  setPreviewError(null);
@@ -13656,7 +13915,7 @@ function StageRulesSection({ tableId, stage, className }) {
13656
13915
  "\u201D. Writing a condition below replaces it."
13657
13916
  ] }) : null,
13658
13917
  /* @__PURE__ */ jsx47(
13659
- BasicInput11,
13918
+ BasicInput12,
13660
13919
  {
13661
13920
  className: "h-8 text-xs",
13662
13921
  "aria-label": "Rule name",
@@ -13776,26 +14035,26 @@ import {
13776
14035
  import { Badge as Badge10, Button as Button34, Separator as Separator6, cn as cn27 } from "@ai-matrx/design-system";
13777
14036
 
13778
14037
  // src/RowActionsEditor.tsx
13779
- import { useCallback as useCallback19, useEffect as useEffect29, useMemo as useMemo26, useState as useState38 } from "react";
13780
- import { useFields as useFields8, useRecords as useRecords5, useRecordsClient as useRecordsClient24 } from "@ai-matrx/records/react";
14038
+ import { useCallback as useCallback19, useEffect as useEffect30, useMemo as useMemo26, useState as useState38 } from "react";
14039
+ import { useFields as useFields8, useRecords as useRecords5, useRecordsClient as useRecordsClient25 } from "@ai-matrx/records/react";
13781
14040
  import {
13782
14041
  Badge as Badge9,
13783
- BasicInput as BasicInput12,
14042
+ BasicInput as BasicInput13,
13784
14043
  BasicTextarea as BasicTextarea8,
13785
14044
  Button as Button33,
13786
14045
  Checkbox as Checkbox6,
13787
14046
  Label as Label11,
13788
- Select as Select5,
13789
- SelectContent as SelectContent5,
13790
- SelectItem as SelectItem5,
13791
- SelectTrigger as SelectTrigger5,
13792
- SelectValue as SelectValue5,
14047
+ Select as Select6,
14048
+ SelectContent as SelectContent6,
14049
+ SelectItem as SelectItem6,
14050
+ SelectTrigger as SelectTrigger6,
14051
+ SelectValue as SelectValue6,
13793
14052
  cn as cn26
13794
14053
  } from "@ai-matrx/design-system";
13795
14054
 
13796
14055
  // src/rowActionPreview.tsx
13797
- import { useEffect as useEffect28, useState as useState37 } from "react";
13798
- import { useRecordsClient as useRecordsClient23 } from "@ai-matrx/records/react";
14056
+ import { useEffect as useEffect29, useState as useState37 } from "react";
14057
+ import { useRecordsClient as useRecordsClient24 } from "@ai-matrx/records/react";
13799
14058
  import { cn as cn25 } from "@ai-matrx/design-system";
13800
14059
  import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
13801
14060
  function isComputed(field2) {
@@ -13846,10 +14105,10 @@ var RESULT_WORDS = {
13846
14105
  unknown: "a value"
13847
14106
  };
13848
14107
  function useFormulaReadings(tableId, formulas) {
13849
- const client = useRecordsClient23();
14108
+ const client = useRecordsClient24();
13850
14109
  const [readings, setReadings] = useState37({});
13851
14110
  const key = formulas.join("\0");
13852
- useEffect28(() => {
14111
+ useEffect29(() => {
13853
14112
  if (!tableId) return;
13854
14113
  let live = true;
13855
14114
  for (const text of formulas) {
@@ -14005,7 +14264,7 @@ function describe(action, fields) {
14005
14264
  return says.charAt(0).toUpperCase() + says.slice(1) + ".";
14006
14265
  }
14007
14266
  function RowActionsSection({ tableId, className }) {
14008
- const client = useRecordsClient24();
14267
+ const client = useRecordsClient25();
14009
14268
  const fields = useFields8(tableId);
14010
14269
  const records = useRecords5(tableId, { pageSize: 20 });
14011
14270
  const [actions, setActions] = useState38([]);
@@ -14029,10 +14288,10 @@ function RowActionsSection({ tableId, className }) {
14029
14288
  setActions(answered.data?.actions ?? []);
14030
14289
  setStale((answered.data?.stale ?? []).length);
14031
14290
  }, [client, tableId]);
14032
- useEffect29(() => {
14291
+ useEffect30(() => {
14033
14292
  void reload();
14034
14293
  }, [reload]);
14035
- useEffect29(() => {
14294
+ useEffect30(() => {
14036
14295
  let live = true;
14037
14296
  void client.tableDecorations({ table_id: tableId }).then((answered) => {
14038
14297
  if (live && answered.ok) setColors(answered.data?.colors ?? []);
@@ -14237,7 +14496,7 @@ function ActionForm({
14237
14496
  /* @__PURE__ */ jsxs43("label", { className: "flex flex-col gap-1", children: [
14238
14497
  /* @__PURE__ */ jsx49(Label11, { className: "text-xs", children: "Name" }),
14239
14498
  /* @__PURE__ */ jsx49(
14240
- BasicInput12,
14499
+ BasicInput13,
14241
14500
  {
14242
14501
  value: draft.name,
14243
14502
  autoFocus: true,
@@ -14291,7 +14550,7 @@ function ActionForm({
14291
14550
  rows.length > 0 ? /* @__PURE__ */ jsxs43("div", { className: "ml-auto flex items-center gap-1", children: [
14292
14551
  /* @__PURE__ */ jsx49("span", { className: "text-muted-foreground", children: "Start from a record" }),
14293
14552
  /* @__PURE__ */ jsxs43(
14294
- Select5,
14553
+ Select6,
14295
14554
  {
14296
14555
  value: "",
14297
14556
  onValueChange: (id) => {
@@ -14309,8 +14568,8 @@ function ActionForm({
14309
14568
  setPreviewId(row.id);
14310
14569
  },
14311
14570
  children: [
14312
- /* @__PURE__ */ jsx49(SelectTrigger5, { size: "sm", "aria-label": "Start from a record", children: /* @__PURE__ */ jsx49(SelectValue5, { placeholder: "Pick one" }) }),
14313
- /* @__PURE__ */ jsx49(SelectContent5, { children: rows.map((row) => /* @__PURE__ */ jsx49(SelectItem5, { value: row.id, children: rowName2(row) }, row.id)) })
14571
+ /* @__PURE__ */ jsx49(SelectTrigger6, { size: "sm", "aria-label": "Start from a record", children: /* @__PURE__ */ jsx49(SelectValue6, { placeholder: "Pick one" }) }),
14572
+ /* @__PURE__ */ jsx49(SelectContent6, { children: rows.map((row) => /* @__PURE__ */ jsx49(SelectItem6, { value: row.id, children: rowName2(row) }, row.id)) })
14314
14573
  ]
14315
14574
  }
14316
14575
  )
@@ -14318,20 +14577,20 @@ function ActionForm({
14318
14577
  ] }),
14319
14578
  draft.steps.length === 0 ? /* @__PURE__ */ jsx49("p", { className: "text-muted-foreground", children: "Nothing yet. Add a change, or start from a record and remove the columns it should leave alone." }) : null,
14320
14579
  draft.steps.map((step2, index) => /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap items-center gap-1", "data-records-action-step": index, children: [
14321
- /* @__PURE__ */ jsxs43(Select5, { value: step2.field, onValueChange: (v) => setStep(index, { field: v }), children: [
14322
- /* @__PURE__ */ jsx49(SelectTrigger5, { size: "sm", "aria-label": `Column for change ${index + 1}`, children: /* @__PURE__ */ jsx49(SelectValue5, { placeholder: "Column" }) }),
14323
- /* @__PURE__ */ jsx49(SelectContent5, { children: settable.map((f) => /* @__PURE__ */ jsx49(SelectItem5, { value: f.id, children: fieldName(f) }, f.id)) })
14580
+ /* @__PURE__ */ jsxs43(Select6, { value: step2.field, onValueChange: (v) => setStep(index, { field: v }), children: [
14581
+ /* @__PURE__ */ jsx49(SelectTrigger6, { size: "sm", "aria-label": `Column for change ${index + 1}`, children: /* @__PURE__ */ jsx49(SelectValue6, { placeholder: "Column" }) }),
14582
+ /* @__PURE__ */ jsx49(SelectContent6, { children: settable.map((f) => /* @__PURE__ */ jsx49(SelectItem6, { value: f.id, children: fieldName(f) }, f.id)) })
14324
14583
  ] }),
14325
- /* @__PURE__ */ jsxs43(Select5, { value: step2.set, onValueChange: (v) => setStep(index, { set: v }), children: [
14326
- /* @__PURE__ */ jsx49(SelectTrigger5, { size: "sm", "aria-label": `How change ${index + 1} sets it`, children: /* @__PURE__ */ jsx49(SelectValue5, {}) }),
14327
- /* @__PURE__ */ jsxs43(SelectContent5, { children: [
14328
- /* @__PURE__ */ jsx49(SelectItem5, { value: "value", children: "Set to" }),
14329
- /* @__PURE__ */ jsx49(SelectItem5, { value: "clear", children: "Clear" }),
14330
- /* @__PURE__ */ jsx49(SelectItem5, { value: "compute", children: "Work out" })
14584
+ /* @__PURE__ */ jsxs43(Select6, { value: step2.set, onValueChange: (v) => setStep(index, { set: v }), children: [
14585
+ /* @__PURE__ */ jsx49(SelectTrigger6, { size: "sm", "aria-label": `How change ${index + 1} sets it`, children: /* @__PURE__ */ jsx49(SelectValue6, {}) }),
14586
+ /* @__PURE__ */ jsxs43(SelectContent6, { children: [
14587
+ /* @__PURE__ */ jsx49(SelectItem6, { value: "value", children: "Set to" }),
14588
+ /* @__PURE__ */ jsx49(SelectItem6, { value: "clear", children: "Clear" }),
14589
+ /* @__PURE__ */ jsx49(SelectItem6, { value: "compute", children: "Work out" })
14331
14590
  ] })
14332
14591
  ] }),
14333
14592
  step2.set === "value" ? /* @__PURE__ */ jsx49(
14334
- BasicInput12,
14593
+ BasicInput13,
14335
14594
  {
14336
14595
  className: "h-7 w-40",
14337
14596
  value: step2.value,
@@ -14339,7 +14598,7 @@ function ActionForm({
14339
14598
  onChange: (e) => setStep(index, { value: e.target.value })
14340
14599
  }
14341
14600
  ) : step2.set === "compute" ? /* @__PURE__ */ jsx49(
14342
- BasicInput12,
14601
+ BasicInput13,
14343
14602
  {
14344
14603
  className: "h-7 w-56",
14345
14604
  value: step2.formula,
@@ -14372,9 +14631,9 @@ function ActionForm({
14372
14631
  /* @__PURE__ */ jsxs43("div", { className: "flex flex-wrap items-center gap-1", children: [
14373
14632
  /* @__PURE__ */ jsx49("span", { className: "font-medium", children: "Before and after" }),
14374
14633
  /* @__PURE__ */ jsx49("span", { className: "text-muted-foreground", children: "on" }),
14375
- /* @__PURE__ */ jsxs43(Select5, { value: previewRow.id, onValueChange: (v) => setPreviewId(v), children: [
14376
- /* @__PURE__ */ jsx49(SelectTrigger5, { size: "sm", "aria-label": "Record to preview on", children: /* @__PURE__ */ jsx49(SelectValue5, {}) }),
14377
- /* @__PURE__ */ jsx49(SelectContent5, { children: rows.map((row) => /* @__PURE__ */ jsx49(SelectItem5, { value: row.id, children: rowName2(row) }, row.id)) })
14634
+ /* @__PURE__ */ jsxs43(Select6, { value: previewRow.id, onValueChange: (v) => setPreviewId(v), children: [
14635
+ /* @__PURE__ */ jsx49(SelectTrigger6, { size: "sm", "aria-label": "Record to preview on", children: /* @__PURE__ */ jsx49(SelectValue6, {}) }),
14636
+ /* @__PURE__ */ jsx49(SelectContent6, { children: rows.map((row) => /* @__PURE__ */ jsx49(SelectItem6, { value: row.id, children: rowName2(row) }, row.id)) })
14378
14637
  ] })
14379
14638
  ] }),
14380
14639
  /* @__PURE__ */ jsx49(
@@ -14409,15 +14668,15 @@ function ActionForm({
14409
14668
  colors.length > 0 ? /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-1", children: [
14410
14669
  /* @__PURE__ */ jsx49("span", { className: "text-muted-foreground", children: "Color" }),
14411
14670
  /* @__PURE__ */ jsxs43(
14412
- Select5,
14671
+ Select6,
14413
14672
  {
14414
14673
  value: draft.color || NO_COLOR,
14415
14674
  onValueChange: (v) => setDraft((d) => ({ ...d, color: v === NO_COLOR ? "" : v })),
14416
14675
  children: [
14417
- /* @__PURE__ */ jsx49(SelectTrigger5, { size: "sm", "aria-label": "Button color", children: /* @__PURE__ */ jsx49(SelectValue5, {}) }),
14418
- /* @__PURE__ */ jsxs43(SelectContent5, { children: [
14419
- /* @__PURE__ */ jsx49(SelectItem5, { value: NO_COLOR, children: "None" }),
14420
- colors.map((c) => /* @__PURE__ */ jsx49(SelectItem5, { value: c, children: c.charAt(0).toUpperCase() + c.slice(1) }, c))
14676
+ /* @__PURE__ */ jsx49(SelectTrigger6, { size: "sm", "aria-label": "Button color", children: /* @__PURE__ */ jsx49(SelectValue6, {}) }),
14677
+ /* @__PURE__ */ jsxs43(SelectContent6, { children: [
14678
+ /* @__PURE__ */ jsx49(SelectItem6, { value: NO_COLOR, children: "None" }),
14679
+ colors.map((c) => /* @__PURE__ */ jsx49(SelectItem6, { value: c, children: c.charAt(0).toUpperCase() + c.slice(1) }, c))
14421
14680
  ] })
14422
14681
  ]
14423
14682
  }
@@ -14650,21 +14909,21 @@ function TableSettings({
14650
14909
 
14651
14910
  // src/Peek.tsx
14652
14911
  import { useState as useState44 } from "react";
14653
- import { useFields as useFields11, useRecord as useRecord2, useRecordsClient as useRecordsClient28, useTable as useTable7 } from "@ai-matrx/records/react";
14912
+ import { useFields as useFields11, useRecord as useRecord2, useRecordsClient as useRecordsClient29, useTable as useTable7 } from "@ai-matrx/records/react";
14654
14913
  import { AlchemyMenu as AlchemyMenu2 } from "@ai-matrx/alchemy/react";
14655
14914
 
14656
14915
  // src/RecordChat.tsx
14657
- import { useEffect as useEffect30, useMemo as useMemo27, useState as useState40 } from "react";
14658
- import { useRecordsClient as useRecordsClient25 } from "@ai-matrx/records/react";
14916
+ import { useEffect as useEffect31, useMemo as useMemo27, useState as useState40 } from "react";
14917
+ import { useRecordsClient as useRecordsClient26 } from "@ai-matrx/records/react";
14659
14918
  import { Skeleton as Skeleton4, cn as cn28 } from "@ai-matrx/design-system";
14660
14919
  import { jsx as jsx51, jsxs as jsxs45 } from "react/jsx-runtime";
14661
14920
  var NO_CHAT_REASON = "Chatting about this record is not switched on here yet, so this panel is empty rather than showing a box that goes nowhere. It is on our list, not yours.";
14662
14921
  function RecordChat({ tableId, recordId, className }) {
14663
- const client = useRecordsClient25();
14922
+ const client = useRecordsClient26();
14664
14923
  const host = useRecordsUi();
14665
14924
  const [scope, setScope] = useState40(null);
14666
14925
  const [error, setError] = useState40(null);
14667
- useEffect30(() => {
14926
+ useEffect31(() => {
14668
14927
  let cancelled = false;
14669
14928
  setScope(null);
14670
14929
  setError(null);
@@ -14781,12 +15040,12 @@ function entriesFor(scope) {
14781
15040
  import { Button as Button37, Separator as Separator8, Skeleton as Skeleton5, cn as cn30 } from "@ai-matrx/design-system";
14782
15041
 
14783
15042
  // src/RecordForm.tsx
14784
- import { useEffect as useEffect32, useMemo as useMemo29, useRef as useRef15, useState as useState42 } from "react";
15043
+ import { useEffect as useEffect33, useMemo as useMemo29, useRef as useRef16, useState as useState42 } from "react";
14785
15044
  import {
14786
15045
  useFields as useFields10,
14787
15046
  useRecord,
14788
15047
  useRecordMutation,
14789
- useRecordsClient as useRecordsClient27
15048
+ useRecordsClient as useRecordsClient28
14790
15049
  } from "@ai-matrx/records/react";
14791
15050
  import { asWriteConflict as asWriteConflict3, predictWriteRefusals, wholeValueOf as wholeValueOf5 } from "@ai-matrx/records/core";
14792
15051
 
@@ -14824,8 +15083,8 @@ async function updateOnTheWinningVersion(client, recordId, patch, expectedVersio
14824
15083
  import { Button as Button35, Separator as Separator7, cn as cn29 } from "@ai-matrx/design-system";
14825
15084
 
14826
15085
  // src/systemTable.ts
14827
- import { useEffect as useEffect31, useMemo as useMemo28, useState as useState41 } from "react";
14828
- import { useRecordsClient as useRecordsClient26 } from "@ai-matrx/records/react";
15086
+ import { useEffect as useEffect32, useMemo as useMemo28, useState as useState41 } from "react";
15087
+ import { useRecordsClient as useRecordsClient27 } from "@ai-matrx/records/react";
14829
15088
  var inFlight = /* @__PURE__ */ new Map();
14830
15089
  async function ensureSystemTable(client, spec) {
14831
15090
  const cacheKey = `${client.config.organizationId}:${spec.slug}`;
@@ -14953,11 +15212,11 @@ async function declare(client, spec) {
14953
15212
  return { ok: true, data: table.data };
14954
15213
  }
14955
15214
  function useSystemTable(spec) {
14956
- const client = useRecordsClient26();
15215
+ const client = useRecordsClient27();
14957
15216
  const [state, setState] = useState41({ tableId: null, loading: true, error: null });
14958
15217
  const slug = spec.slug;
14959
15218
  const stable = useMemo28(() => spec, [slug]);
14960
- useEffect31(() => {
15219
+ useEffect32(() => {
14961
15220
  let cancelled = false;
14962
15221
  setState({ tableId: null, loading: true, error: null });
14963
15222
  void ensureSystemTable(client, stable).then((result) => {
@@ -14973,9 +15232,9 @@ function useSystemTable(spec) {
14973
15232
  return state;
14974
15233
  }
14975
15234
  function useRecordVersion(recordId) {
14976
- const client = useRecordsClient26();
15235
+ const client = useRecordsClient27();
14977
15236
  const [version, setVersion] = useState41(null);
14978
- useEffect31(() => {
15237
+ useEffect32(() => {
14979
15238
  let cancelled = false;
14980
15239
  setVersion(null);
14981
15240
  if (!recordId) return;
@@ -15008,7 +15267,7 @@ function RecordForm({
15008
15267
  const fields = useFields10(tableId, recordType);
15009
15268
  const existing = useRecord(recordId ?? null);
15010
15269
  const mutation = useRecordMutation();
15011
- const client = useRecordsClient27();
15270
+ const client = useRecordsClient28();
15012
15271
  const [edit, setEdit] = useState42({
15013
15272
  saving: false,
15014
15273
  error: null,
@@ -15029,9 +15288,9 @@ function RecordForm({
15029
15288
  const [answered, setAnswered] = useState42(null);
15030
15289
  const loaded = useRecordVersion(recordId ?? null);
15031
15290
  const loadedVersion = loaded.version;
15032
- const changedRef = useRef15({});
15291
+ const changedRef = useRef16({});
15033
15292
  changedRef.current = changed;
15034
- useEffect32(() => {
15293
+ useEffect33(() => {
15035
15294
  const document3 = existing.data?.document;
15036
15295
  if (!document3) return;
15037
15296
  const mine = changedRef.current;
@@ -15232,7 +15491,7 @@ function asWords(value) {
15232
15491
  }
15233
15492
 
15234
15493
  // src/ShareControl.tsx
15235
- import { useEffect as useEffect33, useState as useState43 } from "react";
15494
+ import { useEffect as useEffect34, useState as useState43 } from "react";
15236
15495
  import { Button as Button36 } from "@ai-matrx/design-system";
15237
15496
  import { Fragment as Fragment19, jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
15238
15497
  function useCanShare() {
@@ -15254,7 +15513,7 @@ function ShareControl({
15254
15513
  }) {
15255
15514
  const host = useRecordsUi();
15256
15515
  const [open, setOpen] = useState43(initiallyOpen);
15257
- useEffect33(() => {
15516
+ useEffect34(() => {
15258
15517
  if (initiallyOpen) setOpen(true);
15259
15518
  }, [initiallyOpen]);
15260
15519
  const asked = useRecordRights(may === void 0 ? subjectId : null);
@@ -15293,7 +15552,7 @@ function Peek({ tableId, recordId, onClose, className }) {
15293
15552
  const record = useRecord2(recordId, true);
15294
15553
  const may = useRecordRights(recordId);
15295
15554
  const host = useRecordsUi();
15296
- const organizationId = useRecordsClient28().config.organizationId;
15555
+ const organizationId = useRecordsClient29().config.organizationId;
15297
15556
  const [editing, setEditing] = useState44(false);
15298
15557
  const [talking, setTalking] = useState44(false);
15299
15558
  if (record.error) return /* @__PURE__ */ jsx54(RefusalNotice, { error: record.error, className });
@@ -15470,8 +15729,8 @@ var LOOK_WORDS = {
15470
15729
  };
15471
15730
 
15472
15731
  // src/ViewSwitcher.tsx
15473
- import { useEffect as useEffect35, useMemo as useMemo31, useState as useState46 } from "react";
15474
- import { useFields as useFields13, useRecords as useRecords6, useRecordsClient as useRecordsClient30 } from "@ai-matrx/records/react";
15732
+ import { useEffect as useEffect36, useMemo as useMemo31, useState as useState46 } from "react";
15733
+ import { useFields as useFields13, useRecords as useRecords6, useRecordsClient as useRecordsClient31 } from "@ai-matrx/records/react";
15475
15734
  import { stableFilterKey as stableFilterKey4 } from "@ai-matrx/records";
15476
15735
  import { Button as Button39, Skeleton as Skeleton7, cn as cn32 } from "@ai-matrx/design-system";
15477
15736
  import {
@@ -15480,11 +15739,11 @@ import {
15480
15739
  } from "@ai-matrx/design-system/data-table";
15481
15740
 
15482
15741
  // src/Pipeline.tsx
15483
- import { useCallback as useCallback20, useEffect as useEffect34, useMemo as useMemo30, useRef as useRef16, useState as useState45 } from "react";
15742
+ import { useCallback as useCallback20, useEffect as useEffect35, useMemo as useMemo30, useRef as useRef17, useState as useState45 } from "react";
15484
15743
  import {
15485
15744
  mayDrag,
15486
15745
  useFields as useFields12,
15487
- useRecordsClient as useRecordsClient29
15746
+ useRecordsClient as useRecordsClient30
15488
15747
  } from "@ai-matrx/records/react";
15489
15748
  import { stableFilterKey as stableFilterKey3 } from "@ai-matrx/records";
15490
15749
  import {
@@ -15576,7 +15835,7 @@ function PipelineBoard({
15576
15835
  dateFields,
15577
15836
  className
15578
15837
  }) {
15579
- const client = useRecordsClient29();
15838
+ const client = useRecordsClient30();
15580
15839
  const fields = useFields12(tableId);
15581
15840
  const ownDecorations = useTableDecorations(style ? null : tableId);
15582
15841
  const cardStyle = useMemo30(
@@ -15591,15 +15850,15 @@ function PipelineBoard({
15591
15850
  const [waiting, setWaiting] = useState45(/* @__PURE__ */ new Map());
15592
15851
  const [dragging, setDragging] = useState45(null);
15593
15852
  const [over, setOver] = useState45(null);
15594
- const alive = useRef16(true);
15853
+ const alive = useRef17(true);
15595
15854
  const [selected, setSelected] = useState45(/* @__PURE__ */ new Set());
15596
- const anchor = useRef16(null);
15855
+ const anchor = useRef17(null);
15597
15856
  const [versions, setVersions] = useState45(null);
15598
15857
  const [batch, setBatch] = useState45(/* @__PURE__ */ new Map());
15599
15858
  const [batchSaid, setBatchSaid] = useState45(null);
15600
15859
  const [batchError, setBatchError] = useState45(null);
15601
15860
  const [moving, setMoving] = useState45(false);
15602
- useEffect34(() => {
15861
+ useEffect35(() => {
15603
15862
  alive.current = true;
15604
15863
  return () => {
15605
15864
  alive.current = false;
@@ -15624,10 +15883,10 @@ function PipelineBoard({
15624
15883
  setWaiting(held.ok ? new Map((held.data ?? []).map((p) => [p.record_id, p])) : /* @__PURE__ */ new Map());
15625
15884
  setColumns(board.ok ? board.data ?? [] : []);
15626
15885
  }, [client, tableId, measure, filterKey]);
15627
- useEffect34(() => {
15886
+ useEffect35(() => {
15628
15887
  void reload();
15629
15888
  }, [reload]);
15630
- useEffect34(() => {
15889
+ useEffect35(() => {
15631
15890
  const ids = rows.filter((r) => mayDrag(r.level)).map((r) => r.id);
15632
15891
  if (ids.length === 0) {
15633
15892
  setVersions({ ok: true, map: /* @__PURE__ */ new Map() });
@@ -16227,7 +16486,7 @@ function batchSentence(moved, waiting, notMoved, label) {
16227
16486
  import { Fragment as Fragment22, jsx as jsx57, jsxs as jsxs51 } from "react/jsx-runtime";
16228
16487
  var NO_FIELDS = [];
16229
16488
  function useViewRecords(view, pageSize = 200, filter, viewId) {
16230
- const client = useRecordsClient30();
16489
+ const client = useRecordsClient31();
16231
16490
  const table = useRecords6(view.ruleId ? null : view.subject, {
16232
16491
  pageSize,
16233
16492
  ...filter ? { filter } : {}
@@ -16238,7 +16497,7 @@ function useViewRecords(view, pageSize = 200, filter, viewId) {
16238
16497
  error: null
16239
16498
  });
16240
16499
  const ruleId = view.ruleId ?? null;
16241
- useEffect35(() => {
16500
+ useEffect36(() => {
16242
16501
  if (!ruleId) return;
16243
16502
  let cancelled = false;
16244
16503
  setRuled({ rows: [], loading: true, error: null });
@@ -16325,7 +16584,7 @@ function ViewSwitcher({
16325
16584
  const hostLayouts = useRecordsUi().layouts ?? [];
16326
16585
  const drawnByHost = hostLayout ? hostLayouts.find((h) => h.id === hostLayout) ?? null : null;
16327
16586
  const [local, setLocal] = useState46({});
16328
- useEffect35(() => {
16587
+ useEffect36(() => {
16329
16588
  setLayout(view.layout);
16330
16589
  setLocal({});
16331
16590
  }, [view.layout, view.name, view.subject]);
@@ -16432,12 +16691,12 @@ function offerableFields(all, want) {
16432
16691
  });
16433
16692
  }
16434
16693
  function useStageField(tableId) {
16435
- const client = useRecordsClient30();
16694
+ const client = useRecordsClient31();
16436
16695
  const [stage, setStage] = useState46({
16437
16696
  asked: false,
16438
16697
  key: null
16439
16698
  });
16440
- useEffect35(() => {
16699
+ useEffect36(() => {
16441
16700
  let cancelled = false;
16442
16701
  setStage({ asked: false, key: null });
16443
16702
  void client.tableStageField({ table_id: tableId }).then((r) => {
@@ -16845,7 +17104,7 @@ function Card2({
16845
17104
  }
16846
17105
 
16847
17106
  // src/ArchivedView.tsx
16848
- import { useCallback as useCallback21, useEffect as useEffect36, useState as useState47 } from "react";
17107
+ import { useCallback as useCallback21, useEffect as useEffect37, useState as useState47 } from "react";
16849
17108
  import {
16850
17109
  ARCHIVE_LANES,
16851
17110
  ARCHIVE_LANE_LABEL,
@@ -16854,7 +17113,7 @@ import {
16854
17113
  archivedByLine,
16855
17114
  emptyArchiveLine
16856
17115
  } from "@ai-matrx/records";
16857
- import { useFields as useFields14, useRecordsClient as useRecordsClient31, useTable as useTable8 } from "@ai-matrx/records/react";
17116
+ import { useFields as useFields14, useRecordsClient as useRecordsClient32, useTable as useTable8 } from "@ai-matrx/records/react";
16858
17117
  import { Button as Button40, Skeleton as Skeleton8, cn as cn33 } from "@ai-matrx/design-system";
16859
17118
  import { jsx as jsx58, jsxs as jsxs52 } from "react/jsx-runtime";
16860
17119
  var ARCHIVE_MEANS = "Archiving never destroys anything. A record you remove from the grid waits here until somebody brings it back.";
@@ -16873,7 +17132,7 @@ function ArchivedView({
16873
17132
  onRestored,
16874
17133
  className
16875
17134
  }) {
16876
- const client = useRecordsClient31();
17135
+ const client = useRecordsClient32();
16877
17136
  const table = useTable8(tableId);
16878
17137
  const rights = useTableRights(table.data);
16879
17138
  const fields = useFields14(tableId);
@@ -16883,7 +17142,7 @@ function ArchivedView({
16883
17142
  const [error, setError] = useState47(null);
16884
17143
  const [restoring, setRestoring] = useState47(null);
16885
17144
  const [refusal2, setRefusal] = useState47(null);
16886
- useEffect36(() => {
17145
+ useEffect37(() => {
16887
17146
  if (laneFromHost) setLane(laneFromHost);
16888
17147
  }, [laneFromHost]);
16889
17148
  const read = useCallback21(async () => {
@@ -16898,7 +17157,7 @@ function ArchivedView({
16898
17157
  }
16899
17158
  setLoading(false);
16900
17159
  }, [client, tableId, lane, pageSize]);
16901
- useEffect36(() => {
17160
+ useEffect37(() => {
16902
17161
  void read();
16903
17162
  }, [read]);
16904
17163
  const pick = (next) => {
@@ -16980,14 +17239,14 @@ function ArchivedView({
16980
17239
  }
16981
17240
 
16982
17241
  // src/ArchivedDisclosure.tsx
16983
- import { useCallback as useCallback22, useEffect as useEffect37, useState as useState48 } from "react";
17242
+ import { useCallback as useCallback22, useEffect as useEffect38, useState as useState48 } from "react";
16984
17243
  import {
16985
17244
  emptyPortalArchiveLine,
16986
17245
  portalConfirmLine,
16987
17246
  portalTitleTypedBack
16988
17247
  } from "@ai-matrx/records";
16989
- import { useRecordsClient as useRecordsClient32 } from "@ai-matrx/records/react";
16990
- import { BasicInput as BasicInput13, Button as Button41, Skeleton as Skeleton9, cn as cn34 } from "@ai-matrx/design-system";
17248
+ import { useRecordsClient as useRecordsClient33 } from "@ai-matrx/records/react";
17249
+ import { BasicInput as BasicInput14, Button as Button41, Skeleton as Skeleton9, cn as cn34 } from "@ai-matrx/design-system";
16991
17250
  import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
16992
17251
  var ARCHIVED_NEVER_DESTROYED = "Archiving never destroys anything. What you put away waits here until somebody brings it back.";
16993
17252
  function ArchivedDisclosure({
@@ -17031,7 +17290,7 @@ function ArchivedPortals({
17031
17290
  defaultOpen,
17032
17291
  className
17033
17292
  }) {
17034
- const client = useRecordsClient32();
17293
+ const client = useRecordsClient33();
17035
17294
  const [rows, setRows] = useState48(null);
17036
17295
  const [error, setError] = useState48(null);
17037
17296
  const [confirming, setConfirming] = useState48(null);
@@ -17049,7 +17308,7 @@ function ArchivedPortals({
17049
17308
  setError(answered.error);
17050
17309
  }
17051
17310
  }, [client]);
17052
- useEffect37(() => {
17311
+ useEffect38(() => {
17053
17312
  void read();
17054
17313
  }, [read, refreshToken]);
17055
17314
  const restore = async (portal) => {
@@ -17132,7 +17391,7 @@ function ArchivedPortals({
17132
17391
  ] }),
17133
17392
  /* @__PURE__ */ jsxs53("div", { className: "flex flex-wrap items-center gap-1.5", children: [
17134
17393
  /* @__PURE__ */ jsx59(
17135
- BasicInput13,
17394
+ BasicInput14,
17136
17395
  {
17137
17396
  value: typed,
17138
17397
  placeholder: portal.title,
@@ -17165,14 +17424,14 @@ function ArchivedPortals({
17165
17424
  }
17166
17425
 
17167
17426
  // src/ViewBar.tsx
17168
- import { useCallback as useCallback24, useEffect as useEffect38, useState as useState49 } from "react";
17169
- import { useRecordsClient as useRecordsClient33 } from "@ai-matrx/records/react";
17427
+ import { useCallback as useCallback24, useEffect as useEffect39, useState as useState49 } from "react";
17428
+ import { useRecordsClient as useRecordsClient34 } from "@ai-matrx/records/react";
17170
17429
  import { Badge as Badge11, Button as Button42, Input as Input2, Popover as Popover5, PopoverContent as PopoverContent5, PopoverTrigger as PopoverTrigger5, Skeleton as Skeleton10, cn as cn35 } from "@ai-matrx/design-system";
17171
17430
 
17172
17431
  // src/seedOnce.ts
17173
- import { useCallback as useCallback23, useRef as useRef17 } from "react";
17432
+ import { useCallback as useCallback23, useRef as useRef18 } from "react";
17174
17433
  function useSeedGuard() {
17175
- const claimed = useRef17(/* @__PURE__ */ new Set());
17434
+ const claimed = useRef18(/* @__PURE__ */ new Set());
17176
17435
  return useCallback23((name) => {
17177
17436
  if (claimed.current.has(name)) return false;
17178
17437
  claimed.current.add(name);
@@ -17189,7 +17448,7 @@ function seedIsSatisfied(seed, views) {
17189
17448
  return seed.isDefault === true && views.some((v) => v.isDefault);
17190
17449
  }
17191
17450
  function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, className }) {
17192
- const client = useRecordsClient33();
17451
+ const client = useRecordsClient34();
17193
17452
  const claimSeed = useSeedGuard();
17194
17453
  const table = useTable9(tableId);
17195
17454
  const rights = useTableRights(table.data);
@@ -17241,10 +17500,10 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
17241
17500
  setViews(mine);
17242
17501
  onViews?.(mine);
17243
17502
  }, [client, readViews, tableId, seedKey]);
17244
- useEffect38(() => {
17503
+ useEffect39(() => {
17245
17504
  void load();
17246
17505
  }, [load]);
17247
- useEffect38(() => {
17506
+ useEffect39(() => {
17248
17507
  if (!views || views.length === 0) return;
17249
17508
  const chosen = views.find((v) => v.id === (activeViewId ?? active)) ?? defaultViewOf(views) ?? views[0];
17250
17509
  if (chosen.id !== active) setActive(chosen.id);
@@ -17348,7 +17607,7 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
17348
17607
 
17349
17608
  // src/ProposalRow.tsx
17350
17609
  import { useState as useState50 } from "react";
17351
- import { useRecordsClient as useRecordsClient34 } from "@ai-matrx/records/react";
17610
+ import { useRecordsClient as useRecordsClient35 } from "@ai-matrx/records/react";
17352
17611
  import { Badge as Badge12, Button as Button43, cn as cn36 } from "@ai-matrx/design-system";
17353
17612
  import { jsx as jsx61, jsxs as jsxs55 } from "react/jsx-runtime";
17354
17613
  var ACT_WORD = PROPOSED_CHANGE_ACT_LABEL;
@@ -17361,7 +17620,7 @@ function ProposalRow({
17361
17620
  onSettled,
17362
17621
  className
17363
17622
  }) {
17364
- const client = useRecordsClient34();
17623
+ const client = useRecordsClient35();
17365
17624
  const [settled, setSettled] = useState50(outcome ?? null);
17366
17625
  const [busy, setBusy] = useState50(false);
17367
17626
  const [confirming, setConfirming] = useState50(false);
@@ -17449,15 +17708,15 @@ function ProposalRow({
17449
17708
  }
17450
17709
 
17451
17710
  // src/ActionInbox.tsx
17452
- import { useCallback as useCallback26, useEffect as useEffect40, useMemo as useMemo33, useRef as useRef18, useState as useState52 } from "react";
17453
- import { useRecordsClient as useRecordsClient36 } from "@ai-matrx/records/react";
17711
+ import { useCallback as useCallback26, useEffect as useEffect41, useMemo as useMemo33, useRef as useRef19, useState as useState52 } from "react";
17712
+ import { useRecordsClient as useRecordsClient37 } from "@ai-matrx/records/react";
17454
17713
  import { Badge as Badge14, Button as Button45, Checkbox as Checkbox7, Skeleton as Skeleton12, cn as cn38 } from "@ai-matrx/design-system";
17455
17714
  import { toggleSelection as toggleSelection2 } from "@ai-matrx/design-system/data-table";
17456
17715
 
17457
17716
  // src/ChecklistRunner.tsx
17458
- import { useCallback as useCallback25, useEffect as useEffect39, useMemo as useMemo32, useState as useState51 } from "react";
17459
- import { useRecordsClient as useRecordsClient35, useTable as useTable10 } from "@ai-matrx/records/react";
17460
- import { Badge as Badge13, BasicInput as BasicInput14, BasicTextarea as BasicTextarea9, Button as Button44, Skeleton as Skeleton11, cn as cn37 } from "@ai-matrx/design-system";
17717
+ import { useCallback as useCallback25, useEffect as useEffect40, useMemo as useMemo32, useState as useState51 } from "react";
17718
+ import { useRecordsClient as useRecordsClient36, useTable as useTable10 } from "@ai-matrx/records/react";
17719
+ import { Badge as Badge13, BasicInput as BasicInput15, BasicTextarea as BasicTextarea9, Button as Button44, Skeleton as Skeleton11, cn as cn37 } from "@ai-matrx/design-system";
17461
17720
  import { Fragment as Fragment23, jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
17462
17721
  var DUE_WORD = DUE_STATE_LABEL;
17463
17722
  var REQUIRES_WORD = CHECKLIST_REQUIREMENT_LABEL;
@@ -17470,7 +17729,7 @@ function ChecklistRunner({
17470
17729
  offerToStart,
17471
17730
  className
17472
17731
  }) {
17473
- const client = useRecordsClient35();
17732
+ const client = useRecordsClient36();
17474
17733
  const table = useTable10(tableId ?? null);
17475
17734
  const rights = useTableRights(table.data);
17476
17735
  const [runs, setRuns] = useState51(null);
@@ -17503,10 +17762,10 @@ function ChecklistRunner({
17503
17762
  (held) => held && answered.data.some((r) => r.run_id === held) ? held : answered.data[0]?.run_id ?? null
17504
17763
  );
17505
17764
  }, [client, includeClosed, recordId, runId, tableId]);
17506
- useEffect39(() => {
17765
+ useEffect40(() => {
17507
17766
  void loadRuns();
17508
17767
  }, [loadRuns]);
17509
- useEffect39(() => {
17768
+ useEffect40(() => {
17510
17769
  if (runId) setActiveId(runId);
17511
17770
  }, [runId]);
17512
17771
  const loadSteps = useCallback25(async () => {
@@ -17523,10 +17782,10 @@ function ChecklistRunner({
17523
17782
  setError(null);
17524
17783
  setSteps(answered.data);
17525
17784
  }, [client, activeId]);
17526
- useEffect39(() => {
17785
+ useEffect40(() => {
17527
17786
  void loadSteps();
17528
17787
  }, [loadSteps]);
17529
- useEffect39(() => {
17788
+ useEffect40(() => {
17530
17789
  if (!mayStart || !tableId) return;
17531
17790
  let cancelled = false;
17532
17791
  void client.checklistTemplates({ about_table_id: tableId, limit: 50 }).then((answered) => {
@@ -17692,7 +17951,7 @@ function StepRow({
17692
17951
  }
17693
17952
  ) : null,
17694
17953
  step2.requires === "answer" ? /* @__PURE__ */ jsx62(
17695
- BasicInput14,
17954
+ BasicInput15,
17696
17955
  {
17697
17956
  "aria-label": step2.requires_label ?? REQUIRES_WORD.answer,
17698
17957
  placeholder: step2.requires_label ?? REQUIRES_WORD.answer,
@@ -17719,7 +17978,7 @@ function StepRow({
17719
17978
  );
17720
17979
  }
17721
17980
  function useMyChecklistSteps(limit = 25) {
17722
- const client = useRecordsClient35();
17981
+ const client = useRecordsClient36();
17723
17982
  const me = client.config.actor.user_id ?? null;
17724
17983
  const [steps, setSteps] = useState51([]);
17725
17984
  const [loading, setLoading] = useState51(true);
@@ -17752,7 +18011,7 @@ function useMyChecklistSteps(limit = 25) {
17752
18011
  setSteps(held);
17753
18012
  setLoading(false);
17754
18013
  }, [client, limit, me]);
17755
- useEffect39(() => {
18014
+ useEffect40(() => {
17756
18015
  void refresh();
17757
18016
  }, [refresh]);
17758
18017
  return { steps, loading, error, refresh };
@@ -17763,9 +18022,9 @@ function MyChecklistSteps({
17763
18022
  onSteps,
17764
18023
  actions
17765
18024
  }) {
17766
- const client = useRecordsClient35();
18025
+ const client = useRecordsClient36();
17767
18026
  const { steps: held, loading, error, refresh } = useMyChecklistSteps();
17768
- useEffect39(() => {
18027
+ useEffect40(() => {
17769
18028
  onSteps?.(held.map((s) => s.step_id));
17770
18029
  }, [held, onSteps]);
17771
18030
  const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
@@ -17811,7 +18070,7 @@ function MyChecklistSteps({
17811
18070
  ] });
17812
18071
  }
17813
18072
  function ChecklistsPanel({ tableId, onOpenRecord, className }) {
17814
- const client = useRecordsClient35();
18073
+ const client = useRecordsClient36();
17815
18074
  const table = useTable10(tableId);
17816
18075
  const rights = useTableRights(table.data);
17817
18076
  const [templates, setTemplates] = useState51(null);
@@ -17833,7 +18092,7 @@ function ChecklistsPanel({ tableId, onOpenRecord, className }) {
17833
18092
  if (!r.ok) setRuns([]);
17834
18093
  else setRuns(r.data);
17835
18094
  }, [client, tableId]);
17836
- useEffect39(() => {
18095
+ useEffect40(() => {
17837
18096
  void load();
17838
18097
  }, [load]);
17839
18098
  if (templates === null) return /* @__PURE__ */ jsx62(Skeleton11, { className: cn37("h-40 w-full", className) });
@@ -17972,14 +18231,14 @@ function ChecklistTemplateEditor({
17972
18231
  onDone,
17973
18232
  className
17974
18233
  }) {
17975
- const client = useRecordsClient35();
18234
+ const client = useRecordsClient36();
17976
18235
  const [name, setName] = useState51("");
17977
18236
  const [rows, setRows] = useState51([{ ...EMPTY_ROW }]);
17978
18237
  const [refusal2, setRefusal] = useState51(null);
17979
18238
  const [error, setError] = useState51(null);
17980
18239
  const [busy, setBusy] = useState51(false);
17981
18240
  const [loading, setLoading] = useState51(Boolean(templateId));
17982
- useEffect39(() => {
18241
+ useEffect40(() => {
17983
18242
  if (!templateId) return;
17984
18243
  let cancelled = false;
17985
18244
  void client.checklistTemplateShape({ template_id: templateId }).then((answered) => {
@@ -18016,7 +18275,7 @@ function ChecklistTemplateEditor({
18016
18275
  }),
18017
18276
  [aboutTableId, name, rows]
18018
18277
  );
18019
- useEffect39(() => {
18278
+ useEffect40(() => {
18020
18279
  if (spec.steps.length === 0 || spec.name.length === 0) {
18021
18280
  setRefusal(null);
18022
18281
  return;
@@ -18052,7 +18311,7 @@ function ChecklistTemplateEditor({
18052
18311
  /* @__PURE__ */ jsx62(Button44, { size: "sm", variant: "ghost", className: "ml-auto", onClick: () => onDone?.(), children: "Cancel" })
18053
18312
  ] }),
18054
18313
  /* @__PURE__ */ jsx62(
18055
- BasicInput14,
18314
+ BasicInput15,
18056
18315
  {
18057
18316
  "aria-label": "Checklist name",
18058
18317
  placeholder: "What is this checklist called?",
@@ -18066,7 +18325,7 @@ function ChecklistTemplateEditor({
18066
18325
  /* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-1.5", children: [
18067
18326
  /* @__PURE__ */ jsx62("span", { className: "w-4 text-right text-[11px] tabular-nums text-muted-foreground", children: index + 1 }),
18068
18327
  /* @__PURE__ */ jsx62(
18069
- BasicInput14,
18328
+ BasicInput15,
18070
18329
  {
18071
18330
  "aria-label": `Step ${index + 1}`,
18072
18331
  placeholder: "What happens in this step?",
@@ -18089,7 +18348,7 @@ function ChecklistTemplateEditor({
18089
18348
  ] }),
18090
18349
  /* @__PURE__ */ jsxs56("div", { className: "mt-1 flex flex-wrap items-center gap-1.5 pl-6", children: [
18091
18350
  /* @__PURE__ */ jsx62(
18092
- BasicInput14,
18351
+ BasicInput15,
18093
18352
  {
18094
18353
  "aria-label": `Step ${index + 1} role`,
18095
18354
  placeholder: "whose? (a role)",
@@ -18099,7 +18358,7 @@ function ChecklistTemplateEditor({
18099
18358
  }
18100
18359
  ),
18101
18360
  /* @__PURE__ */ jsx62(
18102
- BasicInput14,
18361
+ BasicInput15,
18103
18362
  {
18104
18363
  "aria-label": `Step ${index + 1} due days`,
18105
18364
  placeholder: "days in",
@@ -18110,7 +18369,7 @@ function ChecklistTemplateEditor({
18110
18369
  }
18111
18370
  ),
18112
18371
  /* @__PURE__ */ jsx62(
18113
- BasicInput14,
18372
+ BasicInput15,
18114
18373
  {
18115
18374
  "aria-label": `Step ${index + 1} waits for`,
18116
18375
  placeholder: "waits for (step numbers)",
@@ -18130,7 +18389,7 @@ function ChecklistTemplateEditor({
18130
18389
  }
18131
18390
  ),
18132
18391
  row.requires === "answer" || row.requires === "record_field" ? /* @__PURE__ */ jsx62(
18133
- BasicInput14,
18392
+ BasicInput15,
18134
18393
  {
18135
18394
  "aria-label": `Step ${index + 1} asks for which value`,
18136
18395
  placeholder: "which value?",
@@ -18263,7 +18522,7 @@ function ActionInbox({
18263
18522
  onOpenRecord,
18264
18523
  className
18265
18524
  }) {
18266
- const client = useRecordsClient36();
18525
+ const client = useRecordsClient37();
18267
18526
  const [showDecided, setShowDecided] = useState52(includeSettled);
18268
18527
  const [groupBy, setGroupBy] = useState52(defaultGroupBy);
18269
18528
  const [everyTable, setEveryTable] = useState52(false);
@@ -18272,9 +18531,9 @@ function ActionInbox({
18272
18531
  const [outcome, setOutcome] = useState52({});
18273
18532
  const [busy, setBusy] = useState52(null);
18274
18533
  const [cursor, setCursor] = useState52(0);
18275
- const listRef = useRef18(null);
18534
+ const listRef = useRef19(null);
18276
18535
  const [selected, setSelected] = useState52(/* @__PURE__ */ new Set());
18277
- const anchor = useRef18(null);
18536
+ const anchor = useRef19(null);
18278
18537
  const [deciding, setDeciding] = useState52(false);
18279
18538
  const [batchSaid, setBatchSaid] = useState52(null);
18280
18539
  const [view, setView] = useState52("inbox");
@@ -18298,7 +18557,7 @@ function ActionInbox({
18298
18557
  setError(null);
18299
18558
  setItems(result.data);
18300
18559
  }, [client, showDecided, view]);
18301
- useEffect40(() => {
18560
+ useEffect41(() => {
18302
18561
  void load();
18303
18562
  }, [load]);
18304
18563
  const narrowed = useMemo33(() => {
@@ -18313,10 +18572,10 @@ function ActionInbox({
18313
18572
  const groups = useMemo33(() => groupInbox(narrowed, groupBy), [narrowed, groupBy]);
18314
18573
  const shown3 = useMemo33(() => groups.flatMap((g) => g.items), [groups]);
18315
18574
  const elsewhere = (items?.length ?? 0) - narrowed.length;
18316
- useEffect40(() => {
18575
+ useEffect41(() => {
18317
18576
  if (cursor >= shown3.length) setCursor(Math.max(0, shown3.length - 1));
18318
18577
  }, [shown3.length, cursor]);
18319
- useEffect40(() => {
18578
+ useEffect41(() => {
18320
18579
  const el = listRef.current?.querySelector(`[data-row="${cursor}"]`);
18321
18580
  el?.scrollIntoView({ block: "nearest" });
18322
18581
  }, [cursor, shown3.length]);
@@ -18337,11 +18596,11 @@ function ActionInbox({
18337
18596
  [client, load]
18338
18597
  );
18339
18598
  const [held, setHeld] = useState52({});
18340
- const holds2 = useRef18(/* @__PURE__ */ new Map());
18341
- const lastHold = useRef18(null);
18342
- const holdSeq = useRef18(0);
18599
+ const holds2 = useRef19(/* @__PURE__ */ new Map());
18600
+ const lastHold = useRef19(null);
18601
+ const holdSeq = useRef19(0);
18343
18602
  const [, tick] = useState52(0);
18344
- useEffect40(() => {
18603
+ useEffect41(() => {
18345
18604
  if (Object.keys(held).length === 0) return;
18346
18605
  const t = setInterval(() => tick((n) => n + 1), 250);
18347
18606
  return () => clearInterval(t);
@@ -18386,7 +18645,7 @@ function ActionInbox({
18386
18645
  });
18387
18646
  setSaid({ text: entry.ids.length === 1 ? "Undone. It is waiting on you again, exactly as it was." : `Undone. All ${entry.ids.length} are waiting on you again, exactly as they were.`, undo: null });
18388
18647
  }, []);
18389
- useEffect40(() => {
18648
+ useEffect41(() => {
18390
18649
  const flush = () => {
18391
18650
  for (const entry of [...holds2.current.values()]) entry.commit();
18392
18651
  };
@@ -18396,8 +18655,8 @@ function ActionInbox({
18396
18655
  flush();
18397
18656
  };
18398
18657
  }, []);
18399
- const resumed = useRef18(false);
18400
- useEffect40(() => {
18658
+ const resumed = useRef19(false);
18659
+ useEffect41(() => {
18401
18660
  if (resumed.current || items === null || view !== "inbox") return;
18402
18661
  resumed.current = true;
18403
18662
  const kept = readHolds();
@@ -19000,17 +19259,17 @@ function ActionInbox({
19000
19259
  }
19001
19260
 
19002
19261
  // src/HistoryPanel.tsx
19003
- import { useCallback as useCallback27, useEffect as useEffect41, useRef as useRef19, useState as useState53 } from "react";
19262
+ import { useCallback as useCallback27, useEffect as useEffect42, useRef as useRef20, useState as useState53 } from "react";
19004
19263
  import {
19005
19264
  useFields as useFields15,
19006
19265
  useRecordChangeRevision,
19007
- useRecordsClient as useRecordsClient37,
19266
+ useRecordsClient as useRecordsClient38,
19008
19267
  useTable as useTable11
19009
19268
  } from "@ai-matrx/records/react";
19010
19269
  import { Badge as Badge15, Button as Button46, Skeleton as Skeleton13, cn as cn39 } from "@ai-matrx/design-system";
19011
19270
  import { jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
19012
19271
  function HistoryPanel({ tableId, recordId, onAskAboutField, className }) {
19013
- const client = useRecordsClient37();
19272
+ const client = useRecordsClient38();
19014
19273
  const table = useTable11(tableId);
19015
19274
  const fields = useFields15(tableId);
19016
19275
  const rights = useTableRights(table.data);
@@ -19019,7 +19278,7 @@ function HistoryPanel({ tableId, recordId, onAskAboutField, className }) {
19019
19278
  const [open, setOpen] = useState53(null);
19020
19279
  const [pending, setPending] = useState53({ phase: "idle" });
19021
19280
  const [said, setSaid] = useState53(null);
19022
- const listRef = useRef19(null);
19281
+ const listRef = useRef20(null);
19023
19282
  const changed = useRecordChangeRevision(recordId);
19024
19283
  const load = useCallback27(async () => {
19025
19284
  const answered = await client.recordHistory({ record_id: recordId });
@@ -19030,7 +19289,7 @@ function HistoryPanel({ tableId, recordId, onAskAboutField, className }) {
19030
19289
  setError(null);
19031
19290
  setEntries(answered.data);
19032
19291
  }, [client, recordId, changed]);
19033
- useEffect41(() => {
19292
+ useEffect42(() => {
19034
19293
  void load();
19035
19294
  }, [load]);
19036
19295
  if (error) return /* @__PURE__ */ jsx64(RefusalNotice, { error, className });
@@ -19311,16 +19570,16 @@ function say(value, field2) {
19311
19570
  }
19312
19571
 
19313
19572
  // src/CommentThread.tsx
19314
- import { useCallback as useCallback28, useEffect as useEffect42, useMemo as useMemo34, useRef as useRef20, useState as useState54 } from "react";
19573
+ import { useCallback as useCallback28, useEffect as useEffect43, useMemo as useMemo34, useRef as useRef21, useState as useState54 } from "react";
19315
19574
  import {
19316
19575
  useFields as useFields16,
19317
- useRecordsClient as useRecordsClient38,
19576
+ useRecordsClient as useRecordsClient39,
19318
19577
  useTable as useTable12
19319
19578
  } from "@ai-matrx/records/react";
19320
19579
  import { Badge as Badge16, Button as Button47, Skeleton as Skeleton14, Textarea, cn as cn40 } from "@ai-matrx/design-system";
19321
19580
  import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
19322
19581
  function CommentThread({ tableId, recordId, fieldKey, className }) {
19323
- const client = useRecordsClient38();
19582
+ const client = useRecordsClient39();
19324
19583
  const table = useTable12(tableId);
19325
19584
  const fields = useFields16(tableId);
19326
19585
  const host = useRecordsUi();
@@ -19334,7 +19593,7 @@ function CommentThread({ tableId, recordId, fieldKey, className }) {
19334
19593
  const [people, setPeople] = useState54([]);
19335
19594
  const [mentionQuery, setMentionQuery] = useState54(null);
19336
19595
  const [picked, setPicked] = useState54([]);
19337
- const box = useRef20(null);
19596
+ const box = useRef21(null);
19338
19597
  const load = useCallback28(async () => {
19339
19598
  const answered = await client.commentThread({ record_id: recordId, include_resolved: showResolved });
19340
19599
  if (!answered.ok) {
@@ -19348,10 +19607,10 @@ function CommentThread({ tableId, recordId, fieldKey, className }) {
19348
19607
  mayResolve: answered.data.may_resolve
19349
19608
  });
19350
19609
  }, [client, recordId, showResolved]);
19351
- useEffect42(() => {
19610
+ useEffect43(() => {
19352
19611
  void load();
19353
19612
  }, [load]);
19354
- useEffect42(() => {
19613
+ useEffect43(() => {
19355
19614
  let alive = true;
19356
19615
  if (!host.members) return;
19357
19616
  void host.members().then((roster) => {
@@ -19554,10 +19813,10 @@ function Line({
19554
19813
  }
19555
19814
 
19556
19815
  // src/FieldHistoryPanel.tsx
19557
- import { useCallback as useCallback29, useEffect as useEffect43, useState as useState55 } from "react";
19816
+ import { useCallback as useCallback29, useEffect as useEffect44, useState as useState55 } from "react";
19558
19817
  import {
19559
19818
  useFields as useFields17,
19560
- useRecordsClient as useRecordsClient39,
19819
+ useRecordsClient as useRecordsClient40,
19561
19820
  useTable as useTable13
19562
19821
  } from "@ai-matrx/records/react";
19563
19822
  import { Badge as Badge17, Button as Button48, Skeleton as Skeleton15, cn as cn41 } from "@ai-matrx/design-system";
@@ -19570,7 +19829,7 @@ function FieldHistoryPanel({
19570
19829
  onOpenRecord,
19571
19830
  className
19572
19831
  }) {
19573
- const client = useRecordsClient39();
19832
+ const client = useRecordsClient40();
19574
19833
  const table = useTable13(tableId);
19575
19834
  const fields = useFields17(tableId);
19576
19835
  const rights = useTableRights(table.data);
@@ -19589,7 +19848,7 @@ function FieldHistoryPanel({
19589
19848
  setError(null);
19590
19849
  setRows(answered.data);
19591
19850
  }, [client, tableId, fieldKey, recordId]);
19592
- useEffect43(() => {
19851
+ useEffect44(() => {
19593
19852
  void load();
19594
19853
  }, [load]);
19595
19854
  const label = (fields.data ?? []).find((f) => f.key === fieldKey)?.label || humanize(fieldKey);
@@ -19801,13 +20060,13 @@ function submissionStamp(args) {
19801
20060
  }
19802
20061
 
19803
20062
  // src/PortalBuilder.tsx
19804
- import { useCallback as useCallback30, useEffect as useEffect44, useMemo as useMemo35, useState as useState56 } from "react";
19805
- import { useRecordsClient as useRecordsClient40, useTables as useTables3 } from "@ai-matrx/records/react";
19806
- import { BasicInput as BasicInput15, Button as Button49, Checkbox as Checkbox8, Label as Label12, Separator as Separator9, Skeleton as Skeleton16, cn as cn42 } from "@ai-matrx/design-system";
20063
+ import { useCallback as useCallback30, useEffect as useEffect45, useMemo as useMemo35, useState as useState56 } from "react";
20064
+ import { useRecordsClient as useRecordsClient41, useTables as useTables3 } from "@ai-matrx/records/react";
20065
+ import { BasicInput as BasicInput16, Button as Button49, Checkbox as Checkbox8, Label as Label12, Separator as Separator9, Skeleton as Skeleton16, cn as cn42 } from "@ai-matrx/design-system";
19807
20066
  import { Fragment as Fragment26, jsx as jsx67, jsxs as jsxs61 } from "react/jsx-runtime";
19808
20067
  var RESTATING_REPLACES = "Saving replaces what this portal shows: a table you untick stops being visible to every client the moment you save. Who is invited is not touched.";
19809
20068
  function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
19810
- const client = useRecordsClient40();
20069
+ const client = useRecordsClient41();
19811
20070
  const tables = useTables3();
19812
20071
  const [title, setTitle] = useState56("");
19813
20072
  const [clientTableId, setClientTableId] = useState56(null);
@@ -19834,7 +20093,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
19834
20093
  },
19835
20094
  [client, fieldsByTable]
19836
20095
  );
19837
- useEffect44(() => {
20096
+ useEffect45(() => {
19838
20097
  if (!portalId) return;
19839
20098
  void (async () => {
19840
20099
  const answered = await client.portalCard({ portal_id: portalId });
@@ -19848,7 +20107,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
19848
20107
  setClientTableId(answered.data.client_table_id);
19849
20108
  })();
19850
20109
  }, [client, portalId]);
19851
- useEffect44(() => {
20110
+ useEffect45(() => {
19852
20111
  if (!tableId) return;
19853
20112
  setExposures(
19854
20113
  (prev) => prev[tableId] ? prev : {
@@ -19931,7 +20190,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
19931
20190
  /* @__PURE__ */ jsxs61("label", { className: "flex flex-col gap-1", children: [
19932
20191
  /* @__PURE__ */ jsx67(Label12, { className: "text-xs font-medium", children: "What your clients see it called" }),
19933
20192
  /* @__PURE__ */ jsx67(
19934
- BasicInput15,
20193
+ BasicInput16,
19935
20194
  {
19936
20195
  value: title,
19937
20196
  placeholder: "Your jobs and invoices",
@@ -20059,7 +20318,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
20059
20318
  /* @__PURE__ */ jsxs61("label", { className: "flex flex-col gap-1", children: [
20060
20319
  /* @__PURE__ */ jsx67("span", { className: "text-xs text-muted-foreground", children: "Their email" }),
20061
20320
  /* @__PURE__ */ jsx67(
20062
- BasicInput15,
20321
+ BasicInput16,
20063
20322
  {
20064
20323
  className: "h-8 w-full @md:w-56",
20065
20324
  value: inviteEmail,
@@ -20070,7 +20329,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
20070
20329
  /* @__PURE__ */ jsxs61("label", { className: "flex flex-col gap-1", children: [
20071
20330
  /* @__PURE__ */ jsx67("span", { className: "text-xs text-muted-foreground", children: "Their record in the client table" }),
20072
20331
  /* @__PURE__ */ jsx67(
20073
- BasicInput15,
20332
+ BasicInput16,
20074
20333
  {
20075
20334
  className: "h-8 w-full @md:w-80",
20076
20335
  placeholder: "the record id",
@@ -20096,15 +20355,15 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
20096
20355
  }
20097
20356
 
20098
20357
  // src/PortalsPanel.tsx
20099
- import { useCallback as useCallback31, useEffect as useEffect46, useMemo as useMemo37, useState as useState58 } from "react";
20100
- import { useRecordsClient as useRecordsClient42 } from "@ai-matrx/records/react";
20358
+ import { useCallback as useCallback31, useEffect as useEffect47, useMemo as useMemo37, useState as useState58 } from "react";
20359
+ import { useRecordsClient as useRecordsClient43 } from "@ai-matrx/records/react";
20101
20360
  import {
20102
20361
  portalArchiveConsequence,
20103
20362
  portalConfirmLine as portalConfirmLine2,
20104
20363
  portalPath,
20105
20364
  portalTitleTypedBack as portalTitleTypedBack2
20106
20365
  } from "@ai-matrx/records";
20107
- import { Badge as Badge18, BasicInput as BasicInput17, Button as Button52, Separator as Separator10, Skeleton as Skeleton17, cn as cn45 } from "@ai-matrx/design-system";
20366
+ import { Badge as Badge18, BasicInput as BasicInput18, Button as Button52, Separator as Separator10, Skeleton as Skeleton17, cn as cn45 } from "@ai-matrx/design-system";
20108
20367
 
20109
20368
  // src/BuildOrAsk.tsx
20110
20369
  import { Button as Button50, cn as cn43 } from "@ai-matrx/design-system";
@@ -20136,9 +20395,9 @@ function BuildOrAsk({
20136
20395
  }
20137
20396
 
20138
20397
  // src/PortalLookEditor.tsx
20139
- import { useEffect as useEffect45, useMemo as useMemo36, useState as useState57 } from "react";
20140
- import { useRecordsClient as useRecordsClient41 } from "@ai-matrx/records/react";
20141
- import { BasicInput as BasicInput16, Button as Button51, cn as cn44 } from "@ai-matrx/design-system";
20398
+ import { useEffect as useEffect46, useMemo as useMemo36, useState as useState57 } from "react";
20399
+ import { useRecordsClient as useRecordsClient42 } from "@ai-matrx/records/react";
20400
+ import { BasicInput as BasicInput17, Button as Button51, cn as cn44 } from "@ai-matrx/design-system";
20142
20401
  import { STYLE_COLOR_LABELS as STYLE_COLOR_LABELS3, SWATCH_CLASS as SWATCH_CLASS2 } from "@ai-matrx/design-system/data-table";
20143
20402
  import { jsx as jsx69, jsxs as jsxs63 } from "react/jsx-runtime";
20144
20403
  function candidateRows(card, available) {
@@ -20165,7 +20424,7 @@ function candidateRows(card, available) {
20165
20424
  return rows;
20166
20425
  }
20167
20426
  function PortalLookEditor({ card, onSaved, className }) {
20168
- const client = useRecordsClient41();
20427
+ const client = useRecordsClient42();
20169
20428
  const stored = card.config?.style ?? {};
20170
20429
  const [name, setName] = useState57(stored.display_name ?? "");
20171
20430
  const [welcome, setWelcome] = useState57(stored.welcome ?? "");
@@ -20178,7 +20437,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20178
20437
  const [said, setSaid] = useState57(null);
20179
20438
  const [formsError, setFormsError] = useState57(null);
20180
20439
  const [formsUnread, setFormsUnread] = useState57(false);
20181
- useEffect45(() => {
20440
+ useEffect46(() => {
20182
20441
  let cancelled = false;
20183
20442
  void (async () => {
20184
20443
  try {
@@ -20255,7 +20514,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20255
20514
  /* @__PURE__ */ jsxs63("label", { className: "flex flex-col gap-1 text-xs", children: [
20256
20515
  /* @__PURE__ */ jsx69("span", { children: "Business name clients see" }),
20257
20516
  /* @__PURE__ */ jsx69(
20258
- BasicInput16,
20517
+ BasicInput17,
20259
20518
  {
20260
20519
  value: name,
20261
20520
  placeholder: orgName ?? card.style.display_name,
@@ -20272,7 +20531,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20272
20531
  /* @__PURE__ */ jsxs63("label", { className: "flex flex-col gap-1 text-xs", children: [
20273
20532
  /* @__PURE__ */ jsx69("span", { children: "Welcome line" }),
20274
20533
  /* @__PURE__ */ jsx69(
20275
- BasicInput16,
20534
+ BasicInput17,
20276
20535
  {
20277
20536
  value: welcome,
20278
20537
  placeholder: "Your service calls and invoices, in one place.",
@@ -20343,7 +20602,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20343
20602
  // never pushed past the edge (measured at 390: it was clipped).
20344
20603
  /* @__PURE__ */ jsxs63("div", { className: "flex flex-wrap items-center gap-1.5", children: [
20345
20604
  /* @__PURE__ */ jsx69(
20346
- BasicInput16,
20605
+ BasicInput17,
20347
20606
  {
20348
20607
  className: "min-w-0 flex-1 basis-32",
20349
20608
  value: link.label,
@@ -20353,7 +20612,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20353
20612
  }
20354
20613
  ),
20355
20614
  /* @__PURE__ */ jsx69(
20356
- BasicInput16,
20615
+ BasicInput17,
20357
20616
  {
20358
20617
  className: "min-w-0 flex-1 basis-40",
20359
20618
  value: link.url,
@@ -20396,7 +20655,7 @@ function PortalLookEditor({ card, onSaved, className }) {
20396
20655
  ] }),
20397
20656
  /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-1.5 pl-5", children: [
20398
20657
  /* @__PURE__ */ jsx69(
20399
- BasicInput16,
20658
+ BasicInput17,
20400
20659
  {
20401
20660
  className: "h-7 min-w-0 flex-1",
20402
20661
  value: f.label,
@@ -20460,13 +20719,13 @@ function stateWords(person) {
20460
20719
  }
20461
20720
  var PORTAL_SUGGESTION = "Let each of my customers sign in and see their own jobs and invoices, and nothing else.";
20462
20721
  function PortalsPanel({ tableId, activePortalId, className }) {
20463
- const client = useRecordsClient42();
20722
+ const client = useRecordsClient43();
20464
20723
  const host = useRecordsUi();
20465
20724
  const [portals, setPortals] = useState58(null);
20466
20725
  const [exposures, setExposures] = useState58([]);
20467
20726
  const [listError, setListError] = useState58(null);
20468
20727
  const [openId, setOpenId] = useState58(activePortalId ?? null);
20469
- useEffect46(() => {
20728
+ useEffect47(() => {
20470
20729
  if (activePortalId) setOpenId(activePortalId);
20471
20730
  }, [activePortalId]);
20472
20731
  const [building, setBuilding] = useState58(false);
@@ -20484,7 +20743,7 @@ function PortalsPanel({ tableId, activePortalId, className }) {
20484
20743
  setPortals(answered.data);
20485
20744
  setExposures(mapped.ok ? mapped.data : []);
20486
20745
  }, [client]);
20487
- useEffect46(() => {
20746
+ useEffect47(() => {
20488
20747
  void load();
20489
20748
  }, [load]);
20490
20749
  if (portals === null) return /* @__PURE__ */ jsx70(Skeleton17, { className: cn45("h-32 w-full", className) });
@@ -20640,7 +20899,7 @@ function ArchivePortalControl({
20640
20899
  portal,
20641
20900
  onArchived
20642
20901
  }) {
20643
- const client = useRecordsClient42();
20902
+ const client = useRecordsClient43();
20644
20903
  const [asking, setAsking] = useState58(false);
20645
20904
  const [typed, setTyped] = useState58("");
20646
20905
  const [busy, setBusy] = useState58(false);
@@ -20686,7 +20945,7 @@ function ArchivePortalControl({
20686
20945
  /* @__PURE__ */ jsx70("p", { className: "text-xs text-muted-foreground", children: portalConfirmLine2(portal.title) }),
20687
20946
  /* @__PURE__ */ jsxs64("div", { className: "flex flex-wrap items-center gap-1.5", children: [
20688
20947
  /* @__PURE__ */ jsx70(
20689
- BasicInput17,
20948
+ BasicInput18,
20690
20949
  {
20691
20950
  value: typed,
20692
20951
  placeholder: portal.title,
@@ -20747,7 +21006,7 @@ function PortalDetail({
20747
21006
  origin,
20748
21007
  onChanged
20749
21008
  }) {
20750
- const client = useRecordsClient42();
21009
+ const client = useRecordsClient43();
20751
21010
  const [card, setCard] = useState58(null);
20752
21011
  const [error, setError] = useState58(null);
20753
21012
  const load = useCallback31(async () => {
@@ -20760,7 +21019,7 @@ function PortalDetail({
20760
21019
  setError(null);
20761
21020
  setCard(answered.data);
20762
21021
  }, [client, portalId]);
20763
- useEffect46(() => {
21022
+ useEffect47(() => {
20764
21023
  void load();
20765
21024
  }, [load]);
20766
21025
  const revoke = useCallback31(
@@ -20968,7 +21227,7 @@ function Preview({
20968
21227
  const [which, setWhich] = useState58(first?.table_id ?? null);
20969
21228
  const [rows, setRows] = useState58(null);
20970
21229
  const [error, setError] = useState58(null);
20971
- useEffect46(() => {
21230
+ useEffect47(() => {
20972
21231
  if (!which) return;
20973
21232
  let cancelled = false;
20974
21233
  setRows(null);
@@ -21005,7 +21264,7 @@ function Preview({
21005
21264
  ] });
21006
21265
  }
21007
21266
  function Invite({ card, onInvited }) {
21008
- const client = useRecordsClient42();
21267
+ const client = useRecordsClient43();
21009
21268
  const [rows, setRows] = useState58(null);
21010
21269
  const [clientTable, setClientTable] = useState58(null);
21011
21270
  const [search, setSearch] = useState58("");
@@ -21014,7 +21273,7 @@ function Invite({ card, onInvited }) {
21014
21273
  const [busy, setBusy] = useState58(false);
21015
21274
  const [said, setSaid] = useState58(null);
21016
21275
  const [error, setError] = useState58(null);
21017
- useEffect46(() => {
21276
+ useEffect47(() => {
21018
21277
  let cancelled = false;
21019
21278
  void client.list({ table_id: card.client_table_id, limit: 200 }).then((answered) => {
21020
21279
  if (cancelled) return;
@@ -21065,7 +21324,7 @@ function Invite({ card, onInvited }) {
21065
21324
  said ? /* @__PURE__ */ jsx70("p", { className: "text-xs text-muted-foreground", children: said }) : null,
21066
21325
  rows === null ? /* @__PURE__ */ jsx70(Skeleton17, { className: "h-9 w-full" }) : /* @__PURE__ */ jsxs64(Fragment27, { children: [
21067
21326
  /* @__PURE__ */ jsx70(
21068
- BasicInput17,
21327
+ BasicInput18,
21069
21328
  {
21070
21329
  className: "text-base",
21071
21330
  placeholder: "Find the client\u2026",
@@ -21093,7 +21352,7 @@ function Invite({ card, onInvited }) {
21093
21352
  ) }, option.id))
21094
21353
  ] }),
21095
21354
  /* @__PURE__ */ jsx70(
21096
- BasicInput17,
21355
+ BasicInput18,
21097
21356
  {
21098
21357
  className: "text-base",
21099
21358
  type: "email",
@@ -21116,9 +21375,9 @@ function Invite({ card, onInvited }) {
21116
21375
  }
21117
21376
 
21118
21377
  // src/DigestScheduler.tsx
21119
- import { useCallback as useCallback32, useEffect as useEffect47, useMemo as useMemo38, useState as useState59 } from "react";
21120
- import { useRecordsClient as useRecordsClient43 } from "@ai-matrx/records/react";
21121
- import { BasicInput as BasicInput18, Button as Button53, Checkbox as Checkbox9, Label as Label13, Separator as Separator11, Skeleton as Skeleton18, cn as cn46 } from "@ai-matrx/design-system";
21378
+ import { useCallback as useCallback32, useEffect as useEffect48, useMemo as useMemo38, useState as useState59 } from "react";
21379
+ import { useRecordsClient as useRecordsClient44 } from "@ai-matrx/records/react";
21380
+ import { BasicInput as BasicInput19, Button as Button53, Checkbox as Checkbox9, Label as Label13, Separator as Separator11, Skeleton as Skeleton18, cn as cn46 } from "@ai-matrx/design-system";
21122
21381
  import { Fragment as Fragment28, jsx as jsx71, jsxs as jsxs65 } from "react/jsx-runtime";
21123
21382
  var WEEKDAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
21124
21383
  var CADENCE_WORDS = {
@@ -21141,7 +21400,7 @@ function DigestScheduler({
21141
21400
  onClose,
21142
21401
  className
21143
21402
  }) {
21144
- const client = useRecordsClient43();
21403
+ const client = useRecordsClient44();
21145
21404
  const host = useRecordsUi();
21146
21405
  const [views, setViews] = useState59(null);
21147
21406
  const [cadences, setCadences] = useState59([]);
@@ -21180,7 +21439,7 @@ function DigestScheduler({
21180
21439
  setMembers([]);
21181
21440
  }
21182
21441
  }, [client, tableId, host]);
21183
- useEffect47(() => {
21442
+ useEffect48(() => {
21184
21443
  void load();
21185
21444
  }, [load]);
21186
21445
  const schedule = useMemo38(() => {
@@ -21258,7 +21517,7 @@ function DigestScheduler({
21258
21517
  /* @__PURE__ */ jsxs65("label", { className: "flex flex-col gap-1", children: [
21259
21518
  /* @__PURE__ */ jsx71(Label13, { className: "text-xs font-medium", children: "What to call it" }),
21260
21519
  /* @__PURE__ */ jsx71(
21261
- BasicInput18,
21520
+ BasicInput19,
21262
21521
  {
21263
21522
  value: name,
21264
21523
  placeholder: "Monday donor summary",
@@ -21309,7 +21568,7 @@ function DigestScheduler({
21309
21568
  ] }) : null,
21310
21569
  cadence === "weekly" || cadence === "daily" ? /* @__PURE__ */ jsxs65("label", { className: "flex flex-col gap-1", children: [
21311
21570
  /* @__PURE__ */ jsx71(Label13, { className: "text-xs font-medium", children: "At" }),
21312
- /* @__PURE__ */ jsx71(BasicInput18, { type: "time", value: time, onChange: (e) => setTime(e.target.value) })
21571
+ /* @__PURE__ */ jsx71(BasicInput19, { type: "time", value: time, onChange: (e) => setTime(e.target.value) })
21313
21572
  ] }) : null,
21314
21573
  cadence !== "instant" ? /* @__PURE__ */ jsxs65(
21315
21574
  "p",
@@ -21360,7 +21619,7 @@ function DigestScheduler({
21360
21619
  ] }),
21361
21620
  quiet ? /* @__PURE__ */ jsxs65("div", { className: "flex items-center gap-2", children: [
21362
21621
  /* @__PURE__ */ jsx71(
21363
- BasicInput18,
21622
+ BasicInput19,
21364
21623
  {
21365
21624
  type: "time",
21366
21625
  className: "h-8 w-28",
@@ -21370,7 +21629,7 @@ function DigestScheduler({
21370
21629
  ),
21371
21630
  /* @__PURE__ */ jsx71("span", { className: "text-xs text-muted-foreground", children: "and" }),
21372
21631
  /* @__PURE__ */ jsx71(
21373
- BasicInput18,
21632
+ BasicInput19,
21374
21633
  {
21375
21634
  type: "time",
21376
21635
  className: "h-8 w-28",
@@ -21432,14 +21691,14 @@ function DigestScheduler({
21432
21691
  }
21433
21692
 
21434
21693
  // src/SubscriptionsPanel.tsx
21435
- import { useCallback as useCallback34, useEffect as useEffect49, useState as useState61 } from "react";
21436
- import { useRecordsClient as useRecordsClient45 } from "@ai-matrx/records/react";
21694
+ import { useCallback as useCallback34, useEffect as useEffect50, useState as useState61 } from "react";
21695
+ import { useRecordsClient as useRecordsClient46 } from "@ai-matrx/records/react";
21437
21696
  import { Badge as Badge19, Button as Button55, Skeleton as Skeleton20, Switch as Switch2, cn as cn48 } from "@ai-matrx/design-system";
21438
21697
 
21439
21698
  // src/WebhooksPanel.tsx
21440
- import { useCallback as useCallback33, useEffect as useEffect48, useState as useState60 } from "react";
21441
- import { useRecordsClient as useRecordsClient44, useTable as useTable14 } from "@ai-matrx/records/react";
21442
- import { BasicInput as BasicInput19, Button as Button54, Checkbox as Checkbox10, ConfirmDialog as ConfirmDialog6, Label as Label14, Skeleton as Skeleton19, cn as cn47 } from "@ai-matrx/design-system";
21699
+ import { useCallback as useCallback33, useEffect as useEffect49, useState as useState60 } from "react";
21700
+ import { useRecordsClient as useRecordsClient45, useTable as useTable14 } from "@ai-matrx/records/react";
21701
+ import { BasicInput as BasicInput20, Button as Button54, Checkbox as Checkbox10, ConfirmDialog as ConfirmDialog6, Label as Label14, Skeleton as Skeleton19, cn as cn47 } from "@ai-matrx/design-system";
21443
21702
  import { jsx as jsx72, jsxs as jsxs66 } from "react/jsx-runtime";
21444
21703
  var WEBHOOK_EVENT_LABEL = {
21445
21704
  "record.created": "A record is added",
@@ -21458,7 +21717,7 @@ function health(hook) {
21458
21717
  return "Nothing has changed since it was set up, so nothing has been sent yet.";
21459
21718
  }
21460
21719
  function WebhooksPanel({ tableId, className }) {
21461
- const client = useRecordsClient44();
21720
+ const client = useRecordsClient45();
21462
21721
  const table = useTable14(tableId);
21463
21722
  const rights = useTableRights(table.data);
21464
21723
  const [hooks, setHooks] = useState60(null);
@@ -21480,7 +21739,7 @@ function WebhooksPanel({ tableId, className }) {
21480
21739
  setError(null);
21481
21740
  setHooks(answered.data ?? []);
21482
21741
  }, [client, tableId]);
21483
- useEffect48(() => {
21742
+ useEffect49(() => {
21484
21743
  void load();
21485
21744
  }, [load]);
21486
21745
  const declare2 = async () => {
@@ -21529,7 +21788,7 @@ function WebhooksPanel({ tableId, className }) {
21529
21788
  /* @__PURE__ */ jsxs66("label", { className: "flex flex-col gap-1", children: [
21530
21789
  /* @__PURE__ */ jsx72(Label14, { className: "text-xs", children: "Where to send it (an https address)" }),
21531
21790
  /* @__PURE__ */ jsx72(
21532
- BasicInput19,
21791
+ BasicInput20,
21533
21792
  {
21534
21793
  value: url,
21535
21794
  "aria-label": "Webhook address",
@@ -21541,7 +21800,7 @@ function WebhooksPanel({ tableId, className }) {
21541
21800
  /* @__PURE__ */ jsxs66("label", { className: "flex flex-col gap-1", children: [
21542
21801
  /* @__PURE__ */ jsx72(Label14, { className: "text-xs", children: "What it is for" }),
21543
21802
  /* @__PURE__ */ jsx72(
21544
- BasicInput19,
21803
+ BasicInput20,
21545
21804
  {
21546
21805
  value: description,
21547
21806
  "aria-label": "What this webhook is for",
@@ -21638,7 +21897,7 @@ function nextSummaryAt(subscription, now) {
21638
21897
  var CHANNEL_WORDS2 = SUBSCRIPTION_CHANNEL_LABEL;
21639
21898
  var DIGEST_SUGGESTION = "Email me a summary of this every Monday at 8 in the morning.";
21640
21899
  function SubscriptionsPanel({ tableId, activeRuleId, className }) {
21641
- const client = useRecordsClient45();
21900
+ const client = useRecordsClient46();
21642
21901
  const [rows, setRows] = useState61(null);
21643
21902
  const [error, setError] = useState61(null);
21644
21903
  const [busy, setBusy] = useState61(null);
@@ -21655,7 +21914,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
21655
21914
  setError(null);
21656
21915
  setRows(answered.data);
21657
21916
  }, [client, tableId]);
21658
- useEffect49(() => {
21917
+ useEffect50(() => {
21659
21918
  void load();
21660
21919
  }, [load]);
21661
21920
  const flip = useCallback34(
@@ -21831,17 +22090,17 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
21831
22090
  }
21832
22091
 
21833
22092
  // src/FormBuilder.tsx
21834
- import { useCallback as useCallback37, useEffect as useEffect53, useMemo as useMemo40, useState as useState65 } from "react";
21835
- import { useFields as useFields19, useRecordsClient as useRecordsClient48, useTable as useTable16 } from "@ai-matrx/records/react";
22093
+ import { useCallback as useCallback37, useEffect as useEffect54, useMemo as useMemo40, useState as useState65 } from "react";
22094
+ import { useFields as useFields19, useRecordsClient as useRecordsClient49, useTable as useTable16 } from "@ai-matrx/records/react";
21836
22095
 
21837
22096
  // src/publish-gate.ts
21838
- import { useEffect as useEffect50, useState as useState62 } from "react";
21839
- import { useRecordsClient as useRecordsClient46 } from "@ai-matrx/records/react";
22097
+ import { useEffect as useEffect51, useState as useState62 } from "react";
22098
+ import { useRecordsClient as useRecordsClient47 } from "@ai-matrx/records/react";
21840
22099
  var PUBLISH_NEEDS_THE_STORE_ON = "This organization has its record store switched off, so publishing would hand you a link that opens nothing. An owner or an administrator turns it on under Database settings, on the unified data screen \u2014 everything you have already built here is kept and starts working the moment they do.";
21841
22100
  function usePublishGate() {
21842
- const client = useRecordsClient46();
22101
+ const client = useRecordsClient47();
21843
22102
  const [storeOpen, setStoreOpen] = useState62(null);
21844
- useEffect50(() => {
22103
+ useEffect51(() => {
21845
22104
  let alive = true;
21846
22105
  void (async () => {
21847
22106
  const answered = await client.storeIsOpen();
@@ -21862,7 +22121,7 @@ function usePublishGate() {
21862
22121
  // src/FormBuilder.tsx
21863
22122
  import { publicFormPath } from "@ai-matrx/records";
21864
22123
  import {
21865
- BasicInput as BasicInput20,
22124
+ BasicInput as BasicInput21,
21866
22125
  BasicTextarea as BasicTextarea10,
21867
22126
  Button as Button58,
21868
22127
  Checkbox as Checkbox11,
@@ -21872,7 +22131,7 @@ import {
21872
22131
  } from "@ai-matrx/design-system";
21873
22132
 
21874
22133
  // src/FormRunner.tsx
21875
- import { useCallback as useCallback35, useEffect as useEffect51, useMemo as useMemo39, useRef as useRef21, useState as useState63 } from "react";
22134
+ import { useCallback as useCallback35, useEffect as useEffect52, useMemo as useMemo39, useRef as useRef22, useState as useState63 } from "react";
21876
22135
  import { useFields as useFields18, useOptionalRecordsClient as useOptionalRecordsClient6 } from "@ai-matrx/records/react";
21877
22136
  import { Button as Button56, Progress, Skeleton as Skeleton21, cn as cn49 } from "@ai-matrx/design-system";
21878
22137
  import { Fragment as Fragment29, jsx as jsx74, jsxs as jsxs68 } from "react/jsx-runtime";
@@ -21972,8 +22231,8 @@ function FormStage({
21972
22231
  const [writing, setWriting] = useState63(false);
21973
22232
  const [done, setDone] = useState63(null);
21974
22233
  const [hidden, setHidden] = useState63({});
21975
- const decoy = useRef21("");
21976
- const stage = useRef21(null);
22234
+ const decoy = useRef22("");
22235
+ const stage = useRef22(null);
21977
22236
  const questions = useMemo39(() => {
21978
22237
  const byKey = new Map((fields ?? []).map((f) => [f.key, f]));
21979
22238
  return (form.questions ?? []).map((q) => {
@@ -21988,7 +22247,7 @@ function FormStage({
21988
22247
  };
21989
22248
  });
21990
22249
  }, [fields, form.questions]);
21991
- useEffect51(() => {
22250
+ useEffect52(() => {
21992
22251
  if (!whichAsked) return;
21993
22252
  if (!questions.some((q) => q.showIf)) return;
21994
22253
  let cancelled = false;
@@ -22031,19 +22290,19 @@ function FormStage({
22031
22290
  };
22032
22291
  }, [whichAsked, questions, answers]);
22033
22292
  const live = questions.filter((q) => !hidden[q.key]);
22034
- const told = useRef21(answers);
22035
- useEffect51(() => {
22293
+ const told = useRef22(answers);
22294
+ useEffect52(() => {
22036
22295
  if (told.current === answers) return;
22037
22296
  told.current = answers;
22038
22297
  onAnswersChange?.(answers);
22039
22298
  }, [answers, onAnswersChange]);
22040
- const resumeAt = useRef21(
22299
+ const resumeAt = useRef22(
22041
22300
  resumed && initialAnswers && Object.keys(initialAnswers).length > 0 ? questions.find((q) => {
22042
22301
  const v = initialAnswers[q.key];
22043
22302
  return v === void 0 || v === null || v === "";
22044
22303
  })?.key ?? null : null
22045
22304
  );
22046
- useEffect51(() => {
22305
+ useEffect52(() => {
22047
22306
  const key = resumeAt.current;
22048
22307
  if (!key) return;
22049
22308
  const i = live.findIndex((q) => q.key === key);
@@ -22109,7 +22368,7 @@ function FormStage({
22109
22368
  if (event.shiftKey) retreat();
22110
22369
  else advance();
22111
22370
  }
22112
- useEffect51(() => {
22371
+ useEffect52(() => {
22113
22372
  const input = stage.current?.querySelector(
22114
22373
  "input:not([tabindex='-1']), textarea, select, [role='combobox']"
22115
22374
  );
@@ -22220,7 +22479,7 @@ function ThankYou({ form, done, className }) {
22220
22479
  const host = useRecordsUi();
22221
22480
  const redirect = form.thankYou?.redirectUrl?.trim() || null;
22222
22481
  const going = redirect !== null && done !== "preview";
22223
- useEffect51(() => {
22482
+ useEffect52(() => {
22224
22483
  if (!going || !redirect) return;
22225
22484
  const timer = window.setTimeout(() => window.location.assign(redirect), REDIRECT_AFTER_MS);
22226
22485
  return () => window.clearTimeout(timer);
@@ -22279,14 +22538,14 @@ function Question({
22279
22538
  }
22280
22539
 
22281
22540
  // src/NotifyRuleEditor.tsx
22282
- import { useCallback as useCallback36, useEffect as useEffect52, useState as useState64 } from "react";
22283
- import { useRecordsClient as useRecordsClient47, useTable as useTable15 } from "@ai-matrx/records/react";
22541
+ import { useCallback as useCallback36, useEffect as useEffect53, useState as useState64 } from "react";
22542
+ import { useRecordsClient as useRecordsClient48, useTable as useTable15 } from "@ai-matrx/records/react";
22284
22543
  import { Button as Button57, Skeleton as Skeleton22, cn as cn50 } from "@ai-matrx/design-system";
22285
22544
  import { jsx as jsx75, jsxs as jsxs69 } from "react/jsx-runtime";
22286
22545
  var CADENCE_WORDS2 = SUBSCRIPTION_CADENCE_LABEL;
22287
22546
  var CHANNEL_WORDS3 = SUBSCRIPTION_CHANNEL_LABEL;
22288
22547
  function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className }) {
22289
- const client = useRecordsClient47();
22548
+ const client = useRecordsClient48();
22290
22549
  const host = useRecordsUi();
22291
22550
  const table = useTable15(tableId);
22292
22551
  const rights = useTableRights(table.data);
@@ -22324,7 +22583,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
22324
22583
  }
22325
22584
  setViews(listed.data.map((v) => ({ id: v.view_id, name: v.name })));
22326
22585
  }, [client, host, tableId]);
22327
- useEffect52(() => {
22586
+ useEffect53(() => {
22328
22587
  void load();
22329
22588
  }, [load]);
22330
22589
  const write = useCallback36(
@@ -22352,7 +22611,7 @@ function NotifyRuleEditor({ tableId, seed, chosenRuleId, onChoose, className })
22352
22611
  },
22353
22612
  [client, tableId]
22354
22613
  );
22355
- useEffect52(() => {
22614
+ useEffect53(() => {
22356
22615
  if (!subscriptions || !seed || seed.length === 0) return;
22357
22616
  const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));
22358
22617
  if (missing.length === 0) return;
@@ -22557,7 +22816,7 @@ function whyNotAskable(fields, hidden = []) {
22557
22816
  // src/FormBuilder.tsx
22558
22817
  import { Fragment as Fragment30, jsx as jsx76, jsxs as jsxs70 } from "react/jsx-runtime";
22559
22818
  function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22560
- const client = useRecordsClient48();
22819
+ const client = useRecordsClient49();
22561
22820
  const publishGate = usePublishGate();
22562
22821
  const host = useRecordsUi();
22563
22822
  const claimSeed = useSeedGuard();
@@ -22602,10 +22861,10 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22602
22861
  setError(null);
22603
22862
  setForms(mine);
22604
22863
  }, [client, tableId, seed, claimSeed]);
22605
- useEffect53(() => {
22864
+ useEffect54(() => {
22606
22865
  void load();
22607
22866
  }, [load]);
22608
- useEffect53(() => {
22867
+ useEffect54(() => {
22609
22868
  if (!forms || forms.length === 0) return;
22610
22869
  const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0];
22611
22870
  if (chosen.id !== activeId) setActiveId(chosen.id);
@@ -22772,7 +23031,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22772
23031
  /* @__PURE__ */ jsxs70("label", { className: "flex flex-col gap-1", children: [
22773
23032
  /* @__PURE__ */ jsx76(Label15, { className: "text-xs font-medium", children: "Thank-you title" }),
22774
23033
  /* @__PURE__ */ jsx76(
22775
- BasicInput20,
23034
+ BasicInput21,
22776
23035
  {
22777
23036
  value: draft.thankYou?.title ?? "",
22778
23037
  placeholder: "Thank you",
@@ -22783,7 +23042,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22783
23042
  /* @__PURE__ */ jsxs70("label", { className: "flex flex-col gap-1", children: [
22784
23043
  /* @__PURE__ */ jsx76(Label15, { className: "text-xs font-medium", children: "Then go to (optional)" }),
22785
23044
  /* @__PURE__ */ jsx76(
22786
- BasicInput20,
23045
+ BasicInput21,
22787
23046
  {
22788
23047
  type: "url",
22789
23048
  inputMode: "url",
@@ -22810,7 +23069,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22810
23069
  /* @__PURE__ */ jsxs70("div", { className: "grid grid-cols-2 gap-2", children: [
22811
23070
  /* @__PURE__ */ jsxs70("label", { className: "flex flex-col gap-1", children: [
22812
23071
  /* @__PURE__ */ jsx76(Label15, { className: "text-xs font-medium", children: "Name" }),
22813
- /* @__PURE__ */ jsx76(BasicInput20, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
23072
+ /* @__PURE__ */ jsx76(BasicInput21, { value: draft.name, onChange: (e) => patch({ name: e.target.value }) })
22814
23073
  ] }),
22815
23074
  /* @__PURE__ */ jsxs70("label", { className: "flex flex-col gap-1", children: [
22816
23075
  /* @__PURE__ */ jsx76(Label15, { className: "text-xs font-medium", children: "Flow" }),
@@ -22838,7 +23097,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22838
23097
  /* @__PURE__ */ jsxs70("label", { className: "flex flex-col gap-1", children: [
22839
23098
  /* @__PURE__ */ jsx76(Label15, { className: "text-xs font-medium", children: "Submit button" }),
22840
23099
  /* @__PURE__ */ jsx76(
22841
- BasicInput20,
23100
+ BasicInput21,
22842
23101
  {
22843
23102
  value: draft.submitLabel ?? "",
22844
23103
  placeholder: "Submit",
@@ -22879,7 +23138,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22879
23138
  ] }),
22880
23139
  asked && question ? /* @__PURE__ */ jsxs70("div", { className: "mt-1.5 grid grid-cols-2 gap-2 pl-6", children: [
22881
23140
  /* @__PURE__ */ jsx76(
22882
- BasicInput20,
23141
+ BasicInput21,
22883
23142
  {
22884
23143
  className: "h-8 text-xs",
22885
23144
  placeholder: fieldName(field2),
@@ -22889,7 +23148,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
22889
23148
  }
22890
23149
  ),
22891
23150
  /* @__PURE__ */ jsx76(
22892
- BasicInput20,
23151
+ BasicInput21,
22893
23152
  {
22894
23153
  className: "h-8 text-xs",
22895
23154
  placeholder: "Help text",
@@ -23183,17 +23442,17 @@ function bucketWindow(groupKey, value) {
23183
23442
 
23184
23443
  // src/chartFrame.tsx
23185
23444
  import {
23186
- useEffect as useEffect54,
23445
+ useEffect as useEffect55,
23187
23446
  useId as useId2,
23188
- useRef as useRef22,
23447
+ useRef as useRef23,
23189
23448
  useState as useState66
23190
23449
  } from "react";
23191
23450
  import { cn as cn52 } from "@ai-matrx/design-system";
23192
23451
  import { jsx as jsx77, jsxs as jsxs71 } from "react/jsx-runtime";
23193
23452
  function useMeasuredWidth(fallback = 480) {
23194
- const ref = useRef22(null);
23453
+ const ref = useRef23(null);
23195
23454
  const [width, setWidth] = useState66(fallback);
23196
- useEffect54(() => {
23455
+ useEffect55(() => {
23197
23456
  const node = ref.current;
23198
23457
  if (!node) return;
23199
23458
  const apply = () => {
@@ -23317,12 +23576,12 @@ function isSignatureField(field2) {
23317
23576
  }
23318
23577
 
23319
23578
  // src/DocTemplate.tsx
23320
- import { useCallback as useCallback38, useEffect as useEffect55, useState as useState67 } from "react";
23321
- import { useFields as useFields20, useRecordsClient as useRecordsClient49, useTable as useTable17 } from "@ai-matrx/records/react";
23322
- import { BasicInput as BasicInput21, BasicTextarea as BasicTextarea11, Button as Button59, Label as Label16, Skeleton as Skeleton24, cn as cn53 } from "@ai-matrx/design-system";
23579
+ import { useCallback as useCallback38, useEffect as useEffect56, useState as useState67 } from "react";
23580
+ import { useFields as useFields20, useRecordsClient as useRecordsClient50, useTable as useTable17 } from "@ai-matrx/records/react";
23581
+ import { BasicInput as BasicInput22, BasicTextarea as BasicTextarea11, Button as Button59, Label as Label16, Skeleton as Skeleton24, cn as cn53 } from "@ai-matrx/design-system";
23323
23582
  import { jsx as jsx78, jsxs as jsxs72 } from "react/jsx-runtime";
23324
23583
  function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }) {
23325
- const client = useRecordsClient49();
23584
+ const client = useRecordsClient50();
23326
23585
  const claimSeed = useSeedGuard();
23327
23586
  const table = useTable17(tableId);
23328
23587
  const rights = useTableRights(table.data);
@@ -23365,10 +23624,10 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
23365
23624
  setError(null);
23366
23625
  setTemplates(rows);
23367
23626
  }, [client, tableId, seed, fields.data]);
23368
- useEffect55(() => {
23627
+ useEffect56(() => {
23369
23628
  void load();
23370
23629
  }, [load]);
23371
- useEffect55(() => {
23630
+ useEffect56(() => {
23372
23631
  if (!templates || templates.length === 0) return;
23373
23632
  const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0];
23374
23633
  if (chosen.id !== activeId) setActiveId(chosen.id);
@@ -23376,7 +23635,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
23376
23635
  setDraftBody(chosen.body);
23377
23636
  onActiveTemplate?.(chosen);
23378
23637
  }, [templates, activeTemplateId]);
23379
- useEffect55(() => {
23638
+ useEffect56(() => {
23380
23639
  let cancelled = false;
23381
23640
  if (draftBody.trim() === "") {
23382
23641
  setUnresolved([]);
@@ -23461,7 +23720,7 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
23461
23720
  ] }),
23462
23721
  /* @__PURE__ */ jsxs72("label", { className: "flex flex-col gap-1", children: [
23463
23722
  /* @__PURE__ */ jsx78(Label16, { className: "text-xs font-medium", children: "Name" }),
23464
- /* @__PURE__ */ jsx78(BasicInput21, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
23723
+ /* @__PURE__ */ jsx78(BasicInput22, { value: draftName, onChange: (e) => setDraftName(e.target.value), placeholder: "Agreement" })
23465
23724
  ] }),
23466
23725
  /* @__PURE__ */ jsxs72("div", { className: "flex flex-wrap items-center gap-1", children: [
23467
23726
  /* @__PURE__ */ jsx78("span", { className: "text-xs text-muted-foreground", children: "Insert" }),
@@ -23501,18 +23760,18 @@ function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, classN
23501
23760
  }
23502
23761
 
23503
23762
  // src/DocRender.tsx
23504
- import { useCallback as useCallback39, useEffect as useEffect56, useRef as useRef23, useState as useState68 } from "react";
23505
- import { useRecordsClient as useRecordsClient50 } from "@ai-matrx/records/react";
23763
+ import { useCallback as useCallback39, useEffect as useEffect57, useRef as useRef24, useState as useState68 } from "react";
23764
+ import { useRecordsClient as useRecordsClient51 } from "@ai-matrx/records/react";
23506
23765
  import { Button as Button60, Skeleton as Skeleton25, cn as cn54 } from "@ai-matrx/design-system";
23507
23766
  import { jsx as jsx79, jsxs as jsxs73 } from "react/jsx-runtime";
23508
23767
  function DocRender({ templateId, recordId, filename, onRendered, className }) {
23509
- const client = useRecordsClient50();
23768
+ const client = useRecordsClient51();
23510
23769
  const [preview, setPreview] = useState68(null);
23511
23770
  const [renders, setRenders] = useState68(null);
23512
23771
  const [showing, setShowing] = useState68(null);
23513
23772
  const [error, setError] = useState68(null);
23514
23773
  const [busy, setBusy] = useState68(null);
23515
- const paper = useRef23(null);
23774
+ const paper = useRef24(null);
23516
23775
  const load = useCallback39(async () => {
23517
23776
  const [body, held] = await Promise.all([
23518
23777
  client.docRenderBody({ template_id: templateId, record_id: recordId }),
@@ -23530,7 +23789,7 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
23530
23789
  setPreview(body.data);
23531
23790
  setRenders(held.data.filter((r) => r.template_id === templateId));
23532
23791
  }, [client, templateId, recordId]);
23533
- useEffect56(() => {
23792
+ useEffect57(() => {
23534
23793
  void load();
23535
23794
  }, [load]);
23536
23795
  async function freeze() {
@@ -23614,13 +23873,13 @@ function DocRender({ templateId, recordId, filename, onRendered, className }) {
23614
23873
  }
23615
23874
 
23616
23875
  // src/SignBlock.tsx
23617
- import { useCallback as useCallback40, useEffect as useEffect57, useState as useState69 } from "react";
23618
- import { useFields as useFields21, useRecordsClient as useRecordsClient51 } from "@ai-matrx/records/react";
23619
- import { BasicInput as BasicInput22, Button as Button61, Skeleton as Skeleton26, cn as cn55 } from "@ai-matrx/design-system";
23876
+ import { useCallback as useCallback40, useEffect as useEffect58, useState as useState69 } from "react";
23877
+ import { useFields as useFields21, useRecordsClient as useRecordsClient52 } from "@ai-matrx/records/react";
23878
+ import { BasicInput as BasicInput23, Button as Button61, Skeleton as Skeleton26, cn as cn55 } from "@ai-matrx/design-system";
23620
23879
  import { useTable as useTable18 } from "@ai-matrx/records/react";
23621
23880
  import { jsx as jsx80, jsxs as jsxs74 } from "react/jsx-runtime";
23622
23881
  function SignBlock({ tableId, recordId, render, className }) {
23623
- const client = useRecordsClient51();
23882
+ const client = useRecordsClient52();
23624
23883
  const table = useTable18(tableId);
23625
23884
  const rights = useTableRights(table.data);
23626
23885
  const fields = useFields21(tableId);
@@ -23644,7 +23903,7 @@ function SignBlock({ tableId, recordId, render, className }) {
23644
23903
  }
23645
23904
  setVerdicts(answers);
23646
23905
  }, [client, recordId]);
23647
- useEffect57(() => {
23906
+ useEffect58(() => {
23648
23907
  void load();
23649
23908
  }, [load]);
23650
23909
  async function sign(field2) {
@@ -23739,7 +23998,7 @@ function SignBlock({ tableId, recordId, render, className }) {
23739
23998
  },
23740
23999
  children: [
23741
24000
  /* @__PURE__ */ jsx80(
23742
- BasicInput22,
24001
+ BasicInput23,
23743
24002
  {
23744
24003
  className: "h-8 w-56 text-xs",
23745
24004
  "aria-label": `Sign ${fieldName(field2)}`,
@@ -24209,22 +24468,22 @@ function Drawing({
24209
24468
  }
24210
24469
 
24211
24470
  // src/DashboardCanvas.tsx
24212
- import { useCallback as useCallback41, useEffect as useEffect58, useMemo as useMemo42, useState as useState70 } from "react";
24213
- import { useFields as useFields22, useRecordsClient as useRecordsClient52, useTable as useTable19 } from "@ai-matrx/records/react";
24471
+ import { useCallback as useCallback41, useEffect as useEffect59, useMemo as useMemo42, useState as useState70 } from "react";
24472
+ import { useFields as useFields22, useRecordsClient as useRecordsClient53, useTable as useTable19 } from "@ai-matrx/records/react";
24214
24473
  import {
24215
- BasicInput as BasicInput23,
24474
+ BasicInput as BasicInput24,
24216
24475
  Button as Button62,
24217
- Select as Select6,
24218
- SelectContent as SelectContent6,
24219
- SelectItem as SelectItem6,
24220
- SelectTrigger as SelectTrigger6,
24221
- SelectValue as SelectValue6,
24476
+ Select as Select7,
24477
+ SelectContent as SelectContent7,
24478
+ SelectItem as SelectItem7,
24479
+ SelectTrigger as SelectTrigger7,
24480
+ SelectValue as SelectValue7,
24222
24481
  Skeleton as Skeleton27,
24223
24482
  cn as cn57
24224
24483
  } from "@ai-matrx/design-system";
24225
24484
  import { Fragment as Fragment32, jsx as jsx82, jsxs as jsxs76 } from "react/jsx-runtime";
24226
24485
  function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
24227
- const client = useRecordsClient52();
24486
+ const client = useRecordsClient53();
24228
24487
  const host = useRecordsUi();
24229
24488
  const table = useTable19(tableId);
24230
24489
  const rights = useTableRights(table.data);
@@ -24256,17 +24515,17 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
24256
24515
  return read;
24257
24516
  }, [client, tableId]);
24258
24517
  const [notKept, setNotKept] = useState70(null);
24259
- useEffect58(() => {
24518
+ useEffect59(() => {
24260
24519
  void load();
24261
24520
  }, [load]);
24262
- useEffect58(() => {
24521
+ useEffect59(() => {
24263
24522
  if (!boards || boards.length === 0) return;
24264
24523
  const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0];
24265
24524
  if (chosen.id !== activeId) setActiveId(chosen.id);
24266
24525
  }, [boards, activeDashboardId]);
24267
24526
  const board = useMemo42(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);
24268
24527
  const filterKey = JSON.stringify(filter ?? {});
24269
- useEffect58(() => {
24528
+ useEffect59(() => {
24270
24529
  if (!activeId) {
24271
24530
  setRun(null);
24272
24531
  return;
@@ -24397,15 +24656,15 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
24397
24656
  rights.admin ? /* @__PURE__ */ jsx82(Button62, { size: "sm", variant: "ghost", onClick: () => void create(), children: "New dashboard" }) : null,
24398
24657
  board ? /* @__PURE__ */ jsxs76("span", { className: "ml-auto flex items-center gap-1", children: [
24399
24658
  (board.blocks ?? []).some((b) => !!b.bucket) ? /* @__PURE__ */ jsxs76(
24400
- Select6,
24659
+ Select7,
24401
24660
  {
24402
24661
  value: grain ?? "saved",
24403
24662
  onValueChange: (v) => setGrain(v === "saved" ? null : v),
24404
24663
  children: [
24405
- /* @__PURE__ */ jsx82(SelectTrigger6, { size: "sm", "aria-label": "Date grain for every chart on this dashboard", className: "h-7 min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue6, {}) }),
24406
- /* @__PURE__ */ jsxs76(SelectContent6, { children: [
24407
- /* @__PURE__ */ jsx82(SelectItem6, { value: "saved", children: "By the saved grain" }),
24408
- Object.keys(GRAIN_LABEL).map((g) => /* @__PURE__ */ jsxs76(SelectItem6, { value: g, children: [
24664
+ /* @__PURE__ */ jsx82(SelectTrigger7, { size: "sm", "aria-label": "Date grain for every chart on this dashboard", className: "h-7 min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue7, {}) }),
24665
+ /* @__PURE__ */ jsxs76(SelectContent7, { children: [
24666
+ /* @__PURE__ */ jsx82(SelectItem7, { value: "saved", children: "By the saved grain" }),
24667
+ Object.keys(GRAIN_LABEL).map((g) => /* @__PURE__ */ jsxs76(SelectItem7, { value: g, children: [
24409
24668
  "By ",
24410
24669
  GRAIN_LABEL[g].toLowerCase()
24411
24670
  ] }, g))
@@ -24457,7 +24716,7 @@ function DashboardCanvas({ tableId, activeDashboardId, filter, className }) {
24457
24716
  board ? /* @__PURE__ */ jsxs76("div", { className: "flex flex-col gap-1", children: [
24458
24717
  /* @__PURE__ */ jsxs76("div", { className: "flex items-center gap-1", children: [
24459
24718
  /* @__PURE__ */ jsx82(
24460
- BasicInput23,
24719
+ BasicInput24,
24461
24720
  {
24462
24721
  value: question,
24463
24722
  "aria-label": "Ask for a change to this dashboard",
@@ -24583,18 +24842,18 @@ function GroupingPicker({
24583
24842
  const known = choices.some((c) => c.field.key === current);
24584
24843
  return /* @__PURE__ */ jsxs76(Fragment32, { children: [
24585
24844
  /* @__PURE__ */ jsx82("label", { className: "text-muted-foreground", htmlFor: `block-group-${block.title}`, children: "Group by" }),
24586
- /* @__PURE__ */ jsxs76(Select6, { value: known ? current : "", onValueChange: onPick, children: [
24845
+ /* @__PURE__ */ jsxs76(Select7, { value: known ? current : "", onValueChange: onPick, children: [
24587
24846
  /* @__PURE__ */ jsx82(
24588
- SelectTrigger6,
24847
+ SelectTrigger7,
24589
24848
  {
24590
24849
  size: "sm",
24591
24850
  id: `block-group-${block.title}`,
24592
24851
  "aria-label": `Which column ${block.title} is grouped by`,
24593
24852
  className: "h-7 min-w-[10rem] text-xs",
24594
- children: /* @__PURE__ */ jsx82(SelectValue6, { placeholder: "Choose a column" })
24853
+ children: /* @__PURE__ */ jsx82(SelectValue7, { placeholder: "Choose a column" })
24595
24854
  }
24596
24855
  ),
24597
- /* @__PURE__ */ jsx82(SelectContent6, { children: choices.map(({ field: field2, unusual }) => /* @__PURE__ */ jsx82(SelectItem6, { value: field2.key, children: unusual ? `${fieldName(field2)} \u2014 ${UNUSUAL_FIELD_NOTE}` : fieldName(field2) }, field2.key)) })
24856
+ /* @__PURE__ */ jsx82(SelectContent7, { children: choices.map(({ field: field2, unusual }) => /* @__PURE__ */ jsx82(SelectItem7, { value: field2.key, children: unusual ? `${fieldName(field2)} \u2014 ${UNUSUAL_FIELD_NOTE}` : fieldName(field2) }, field2.key)) })
24598
24857
  ] }),
24599
24858
  known ? null : /* @__PURE__ */ jsx82("span", { className: "text-muted-foreground", children: "The column this block was grouped by is no longer on this table \u2014 choose another." })
24600
24859
  ] });
@@ -24680,7 +24939,7 @@ function CompareControl({
24680
24939
  );
24681
24940
  return /* @__PURE__ */ jsxs76(Fragment32, { children: [
24682
24941
  /* @__PURE__ */ jsxs76(
24683
- Select6,
24942
+ Select7,
24684
24943
  {
24685
24944
  value: current ?? "none",
24686
24945
  onValueChange: (v) => {
@@ -24694,22 +24953,22 @@ function CompareControl({
24694
24953
  });
24695
24954
  },
24696
24955
  children: [
24697
- /* @__PURE__ */ jsx82(SelectTrigger6, { size: "sm", "aria-label": `What ${block.title} is compared with`, className: "h-7 w-auto min-w-[9rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue6, {}) }),
24698
- /* @__PURE__ */ jsxs76(SelectContent6, { children: [
24699
- /* @__PURE__ */ jsx82(SelectItem6, { value: "none", children: "No comparison" }),
24700
- kinds.map((k) => /* @__PURE__ */ jsx82(SelectItem6, { value: k, children: COMPARE_LABEL[k] }, k))
24956
+ /* @__PURE__ */ jsx82(SelectTrigger7, { size: "sm", "aria-label": `What ${block.title} is compared with`, className: "h-7 w-auto min-w-[9rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue7, {}) }),
24957
+ /* @__PURE__ */ jsxs76(SelectContent7, { children: [
24958
+ /* @__PURE__ */ jsx82(SelectItem7, { value: "none", children: "No comparison" }),
24959
+ kinds.map((k) => /* @__PURE__ */ jsx82(SelectItem7, { value: k, children: COMPARE_LABEL[k] }, k))
24701
24960
  ] })
24702
24961
  ]
24703
24962
  }
24704
24963
  ),
24705
24964
  current && !explicitWindow ? /* @__PURE__ */ jsxs76(
24706
- Select6,
24965
+ Select7,
24707
24966
  {
24708
24967
  value: period,
24709
24968
  onValueChange: (v) => onChange({ ...block.compare ?? { against: current, key }, period: v }),
24710
24969
  children: [
24711
- /* @__PURE__ */ jsx82(SelectTrigger6, { size: "sm", "aria-label": `Which period ${block.title} shows`, className: "h-7 w-auto min-w-[7rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue6, {}) }),
24712
- /* @__PURE__ */ jsx82(SelectContent6, { children: Object.keys(GRAIN_LABEL).map((g) => /* @__PURE__ */ jsxs76(SelectItem6, { value: g, children: [
24970
+ /* @__PURE__ */ jsx82(SelectTrigger7, { size: "sm", "aria-label": `Which period ${block.title} shows`, className: "h-7 w-auto min-w-[7rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue7, {}) }),
24971
+ /* @__PURE__ */ jsx82(SelectContent7, { children: Object.keys(GRAIN_LABEL).map((g) => /* @__PURE__ */ jsxs76(SelectItem7, { value: g, children: [
24713
24972
  "This ",
24714
24973
  GRAIN_LABEL[g].toLowerCase()
24715
24974
  ] }, g)) })
@@ -24727,7 +24986,7 @@ function TargetControl({
24727
24986
  const [mode, setMode] = useState70(saved);
24728
24987
  const savedValue = block.target && "value" in block.target && typeof block.target.value === "number" ? block.target.value : null;
24729
24988
  const [draft, setDraft] = useState70(savedValue === null ? "" : String(savedValue));
24730
- useEffect58(() => {
24989
+ useEffect59(() => {
24731
24990
  setMode(saved);
24732
24991
  setDraft(savedValue === null ? "" : String(savedValue));
24733
24992
  }, [saved, savedValue]);
@@ -24742,7 +25001,7 @@ function TargetControl({
24742
25001
  }
24743
25002
  return /* @__PURE__ */ jsxs76(Fragment32, { children: [
24744
25003
  /* @__PURE__ */ jsxs76(
24745
- Select6,
25004
+ Select7,
24746
25005
  {
24747
25006
  value: mode,
24748
25007
  onValueChange: (v) => {
@@ -24751,17 +25010,17 @@ function TargetControl({
24751
25010
  if (next === "none" && saved !== "none") onChange(null);
24752
25011
  },
24753
25012
  children: [
24754
- /* @__PURE__ */ jsx82(SelectTrigger6, { size: "sm", "aria-label": `The target ${block.title} aims for`, className: "h-7 w-auto min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue6, {}) }),
24755
- /* @__PURE__ */ jsxs76(SelectContent6, { children: [
24756
- /* @__PURE__ */ jsx82(SelectItem6, { value: "none", children: "No target" }),
24757
- /* @__PURE__ */ jsx82(SelectItem6, { value: "value", children: "A target number" }),
24758
- columns.length > 0 ? /* @__PURE__ */ jsx82(SelectItem6, { value: "field", children: "A goal column" }) : null
25013
+ /* @__PURE__ */ jsx82(SelectTrigger7, { size: "sm", "aria-label": `The target ${block.title} aims for`, className: "h-7 w-auto min-w-[8rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue7, {}) }),
25014
+ /* @__PURE__ */ jsxs76(SelectContent7, { children: [
25015
+ /* @__PURE__ */ jsx82(SelectItem7, { value: "none", children: "No target" }),
25016
+ /* @__PURE__ */ jsx82(SelectItem7, { value: "value", children: "A target number" }),
25017
+ columns.length > 0 ? /* @__PURE__ */ jsx82(SelectItem7, { value: "field", children: "A goal column" }) : null
24759
25018
  ] })
24760
25019
  ]
24761
25020
  }
24762
25021
  ),
24763
25022
  mode === "value" ? /* @__PURE__ */ jsx82(
24764
- BasicInput23,
25023
+ BasicInput24,
24765
25024
  {
24766
25025
  inputMode: "decimal",
24767
25026
  value: draft,
@@ -24776,7 +25035,7 @@ function TargetControl({
24776
25035
  }
24777
25036
  ) : null,
24778
25037
  mode === "field" ? /* @__PURE__ */ jsxs76(
24779
- Select6,
25038
+ Select7,
24780
25039
  {
24781
25040
  value: block.target && "field" in block.target && block.target.field ? block.target.field : "",
24782
25041
  onValueChange: (key) => {
@@ -24785,8 +25044,8 @@ function TargetControl({
24785
25044
  onChange({ field: key, op: "sum", label: fieldName(picked) });
24786
25045
  },
24787
25046
  children: [
24788
- /* @__PURE__ */ jsx82(SelectTrigger6, { size: "sm", "aria-label": `Which column holds the goal for ${block.title}`, className: "h-7 w-auto min-w-[9rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue6, { placeholder: "Choose a column" }) }),
24789
- /* @__PURE__ */ jsx82(SelectContent6, { children: columns.map((f) => /* @__PURE__ */ jsx82(SelectItem6, { value: f.key, children: fieldName(f) }, f.key)) })
25047
+ /* @__PURE__ */ jsx82(SelectTrigger7, { size: "sm", "aria-label": `Which column holds the goal for ${block.title}`, className: "h-7 w-auto min-w-[9rem] text-xs", children: /* @__PURE__ */ jsx82(SelectValue7, { placeholder: "Choose a column" }) }),
25048
+ /* @__PURE__ */ jsx82(SelectContent7, { children: columns.map((f) => /* @__PURE__ */ jsx82(SelectItem7, { value: f.key, children: fieldName(f) }, f.key)) })
24790
25049
  ]
24791
25050
  }
24792
25051
  ) : null
@@ -24794,8 +25053,8 @@ function TargetControl({
24794
25053
  }
24795
25054
 
24796
25055
  // src/FormsPanel.tsx
24797
- import { useCallback as useCallback42, useEffect as useEffect59, useState as useState71 } from "react";
24798
- import { useRecordsClient as useRecordsClient53, useTable as useTable20 } from "@ai-matrx/records/react";
25056
+ import { useCallback as useCallback42, useEffect as useEffect60, useState as useState71 } from "react";
25057
+ import { useRecordsClient as useRecordsClient54, useTable as useTable20 } from "@ai-matrx/records/react";
24799
25058
  import { publicFormPath as publicFormPath2 } from "@ai-matrx/records";
24800
25059
  import { Badge as Badge20, Button as Button63, Skeleton as Skeleton28, cn as cn58 } from "@ai-matrx/design-system";
24801
25060
  import { Fragment as Fragment33, jsx as jsx83, jsxs as jsxs77 } from "react/jsx-runtime";
@@ -24807,7 +25066,7 @@ function formSuggestion(tableName2) {
24807
25066
  return `Make me a form that collects new ${subject} entries and tells me when somebody answers.`;
24808
25067
  }
24809
25068
  function FormsPanel({ tableId, activeFormId, className }) {
24810
- const client = useRecordsClient53();
25069
+ const client = useRecordsClient54();
24811
25070
  const publishGate = usePublishGate();
24812
25071
  const host = useRecordsUi();
24813
25072
  const table = useTable20(tableId);
@@ -24819,7 +25078,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
24819
25078
  const [building, setBuilding] = useState71(false);
24820
25079
  const linked = activeFormId && forms !== null ? forms.find((f) => f.form_id === activeFormId) ?? null : null;
24821
25080
  const linkedMissing = Boolean(activeFormId) && forms !== null && linked === null;
24822
- useEffect59(() => {
25081
+ useEffect60(() => {
24823
25082
  if (linked && rights.structure) setBuilding(true);
24824
25083
  }, [linked, rights.structure]);
24825
25084
  const load = useCallback42(async () => {
@@ -24832,7 +25091,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
24832
25091
  setError(null);
24833
25092
  setForms(answered.data);
24834
25093
  }, [client, tableId]);
24835
- useEffect59(() => {
25094
+ useEffect60(() => {
24836
25095
  void load();
24837
25096
  }, [load]);
24838
25097
  const toggle = useCallback42(
@@ -24963,12 +25222,12 @@ function FormsPanel({ tableId, activeFormId, className }) {
24963
25222
  }
24964
25223
 
24965
25224
  // src/BookingBuilder.tsx
24966
- import { useCallback as useCallback43, useEffect as useEffect60, useMemo as useMemo43, useState as useState72 } from "react";
24967
- import { useFields as useFields23, useRecordsClient as useRecordsClient54, useTable as useTable21 } from "@ai-matrx/records/react";
25225
+ import { useCallback as useCallback43, useEffect as useEffect61, useMemo as useMemo43, useState as useState72 } from "react";
25226
+ import { useFields as useFields23, useRecordsClient as useRecordsClient55, useTable as useTable21 } from "@ai-matrx/records/react";
24968
25227
  import {
24969
25228
  bookingPath
24970
25229
  } from "@ai-matrx/records";
24971
- import { BasicInput as BasicInput24, BasicTextarea as BasicTextarea12, Button as Button64, Checkbox as Checkbox12, Label as Label17, Skeleton as Skeleton29, cn as cn59 } from "@ai-matrx/design-system";
25230
+ import { BasicInput as BasicInput25, BasicTextarea as BasicTextarea12, Button as Button64, Checkbox as Checkbox12, Label as Label17, Skeleton as Skeleton29, cn as cn59 } from "@ai-matrx/design-system";
24972
25231
  import { Fragment as Fragment34, jsx as jsx84, jsxs as jsxs78 } from "react/jsx-runtime";
24973
25232
  var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
24974
25233
  var DAYS = [
@@ -24994,7 +25253,7 @@ function draftWindows(availability) {
24994
25253
  });
24995
25254
  }
24996
25255
  function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
24997
- const client = useRecordsClient54();
25256
+ const client = useRecordsClient55();
24998
25257
  const publishGate = usePublishGate();
24999
25258
  const host = useRecordsUi();
25000
25259
  const table = useTable21(tableId);
@@ -25038,18 +25297,18 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25038
25297
  setLoaded(true);
25039
25298
  if (mine) setFormId(mine.form_id);
25040
25299
  }, [client, tableId, bookingId]);
25041
- useEffect60(() => {
25300
+ useEffect61(() => {
25042
25301
  void load();
25043
25302
  }, [load]);
25044
- useEffect60(() => {
25303
+ useEffect61(() => {
25045
25304
  if (title !== "" || !table.data) return;
25046
25305
  setTitle(existing?.title ?? `Book a ${minutes}-minute ${table.data.name} appointment`);
25047
25306
  }, [table.data, existing]);
25048
- useEffect60(() => {
25307
+ useEffect61(() => {
25049
25308
  if (!existing) return;
25050
25309
  setMinutes(existing.slot_minutes);
25051
25310
  }, [existing]);
25052
- useEffect60(() => {
25311
+ useEffect61(() => {
25053
25312
  if (!offer) return;
25054
25313
  setWindows(draftWindows(offer));
25055
25314
  setMinutes(offer.slot_minutes);
@@ -25127,7 +25386,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25127
25386
  error ? /* @__PURE__ */ jsx84(RefusalNotice, { error }) : null,
25128
25387
  /* @__PURE__ */ jsxs78("label", { className: "flex flex-col gap-1", children: [
25129
25388
  /* @__PURE__ */ jsx84(Label17, { className: "text-xs font-medium", children: "What it is called" }),
25130
- /* @__PURE__ */ jsx84(BasicInput24, { value: title, onChange: (e) => setTitle(e.target.value) })
25389
+ /* @__PURE__ */ jsx84(BasicInput25, { value: title, onChange: (e) => setTitle(e.target.value) })
25131
25390
  ] }),
25132
25391
  /* @__PURE__ */ jsxs78("div", { className: "grid grid-cols-1 gap-2 @md:grid-cols-2", children: [
25133
25392
  /* @__PURE__ */ jsxs78("label", { className: "flex flex-col gap-1", children: [
@@ -25172,7 +25431,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25172
25431
  /* @__PURE__ */ jsxs78("label", { className: "flex flex-col gap-1", children: [
25173
25432
  /* @__PURE__ */ jsx84(Label17, { className: "text-xs font-medium", children: "Most in one day" }),
25174
25433
  /* @__PURE__ */ jsx84(
25175
- BasicInput24,
25434
+ BasicInput25,
25176
25435
  {
25177
25436
  type: "number",
25178
25437
  min: 1,
@@ -25212,7 +25471,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25212
25471
  ] }),
25213
25472
  w.on ? /* @__PURE__ */ jsxs78(Fragment34, { children: [
25214
25473
  /* @__PURE__ */ jsx84(
25215
- BasicInput24,
25474
+ BasicInput25,
25216
25475
  {
25217
25476
  type: "time",
25218
25477
  className: "h-8 w-28",
@@ -25222,7 +25481,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25222
25481
  ),
25223
25482
  /* @__PURE__ */ jsx84("span", { className: "text-xs text-muted-foreground", children: "to" }),
25224
25483
  /* @__PURE__ */ jsx84(
25225
- BasicInput24,
25484
+ BasicInput25,
25226
25485
  {
25227
25486
  type: "time",
25228
25487
  className: "h-8 w-28",
@@ -25311,8 +25570,8 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
25311
25570
  }
25312
25571
 
25313
25572
  // src/BookingSlots.tsx
25314
- import { useCallback as useCallback44, useEffect as useEffect61, useMemo as useMemo44, useState as useState73 } from "react";
25315
- import { useRecordsClient as useRecordsClient55, useMyLevels as useMyLevels2 } from "@ai-matrx/records/react";
25573
+ import { useCallback as useCallback44, useEffect as useEffect62, useMemo as useMemo44, useState as useState73 } from "react";
25574
+ import { useRecordsClient as useRecordsClient56, useMyLevels as useMyLevels2 } from "@ai-matrx/records/react";
25316
25575
  import { bookingPath as bookingPath2 } from "@ai-matrx/records";
25317
25576
  import { Badge as Badge21, Button as Button65, Skeleton as Skeleton30, cn as cn60 } from "@ai-matrx/design-system";
25318
25577
  import { Fragment as Fragment35, jsx as jsx85, jsxs as jsxs79 } from "react/jsx-runtime";
@@ -25325,7 +25584,7 @@ function bookingSuggestion(tableName2) {
25325
25584
  var NO_ADMIN2 = "Opening a booking page lets people with no account take time in your calendar, so it needs the admin level on the table the appointments land in.";
25326
25585
  var STATE_WORDS = BOOKING_PAGE_STATE_LABEL;
25327
25586
  function BookingSlots({ tableId, activeBookingId, className }) {
25328
- const client = useRecordsClient55();
25587
+ const client = useRecordsClient56();
25329
25588
  const host = useRecordsUi();
25330
25589
  const [pages, setPages] = useState73(null);
25331
25590
  const [error, setError] = useState73(null);
@@ -25343,7 +25602,7 @@ function BookingSlots({ tableId, activeBookingId, className }) {
25343
25602
  setError(null);
25344
25603
  setPages(answered.data);
25345
25604
  }, [client, tableId]);
25346
- useEffect61(() => {
25605
+ useEffect62(() => {
25347
25606
  void load();
25348
25607
  }, [load]);
25349
25608
  const subjectIds = useMemo44(
@@ -25526,18 +25785,18 @@ function nextInWords(page) {
25526
25785
  }
25527
25786
 
25528
25787
  // src/CaptureSheet.tsx
25529
- import { useCallback as useCallback46, useEffect as useEffect63, useRef as useRef25, useState as useState75 } from "react";
25530
- import { useFields as useFields24, useRecordsClient as useRecordsClient57, useTable as useTable22 } from "@ai-matrx/records/react";
25788
+ import { useCallback as useCallback46, useEffect as useEffect64, useRef as useRef26, useState as useState75 } from "react";
25789
+ import { useFields as useFields24, useRecordsClient as useRecordsClient58, useTable as useTable22 } from "@ai-matrx/records/react";
25531
25790
  import { Button as Button67, Input as Input4, Skeleton as Skeleton32, Textarea as Textarea3, cn as cn62 } from "@ai-matrx/design-system";
25532
25791
 
25533
25792
  // src/CaptureRun.tsx
25534
- import { useCallback as useCallback45, useEffect as useEffect62, useMemo as useMemo45, useRef as useRef24, useState as useState74 } from "react";
25793
+ import { useCallback as useCallback45, useEffect as useEffect63, useMemo as useMemo45, useRef as useRef25, useState as useState74 } from "react";
25535
25794
  import {
25536
25795
  coerceTypedAnswer as coerceTypedAnswer3,
25537
25796
  coercionLabel,
25538
25797
  openCaptureQueue
25539
25798
  } from "@ai-matrx/records";
25540
- import { useRecordsClient as useRecordsClient56 } from "@ai-matrx/records/react";
25799
+ import { useRecordsClient as useRecordsClient57 } from "@ai-matrx/records/react";
25541
25800
  import { Button as Button66, Input as Input3, Skeleton as Skeleton31, Textarea as Textarea2, cn as cn61 } from "@ai-matrx/design-system";
25542
25801
  import { jsx as jsx86, jsxs as jsxs80 } from "react/jsx-runtime";
25543
25802
  function controlFor(field2) {
@@ -25576,7 +25835,7 @@ function whereWeAre(timeoutMs = 4e3) {
25576
25835
  });
25577
25836
  }
25578
25837
  function CaptureRun({ sheetId, face: given, className }) {
25579
- const client = useRecordsClient56();
25838
+ const client = useRecordsClient57();
25580
25839
  const host = useRecordsUi();
25581
25840
  const [face, setFace] = useState74(given);
25582
25841
  const [loadFailed, setLoadFailed] = useState74(null);
@@ -25589,8 +25848,8 @@ function CaptureRun({ sheetId, face: given, className }) {
25589
25848
  const [items, setItems] = useState74([]);
25590
25849
  const [lastSynced, setLastSynced] = useState74(null);
25591
25850
  const [sending, setSending] = useState74(false);
25592
- const queueRef = useRef24(null);
25593
- useEffect62(() => {
25851
+ const queueRef = useRef25(null);
25852
+ useEffect63(() => {
25594
25853
  const q2 = openCaptureQueue({
25595
25854
  onChange: (c, all) => {
25596
25855
  setCounts(c);
@@ -25628,7 +25887,7 @@ function CaptureRun({ sheetId, face: given, className }) {
25628
25887
  void q2.sync().then(() => void q2.lastSyncedAt().then(setLastSynced));
25629
25888
  return () => q2.dispose();
25630
25889
  }, [client, host]);
25631
- useEffect62(() => {
25890
+ useEffect63(() => {
25632
25891
  if (given !== void 0) return;
25633
25892
  let cancelled = false;
25634
25893
  void client.captureOpen({ sheet_id: sheetId }).then((res) => {
@@ -25956,7 +26215,7 @@ function AdHocCaptureSheet({
25956
26215
  attachmentField,
25957
26216
  className
25958
26217
  }) {
25959
- const client = useRecordsClient57();
26218
+ const client = useRecordsClient58();
25960
26219
  const host = useRecordsUi();
25961
26220
  const table = useTable22(tableId);
25962
26221
  const fields = useFields24(tableId);
@@ -25969,7 +26228,7 @@ function AdHocCaptureSheet({
25969
26228
  const [error, setError] = useState75(null);
25970
26229
  const [uploadError, setUploadError] = useState75(null);
25971
26230
  const [flushing, setFlushing] = useState75(false);
25972
- const queue = useRef25([]);
26231
+ const queue = useRef26([]);
25973
26232
  const keep = useCallback46(
25974
26233
  async (next) => {
25975
26234
  queue.current = next;
@@ -25978,7 +26237,7 @@ function AdHocCaptureSheet({
25978
26237
  },
25979
26238
  [host]
25980
26239
  );
25981
- useEffect63(() => {
26240
+ useEffect64(() => {
25982
26241
  let cancelled = false;
25983
26242
  void (async () => {
25984
26243
  const held = host.captureQueue ? await host.captureQueue.load() : [];
@@ -26157,12 +26416,12 @@ function AdHocCaptureSheet({
26157
26416
  }
26158
26417
 
26159
26418
  // src/PortalShell.tsx
26160
- import { useCallback as useCallback47, useEffect as useEffect64, useState as useState76 } from "react";
26161
- import { useRecordsClient as useRecordsClient58 } from "@ai-matrx/records/react";
26419
+ import { useCallback as useCallback47, useEffect as useEffect65, useState as useState76 } from "react";
26420
+ import { useRecordsClient as useRecordsClient59 } from "@ai-matrx/records/react";
26162
26421
  import { Button as Button68, Skeleton as Skeleton33, cn as cn63 } from "@ai-matrx/design-system";
26163
26422
  import { jsx as jsx88, jsxs as jsxs82 } from "react/jsx-runtime";
26164
26423
  function PortalShell({ tableId, form, resourceType = "record", className }) {
26165
- const client = useRecordsClient58();
26424
+ const client = useRecordsClient59();
26166
26425
  const [card, setCard] = useState76(null);
26167
26426
  const [reach, setReach] = useState76(null);
26168
26427
  const [error, setError] = useState76(null);
@@ -26183,7 +26442,7 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
26183
26442
  }
26184
26443
  setReach(reached.data.map((row) => row.resource_id));
26185
26444
  }, [client, resourceType]);
26186
- useEffect64(() => {
26445
+ useEffect65(() => {
26187
26446
  void load();
26188
26447
  }, [load]);
26189
26448
  if (error) {
@@ -26241,9 +26500,9 @@ function PortalShell({ tableId, form, resourceType = "record", className }) {
26241
26500
  ] });
26242
26501
  }
26243
26502
  function PortalRow({ tableId, recordId }) {
26244
- const client = useRecordsClient58();
26503
+ const client = useRecordsClient59();
26245
26504
  const [title, setTitle] = useState76(null);
26246
- useEffect64(() => {
26505
+ useEffect65(() => {
26247
26506
  let cancelled = false;
26248
26507
  void client.recordRead({ record_id: recordId }).then((answered) => {
26249
26508
  if (cancelled) return;
@@ -26263,12 +26522,12 @@ function PortalRow({ tableId, recordId }) {
26263
26522
  }
26264
26523
 
26265
26524
  // src/PublicViewPage.tsx
26266
- import { useCallback as useCallback48, useEffect as useEffect65, useState as useState77 } from "react";
26267
- import { useRecordsClient as useRecordsClient59 } from "@ai-matrx/records/react";
26525
+ import { useCallback as useCallback48, useEffect as useEffect66, useState as useState77 } from "react";
26526
+ import { useRecordsClient as useRecordsClient60 } from "@ai-matrx/records/react";
26268
26527
  import { Skeleton as Skeleton34, cn as cn64 } from "@ai-matrx/design-system";
26269
26528
  import { jsx as jsx89, jsxs as jsxs83 } from "react/jsx-runtime";
26270
26529
  function PublicViewPage({ slug, className }) {
26271
- const client = useRecordsClient59();
26530
+ const client = useRecordsClient60();
26272
26531
  const [binding, setBinding] = useState77(null);
26273
26532
  const [rows, setRows] = useState77(null);
26274
26533
  const [fields, setFields] = useState77(null);
@@ -26307,7 +26566,7 @@ function PublicViewPage({ slug, className }) {
26307
26566
  }
26308
26567
  setRows([{ id: found.resource_id, document: read.data.document, level: "viewer", hidden: read.data.hidden }]);
26309
26568
  }, [client, slug]);
26310
- useEffect65(() => {
26569
+ useEffect66(() => {
26311
26570
  void load();
26312
26571
  }, [load]);
26313
26572
  if (error) return /* @__PURE__ */ jsx89(RefusalNotice, { error, className });
@@ -26344,8 +26603,8 @@ function PublicRow({ row, fields }) {
26344
26603
  }
26345
26604
 
26346
26605
  // src/EmbedFrame.tsx
26347
- import { useCallback as useCallback49, useEffect as useEffect66, useState as useState78 } from "react";
26348
- import { useRecordsClient as useRecordsClient60 } from "@ai-matrx/records/react";
26606
+ import { useCallback as useCallback49, useEffect as useEffect67, useState as useState78 } from "react";
26607
+ import { useRecordsClient as useRecordsClient61 } from "@ai-matrx/records/react";
26349
26608
  import { Button as Button69, Input as Input5, Skeleton as Skeleton35, Textarea as Textarea4, cn as cn65 } from "@ai-matrx/design-system";
26350
26609
  import { useTable as useTable23 } from "@ai-matrx/records/react";
26351
26610
  import { Fragment as Fragment37, jsx as jsx90, jsxs as jsxs84 } from "react/jsx-runtime";
@@ -26357,7 +26616,7 @@ function EmbedFrame({
26357
26616
  embedUrl,
26358
26617
  className
26359
26618
  }) {
26360
- const client = useRecordsClient60();
26619
+ const client = useRecordsClient61();
26361
26620
  const host = useRecordsUi();
26362
26621
  const table = useTable23(tableId);
26363
26622
  const rights = useTableRights(table.data);
@@ -26451,13 +26710,13 @@ function EmbedFrame({
26451
26710
  ] });
26452
26711
  }
26453
26712
  function useEmbedHandshake(args) {
26454
- const client = useRecordsClient60();
26713
+ const client = useRecordsClient61();
26455
26714
  const [binding, setBinding] = useState78(null);
26456
26715
  const [error, setError] = useState78(null);
26457
26716
  const [loading, setLoading] = useState78(true);
26458
26717
  const origin = args.origin ?? (typeof location === "undefined" ? "" : location.origin);
26459
26718
  const { secret, requiredMode } = args;
26460
- useEffect66(() => {
26719
+ useEffect67(() => {
26461
26720
  let cancelled = false;
26462
26721
  setLoading(true);
26463
26722
  setError(null);
@@ -26479,7 +26738,7 @@ function useEmbedHandshake(args) {
26479
26738
  }
26480
26739
 
26481
26740
  // src/RecordsMount.tsx
26482
- import { useRef as useRef26 } from "react";
26741
+ import { useRef as useRef27 } from "react";
26483
26742
  import { RecordsProvider } from "@ai-matrx/records/react";
26484
26743
  import { jsx as jsx91 } from "react/jsx-runtime";
26485
26744
  var STORE_DECIDES_REASON = "This host offers exactly what the record store says this person may do: the level comes back with the table on the read door, so a control they cannot use is never drawn in the first place.";
@@ -26497,7 +26756,7 @@ function RecordsMount({
26497
26756
  return /* @__PURE__ */ jsx91(RecordsProvider, { config, children: /* @__PURE__ */ jsx91(RecordsUiProvider, { value: bound, children: /* @__PURE__ */ jsx91(RecordLabelProvider, { children }) }) });
26498
26757
  }
26499
26758
  function useShallowStableHost(host) {
26500
- const held = useRef26(null);
26759
+ const held = useRef27(null);
26501
26760
  const next = host ?? {};
26502
26761
  const previous = held.current;
26503
26762
  if (previous !== null && sameParts(previous, next)) return previous;
@@ -26529,15 +26788,15 @@ function recordsDataSource(client, fallbackSchema = "custom") {
26529
26788
  }
26530
26789
 
26531
26790
  // src/TablesHome.tsx
26532
- import { useCallback as useCallback50, useEffect as useEffect69, useState as useState81 } from "react";
26533
- import { useRecordsClient as useRecordsClient63, useTables as useTables4 } from "@ai-matrx/records/react";
26791
+ import { useCallback as useCallback50, useEffect as useEffect70, useState as useState81 } from "react";
26792
+ import { useRecordsClient as useRecordsClient64, useTables as useTables4 } from "@ai-matrx/records/react";
26534
26793
  import { withTableFacts } from "@ai-matrx/records/core";
26535
26794
  import { withTablePlacement } from "@ai-matrx/records";
26536
- import { BasicInput as BasicInput25, Button as Button72, Skeleton as Skeleton37, cn as cn67 } from "@ai-matrx/design-system";
26795
+ import { BasicInput as BasicInput26, Button as Button72, Skeleton as Skeleton37, cn as cn67 } from "@ai-matrx/design-system";
26537
26796
 
26538
26797
  // src/ExampleTables.tsx
26539
- import { useEffect as useEffect67, useState as useState79 } from "react";
26540
- import { useRecordsClient as useRecordsClient61 } from "@ai-matrx/records/react";
26798
+ import { useEffect as useEffect68, useState as useState79 } from "react";
26799
+ import { useRecordsClient as useRecordsClient62 } from "@ai-matrx/records/react";
26541
26800
  import { loadUseCase, summarize as summarize2, useCaseIds } from "@ai-matrx/records/use-cases";
26542
26801
  import { Button as Button70, Skeleton as Skeleton36, cn as cn66 } from "@ai-matrx/design-system";
26543
26802
  import { jsx as jsx92, jsxs as jsxs85 } from "react/jsx-runtime";
@@ -26546,12 +26805,12 @@ function ExampleTables({
26546
26805
  onClose,
26547
26806
  className
26548
26807
  }) {
26549
- const client = useRecordsClient61();
26808
+ const client = useRecordsClient62();
26550
26809
  const [summaries, setSummaries] = useState79(null);
26551
26810
  const [busy, setBusy] = useState79(null);
26552
26811
  const [error, setError] = useState79(null);
26553
26812
  const [built, setBuilt] = useState79(null);
26554
- useEffect67(() => {
26813
+ useEffect68(() => {
26555
26814
  let alive = true;
26556
26815
  void Promise.all(useCaseIds().map(async (id) => summarize2(await loadUseCase(id)))).then((rows) => {
26557
26816
  if (alive) setSummaries(rows);
@@ -26635,13 +26894,13 @@ import {
26635
26894
  } from "@ai-matrx/records/core";
26636
26895
 
26637
26896
  // src/WhereItLives.tsx
26638
- import { useEffect as useEffect68, useState as useState80 } from "react";
26897
+ import { useEffect as useEffect69, useState as useState80 } from "react";
26639
26898
  import { moveConsequence } from "@ai-matrx/records";
26640
- import { useRecordsClient as useRecordsClient62 } from "@ai-matrx/records/react";
26899
+ import { useRecordsClient as useRecordsClient63 } from "@ai-matrx/records/react";
26641
26900
  import { Button as Button71, ErrorBox as ErrorBox2, Popover as Popover6, PopoverContent as PopoverContent6, PopoverTrigger as PopoverTrigger6 } from "@ai-matrx/design-system";
26642
26901
  import { jsx as jsx93, jsxs as jsxs86 } from "react/jsx-runtime";
26643
26902
  function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "header" }) {
26644
- const client = useRecordsClient62();
26903
+ const client = useRecordsClient63();
26645
26904
  const host = useRecordsUi();
26646
26905
  const [answer, setAnswer] = useState80(null);
26647
26906
  const [attempt, setAttempt] = useState80(0);
@@ -26650,7 +26909,7 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
26650
26909
  const [choosing, setChoosing] = useState80(null);
26651
26910
  const [moving, setMoving] = useState80(false);
26652
26911
  const [said, setSaid] = useState80(null);
26653
- useEffect68(() => {
26912
+ useEffect69(() => {
26654
26913
  if (!armed) return;
26655
26914
  let alive = true;
26656
26915
  setAnswer(null);
@@ -26896,11 +27155,11 @@ function visibilityLaneFor(table) {
26896
27155
  return "organization";
26897
27156
  }
26898
27157
  function TablesHome({ onOpenTable, organizationName, makingOnly = false, className }) {
26899
- const client = useRecordsClient63();
27158
+ const client = useRecordsClient64();
26900
27159
  const tables = useTables4();
26901
27160
  const me = client.config.actor.user_id ?? null;
26902
27161
  const [facts, setFacts] = useState81({ phase: "reading" });
26903
- useEffect69(() => {
27162
+ useEffect70(() => {
26904
27163
  let alive = true;
26905
27164
  void client.tableFacts().then((answered) => {
26906
27165
  if (!alive) return;
@@ -26918,7 +27177,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
26918
27177
  const keptCount = listed.filter((t) => laneFor(t) === "app").length;
26919
27178
  const [askedName, setAskedName] = useState81(null);
26920
27179
  const firstTableId = listed[0]?.id ?? null;
26921
- useEffect69(() => {
27180
+ useEffect70(() => {
26922
27181
  if (organizationName || !firstTableId) return;
26923
27182
  let alive = true;
26924
27183
  void client.tableHome({ table_id: firstTableId }).then((answered) => {
@@ -26938,7 +27197,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
26938
27197
  const [importInto, setImportInto] = useState81(null);
26939
27198
  const [examples, setExamples] = useState81(false);
26940
27199
  const [boards, setBoards] = useState81(null);
26941
- useEffect69(() => {
27200
+ useEffect70(() => {
26942
27201
  if (makingOnly) return;
26943
27202
  let cancelled = false;
26944
27203
  void client.dashboards({}).then((result) => {
@@ -26972,7 +27231,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
26972
27231
  return /* @__PURE__ */ jsxs87("div", { className: cn67("flex min-h-0 flex-col gap-4", className), children: [
26973
27232
  /* @__PURE__ */ jsx94("div", { className: "flex items-center gap-2", children: creating ? /* @__PURE__ */ jsxs87(Fragment38, { children: [
26974
27233
  /* @__PURE__ */ jsx94(
26975
- BasicInput25,
27234
+ BasicInput26,
26976
27235
  {
26977
27236
  autoFocus: true,
26978
27237
  value: name,
@@ -27114,9 +27373,9 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
27114
27373
  }
27115
27374
 
27116
27375
  // src/TablePage.tsx
27117
- import { useCallback as useCallback51, useEffect as useEffect72, useRef as useRef27, useState as useState84 } from "react";
27376
+ import { useCallback as useCallback51, useEffect as useEffect73, useRef as useRef28, useState as useState84 } from "react";
27118
27377
  import { archivedByLine as archivedByLine2 } from "@ai-matrx/records";
27119
- import { useFields as useFields26, useRecordsClient as useRecordsClient64, useTable as useTable24 } from "@ai-matrx/records/react";
27378
+ import { useFields as useFields26, useRecordsClient as useRecordsClient65, useTable as useTable24 } from "@ai-matrx/records/react";
27120
27379
  import {
27121
27380
  BottomSheet,
27122
27381
  Button as Button74,
@@ -27137,7 +27396,7 @@ import {
27137
27396
  } from "@ai-matrx/design-system";
27138
27397
 
27139
27398
  // src/ViewFilter.tsx
27140
- import { useEffect as useEffect70, useMemo as useMemo46, useState as useState82 } from "react";
27399
+ import { useEffect as useEffect71, useMemo as useMemo46, useState as useState82 } from "react";
27141
27400
  import { Button as Button73, cn as cn68 } from "@ai-matrx/design-system";
27142
27401
  import { useFields as useFields25 } from "@ai-matrx/records/react";
27143
27402
  import { jsx as jsx95, jsxs as jsxs88 } from "react/jsx-runtime";
@@ -27155,7 +27414,7 @@ function ViewFilter({ tableId, view, onApply, className }) {
27155
27414
  const saved = view?.where ?? null;
27156
27415
  const [draft, setDraft] = useState82(saved);
27157
27416
  const savedKey = JSON.stringify(saved);
27158
- useEffect70(() => {
27417
+ useEffect71(() => {
27159
27418
  setDraft(saved);
27160
27419
  }, [view?.id, savedKey]);
27161
27420
  const conditionFields = useMemo46(
@@ -27238,7 +27497,7 @@ function ViewFilter({ tableId, view, onApply, className }) {
27238
27497
  }
27239
27498
 
27240
27499
  // src/toolbarFit.ts
27241
- import { useEffect as useEffect71, useState as useState83 } from "react";
27500
+ import { useEffect as useEffect72, useState as useState83 } from "react";
27242
27501
  var FOLDED_GUESS = { look: 104, chooser: 96, tools: 120 };
27243
27502
  function toolbarFold(input) {
27244
27503
  const { available, needsNow, gap, folded } = input;
@@ -27290,7 +27549,7 @@ function rowNeeds(row) {
27290
27549
  }
27291
27550
  function useToolbarFit(row) {
27292
27551
  const [fold, setFold] = useState83(0);
27293
- useEffect71(() => {
27552
+ useEffect72(() => {
27294
27553
  if (!row) return;
27295
27554
  const widths = {
27296
27555
  look: { full: null, folded: null },
@@ -27371,7 +27630,7 @@ function clippedEnds(scrollLeft, clientWidth, scrollWidth) {
27371
27630
  }
27372
27631
  function useSlotScroll(slot) {
27373
27632
  const [ends, setEnds] = useState83("none");
27374
- useEffect71(() => {
27633
+ useEffect72(() => {
27375
27634
  if (!slot) return;
27376
27635
  let pending = 0;
27377
27636
  const read = () => {
@@ -27487,11 +27746,11 @@ function TableNotHere({
27487
27746
  leaveLabel,
27488
27747
  className
27489
27748
  }) {
27490
- const client = useRecordsClient64();
27749
+ const client = useRecordsClient65();
27491
27750
  const [archived, setArchived] = useState84({ phase: "asking" });
27492
27751
  const [restoring, setRestoring] = useState84(false);
27493
27752
  const [refusal2, setRefusal] = useState84(null);
27494
- useEffect72(() => {
27753
+ useEffect73(() => {
27495
27754
  let alive = true;
27496
27755
  void client.tableArchived({ table_id: tableId }).then((answered) => {
27497
27756
  if (!alive) return;
@@ -27668,15 +27927,15 @@ function TablePage({
27668
27927
  onShownViewChange,
27669
27928
  className
27670
27929
  }) {
27671
- const client = useRecordsClient64();
27930
+ const client = useRecordsClient65();
27672
27931
  const table = useTable24(tableId);
27673
27932
  const rights = useTableRights(table.data);
27674
27933
  const pageFields = useFields26(filter ? tableId : null);
27675
27934
  const askedInWords = filter ? filterInWords(filter, pageFields.data ?? []) : null;
27676
- const organizationId = useRecordsClient64().config.organizationId;
27935
+ const organizationId = useRecordsClient65().config.organizationId;
27677
27936
  const [view, setView] = useState84(null);
27678
27937
  const [looks, setLooks] = useState84(void 0);
27679
- useEffect72(() => {
27938
+ useEffect73(() => {
27680
27939
  let live = true;
27681
27940
  setLooks(void 0);
27682
27941
  void readLooks(client, tableId).then((answered) => {
@@ -27725,7 +27984,7 @@ function TablePage({
27725
27984
  const chooserInline = !designated && !phone && toolbarFold2 < 2;
27726
27985
  const chooserCompact = !designated && !phone && toolbarFold2 >= 2;
27727
27986
  const controlsInSheet = phone && !designated;
27728
- useEffect72(() => {
27987
+ useEffect73(() => {
27729
27988
  if (face.kind !== "designated") return;
27730
27989
  if (hostFromLink || opened.layout || layoutChosen) return;
27731
27990
  setHostLayout(face.hostLayout);
@@ -27756,9 +28015,9 @@ function TablePage({
27756
28015
  lookDiffers: view ? lookDiffers(view, look) : false
27757
28016
  };
27758
28017
  const shownSignature = JSON.stringify(shownReport);
27759
- const reportRef = useRef27(onShownViewChange);
28018
+ const reportRef = useRef28(onShownViewChange);
27760
28019
  reportRef.current = onShownViewChange;
27761
- useEffect72(() => {
28020
+ useEffect73(() => {
27762
28021
  reportRef.current?.(JSON.parse(shownSignature));
27763
28022
  }, [shownSignature]);
27764
28023
  const pickLayout = (next) => {
@@ -27776,18 +28035,18 @@ function TablePage({
27776
28035
  onViewChanged?.(id);
27777
28036
  };
27778
28037
  const openedFromMenu = MENU.find((entry) => entry.press.main !== void 0 && entry.press.main === main) ?? MENU.find((entry) => entry.press.rail !== void 0 && entry.press.rail === rail) ?? null;
27779
- useEffect72(() => {
28038
+ useEffect73(() => {
27780
28039
  if (!activeRecordId) return;
27781
28040
  setOpenRecord(activeRecordId);
27782
28041
  setSurface((now) => ({ ...now, rail: "record" }));
27783
28042
  }, [activeRecordId]);
27784
- useEffect72(() => {
28043
+ useEffect73(() => {
27785
28044
  if (activeRecordId) return;
27786
28045
  const named = railFromParam(activeRail);
27787
28046
  if (named === null || named === "share") return;
27788
28047
  setSurface((now) => ({ ...now, rail: named }));
27789
28048
  }, [activeRail, activeRecordId]);
27790
- useEffect72(() => {
28049
+ useEffect73(() => {
27791
28050
  const host = hostLayoutFor(activeView);
27792
28051
  if (host) {
27793
28052
  setHostLayout(host);
@@ -28414,6 +28673,7 @@ export {
28414
28673
  CHECKLIST_REQUIREMENT_LABEL,
28415
28674
  CONDITION_OPS,
28416
28675
  CONTEXT_POLICY_LABEL,
28676
+ ADDABLE_TYPES as CUSTOM_FIELD_ADDABLE_TYPES,
28417
28677
  CaptureRun,
28418
28678
  CaptureSheet,
28419
28679
  ChartBlock,
@@ -28606,6 +28866,7 @@ export {
28606
28866
  conditionValue,
28607
28867
  controlFor,
28608
28868
  currencyCodeFor,
28869
+ customFieldRequestProblems,
28609
28870
  dashboardDeclareArgs,
28610
28871
  dashboardFromSummary,
28611
28872
  dateFormatFor,