@ai-matrx/records-ui 0.85.6 → 0.85.7

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.cjs CHANGED
@@ -105,6 +105,7 @@ __export(src_exports, {
105
105
  GridCell: () => GridCell,
106
106
  HistoryPanel: () => HistoryPanel,
107
107
  INBOX_GROUPINGS: () => INBOX_GROUPINGS,
108
+ INBOX_VIEWS: () => INBOX_VIEWS,
108
109
  IN_MEMORY_QUEUE_REASON: () => IN_MEMORY_QUEUE_REASON,
109
110
  ImportWizard: () => ImportWizard,
110
111
  KERNEL_REASON: () => KERNEL_REASON,
@@ -315,6 +316,7 @@ __export(src_exports, {
315
316
  scalarText: () => scalarText,
316
317
  seedIsSatisfied: () => seedIsSatisfied,
317
318
  shareUnavailableReason: () => shareUnavailableReason,
319
+ snoozeChoices: () => snoozeChoices,
318
320
  specFromBlock: () => specFromBlock,
319
321
  storeDecidesRights: () => storeDecidesRights,
320
322
  styleFromDecorations: () => styleFromDecorations,
@@ -3418,6 +3420,7 @@ function OpenCell({
3418
3420
  // src/Grid.tsx
3419
3421
  var import_react30 = require("react");
3420
3422
  var import_react31 = require("@ai-matrx/records/react");
3423
+ var import_records9 = require("@ai-matrx/records");
3421
3424
  var import_data_table3 = require("@ai-matrx/design-system/data-table");
3422
3425
 
3423
3426
  // src/presentation.ts
@@ -5778,7 +5781,12 @@ function Grid({
5778
5781
  recordId: row.id,
5779
5782
  title: recordNameIn(table.data, row.document ?? {}),
5780
5783
  action: action.name,
5781
- prompt: action.prompt ?? action.name
5784
+ prompt: action.prompt ?? action.name,
5785
+ // No second read: what the grid holds travels with the press.
5786
+ tableName: table.data ? tableName(table.data) : "",
5787
+ fields: fields.data ?? [],
5788
+ document: row.document ?? {},
5789
+ level: (0, import_records9.asPermissionLevel)(row.level)
5782
5790
  })
5783
5791
  },
5784
5792
  action.id
@@ -7161,10 +7169,10 @@ var import_design_system22 = require("@ai-matrx/design-system");
7161
7169
  // src/FormulaTextEditor.tsx
7162
7170
  var import_react40 = require("react");
7163
7171
  var import_react41 = require("@ai-matrx/records/react");
7164
- var import_records9 = require("@ai-matrx/records");
7172
+ var import_records10 = require("@ai-matrx/records");
7165
7173
  var import_design_system20 = require("@ai-matrx/design-system");
7166
7174
  var import_jsx_runtime25 = require("react/jsx-runtime");
7167
- var FORMULA_FUNCTIONS = import_records9.RULE_NODE_KINDS.map((row) => row.node).filter((node) => node.startsWith("fx.")).map((node) => node.slice(3).toUpperCase()).filter((name) => !["ADD", "SUB", "MUL", "DIV", "EQ", "NEQ", "GT", "GTE", "LT", "LTE", "NEG", "FIELD", "CONST"].includes(name)).sort();
7175
+ var FORMULA_FUNCTIONS = import_records10.RULE_NODE_KINDS.map((row) => row.node).filter((node) => node.startsWith("fx.")).map((node) => node.slice(3).toUpperCase()).filter((name) => !["ADD", "SUB", "MUL", "DIV", "EQ", "NEQ", "GT", "GTE", "LT", "LTE", "NEG", "FIELD", "CONST"].includes(name)).sort();
7168
7176
  var RESULT_WORD = {
7169
7177
  number: "a number",
7170
7178
  text: "text",
@@ -7385,11 +7393,11 @@ function EntityReferenceKindPicker({ value, onChange, locked = false, className
7385
7393
  }
7386
7394
 
7387
7395
  // src/FieldEditor.tsx
7388
- var import_records10 = require("@ai-matrx/records");
7396
+ var import_records11 = require("@ai-matrx/records");
7389
7397
  var import_jsx_runtime27 = require("react/jsx-runtime");
7390
7398
  var RULE_KINDS = FIELD_RULE_KIND_VALUES.map((kind) => ({ kind, label: FIELD_RULE_KIND_LABEL[kind] }));
7391
- var SENSITIVITIES = import_records10.FIELD_SENSITIVITIES.map((value) => ({ value, label: FIELD_SENSITIVITY_LABEL[value] }));
7392
- var AGENT_VISIBILITY = import_records10.CONTEXT_POLICIES.map((value) => ({ value, label: CONTEXT_POLICY_LABEL[value] }));
7399
+ var SENSITIVITIES = import_records11.FIELD_SENSITIVITIES.map((value) => ({ value, label: FIELD_SENSITIVITY_LABEL[value] }));
7400
+ var AGENT_VISIBILITY = import_records11.CONTEXT_POLICIES.map((value) => ({ value, label: CONTEXT_POLICY_LABEL[value] }));
7393
7401
  var ROLLUP_OPERATIONS = ROLLUP_AGG_VALUES.map((value) => ({
7394
7402
  value,
7395
7403
  label: ROLLUP_AGG_LABEL[value]
@@ -10499,14 +10507,14 @@ function viewPatchDocument(patch) {
10499
10507
  // src/ViewSwitcher.tsx
10500
10508
  var import_react65 = require("react");
10501
10509
  var import_react66 = require("@ai-matrx/records/react");
10502
- var import_records12 = require("@ai-matrx/records");
10510
+ var import_records13 = require("@ai-matrx/records");
10503
10511
  var import_design_system32 = require("@ai-matrx/design-system");
10504
10512
  var import_data_table5 = require("@ai-matrx/design-system/data-table");
10505
10513
 
10506
10514
  // src/Pipeline.tsx
10507
10515
  var import_react63 = require("react");
10508
10516
  var import_react64 = require("@ai-matrx/records/react");
10509
- var import_records11 = require("@ai-matrx/records");
10517
+ var import_records12 = require("@ai-matrx/records");
10510
10518
  var import_design_system31 = require("@ai-matrx/design-system");
10511
10519
  var import_data_table4 = require("@ai-matrx/design-system/data-table");
10512
10520
  var import_jsx_runtime36 = require("react/jsx-runtime");
@@ -10572,7 +10580,7 @@ function PipelineBoard({
10572
10580
  alive.current = false;
10573
10581
  };
10574
10582
  }, []);
10575
- const filterKey = (0, import_records11.stableFilterKey)(filter);
10583
+ const filterKey = (0, import_records12.stableFilterKey)(filter);
10576
10584
  const reload = (0, import_react63.useCallback)(async () => {
10577
10585
  setLoading(true);
10578
10586
  const [read, board, held] = await Promise.all([
@@ -11216,8 +11224,8 @@ function useViewRecords(view, pageSize = 200, filter) {
11216
11224
  cancelled = true;
11217
11225
  };
11218
11226
  }, [client, ruleId, pageSize]);
11219
- const asked = (0, import_records12.stableFilterKey)(filter ?? null);
11220
- const fromView = asked !== "{}" && (asked === (0, import_records12.stableFilterKey)(view.where ?? null) || asked === (0, import_records12.stableFilterKey)(view.filters ?? null));
11227
+ const asked = (0, import_records13.stableFilterKey)(filter ?? null);
11228
+ const fromView = asked !== "{}" && (asked === (0, import_records13.stableFilterKey)(view.where ?? null) || asked === (0, import_records13.stableFilterKey)(view.filters ?? null));
11221
11229
  const rows = ruleId ? ruled.rows : table.data?.rows ?? [];
11222
11230
  return {
11223
11231
  rows: sortRows(rows, view.sorts ?? []),
@@ -11747,7 +11755,7 @@ function Card2({
11747
11755
 
11748
11756
  // src/ArchivedView.tsx
11749
11757
  var import_react67 = require("react");
11750
- var import_records13 = require("@ai-matrx/records");
11758
+ var import_records14 = require("@ai-matrx/records");
11751
11759
  var import_react68 = require("@ai-matrx/records/react");
11752
11760
  var import_design_system33 = require("@ai-matrx/design-system");
11753
11761
  var import_jsx_runtime38 = require("react/jsx-runtime");
@@ -11757,7 +11765,7 @@ function mayNotRestoreLine(why) {
11757
11765
  return said === "" ? "Bringing a record back needs permission to edit this table. Ask somebody who has it." : said;
11758
11766
  }
11759
11767
  function archivedRowLine(row, titleKey) {
11760
- return `${recordName(row.document, titleKey)} \u2014 ${(0, import_records13.archivedByLine)(row)}`;
11768
+ return `${recordName(row.document, titleKey)} \u2014 ${(0, import_records14.archivedByLine)(row)}`;
11761
11769
  }
11762
11770
  function ArchivedView({
11763
11771
  tableId,
@@ -11771,7 +11779,7 @@ function ArchivedView({
11771
11779
  const table = (0, import_react68.useTable)(tableId);
11772
11780
  const rights = useTableRights(table.data);
11773
11781
  const fields = (0, import_react68.useFields)(tableId);
11774
- const [lane, setLane] = (0, import_react67.useState)(laneFromHost ?? import_records13.DEFAULT_ARCHIVE_LANE);
11782
+ const [lane, setLane] = (0, import_react67.useState)(laneFromHost ?? import_records14.DEFAULT_ARCHIVE_LANE);
11775
11783
  const [rows, setRows] = (0, import_react67.useState)([]);
11776
11784
  const [loading, setLoading] = (0, import_react67.useState)(true);
11777
11785
  const [error, setError] = (0, import_react67.useState)(null);
@@ -11818,15 +11826,15 @@ function ArchivedView({
11818
11826
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: (0, import_design_system33.cn)("flex min-h-0 flex-col gap-2", className), "data-testid": "archived-view", children: [
11819
11827
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
11820
11828
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-sm font-medium", children: "Archived" }),
11821
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ml-auto flex items-center gap-0.5", role: "group", "aria-label": "Archived by", children: import_records13.ARCHIVE_LANES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11829
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ml-auto flex items-center gap-0.5", role: "group", "aria-label": "Archived by", children: import_records14.ARCHIVE_LANES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
11822
11830
  import_design_system33.Button,
11823
11831
  {
11824
11832
  size: "sm",
11825
11833
  variant: option === lane ? "secondary" : "ghost",
11826
11834
  "aria-pressed": option === lane,
11827
- title: import_records13.ARCHIVE_LANE_MEANS[option],
11835
+ title: import_records14.ARCHIVE_LANE_MEANS[option],
11828
11836
  onClick: () => pick(option),
11829
- children: import_records13.ARCHIVE_LANE_LABEL[option]
11837
+ children: import_records14.ARCHIVE_LANE_LABEL[option]
11830
11838
  },
11831
11839
  option
11832
11840
  )) })
@@ -11842,7 +11850,7 @@ function ArchivedView({
11842
11850
  ),
11843
11851
  error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error }) : null,
11844
11852
  loading && !error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system33.Skeleton, { className: "h-24 w-full" }) : null,
11845
- !loading && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { "data-testid": "archived-empty", className: "rounded-md border border-dashed px-3 py-6 text-xs text-muted-foreground", children: (0, import_records13.emptyArchiveLine)(lane) }) : null,
11853
+ !loading && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { "data-testid": "archived-empty", className: "rounded-md border border-dashed px-3 py-6 text-xs text-muted-foreground", children: (0, import_records14.emptyArchiveLine)(lane) }) : null,
11846
11854
  !loading && !error && rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-col gap-1", "data-testid": "archived-rows", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
11847
11855
  "li",
11848
11856
  {
@@ -11852,7 +11860,7 @@ function ArchivedView({
11852
11860
  children: [
11853
11861
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
11854
11862
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-sm", children: recordName(row.document, titleKey) }),
11855
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: (0, import_records13.archivedByLine)(row) }),
11863
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-xs text-muted-foreground", "data-testid": "archived-who", children: (0, import_records14.archivedByLine)(row) }),
11856
11864
  refusal2 && refusal2.recordId === row.id ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefusalNotice, { error: refusal2.error, className: "mt-2" }) : null
11857
11865
  ] }),
11858
11866
  mayRestore ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
@@ -11875,7 +11883,7 @@ function ArchivedView({
11875
11883
 
11876
11884
  // src/ArchivedDisclosure.tsx
11877
11885
  var import_react69 = require("react");
11878
- var import_records14 = require("@ai-matrx/records");
11886
+ var import_records15 = require("@ai-matrx/records");
11879
11887
  var import_react70 = require("@ai-matrx/records/react");
11880
11888
  var import_design_system34 = require("@ai-matrx/design-system");
11881
11889
  var import_jsx_runtime39 = require("react/jsx-runtime");
@@ -11975,10 +11983,10 @@ function ArchivedPortals({
11975
11983
  error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RefusalNotice, { error }) : null,
11976
11984
  rows === null && !error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system34.Skeleton, { className: "h-16 w-full" }) : null,
11977
11985
  said ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "rounded-md border border-border px-3 py-2 text-xs", "data-testid": "archived-portal-said", children: said }) : null,
11978
- rows !== null && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { "data-testid": "archived-portals-empty", className: "text-xs text-muted-foreground", children: (0, import_records14.emptyPortalArchiveLine)() }) : null,
11986
+ rows !== null && !error && rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { "data-testid": "archived-portals-empty", className: "text-xs text-muted-foreground", children: (0, import_records15.emptyPortalArchiveLine)() }) : null,
11979
11987
  rows !== null && rows.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "flex flex-col gap-1.5", "data-testid": "archived-portals", children: rows.map((portal) => {
11980
11988
  const asking = confirming === portal.portal_id;
11981
- const matches2 = (0, import_records14.portalTitleTypedBack)(typed, portal.title);
11989
+ const matches2 = (0, import_records15.portalTitleTypedBack)(typed, portal.title);
11982
11990
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
11983
11991
  "li",
11984
11992
  {
@@ -12017,7 +12025,7 @@ function ArchivedPortals({
12017
12025
  ] }),
12018
12026
  asking ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
12019
12027
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
12020
- (0, import_records14.portalConfirmLine)(portal.title),
12028
+ (0, import_records15.portalConfirmLine)(portal.title),
12021
12029
  " Restoring it puts it back exactly as it was: everyone who was invited can sign in again, and it shows the same Tables."
12022
12030
  ] }),
12023
12031
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
@@ -12615,9 +12623,18 @@ function useMyChecklistSteps(limit = 25) {
12615
12623
  }, [refresh]);
12616
12624
  return { steps, loading, error, refresh };
12617
12625
  }
12618
- function MyChecklistSteps({ className }) {
12626
+ function MyChecklistSteps({
12627
+ className,
12628
+ onlyIds,
12629
+ onSteps,
12630
+ actions
12631
+ }) {
12619
12632
  const client = (0, import_react78.useRecordsClient)();
12620
- const { steps, loading, error, refresh } = useMyChecklistSteps();
12633
+ const { steps: held, loading, error, refresh } = useMyChecklistSteps();
12634
+ (0, import_react77.useEffect)(() => {
12635
+ onSteps?.(held.map((s) => s.step_id));
12636
+ }, [held, onSteps]);
12637
+ const steps = onlyIds ? held.filter((s) => onlyIds.has(s.step_id)) : held;
12621
12638
  const [busy, setBusy] = (0, import_react77.useState)(null);
12622
12639
  const [refusal2, setRefusal] = (0, import_react77.useState)(null);
12623
12640
  const complete = (0, import_react77.useCallback)(
@@ -12643,15 +12660,20 @@ function MyChecklistSteps({ className }) {
12643
12660
  ] }),
12644
12661
  error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error }) : null,
12645
12662
  refusal2 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(RefusalNotice, { error: refusal2 }) : null,
12646
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ol", { className: "flex flex-col gap-1.5", children: steps.map((step2) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
12647
- StepRow,
12648
- {
12649
- step: step2,
12650
- busy: busy === step2.step_id,
12651
- onComplete: (evidence) => void complete(step2, evidence)
12652
- },
12653
- step2.step_id
12654
- )) })
12663
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ol", { className: "flex flex-col gap-1.5", children: steps.map(
12664
+ (step2) => actions ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-0.5", "data-step-row": step2.step_id, children: [
12665
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StepRow, { step: step2, busy: busy === step2.step_id, onComplete: (evidence) => void complete(step2, evidence) }),
12666
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex items-center justify-end gap-1", children: actions(step2.step_id) })
12667
+ ] }, step2.step_id) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
12668
+ StepRow,
12669
+ {
12670
+ step: step2,
12671
+ busy: busy === step2.step_id,
12672
+ onComplete: (evidence) => void complete(step2, evidence)
12673
+ },
12674
+ step2.step_id
12675
+ )
12676
+ ) })
12655
12677
  ] });
12656
12678
  }
12657
12679
  function ChecklistsPanel({ tableId, onOpenRecord, className }) {
@@ -13031,6 +13053,24 @@ var DUE_WORD2 = DUE_STATE_LABEL;
13031
13053
  var INBOX_GROUPINGS = ["kind", "table", "none"];
13032
13054
  var GROUPING_WORD = { kind: "Kind", table: "Table", none: "None" };
13033
13055
  var KIND_ORDER = { approval: 0, proposal: 1, assignment: 2 };
13056
+ var INBOX_VIEWS = ["inbox", "snoozed", "done"];
13057
+ var VIEW_WORD = { inbox: "Inbox", snoozed: "Snoozed", done: "Done" };
13058
+ function snoozeChoices(now = /* @__PURE__ */ new Date()) {
13059
+ const at8 = (d) => {
13060
+ const x = new Date(d);
13061
+ x.setHours(8, 0, 0, 0);
13062
+ return x;
13063
+ };
13064
+ const later = new Date(now.getTime() + 3 * 36e5);
13065
+ const tomorrow = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));
13066
+ const daysToMonday = (8 - now.getDay()) % 7 || 7;
13067
+ const monday = at8(new Date(now.getFullYear(), now.getMonth(), now.getDate() + daysToMonday));
13068
+ return [
13069
+ { key: "1", label: "Later today", until: later },
13070
+ { key: "2", label: "Tomorrow, 8 AM", until: tomorrow },
13071
+ { key: "3", label: "Next Monday, 8 AM", until: monday }
13072
+ ];
13073
+ }
13034
13074
  function groupInbox(items, by) {
13035
13075
  if (by === "none") return [{ key: "all", label: null, items: [...items] }];
13036
13076
  const groups = /* @__PURE__ */ new Map();
@@ -13072,8 +13112,19 @@ function ActionInbox({
13072
13112
  const anchor = (0, import_react79.useRef)(null);
13073
13113
  const [deciding, setDeciding] = (0, import_react79.useState)(false);
13074
13114
  const [batchSaid, setBatchSaid] = (0, import_react79.useState)(null);
13115
+ const [view, setView] = (0, import_react79.useState)("inbox");
13116
+ const [counts, setCounts] = (0, import_react79.useState)(null);
13117
+ const [snoozing, setSnoozing] = (0, import_react79.useState)(null);
13118
+ const [pickAt, setPickAt] = (0, import_react79.useState)("");
13119
+ const [said, setSaid] = (0, import_react79.useState)(null);
13120
+ const [stepIds, setStepIds] = (0, import_react79.useState)(/* @__PURE__ */ new Set());
13121
+ const onSteps = (0, import_react79.useCallback)((ids) => setStepIds(new Set(ids)), []);
13075
13122
  const load = (0, import_react79.useCallback)(async () => {
13076
- const result = await client.workInbox({ limit: 200, includeDecided: showDecided });
13123
+ const [result, counted] = await Promise.all([
13124
+ client.workInbox({ limit: 200, includeDecided: view === "inbox" && showDecided, view }),
13125
+ client.inboxCounts()
13126
+ ]);
13127
+ setCounts(counted.ok ? counted.data[0] ?? null : null);
13077
13128
  if (!result.ok) {
13078
13129
  setError(result.error);
13079
13130
  setItems([]);
@@ -13081,15 +13132,19 @@ function ActionInbox({
13081
13132
  }
13082
13133
  setError(null);
13083
13134
  setItems(result.data);
13084
- }, [client, showDecided]);
13135
+ }, [client, showDecided, view]);
13085
13136
  (0, import_react79.useEffect)(() => {
13086
13137
  void load();
13087
13138
  }, [load]);
13088
13139
  const narrowed = (0, import_react79.useMemo)(() => {
13089
- const all = items ?? [];
13140
+ const all = (items ?? []).filter((i) => !(view === "inbox" && i.kind === "assignment" && stepIds.has(i.item_id)));
13090
13141
  if (!tableId || everyTable) return all;
13091
13142
  return all.filter((i) => i.table_id === tableId);
13092
- }, [items, tableId, everyTable]);
13143
+ }, [items, tableId, everyTable, view, stepIds]);
13144
+ const waitingIds = (0, import_react79.useMemo)(
13145
+ () => new Set((items ?? []).filter((i) => i.kind === "assignment").map((i) => i.item_id)),
13146
+ [items]
13147
+ );
13093
13148
  const groups = (0, import_react79.useMemo)(() => groupInbox(narrowed, groupBy), [narrowed, groupBy]);
13094
13149
  const shown3 = (0, import_react79.useMemo)(() => groups.flatMap((g) => g.items), [groups]);
13095
13150
  const elsewhere = (items?.length ?? 0) - narrowed.length;
@@ -13148,9 +13203,9 @@ function ActionInbox({
13148
13203
  setError(result.error);
13149
13204
  return;
13150
13205
  }
13151
- const said = {};
13152
- for (const r of result.data.results) said[r.item] = r.sentence;
13153
- setOutcome((o) => ({ ...o, ...said }));
13206
+ const said2 = {};
13207
+ for (const r of result.data.results) said2[r.item] = r.sentence;
13208
+ setOutcome((o) => ({ ...o, ...said2 }));
13154
13209
  const { approved, declined, not_decided } = result.data;
13155
13210
  setBatchSaid(
13156
13211
  [
@@ -13164,6 +13219,79 @@ function ActionInbox({
13164
13219
  },
13165
13220
  [client, shown3, selected, decidable, load]
13166
13221
  );
13222
+ const snooze = (0, import_react79.useCallback)(
13223
+ async (itemId, title, until) => {
13224
+ setSnoozing(null);
13225
+ const result = await client.inboxSnooze({ item_id: itemId, until: until.toISOString() });
13226
+ if (!result.ok) {
13227
+ setError(result.error);
13228
+ return;
13229
+ }
13230
+ setSaid({
13231
+ text: `Snoozed until ${whenWords2(until.toISOString())}: ${title}`,
13232
+ undo: async () => {
13233
+ const back = await client.inboxUnsnooze({ item_id: itemId });
13234
+ if (!back.ok) setError(back.error);
13235
+ else setSaid({ text: back.data.sentence, undo: null });
13236
+ await load();
13237
+ }
13238
+ });
13239
+ await load();
13240
+ },
13241
+ [client, load]
13242
+ );
13243
+ const unsnooze = (0, import_react79.useCallback)(
13244
+ async (itemId) => {
13245
+ const result = await client.inboxUnsnooze({ item_id: itemId });
13246
+ if (!result.ok) {
13247
+ setError(result.error);
13248
+ return;
13249
+ }
13250
+ setSaid({ text: result.data.sentence, undo: null });
13251
+ await load();
13252
+ },
13253
+ [client, load]
13254
+ );
13255
+ const clearItem = (0, import_react79.useCallback)(
13256
+ async (itemId) => {
13257
+ const result = await client.inboxClear({ item_id: itemId });
13258
+ if (!result.ok) {
13259
+ setError(result.error);
13260
+ return;
13261
+ }
13262
+ setSaid({
13263
+ text: result.data.sentence,
13264
+ undo: async () => {
13265
+ const back = await client.inboxUnclear({ item_id: itemId });
13266
+ if (!back.ok) setError(back.error);
13267
+ else setSaid({ text: back.data.sentence, undo: null });
13268
+ await load();
13269
+ }
13270
+ });
13271
+ await load();
13272
+ },
13273
+ [client, load]
13274
+ );
13275
+ const unclear = (0, import_react79.useCallback)(
13276
+ async (itemId) => {
13277
+ const result = await client.inboxUnclear({ item_id: itemId });
13278
+ if (!result.ok) {
13279
+ setError(result.error);
13280
+ return;
13281
+ }
13282
+ setSaid({ text: result.data.sentence, undo: null });
13283
+ await load();
13284
+ },
13285
+ [client, load]
13286
+ );
13287
+ const clearable = (0, import_react79.useCallback)(
13288
+ (item) => item.kind === "assignment" && view === "inbox",
13289
+ [view]
13290
+ );
13291
+ const snoozable = (0, import_react79.useCallback)(
13292
+ (item) => view === "inbox" && (item.kind === "assignment" || item.state === "pending") && !outcome[item.item_id],
13293
+ [view, outcome]
13294
+ );
13167
13295
  const open = (0, import_react79.useCallback)(
13168
13296
  (item) => {
13169
13297
  if (!onOpenRecord || !item.subject_id) return;
@@ -13175,6 +13303,47 @@ function ActionInbox({
13175
13303
  (event) => {
13176
13304
  const item = shown3[cursor];
13177
13305
  const key = event.key;
13306
+ if (event.target?.tagName === "INPUT") return;
13307
+ if (snoozing) {
13308
+ const choice = snoozeChoices().find((c) => c.key === key);
13309
+ const row = shown3.find((i) => i.item_id === snoozing);
13310
+ if (choice && row) {
13311
+ event.preventDefault();
13312
+ void snooze(row.item_id, row.title, choice.until);
13313
+ return;
13314
+ }
13315
+ if (key === "Escape") {
13316
+ event.preventDefault();
13317
+ setSnoozing(null);
13318
+ return;
13319
+ }
13320
+ }
13321
+ if (key === "s" && item && snoozable(item)) {
13322
+ event.preventDefault();
13323
+ setSnoozing((open2) => open2 === item.item_id ? null : item.item_id);
13324
+ return;
13325
+ }
13326
+ if (key === "e" && item && clearable(item)) {
13327
+ event.preventDefault();
13328
+ void clearItem(item.item_id);
13329
+ return;
13330
+ }
13331
+ if (key === "u" && item && view !== "inbox") {
13332
+ event.preventDefault();
13333
+ void (view === "snoozed" ? unsnooze(item.item_id) : unclear(item.item_id));
13334
+ return;
13335
+ }
13336
+ if (key === "z" && said?.undo) {
13337
+ event.preventDefault();
13338
+ void said.undo();
13339
+ return;
13340
+ }
13341
+ if (key === "v") {
13342
+ event.preventDefault();
13343
+ setView((v) => INBOX_VIEWS[(INBOX_VIEWS.indexOf(v) + 1) % INBOX_VIEWS.length]);
13344
+ setSelected(/* @__PURE__ */ new Set());
13345
+ return;
13346
+ }
13178
13347
  if (key === "j" || key === "ArrowDown") {
13179
13348
  event.preventDefault();
13180
13349
  setCursor((c) => Math.min(shown3.length - 1, c + 1));
@@ -13208,7 +13377,7 @@ function ActionInbox({
13208
13377
  void decide(item, key === "a");
13209
13378
  }
13210
13379
  },
13211
- [shown3, cursor, decide, open, load, decidable, select, selected, decideSelected]
13380
+ [shown3, cursor, decide, open, load, decidable, select, selected, decideSelected, snoozing, snooze, clearItem, unsnooze, unclear, said, view, snoozable, clearable]
13212
13381
  );
13213
13382
  const renderRow = (item, index) => {
13214
13383
  const settled = outcome[item.item_id];
@@ -13260,9 +13429,84 @@ function ActionInbox({
13260
13429
  children: DUE_WORD2[item.due_state] ?? item.due_state
13261
13430
  }
13262
13431
  ) : null,
13432
+ view === "snoozed" && item.snoozed_until ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "shrink-0 text-[11px] text-muted-foreground", "data-testid": "inbox-back-at", children: [
13433
+ "Back ",
13434
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("time", { dateTime: item.snoozed_until, children: whenWords2(item.snoozed_until) })
13435
+ ] }) : null,
13436
+ view === "done" && item.cleared_at ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: [
13437
+ "Cleared ",
13438
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("time", { dateTime: item.cleared_at, children: whenWords2(item.cleared_at) })
13439
+ ] }) : null,
13440
+ snoozable(item) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13441
+ import_design_system38.Button,
13442
+ {
13443
+ size: "sm",
13444
+ variant: "ghost",
13445
+ className: "h-5 px-1 text-[11px]",
13446
+ "aria-expanded": snoozing === item.item_id,
13447
+ onClick: () => setSnoozing((o) => o === item.item_id ? null : item.item_id),
13448
+ children: "Snooze"
13449
+ }
13450
+ ) : null,
13451
+ clearable(item) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(item.item_id), children: "Done" }) : null,
13452
+ view === "snoozed" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unsnooze(item.item_id), children: "Unsnooze" }) : null,
13453
+ view === "done" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void unclear(item.item_id), children: "Put back" }) : null,
13263
13454
  item.subject_id && onOpenRecord ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => open(item), children: "Open" }) : null
13264
13455
  ] }),
13265
13456
  item.summary ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", children: item.summary }) : null,
13457
+ snoozing === item.item_id ? (
13458
+ // SUPERHUMAN'S CHOICES, then any moment the person names. The picked time's own Snooze is
13459
+ // absent until a time is picked — never a greyed button that does nothing.
13460
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
13461
+ "div",
13462
+ {
13463
+ role: "group",
13464
+ "aria-label": `Snooze ${item.title} until`,
13465
+ "data-testid": "inbox-snooze-choices",
13466
+ className: "flex flex-wrap items-center gap-1 rounded border border-border bg-muted/40 p-1.5",
13467
+ children: [
13468
+ snoozeChoices().map((c) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
13469
+ import_design_system38.Button,
13470
+ {
13471
+ size: "sm",
13472
+ variant: "ghost",
13473
+ className: "h-6 px-2 text-[11px]",
13474
+ title: c.until.toLocaleString(),
13475
+ onClick: () => void snooze(item.item_id, item.title, c.until),
13476
+ children: [
13477
+ c.label,
13478
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-1 text-muted-foreground", children: c.key })
13479
+ ]
13480
+ },
13481
+ c.key
13482
+ )),
13483
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13484
+ "input",
13485
+ {
13486
+ type: "datetime-local",
13487
+ "aria-label": "Pick a time",
13488
+ value: pickAt,
13489
+ onChange: (e) => setPickAt(e.target.value),
13490
+ className: "h-6 rounded border border-border bg-background px-1 text-[11px]"
13491
+ }
13492
+ ),
13493
+ pickAt ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13494
+ import_design_system38.Button,
13495
+ {
13496
+ size: "sm",
13497
+ className: "h-6 px-2 text-[11px]",
13498
+ onClick: () => {
13499
+ const until = new Date(pickAt);
13500
+ setPickAt("");
13501
+ void snooze(item.item_id, item.title, until);
13502
+ },
13503
+ children: "Snooze until then"
13504
+ }
13505
+ ) : null
13506
+ ]
13507
+ }
13508
+ )
13509
+ ) : null,
13266
13510
  settled ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs", children: settled }) : item.kind === "assignment" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[11px] text-muted-foreground", children: item.state === "open" ? "Waiting on you." : `${item.state}.` }) : closed ? (
13267
13511
  // A CLOSED ITEM SAYS WHO AND WHEN, and then what happened, in the store's own sentence.
13268
13512
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-col gap-0.5", "data-testid": "inbox-closed", children: [
@@ -13302,9 +13546,34 @@ function ActionInbox({
13302
13546
  "aria-label": "Inbox",
13303
13547
  children: [
13304
13548
  /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
13305
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "text-sm font-medium", children: "Inbox" }),
13306
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: shown3.length }),
13307
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-auto hidden text-[10px] text-muted-foreground lg:inline", children: "j/k move \xB7 x select \xB7 a approve \xB7 d decline \xB7 o open \xB7 g group \xB7 h decided \xB7 r refresh" }),
13549
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "sr-only", children: "Inbox" }),
13550
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { role: "tablist", "aria-label": "Inbox views", className: "flex items-center gap-0.5", children: INBOX_VIEWS.map((v) => {
13551
+ const n = counts === null ? v === view ? shown3.length : null : v === "inbox" ? counts.waiting : v === "snoozed" ? counts.snoozed : counts.cleared;
13552
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
13553
+ "button",
13554
+ {
13555
+ type: "button",
13556
+ role: "tab",
13557
+ "aria-selected": view === v,
13558
+ "data-inbox-view": v,
13559
+ onClick: () => {
13560
+ setView(v);
13561
+ setSelected(/* @__PURE__ */ new Set());
13562
+ setSnoozing(null);
13563
+ },
13564
+ className: (0, import_design_system38.cn)(
13565
+ "flex items-baseline gap-1 rounded px-1.5 py-0.5 text-xs",
13566
+ view === v ? "bg-accent font-medium text-foreground" : "text-muted-foreground"
13567
+ ),
13568
+ children: [
13569
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: VIEW_WORD[v] }),
13570
+ n !== null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "tabular-nums text-[11px] text-muted-foreground", children: n }) : null
13571
+ ]
13572
+ },
13573
+ v
13574
+ );
13575
+ }) }),
13576
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-auto hidden text-[10px] text-muted-foreground lg:inline", children: view === "inbox" ? "j/k move \xB7 x select \xB7 a approve \xB7 d decline \xB7 s snooze \xB7 e done \xB7 z undo \xB7 o open \xB7 v view \xB7 g group \xB7 h decided" : "j/k move \xB7 u put back \xB7 z undo \xB7 o open \xB7 v view \xB7 g group" }),
13308
13577
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13309
13578
  "div",
13310
13579
  {
@@ -13327,7 +13596,7 @@ function ActionInbox({
13327
13596
  ))
13328
13597
  }
13329
13598
  ),
13330
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }),
13599
+ view === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => setShowDecided((s) => !s), children: showDecided ? "Hide decided" : "Show decided" }) : null,
13331
13600
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-7 px-2 text-xs", onClick: () => void load(), children: "Refresh" })
13332
13601
  ] }),
13333
13602
  error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(RefusalNotice, { error }) : null,
@@ -13372,7 +13641,12 @@ function ActionInbox({
13372
13641
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: batchSaid }),
13373
13642
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setBatchSaid(null), children: "Close" })
13374
13643
  ] }) : null,
13375
- shown3.length === 0 ? (
13644
+ said ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "flex items-center gap-2 text-xs", role: "status", "data-testid": "inbox-said", children: [
13645
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: said.text }),
13646
+ said.undo ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => void said.undo?.(), children: "Undo" }) : null,
13647
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-6 px-2", onClick: () => setSaid(null), children: "Close" })
13648
+ ] }) : null,
13649
+ shown3.length === 0 && view === "snoozed" && !error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "inbox-empty", children: "Nothing is snoozed. Press s on a row to put it off until a time; it comes back to the top of your inbox then, and only your inbox changes." }) : shown3.length === 0 && view === "done" && !error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "inbox-empty", children: "Nothing is cleared. Press e on a piece of work you have seen to take it out of your inbox; it comes back if somebody else changes it." }) : shown3.length === 0 ? (
13376
13650
  // AN EMPTY INBOX SAYS WHY — and never under a refusal, where "nothing is waiting" would be
13377
13651
  // a guess dressed as an answer.
13378
13652
  error ? null : tableId && !everyTable && elsewhere > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground", "data-testid": "inbox-empty", children: [
@@ -13402,7 +13676,31 @@ function ActionInbox({
13402
13676
  ) : null,
13403
13677
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ol", { className: "flex flex-col gap-1", children: group.items.map((item) => renderRow(item, shown3.indexOf(item))) })
13404
13678
  ] }, group.key)) }),
13405
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(MyChecklistSteps, { className: "border-t pt-2" })
13679
+ view === "inbox" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13680
+ MyChecklistSteps,
13681
+ {
13682
+ className: "border-t pt-2",
13683
+ onlyIds: waitingIds,
13684
+ onSteps,
13685
+ actions: (stepId) => {
13686
+ const title = items?.find((i) => i.item_id === stepId)?.title ?? "this step";
13687
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
13688
+ snoozing === stepId ? snoozeChoices().map((c) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
13689
+ import_design_system38.Button,
13690
+ {
13691
+ size: "sm",
13692
+ variant: "ghost",
13693
+ className: "h-5 px-1 text-[11px]",
13694
+ onClick: () => void snooze(stepId, title, c.until),
13695
+ children: c.label
13696
+ },
13697
+ c.key
13698
+ )) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => setSnoozing(stepId), children: "Snooze" }),
13699
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_design_system38.Button, { size: "sm", variant: "ghost", className: "h-5 px-1 text-[11px]", onClick: () => void clearItem(stepId), children: "Done" })
13700
+ ] });
13701
+ }
13702
+ }
13703
+ ) : null
13406
13704
  ]
13407
13705
  }
13408
13706
  );
@@ -14494,7 +14792,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
14494
14792
  // src/PortalsPanel.tsx
14495
14793
  var import_react91 = require("react");
14496
14794
  var import_react92 = require("@ai-matrx/records/react");
14497
- var import_records15 = require("@ai-matrx/records");
14795
+ var import_records16 = require("@ai-matrx/records");
14498
14796
  var import_design_system45 = require("@ai-matrx/design-system");
14499
14797
 
14500
14798
  // src/BuildOrAsk.tsx
@@ -14943,7 +15241,7 @@ function PortalsPanel({ tableId, activePortalId, className }) {
14943
15241
  ] }) : null,
14944
15242
  activePortalId && !shown3.some((p) => p.portal_id === activePortalId) ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "rounded-md border border-amber-600/40 bg-amber-500/5 px-3 py-2 text-xs leading-relaxed text-amber-700 dark:border-amber-400/40 dark:text-amber-300", children: PORTAL_NOT_HERE_LINE }) : null,
14945
15243
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("ul", { className: "flex flex-col gap-2", children: shown3.map((portal) => {
14946
- const url = `${origin}${(0, import_records15.portalPath)(portal.slug)}`;
15244
+ const url = `${origin}${(0, import_records16.portalPath)(portal.slug)}`;
14947
15245
  const open = openId === portal.portal_id;
14948
15246
  const linked = portal.portal_id === activePortalId;
14949
15247
  return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
@@ -15058,8 +15356,8 @@ function ArchivePortalControl({
15058
15356
  }
15059
15357
  ),
15060
15358
  asking ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "mt-1.5 flex w-full flex-col gap-1.5 rounded-md border border-dashed border-border p-2.5", children: [
15061
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "portal-archive-consequence", children: (0, import_records15.portalArchiveConsequence)(portal.title, portal.signed_in, portal.invited) }),
15062
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records15.portalConfirmLine)(portal.title) }),
15359
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "portal-archive-consequence", children: (0, import_records16.portalArchiveConsequence)(portal.title, portal.signed_in, portal.invited) }),
15360
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records16.portalConfirmLine)(portal.title) }),
15063
15361
  /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", children: [
15064
15362
  /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
15065
15363
  import_design_system45.BasicInput,
@@ -15077,7 +15375,7 @@ function ArchivePortalControl({
15077
15375
  size: "sm",
15078
15376
  variant: "destructive",
15079
15377
  "data-testid": "portal-archive-do",
15080
- disabled: busy || !(0, import_records15.portalTitleTypedBack)(typed, portal.title),
15378
+ disabled: busy || !(0, import_records16.portalTitleTypedBack)(typed, portal.title),
15081
15379
  onClick: () => void go(),
15082
15380
  children: busy ? "Archiving\u2026" : "Archive it"
15083
15381
  }
@@ -16236,7 +16534,7 @@ function usePublishGate() {
16236
16534
  }
16237
16535
 
16238
16536
  // src/FormBuilder.tsx
16239
- var import_records16 = require("@ai-matrx/records");
16537
+ var import_records17 = require("@ai-matrx/records");
16240
16538
  var import_design_system51 = require("@ai-matrx/design-system");
16241
16539
 
16242
16540
  // src/FormRunner.tsx
@@ -17101,7 +17399,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
17101
17399
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
17102
17400
  PublishRow,
17103
17401
  {
17104
- url: `${publicOrigin}${(0, import_records16.publicFormPath)(draft.id)}`,
17402
+ url: `${publicOrigin}${(0, import_records17.publicFormPath)(draft.id)}`,
17105
17403
  state: draft.state,
17106
17404
  mayPublish: rights.structure && !publishGate.blocked,
17107
17405
  why: publishGate.why ?? rights.why("structure"),
@@ -18119,7 +18417,7 @@ function SignBlock({ tableId, recordId, render, className }) {
18119
18417
  // src/ChartBlock.tsx
18120
18418
  var import_react115 = require("react");
18121
18419
  var import_recharts = require("recharts");
18122
- var import_records17 = require("@ai-matrx/records");
18420
+ var import_records18 = require("@ai-matrx/records");
18123
18421
  var import_core8 = require("@ai-matrx/records/core");
18124
18422
  var import_design_system56 = require("@ai-matrx/design-system");
18125
18423
  var import_jsx_runtime61 = require("react/jsx-runtime");
@@ -18190,7 +18488,7 @@ function ChartBlock({ block, subject, className }) {
18190
18488
  const kind = block.kind;
18191
18489
  const tableId = block.table_id ?? subject;
18192
18490
  const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: "count" }];
18193
- const primary = (0, import_records17.measureKey)(measures[0]);
18491
+ const primary = (0, import_records18.measureKey)(measures[0]);
18194
18492
  const windows = kind === "stuck" ? null : block.compare ?? null;
18195
18493
  const compared = !!windows;
18196
18494
  const grain = block.bucket?.by ?? null;
@@ -19110,7 +19408,7 @@ function TargetControl({
19110
19408
  // src/FormsPanel.tsx
19111
19409
  var import_react118 = require("react");
19112
19410
  var import_react119 = require("@ai-matrx/records/react");
19113
- var import_records18 = require("@ai-matrx/records");
19411
+ var import_records19 = require("@ai-matrx/records");
19114
19412
  var import_design_system58 = require("@ai-matrx/design-system");
19115
19413
  var import_jsx_runtime63 = require("react/jsx-runtime");
19116
19414
  var FORM_NOT_HERE_LINE = "The link named a form this table does not have \u2014 it may have been removed, or it belongs to another table. The forms this table does have are listed here.";
@@ -19214,7 +19512,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
19214
19512
  }
19215
19513
  ) : null,
19216
19514
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("ul", { className: "flex flex-col gap-2", children: forms.map((form) => {
19217
- const url = `${origin}${(0, import_records18.publicFormPath)(form.form_id)}`;
19515
+ const url = `${origin}${(0, import_records19.publicFormPath)(form.form_id)}`;
19218
19516
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
19219
19517
  "li",
19220
19518
  {
@@ -19279,7 +19577,7 @@ function FormsPanel({ tableId, activeFormId, className }) {
19279
19577
  // src/BookingBuilder.tsx
19280
19578
  var import_react120 = require("react");
19281
19579
  var import_react121 = require("@ai-matrx/records/react");
19282
- var import_records19 = require("@ai-matrx/records");
19580
+ var import_records20 = require("@ai-matrx/records");
19283
19581
  var import_design_system59 = require("@ai-matrx/design-system");
19284
19582
  var import_jsx_runtime64 = require("react/jsx-runtime");
19285
19583
  var STORE_ANSWERS_THESE = ["slot", "status", "booked_with"];
@@ -19423,7 +19721,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
19423
19721
  if (!rights.structure) {
19424
19722
  return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { className: (0, import_design_system59.cn)("text-xs text-muted-foreground", className), children: rights.why("structure") ?? "Making a booking page needs the admin level on this table, because it lets people with no account take time in your calendar." });
19425
19723
  }
19426
- const url = formId ? `${publicOrigin}${(0, import_records19.bookingPath)(formId)}` : null;
19724
+ const url = formId ? `${publicOrigin}${(0, import_records20.bookingPath)(formId)}` : null;
19427
19725
  const shown3 = offer ?? null;
19428
19726
  return (
19429
19727
  // THE RAIL IS 384px WIDE AND THE VIEWPORT IS NOT (walk 1, 2026-09-21):
@@ -19625,7 +19923,7 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
19625
19923
  // src/BookingSlots.tsx
19626
19924
  var import_react122 = require("react");
19627
19925
  var import_react123 = require("@ai-matrx/records/react");
19628
- var import_records20 = require("@ai-matrx/records");
19926
+ var import_records21 = require("@ai-matrx/records");
19629
19927
  var import_design_system60 = require("@ai-matrx/design-system");
19630
19928
  var import_jsx_runtime65 = require("react/jsx-runtime");
19631
19929
  var BOOKING_NOT_HERE_LINE = "The link named a booking page this table does not have \u2014 it may have been closed for good, or it writes into another table. The booking pages this table does have are listed here.";
@@ -19742,7 +20040,7 @@ function BookingSlots({ tableId, activeBookingId, className }) {
19742
20040
  " Open the table the appointments should land in to make one."
19743
20041
  ] }) : null,
19744
20042
  /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("ul", { className: "flex flex-col gap-2", children: pages.map((page) => {
19745
- const url = `${origin}${(0, import_records20.bookingPath)(page.form_id)}`;
20043
+ const url = `${origin}${(0, import_records21.bookingPath)(page.form_id)}`;
19746
20044
  const mayOpen = levels.data?.[page.table_id] === "admin";
19747
20045
  const open = page.published_at !== null && page.closed_at === null;
19748
20046
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
@@ -19844,7 +20142,7 @@ var import_design_system62 = require("@ai-matrx/design-system");
19844
20142
 
19845
20143
  // src/CaptureRun.tsx
19846
20144
  var import_react124 = require("react");
19847
- var import_records21 = require("@ai-matrx/records");
20145
+ var import_records22 = require("@ai-matrx/records");
19848
20146
  var import_react125 = require("@ai-matrx/records/react");
19849
20147
  var import_design_system61 = require("@ai-matrx/design-system");
19850
20148
  var import_jsx_runtime66 = require("react/jsx-runtime");
@@ -19899,7 +20197,7 @@ function CaptureRun({ sheetId, face: given, className }) {
19899
20197
  const [sending, setSending] = (0, import_react124.useState)(false);
19900
20198
  const queueRef = (0, import_react124.useRef)(null);
19901
20199
  (0, import_react124.useEffect)(() => {
19902
- const q2 = (0, import_records21.openCaptureQueue)({
20200
+ const q2 = (0, import_records22.openCaptureQueue)({
19903
20201
  onChange: (c, all) => {
19904
20202
  setCounts(c);
19905
20203
  setItems(all);
@@ -20166,7 +20464,7 @@ function CaptureRun({ sheetId, face: given, className }) {
20166
20464
  value: String(answers[q.field] ?? ""),
20167
20465
  onChange: (e) => {
20168
20466
  const raw = e.target.value;
20169
- const answered2 = field ? (0, import_records21.coerceTypedAnswer)(field, raw, { label: q.ask ?? (0, import_records21.coercionLabel)(field) }) : { value: raw };
20467
+ const answered2 = field ? (0, import_records22.coerceTypedAnswer)(field, raw, { label: q.ask ?? (0, import_records22.coercionLabel)(field) }) : { value: raw };
20170
20468
  setAnswers((held) => ({
20171
20469
  ...held,
20172
20470
  [q.field]: raw === "" ? "" : "refusal" in answered2 ? raw : answered2.value
@@ -20823,7 +21121,7 @@ function recordsDataSource(client, fallbackSchema = "custom") {
20823
21121
  var import_react140 = require("react");
20824
21122
  var import_react141 = require("@ai-matrx/records/react");
20825
21123
  var import_core10 = require("@ai-matrx/records/core");
20826
- var import_records23 = require("@ai-matrx/records");
21124
+ var import_records24 = require("@ai-matrx/records");
20827
21125
  var import_design_system68 = require("@ai-matrx/design-system");
20828
21126
 
20829
21127
  // src/ExampleTables.tsx
@@ -20921,7 +21219,7 @@ var import_core9 = require("@ai-matrx/records/core");
20921
21219
 
20922
21220
  // src/WhereItLives.tsx
20923
21221
  var import_react138 = require("react");
20924
- var import_records22 = require("@ai-matrx/records");
21222
+ var import_records23 = require("@ai-matrx/records");
20925
21223
  var import_react139 = require("@ai-matrx/records/react");
20926
21224
  var import_design_system67 = require("@ai-matrx/design-system");
20927
21225
  var import_jsx_runtime73 = require("react/jsx-runtime");
@@ -21033,7 +21331,7 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
21033
21331
  choosing.name,
21034
21332
  "?"
21035
21333
  ] }),
21036
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0, import_records22.moveConsequence)(answer.home, choosing) }),
21334
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0, import_records23.moveConsequence)(answer.home, choosing) }),
21037
21335
  /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "flex gap-2", children: [
21038
21336
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", className: "h-7 text-xs", disabled: moving, onClick: () => void move(choosing), children: moving ? `Moving to ${choosing.name}\u2026` : "Move it" }),
21039
21337
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", variant: "ghost", className: "h-7 text-xs", disabled: moving, onClick: () => setChoosing(null), children: "Cancel" })
@@ -21138,7 +21436,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
21138
21436
  alive = false;
21139
21437
  };
21140
21438
  }, [client]);
21141
- const listed = facts.phase === "read" ? (0, import_records23.withTablePlacement)(
21439
+ const listed = facts.phase === "read" ? (0, import_records24.withTablePlacement)(
21142
21440
  (0, import_core10.withTableFacts)(tables.data ?? [], facts.rows, me),
21143
21441
  facts.rows
21144
21442
  ) : tables.data ?? [];
@@ -21343,7 +21641,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, classNa
21343
21641
 
21344
21642
  // src/TablePage.tsx
21345
21643
  var import_react144 = require("react");
21346
- var import_records24 = require("@ai-matrx/records");
21644
+ var import_records25 = require("@ai-matrx/records");
21347
21645
  var import_react145 = require("@ai-matrx/records/react");
21348
21646
  var import_design_system70 = require("@ai-matrx/design-system");
21349
21647
 
@@ -21545,7 +21843,7 @@ function TableNotHere({
21545
21843
  return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: (0, import_design_system70.cn)("flex flex-col items-start gap-2 rounded-md border border-dashed p-6", className), children: [
21546
21844
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-sm font-medium", children: "This table is archived" }),
21547
21845
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "max-w-prose text-xs text-muted-foreground", children: TABLE_IS_ARCHIVED }),
21548
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records24.archivedByLine)(row) }),
21846
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-xs text-muted-foreground", children: (0, import_records25.archivedByLine)(row) }),
21549
21847
  refusal2 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(RefusalNotice, { error: refusal2 }) : null,
21550
21848
  /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "flex gap-2", children: [
21551
21849
  /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(