@ai-matrx/records-ui 0.107.5 → 0.109.1

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
@@ -1462,8 +1462,8 @@ function FormulaTextEditor({
1462
1462
  }
1463
1463
 
1464
1464
  // src/TableDetails.tsx
1465
- var import_react15 = require("react");
1466
- var import_react16 = require("@ai-matrx/records/react");
1465
+ var import_react16 = require("react");
1466
+ var import_react17 = require("@ai-matrx/records/react");
1467
1467
  var import_design_system8 = require("@ai-matrx/design-system");
1468
1468
 
1469
1469
  // src/reversePrefix.ts
@@ -1473,6 +1473,54 @@ var REVERSE_COLUMN_PREFIX = "linked:";
1473
1473
  var import_records5 = require("@ai-matrx/records");
1474
1474
  var import_data_table2 = require("@ai-matrx/design-system/data-table");
1475
1475
 
1476
+ // src/personTime.ts
1477
+ var import_react6 = require("react");
1478
+ var zone = null;
1479
+ var listeners = /* @__PURE__ */ new Set();
1480
+ function valid(z) {
1481
+ if (typeof z !== "string" || !z.trim()) return false;
1482
+ try {
1483
+ new Intl.DateTimeFormat("en-US", { timeZone: z });
1484
+ return true;
1485
+ } catch {
1486
+ return false;
1487
+ }
1488
+ }
1489
+ function setPersonTimeZone(next) {
1490
+ const clean = valid(next) ? next : null;
1491
+ if (clean === zone) return;
1492
+ zone = clean;
1493
+ listeners.forEach((l) => l());
1494
+ }
1495
+ function getPersonTimeZone() {
1496
+ return zone;
1497
+ }
1498
+ function usePersonTimeZone() {
1499
+ return (0, import_react6.useSyncExternalStore)(
1500
+ (cb) => {
1501
+ listeners.add(cb);
1502
+ return () => listeners.delete(cb);
1503
+ },
1504
+ () => zone,
1505
+ () => null
1506
+ );
1507
+ }
1508
+ function personWallNow(at = /* @__PURE__ */ new Date()) {
1509
+ if (!zone) return at;
1510
+ const parts = new Intl.DateTimeFormat("en-US", {
1511
+ timeZone: zone,
1512
+ year: "numeric",
1513
+ month: "2-digit",
1514
+ day: "2-digit",
1515
+ hour: "2-digit",
1516
+ minute: "2-digit",
1517
+ second: "2-digit",
1518
+ hourCycle: "h23"
1519
+ }).formatToParts(at);
1520
+ const n = (t) => Number(parts.find((p) => p.type === t)?.value ?? 0);
1521
+ return new Date(n("year"), n("month") - 1, n("day"), n("hour"), n("minute"), n("second"));
1522
+ }
1523
+
1476
1524
  // src/choiceLooks.ts
1477
1525
  var import_data_table = require("@ai-matrx/design-system/data-table");
1478
1526
  function displayFormatOf(field2) {
@@ -1815,9 +1863,10 @@ function clauseFor(f, value, now = /* @__PURE__ */ new Date()) {
1815
1863
  return { rule: value.negated ? not(range) : range };
1816
1864
  }
1817
1865
  case "date": {
1818
- const moments = (0, import_data_table2.dateFilterBounds)(value.preset ? { ...value, anchor: now.toISOString() } : value, now);
1866
+ const zone2 = getPersonTimeZone() ?? void 0;
1867
+ const moments = (0, import_data_table2.dateFilterBounds)(value.preset ? { ...value, anchor: now.toISOString() } : value, now, zone2);
1819
1868
  const holdsDays = String((f.config ?? {})["kind"] ?? "") === "date";
1820
- const bounds = holdsDays ? (0, import_data_table2.dateFilterDayBounds)(moments) : moments;
1869
+ const bounds = holdsDays ? (0, import_data_table2.dateFilterDayBounds)(moments, zone2) : moments;
1821
1870
  if (bounds.since === void 0 && bounds.until === void 0) return null;
1822
1871
  return {
1823
1872
  flat: {
@@ -1833,11 +1882,10 @@ function clauseFor(f, value, now = /* @__PURE__ */ new Date()) {
1833
1882
  }
1834
1883
  }
1835
1884
  function dayWindow(day, holdsDays) {
1885
+ if (!holdsDays) return (0, import_data_table2.dayInstantWindow)(day, getPersonTimeZone() ?? void 0);
1836
1886
  const [y, m, d] = day.split("-").map(Number);
1837
- const start = new Date(y, (m ?? 1) - 1, d ?? 1);
1838
- const next = new Date(y, (m ?? 1) - 1, (d ?? 1) + 1);
1839
- const ymd = (t) => `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
1840
- return holdsDays ? { from: ymd(start), to: ymd(next) } : { from: start.toISOString(), to: next.toISOString() };
1887
+ const ymd = (t) => `${t.getUTCFullYear()}-${String(t.getUTCMonth() + 1).padStart(2, "0")}-${String(t.getUTCDate()).padStart(2, "0")}`;
1888
+ return { from: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, d ?? 1))), to: ymd(new Date(Date.UTC(y, (m ?? 1) - 1, (d ?? 1) + 1))) };
1841
1889
  }
1842
1890
  function storeQuestion(fields, base, columnFilters, now = /* @__PURE__ */ new Date()) {
1843
1891
  const refused = [];
@@ -1920,15 +1968,15 @@ function fieldOptionsOnce(client, fieldId) {
1920
1968
  }
1921
1969
 
1922
1970
  // src/labels.tsx
1923
- var import_react8 = require("react");
1924
- var import_react9 = require("@ai-matrx/records/react");
1971
+ var import_react9 = require("react");
1972
+ var import_react10 = require("@ai-matrx/records/react");
1925
1973
  var import_records6 = require("@ai-matrx/records");
1926
1974
  var import_uuid2 = require("@ai-matrx/kit/uuid");
1927
1975
 
1928
1976
  // src/signature.tsx
1929
- var import_react6 = require("react");
1977
+ var import_react7 = require("react");
1930
1978
  var import_design_system3 = require("@ai-matrx/design-system");
1931
- var import_react7 = require("@ai-matrx/records/react");
1979
+ var import_react8 = require("@ai-matrx/records/react");
1932
1980
  var import_jsx_runtime4 = require("react/jsx-runtime");
1933
1981
  var DRAWN = /^data:image\/(png|jpeg);base64,[A-Za-z0-9+/=]{64,}$/;
1934
1982
  function drawnSignatureOf(value) {
@@ -2003,10 +2051,10 @@ function SignatureDrawing({
2003
2051
  value,
2004
2052
  inCell
2005
2053
  }) {
2006
- const client = (0, import_react7.useOptionalRecordsClient)();
2054
+ const client = (0, import_react8.useOptionalRecordsClient)();
2007
2055
  const host = useRecordsUi();
2008
- const [drawing, setDrawing] = (0, import_react6.useState)(null);
2009
- (0, import_react6.useEffect)(() => {
2056
+ const [drawing, setDrawing] = (0, import_react7.useState)(null);
2057
+ (0, import_react7.useEffect)(() => {
2010
2058
  let cancelled = false;
2011
2059
  setDrawing(null);
2012
2060
  if (!client) return;
@@ -2053,12 +2101,12 @@ function SignaturePad({
2053
2101
  }) {
2054
2102
  const kept = drawnSignatureOf(value);
2055
2103
  const named = !kept && typeof value === "string" && value !== "" ? value : null;
2056
- const [showPad, setShowPad] = (0, import_react6.useState)(() => !kept && !named);
2057
- const canvasRef = (0, import_react6.useRef)(null);
2058
- const drawing = (0, import_react6.useRef)(false);
2059
- const [dirty, setDirty] = (0, import_react6.useState)(false);
2060
- const [tooBig, setTooBig] = (0, import_react6.useState)(false);
2061
- (0, import_react6.useEffect)(() => {
2104
+ const [showPad, setShowPad] = (0, import_react7.useState)(() => !kept && !named);
2105
+ const canvasRef = (0, import_react7.useRef)(null);
2106
+ const drawing = (0, import_react7.useRef)(false);
2107
+ const [dirty, setDirty] = (0, import_react7.useState)(false);
2108
+ const [tooBig, setTooBig] = (0, import_react7.useState)(false);
2109
+ (0, import_react7.useEffect)(() => {
2062
2110
  if (!showPad) return;
2063
2111
  const canvas = canvasRef.current;
2064
2112
  if (!canvas) return;
@@ -2197,7 +2245,7 @@ function encodeAt(canvas, type, maxWidth, quality) {
2197
2245
 
2198
2246
  // src/labels.tsx
2199
2247
  var import_jsx_runtime5 = require("react/jsx-runtime");
2200
- var LabelContext = (0, import_react8.createContext)({
2248
+ var LabelContext = (0, import_react9.createContext)({
2201
2249
  // With no provider the resolver is ABSENT, not silently empty: a caller gets
2202
2250
  // null and says "Loading…" forever, which is visible. The mount always
2203
2251
  // provides one, so this is only ever a bare unit test.
@@ -2238,16 +2286,16 @@ function shownValue(field2, value, labels) {
2238
2286
  return Array.isArray(value) ? words2 : words2[0];
2239
2287
  }
2240
2288
  function RecordLabelProvider({ children }) {
2241
- const client = (0, import_react9.useRecordsClient)();
2242
- const [names, setNames] = (0, import_react8.useState)({});
2243
- const [archivedRefs, setArchivedRefs] = (0, import_react8.useState)({});
2244
- const [iconsOf, setIconsOf] = (0, import_react8.useState)({});
2245
- const [settled, setSettled] = (0, import_react8.useState)({});
2246
- const [waitingLines, setWaitingLines] = (0, import_react8.useState)({});
2247
- const asked3 = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
2248
- const chased = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
2249
- const timers = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
2250
- const startWaitClock = (0, import_react8.useCallback)((field2, target) => {
2289
+ const client = (0, import_react10.useRecordsClient)();
2290
+ const [names, setNames] = (0, import_react9.useState)({});
2291
+ const [archivedRefs, setArchivedRefs] = (0, import_react9.useState)({});
2292
+ const [iconsOf, setIconsOf] = (0, import_react9.useState)({});
2293
+ const [settled, setSettled] = (0, import_react9.useState)({});
2294
+ const [waitingLines, setWaitingLines] = (0, import_react9.useState)({});
2295
+ const asked3 = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
2296
+ const chased = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
2297
+ const timers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
2298
+ const startWaitClock = (0, import_react9.useCallback)((field2, target) => {
2251
2299
  if (timers.current.has(field2.id)) return;
2252
2300
  timers.current.set(
2253
2301
  field2.id,
@@ -2259,7 +2307,7 @@ function RecordLabelProvider({ children }) {
2259
2307
  }, SAY_WHAT_YOU_ARE_WAITING_FOR_AFTER_MS)
2260
2308
  );
2261
2309
  }, []);
2262
- const stopWaitClock = (0, import_react8.useCallback)((fieldId) => {
2310
+ const stopWaitClock = (0, import_react9.useCallback)((fieldId) => {
2263
2311
  const timer = timers.current.get(fieldId);
2264
2312
  if (timer) {
2265
2313
  clearTimeout(timer);
@@ -2272,14 +2320,14 @@ function RecordLabelProvider({ children }) {
2272
2320
  return next;
2273
2321
  });
2274
2322
  }, []);
2275
- (0, import_react8.useEffect)(
2323
+ (0, import_react9.useEffect)(
2276
2324
  () => () => {
2277
2325
  for (const timer of timers.current.values()) clearTimeout(timer);
2278
2326
  timers.current.clear();
2279
2327
  },
2280
2328
  []
2281
2329
  );
2282
- const want = (0, import_react8.useCallback)(
2330
+ const want = (0, import_react9.useCallback)(
2283
2331
  (field2) => {
2284
2332
  if (!pointsAtRecords(field2)) return;
2285
2333
  if (asked3.current.has(field2.id)) return;
@@ -2314,9 +2362,9 @@ function RecordLabelProvider({ children }) {
2314
2362
  },
2315
2363
  [client, startWaitClock, stopWaitClock]
2316
2364
  );
2317
- const queued = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
2318
- const flushing = (0, import_react8.useRef)(null);
2319
- const flush = (0, import_react8.useCallback)(() => {
2365
+ const queued = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
2366
+ const flushing = (0, import_react9.useRef)(null);
2367
+ const flush = (0, import_react9.useCallback)(() => {
2320
2368
  flushing.current = null;
2321
2369
  const batch = [...queued.current.values()];
2322
2370
  queued.current.clear();
@@ -2346,7 +2394,7 @@ function RecordLabelProvider({ children }) {
2346
2394
  for (const { field: field2 } of batch) stopWaitClock(field2.id);
2347
2395
  })();
2348
2396
  }, [client, stopWaitClock]);
2349
- const chase = (0, import_react8.useCallback)(
2397
+ const chase = (0, import_react9.useCallback)(
2350
2398
  (field2, id) => {
2351
2399
  const key = `${field2.id}:${id}`;
2352
2400
  if (chased.current.has(key)) return;
@@ -2359,14 +2407,14 @@ function RecordLabelProvider({ children }) {
2359
2407
  },
2360
2408
  [flush, startWaitClock]
2361
2409
  );
2362
- (0, import_react8.useEffect)(
2410
+ (0, import_react9.useEffect)(
2363
2411
  () => () => {
2364
2412
  if (flushing.current !== null) clearTimeout(flushing.current);
2365
2413
  },
2366
2414
  []
2367
2415
  );
2368
- const rereadFor = (0, import_react8.useRef)(/* @__PURE__ */ new Set());
2369
- const lookupWords = (0, import_react8.useCallback)(
2416
+ const rereadFor = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
2417
+ const lookupWords = (0, import_react9.useCallback)(
2370
2418
  (field2, id) => {
2371
2419
  if (field2.type === "list" && !isId(id)) {
2372
2420
  const named = names[choiceKeyName(field2.id, id)];
@@ -2386,7 +2434,7 @@ function RecordLabelProvider({ children }) {
2386
2434
  },
2387
2435
  [names, settled, chase, want]
2388
2436
  );
2389
- const lookup = (0, import_react8.useMemo)(
2437
+ const lookup = (0, import_react9.useMemo)(
2390
2438
  () => {
2391
2439
  const answer = ((field2, id) => lookupWords(field2, id));
2392
2440
  answer.archived = (field2, id) => archivedRefs[`${field2.id}:${id}`] === true;
@@ -2395,19 +2443,19 @@ function RecordLabelProvider({ children }) {
2395
2443
  },
2396
2444
  [lookupWords, archivedRefs, iconsOf]
2397
2445
  );
2398
- const waiting = (0, import_react8.useCallback)((field2) => waitingLines[field2.id] ?? null, [waitingLines]);
2399
- const value = (0, import_react8.useMemo)(() => ({ lookup, want, waiting }), [lookup, want, waiting]);
2446
+ const waiting = (0, import_react9.useCallback)((field2) => waitingLines[field2.id] ?? null, [waitingLines]);
2447
+ const value = (0, import_react9.useMemo)(() => ({ lookup, want, waiting }), [lookup, want, waiting]);
2400
2448
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LabelContext.Provider, { value, children });
2401
2449
  }
2402
2450
  function useRecordLabels(fields) {
2403
- const { lookup, want } = (0, import_react8.useContext)(LabelContext);
2404
- (0, import_react8.useEffect)(() => {
2451
+ const { lookup, want } = (0, import_react9.useContext)(LabelContext);
2452
+ (0, import_react9.useEffect)(() => {
2405
2453
  for (const field2 of fields ?? []) want(field2);
2406
2454
  }, [fields, want]);
2407
2455
  return lookup;
2408
2456
  }
2409
2457
  function useLabelWait(field2) {
2410
- const { waiting } = (0, import_react8.useContext)(LabelContext);
2458
+ const { waiting } = (0, import_react9.useContext)(LabelContext);
2411
2459
  return field2 ? waiting(field2) : null;
2412
2460
  }
2413
2461
 
@@ -2589,9 +2637,9 @@ function gridCopyConfig(args) {
2589
2637
  }
2590
2638
 
2591
2639
  // src/FieldRetype.tsx
2592
- var import_react10 = require("react");
2640
+ var import_react11 = require("react");
2593
2641
  var import_records7 = require("@ai-matrx/records");
2594
- var import_react11 = require("@ai-matrx/records/react");
2642
+ var import_react12 = require("@ai-matrx/records/react");
2595
2643
  var import_design_system4 = require("@ai-matrx/design-system");
2596
2644
  var import_jsx_runtime6 = require("react/jsx-runtime");
2597
2645
  var RETYPE_TARGETS = [
@@ -2628,17 +2676,17 @@ function currentTarget(field2) {
2628
2676
  return "text";
2629
2677
  }
2630
2678
  function FieldRetype({ field: field2, tableId, onRetyped }) {
2631
- const client = (0, import_react11.useRecordsClient)();
2679
+ const client = (0, import_react12.useRecordsClient)();
2632
2680
  const notify = useRecordsUi().notify;
2633
- const [to, setTo] = (0, import_react10.useState)(null);
2634
- const [preview, setPreview] = (0, import_react10.useState)(null);
2635
- const [asking, setAsking] = (0, import_react10.useState)(false);
2636
- const [refusal4, setRefusal] = (0, import_react10.useState)(null);
2637
- const [busy, setBusy] = (0, import_react10.useState)(false);
2638
- const [said2, setSaid] = (0, import_react10.useState)(null);
2681
+ const [to, setTo] = (0, import_react11.useState)(null);
2682
+ const [preview, setPreview] = (0, import_react11.useState)(null);
2683
+ const [asking, setAsking] = (0, import_react11.useState)(false);
2684
+ const [refusal4, setRefusal] = (0, import_react11.useState)(null);
2685
+ const [busy, setBusy] = (0, import_react11.useState)(false);
2686
+ const [said2, setSaid] = (0, import_react11.useState)(null);
2639
2687
  const name = fieldName(field2);
2640
2688
  const targets = RETYPE_TARGETS.filter((t) => t.id !== currentTarget(field2));
2641
- (0, import_react10.useEffect)(() => {
2689
+ (0, import_react11.useEffect)(() => {
2642
2690
  if (!to) return;
2643
2691
  let cancelled = false;
2644
2692
  setPreview(null);
@@ -2694,7 +2742,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
2694
2742
  undo: async () => {
2695
2743
  const back = await client.migrateUndo({ migration_id: migration });
2696
2744
  if (!back.ok) throw new Error(refusalSentence(back.error));
2697
- (0, import_react11.tableShapeChanged)(tableId);
2745
+ (0, import_react12.tableShapeChanged)(tableId);
2698
2746
  onRetyped?.();
2699
2747
  }
2700
2748
  });
@@ -2705,7 +2753,7 @@ function FieldRetype({ field: field2, tableId, onRetyped }) {
2705
2753
  );
2706
2754
  setTo(null);
2707
2755
  setPreview(null);
2708
- (0, import_react11.tableShapeChanged)(tableId);
2756
+ (0, import_react12.tableShapeChanged)(tableId);
2709
2757
  onRetyped?.();
2710
2758
  };
2711
2759
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-1.5", "data-records-retype": "", children: [
@@ -3075,11 +3123,11 @@ function nextFieldSort(fields) {
3075
3123
  }
3076
3124
 
3077
3125
  // src/PickOne.tsx
3078
- var import_react13 = require("react");
3126
+ var import_react14 = require("react");
3079
3127
  var import_design_system7 = require("@ai-matrx/design-system");
3080
3128
 
3081
3129
  // src/PickOrAdd.tsx
3082
- var import_react12 = require("react");
3130
+ var import_react13 = require("react");
3083
3131
 
3084
3132
  // src/personChip.tsx
3085
3133
  var import_design_system5 = require("@ai-matrx/design-system");
@@ -3130,9 +3178,9 @@ var CROSS = "M18 6 6 18M6 6l12 12";
3130
3178
  var PLUS = "M12 5v14M5 12h14";
3131
3179
  function useListKeys(args) {
3132
3180
  const { count, resetOn, onPick, onNothing, onClose, onFinish, onBackspaceEmpty, searchEmpty } = args;
3133
- const [highlight, setHighlight] = (0, import_react12.useState)(0);
3134
- const [moved, setMoved] = (0, import_react12.useState)(false);
3135
- (0, import_react12.useEffect)(() => {
3181
+ const [highlight, setHighlight] = (0, import_react13.useState)(0);
3182
+ const [moved, setMoved] = (0, import_react13.useState)(false);
3183
+ (0, import_react13.useEffect)(() => {
3136
3184
  setHighlight(0);
3137
3185
  setMoved(false);
3138
3186
  }, [resetOn]);
@@ -3177,8 +3225,8 @@ function PickRow({
3177
3225
  onPick,
3178
3226
  onPoint
3179
3227
  }) {
3180
- const ref = (0, import_react12.useRef)(null);
3181
- (0, import_react12.useEffect)(() => {
3228
+ const ref = (0, import_react13.useRef)(null);
3229
+ (0, import_react13.useEffect)(() => {
3182
3230
  if (highlighted) ref.current?.scrollIntoView?.({ block: "nearest" });
3183
3231
  }, [highlighted]);
3184
3232
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
@@ -3390,8 +3438,8 @@ function PickOne({
3390
3438
  disabled,
3391
3439
  attrs
3392
3440
  }) {
3393
- const [open, setOpen] = (0, import_react13.useState)(false);
3394
- const [search, setSearch] = (0, import_react13.useState)("");
3441
+ const [open, setOpen] = (0, import_react14.useState)(false);
3442
+ const [search, setSearch] = (0, import_react14.useState)("");
3395
3443
  const current = options.find((o) => o.value === value);
3396
3444
  if (options.length > PICK_ONE_SEARCH_AFTER) {
3397
3445
  const q = search.trim().toLowerCase();
@@ -3459,7 +3507,7 @@ function groupsOf(options) {
3459
3507
  }
3460
3508
 
3461
3509
  // src/recordVersions.ts
3462
- var import_react14 = require("react");
3510
+ var import_react15 = require("react");
3463
3511
 
3464
3512
  // src/refusals.ts
3465
3513
  function refusal(code, sentence2, remedy, diagnostic) {
@@ -3516,22 +3564,22 @@ function signatureOf(row) {
3516
3564
  }
3517
3565
  }
3518
3566
  function useRecordVersions(client, rows, mayRead) {
3519
- const versions = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
3520
- const drawn = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
3521
- const unread = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
3522
- const pending = (0, import_react14.useRef)(/* @__PURE__ */ new Map());
3523
- const generation = (0, import_react14.useRef)(0);
3524
- const mayReadRef = (0, import_react14.useRef)(mayRead);
3567
+ const versions = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
3568
+ const drawn = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
3569
+ const unread = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
3570
+ const pending = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
3571
+ const generation = (0, import_react15.useRef)(0);
3572
+ const mayReadRef = (0, import_react15.useRef)(mayRead);
3525
3573
  mayReadRef.current = mayRead;
3526
- const rowsRef = (0, import_react14.useRef)(rows);
3574
+ const rowsRef = (0, import_react15.useRef)(rows);
3527
3575
  rowsRef.current = rows;
3528
- const key = (0, import_react14.useMemo)(() => rows.map((row) => `${row.id}${signatureOf(row)}`).join(""), [rows]);
3576
+ const key = (0, import_react15.useMemo)(() => rows.map((row) => `${row.id}${signatureOf(row)}`).join(""), [rows]);
3529
3577
  const raise = (id, version) => {
3530
3578
  const held = versions.current.get(id);
3531
3579
  if (held === void 0 || version > held) versions.current.set(id, version);
3532
3580
  unread.current.delete(id);
3533
3581
  };
3534
- const readHeaders = (0, import_react14.useCallback)(
3582
+ const readHeaders = (0, import_react15.useCallback)(
3535
3583
  (toRead) => {
3536
3584
  if (toRead.length === 0) return;
3537
3585
  generation.current += 1;
@@ -3562,7 +3610,7 @@ function useRecordVersions(client, rows, mayRead) {
3562
3610
  // eslint-disable-next-line react-hooks/exhaustive-deps
3563
3611
  [client]
3564
3612
  );
3565
- (0, import_react14.useEffect)(() => {
3613
+ (0, import_react15.useEffect)(() => {
3566
3614
  const toRead = [];
3567
3615
  for (const row of rowsRef.current) {
3568
3616
  if (mayReadRef.current && !mayReadRef.current(row)) continue;
@@ -3575,8 +3623,8 @@ function useRecordVersions(client, rows, mayRead) {
3575
3623
  }
3576
3624
  readHeaders(toRead);
3577
3625
  }, [readHeaders, key]);
3578
- const refresh = (0, import_react14.useCallback)((ids) => readHeaders([...ids]), [readHeaders]);
3579
- const seen = (0, import_react14.useCallback)(async (id) => {
3626
+ const refresh = (0, import_react15.useCallback)((ids) => readHeaders([...ids]), [readHeaders]);
3627
+ const seen = (0, import_react15.useCallback)(async (id) => {
3580
3628
  for (let guard = 0; guard < 5; guard += 1) {
3581
3629
  const waiting = pending.current.get(id);
3582
3630
  if (!waiting) break;
@@ -3585,7 +3633,7 @@ function useRecordVersions(client, rows, mayRead) {
3585
3633
  if (unread.current.has(id)) return null;
3586
3634
  return versions.current.get(id) ?? null;
3587
3635
  }, []);
3588
- const seenMany = (0, import_react14.useCallback)(
3636
+ const seenMany = (0, import_react15.useCallback)(
3589
3637
  async (ids) => {
3590
3638
  const out = /* @__PURE__ */ new Map();
3591
3639
  for (const id of ids) out.set(id, await seen(id));
@@ -3593,14 +3641,14 @@ function useRecordVersions(client, rows, mayRead) {
3593
3641
  },
3594
3642
  [seen]
3595
3643
  );
3596
- const wrote = (0, import_react14.useCallback)(
3644
+ const wrote = (0, import_react15.useCallback)(
3597
3645
  (id, version) => {
3598
3646
  raise(id, version);
3599
3647
  readHeaders([id]);
3600
3648
  },
3601
3649
  [readHeaders]
3602
3650
  );
3603
- return (0, import_react14.useMemo)(() => ({ seen, seenMany, wrote, refresh }), [seen, seenMany, wrote, refresh]);
3651
+ return (0, import_react15.useMemo)(() => ({ seen, seenMany, wrote, refresh }), [seen, seenMany, wrote, refresh]);
3604
3652
  }
3605
3653
  async function readVersionNow(client, id) {
3606
3654
  try {
@@ -3666,19 +3714,19 @@ async function readTableVersionNow(client, tableId) {
3666
3714
  }
3667
3715
  }
3668
3716
  function useTableVersion(client, tableId, table) {
3669
- const key = (0, import_react14.useMemo)(() => {
3717
+ const key = (0, import_react15.useMemo)(() => {
3670
3718
  try {
3671
3719
  return `${tableId ?? ""}${JSON.stringify(table ?? null)}`;
3672
3720
  } catch {
3673
3721
  return String(tableId ?? "");
3674
3722
  }
3675
3723
  }, [tableId, table]);
3676
- const read = (0, import_react14.useRef)(null);
3677
- const clientRef = (0, import_react14.useRef)(client);
3724
+ const read = (0, import_react15.useRef)(null);
3725
+ const clientRef = (0, import_react15.useRef)(client);
3678
3726
  clientRef.current = client;
3679
- const keyRef = (0, import_react14.useRef)(key);
3727
+ const keyRef = (0, import_react15.useRef)(key);
3680
3728
  keyRef.current = key;
3681
- return (0, import_react14.useCallback)(async () => {
3729
+ return (0, import_react15.useCallback)(async () => {
3682
3730
  if (!tableId) return null;
3683
3731
  if (read.current && read.current.key === keyRef.current) return read.current.version;
3684
3732
  const version = readTableVersionNow(clientRef.current, tableId);
@@ -3731,17 +3779,17 @@ function TableDetails({
3731
3779
  fields,
3732
3780
  onSaved
3733
3781
  }) {
3734
- const client = (0, import_react16.useRecordsClient)();
3782
+ const client = (0, import_react17.useRecordsClient)();
3735
3783
  const kept = typeof table.metadata?.["description"] === "string" ? table.metadata["description"] : "";
3736
- const [text2, setText] = (0, import_react15.useState)(kept);
3737
- const [busy, setBusy] = (0, import_react15.useState)(false);
3738
- const [refused, setRefused] = (0, import_react15.useState)(null);
3739
- (0, import_react15.useEffect)(() => setText(kept), [kept]);
3740
- const choices = (0, import_react15.useMemo)(() => rowLabelChoices(fields), [fields]);
3784
+ const [text2, setText] = (0, import_react16.useState)(kept);
3785
+ const [busy, setBusy] = (0, import_react16.useState)(false);
3786
+ const [refused, setRefused] = (0, import_react16.useState)(null);
3787
+ (0, import_react16.useEffect)(() => setText(kept), [kept]);
3788
+ const choices = (0, import_react16.useMemo)(() => rowLabelChoices(fields), [fields]);
3741
3789
  const slots = useSettingsAgentSlots();
3742
- const drafted = (0, import_react15.useRef)({ description: text2, kept });
3790
+ const drafted = (0, import_react16.useRef)({ description: text2, kept });
3743
3791
  drafted.current = { description: text2, kept };
3744
- (0, import_react15.useEffect)(() => {
3792
+ (0, import_react16.useEffect)(() => {
3745
3793
  if (!slots) return void 0;
3746
3794
  const slot = { draft: () => drafted.current, stageDescription: (next) => setText(next) };
3747
3795
  slots.details.current = slot;
@@ -3758,7 +3806,7 @@ function TableDetails({
3758
3806
  setRefused(refusalSentence(written.error));
3759
3807
  return;
3760
3808
  }
3761
- (0, import_react16.tableShapeChanged)(tableId);
3809
+ (0, import_react17.tableShapeChanged)(tableId);
3762
3810
  onSaved?.();
3763
3811
  };
3764
3812
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-2", "data-table-details": "", children: [
@@ -3822,22 +3870,22 @@ async function saveTableDescription(client, tableId, text2) {
3822
3870
  { metadata: table.metadata ?? {} }
3823
3871
  );
3824
3872
  if (!written.ok) return { ok: false, says: refusalSentence(written.error) };
3825
- (0, import_react16.tableShapeChanged)(tableId);
3873
+ (0, import_react17.tableShapeChanged)(tableId);
3826
3874
  return { ok: true };
3827
3875
  }
3828
3876
 
3829
3877
  // src/ReferenceBuilder.tsx
3830
- var import_react19 = require("react");
3831
- var import_react20 = require("@ai-matrx/records/react");
3878
+ var import_react20 = require("react");
3879
+ var import_react21 = require("@ai-matrx/records/react");
3832
3880
  var import_core3 = require("@ai-matrx/records/core");
3833
3881
 
3834
3882
  // src/createTable.ts
3835
3883
  var import_core2 = require("@ai-matrx/records/core");
3836
3884
 
3837
3885
  // src/tablePicking.tsx
3838
- var import_react17 = require("react");
3886
+ var import_react18 = require("react");
3839
3887
  var import_records8 = require("@ai-matrx/records");
3840
- var import_react18 = require("@ai-matrx/records/react");
3888
+ var import_react19 = require("@ai-matrx/records/react");
3841
3889
  var import_design_system9 = require("@ai-matrx/design-system");
3842
3890
  var import_jsx_runtime11 = require("react/jsx-runtime");
3843
3891
  var APP_TABLE_PREFIX = "records_ui_";
@@ -3881,16 +3929,16 @@ function madeOn(stamp) {
3881
3929
  return new Intl.DateTimeFormat(void 0, { month: "short", day: "numeric", year: "numeric" }).format(at);
3882
3930
  }
3883
3931
  function usePickerTables() {
3884
- const client = (0, import_react18.useRecordsClient)();
3885
- const tables = (0, import_react18.useTables)();
3886
- const [facts, setFacts] = (0, import_react17.useState)("reading");
3887
- const [nonce, setNonce] = (0, import_react17.useState)(0);
3932
+ const client = (0, import_react19.useRecordsClient)();
3933
+ const tables = (0, import_react19.useTables)();
3934
+ const [facts, setFacts] = (0, import_react18.useState)("reading");
3935
+ const [nonce, setNonce] = (0, import_react18.useState)(0);
3888
3936
  const reloadTables = tables.reload;
3889
- const reload = (0, import_react17.useCallback)(() => {
3937
+ const reload = (0, import_react18.useCallback)(() => {
3890
3938
  reloadTables();
3891
3939
  setNonce((n) => n + 1);
3892
3940
  }, [reloadTables]);
3893
- (0, import_react17.useEffect)(() => {
3941
+ (0, import_react18.useEffect)(() => {
3894
3942
  let alive = true;
3895
3943
  void client.tableFacts().then((answered) => {
3896
3944
  if (alive) setFacts(answered.ok ? answered.data ?? null : null);
@@ -3899,7 +3947,7 @@ function usePickerTables() {
3899
3947
  alive = false;
3900
3948
  };
3901
3949
  }, [client, nonce]);
3902
- const data = (0, import_react17.useMemo)(
3950
+ const data = (0, import_react18.useMemo)(
3903
3951
  () => (0, import_records8.withTablePlacement)(tables.data ?? [], facts === "reading" ? null : facts),
3904
3952
  [tables.data, facts]
3905
3953
  );
@@ -3955,11 +4003,11 @@ function previewWords(document2, display, titleField) {
3955
4003
  return "an untitled record";
3956
4004
  }
3957
4005
  function useTargetColumns(target) {
3958
- const declared2 = (0, import_react20.useFields)(target);
4006
+ const declared2 = (0, import_react21.useFields)(target);
3959
4007
  const usable = (declared2.data ?? []).filter((f) => f.type !== "formula");
3960
4008
  const needSample = usable.length === 0 && !declared2.loading && target !== null;
3961
- const sample = (0, import_react20.useRecords)(needSample ? target : null, { pageSize: 1 });
3962
- return (0, import_react19.useMemo)(() => {
4009
+ const sample = (0, import_react21.useRecords)(needSample ? target : null, { pageSize: 1 });
4010
+ return (0, import_react20.useMemo)(() => {
3963
4011
  if (usable.length > 0) return { keys: usable.map((f) => f.key), loading: false };
3964
4012
  const carried = sample.data?.rows[0]?.document ?? null;
3965
4013
  if (!carried) return { keys: [], loading: declared2.loading || sample.loading };
@@ -3977,19 +4025,19 @@ function ReferenceBuilder({
3977
4025
  className
3978
4026
  }) {
3979
4027
  const tables = usePickerTables();
3980
- const client = (0, import_react20.useRecordsClient)();
3981
- const [naming, setNaming] = (0, import_react19.useState)(null);
3982
- const [making, setMaking] = (0, import_react19.useState)(false);
3983
- const [refused, setRefused] = (0, import_react19.useState)(null);
3984
- const [born, setBorn] = (0, import_react19.useState)(null);
4028
+ const client = (0, import_react21.useRecordsClient)();
4029
+ const [naming, setNaming] = (0, import_react20.useState)(null);
4030
+ const [making, setMaking] = (0, import_react20.useState)(false);
4031
+ const [refused, setRefused] = (0, import_react20.useState)(null);
4032
+ const [born, setBorn] = (0, import_react20.useState)(null);
3985
4033
  const target = value.targetTableId || null;
3986
4034
  const columns = useTargetColumns(target);
3987
- const preview = (0, import_react20.useRecords)(target, { pageSize: 3 });
4035
+ const preview = (0, import_react21.useRecords)(target, { pageSize: 3 });
3988
4036
  const targetTable = (tables.data ?? []).find((t) => t.id === target) ?? null;
3989
4037
  const titleField = targetTable?.title_field ?? null;
3990
- const [overriding, setOverriding] = (0, import_react19.useState)(value.display !== null);
3991
- const [showLists, setShowLists] = (0, import_react19.useState)(false);
3992
- const picking = (0, import_react19.useMemo)(
4038
+ const [overriding, setOverriding] = (0, import_react20.useState)(value.display !== null);
4039
+ const [showLists, setShowLists] = (0, import_react20.useState)(false);
4040
+ const picking = (0, import_react20.useMemo)(
3993
4041
  () => tablePickerEntries(
3994
4042
  [
3995
4043
  ...(tables.data ?? []).map((t) => ({ ...t, name: tableName(t) })),
@@ -4250,9 +4298,9 @@ function ReferenceBuilder({
4250
4298
  }
4251
4299
 
4252
4300
  // src/PersonPicker.tsx
4253
- var import_react21 = require("react");
4301
+ var import_react22 = require("react");
4254
4302
  var import_records9 = require("@ai-matrx/records");
4255
- var import_react22 = require("@ai-matrx/records/react");
4303
+ var import_react23 = require("@ai-matrx/records/react");
4256
4304
  var import_design_system11 = require("@ai-matrx/design-system");
4257
4305
  var import_jsx_runtime13 = require("react/jsx-runtime");
4258
4306
  function personFromRow(row) {
@@ -4285,27 +4333,27 @@ async function personRecordForMember(client, personTableId, people, member) {
4285
4333
  return written;
4286
4334
  }
4287
4335
  function PersonPicker({ field: field2, value, onChange, disabled, id, className, autoOpen, onClose, onCancel, initialSearch }) {
4288
- const client = (0, import_react22.useOptionalRecordsClient)();
4336
+ const client = (0, import_react23.useOptionalRecordsClient)();
4289
4337
  const host = useRecordsUi();
4290
- const [members, setMembers] = (0, import_react21.useState)(null);
4291
- const [people, setPeople] = (0, import_react21.useState)([]);
4292
- const [error, setError] = (0, import_react21.useState)(null);
4293
- const [search, setSearch] = (0, import_react21.useState)(initialSearch ?? "");
4294
- const [open, setOpenState] = (0, import_react21.useState)(autoOpen === true);
4295
- const onCloseRef = (0, import_react21.useRef)(onClose);
4338
+ const [members, setMembers] = (0, import_react22.useState)(null);
4339
+ const [people, setPeople] = (0, import_react22.useState)([]);
4340
+ const [error, setError] = (0, import_react22.useState)(null);
4341
+ const [search, setSearch] = (0, import_react22.useState)(initialSearch ?? "");
4342
+ const [open, setOpenState] = (0, import_react22.useState)(autoOpen === true);
4343
+ const onCloseRef = (0, import_react22.useRef)(onClose);
4296
4344
  onCloseRef.current = onClose;
4297
- const setOpen = (0, import_react21.useCallback)((next) => {
4345
+ const setOpen = (0, import_react22.useCallback)((next) => {
4298
4346
  setOpenState(next);
4299
4347
  if (!next) onCloseRef.current?.();
4300
4348
  }, []);
4301
- const [busy, setBusy] = (0, import_react21.useState)(false);
4349
+ const [busy, setBusy] = (0, import_react22.useState)(false);
4302
4350
  const membersPort = host.members;
4303
4351
  const personTable = field2.relation_target;
4304
- const picked = (0, import_react21.useMemo)(
4352
+ const picked = (0, import_react22.useMemo)(
4305
4353
  () => Array.isArray(value) ? value.map(String) : value === null || value === void 0 ? [] : [String(value)],
4306
4354
  [value]
4307
4355
  );
4308
- const load = (0, import_react21.useCallback)(async () => {
4356
+ const load = (0, import_react22.useCallback)(async () => {
4309
4357
  if (!membersPort || !client) return;
4310
4358
  const [roster, records] = await Promise.all([
4311
4359
  membersPort(),
@@ -4318,11 +4366,11 @@ function PersonPicker({ field: field2, value, onChange, disabled, id, className,
4318
4366
  }
4319
4367
  setPeople(records ? records.data.rows.map(personFromRow).filter((p) => p.userId !== null) : []);
4320
4368
  }, [membersPort, client, personTable]);
4321
- (0, import_react21.useEffect)(() => {
4369
+ (0, import_react22.useEffect)(() => {
4322
4370
  if (!open) return;
4323
4371
  void load();
4324
4372
  }, [open, load]);
4325
- (0, import_react21.useEffect)(() => {
4373
+ (0, import_react22.useEffect)(() => {
4326
4374
  if (picked.length === 0 || !personTable || people.length > 0 || !client) return;
4327
4375
  let cancelled = false;
4328
4376
  void client.list({ table_id: personTable, limit: 500 }).then((result) => {
@@ -4437,11 +4485,12 @@ function PersonPicker({ field: field2, value, onChange, disabled, id, className,
4437
4485
 
4438
4486
  // src/gridEditing.tsx
4439
4487
  var import_react48 = require("react");
4440
- var import_core6 = require("@ai-matrx/records/core");
4488
+ var import_core7 = require("@ai-matrx/records/core");
4441
4489
  var import_react49 = require("@ai-matrx/records/react");
4442
4490
  var import_design_system26 = require("@ai-matrx/design-system");
4443
4491
 
4444
4492
  // src/presentation.ts
4493
+ var import_table_style = require("@ai-matrx/design-system/data-table/table-style");
4445
4494
  var import_data_table3 = require("@ai-matrx/design-system/data-table");
4446
4495
  var import_field_formats2 = require("@ai-matrx/design-system/field-formats");
4447
4496
  var import_records10 = require("@ai-matrx/records");
@@ -4574,8 +4623,8 @@ function parseGridPresentation(raw) {
4574
4623
  }
4575
4624
  if (!isRecord(value)) return {};
4576
4625
  const out = {};
4577
- const style = (0, import_data_table3.parseTableStyle)(value["style"]);
4578
- if (!(0, import_data_table3.tableStyleIsEmpty)(style)) out.style = style;
4626
+ const style = (0, import_table_style.parseTableStyle)(value["style"]);
4627
+ if (!(0, import_table_style.tableStyleIsEmpty)(style)) out.style = style;
4579
4628
  if (isRecord(value["formats"])) {
4580
4629
  const formats = {};
4581
4630
  for (const [key, cfg] of Object.entries(value["formats"])) {
@@ -4705,7 +4754,7 @@ function parseGrouping(raw) {
4705
4754
  return out;
4706
4755
  }
4707
4756
  function presentationIsEmpty(p) {
4708
- return (p.style === void 0 || (0, import_data_table3.tableStyleIsEmpty)(p.style)) && Object.keys(p.formats ?? {}).length === 0 && (p.frozen?.length ?? 0) === 0 && p.grouping === void 0 && Object.keys(p.widths ?? {}).length === 0 && p.rowHeight === void 0 && (p.hiddenFields?.length ?? 0) === 0 && p.cardHidden === void 0 && (p.columnOrder?.length ?? 0) === 0 && p.gallerySize === void 0 && p.wrap === void 0 && p.fit === void 0 && p.freezeFirst === void 0 && p.footer === void 0 && Object.keys(p.summaries ?? {}).length === 0;
4757
+ return (p.style === void 0 || (0, import_table_style.tableStyleIsEmpty)(p.style)) && Object.keys(p.formats ?? {}).length === 0 && (p.frozen?.length ?? 0) === 0 && p.grouping === void 0 && Object.keys(p.widths ?? {}).length === 0 && p.rowHeight === void 0 && (p.hiddenFields?.length ?? 0) === 0 && p.cardHidden === void 0 && (p.columnOrder?.length ?? 0) === 0 && p.gallerySize === void 0 && p.wrap === void 0 && p.fit === void 0 && p.freezeFirst === void 0 && p.footer === void 0 && Object.keys(p.summaries ?? {}).length === 0;
4709
4758
  }
4710
4759
  function presentationDocument(p) {
4711
4760
  return presentationIsEmpty(p) ? "" : JSON.stringify(p);
@@ -4850,7 +4899,7 @@ var import_react39 = require("@ai-matrx/records/react");
4850
4899
  var import_design_system20 = require("@ai-matrx/design-system");
4851
4900
 
4852
4901
  // src/newerKindValues.tsx
4853
- var import_react23 = require("react");
4902
+ var import_react24 = require("react");
4854
4903
  var import_source = require("@ai-matrx/content-ir/source");
4855
4904
  var import_records11 = require("@ai-matrx/records");
4856
4905
  var import_design_system12 = require("@ai-matrx/design-system");
@@ -5033,9 +5082,9 @@ function newerKindControl(props) {
5033
5082
  }
5034
5083
  }
5035
5084
  function DurationControl({ value, onChange, disabled, id }) {
5036
- const [text2, setText] = (0, import_react23.useState)(() => (0, import_records11.durationText)(value) ?? "");
5037
- const [wrong, setWrong] = (0, import_react23.useState)(false);
5038
- (0, import_react23.useEffect)(() => {
5085
+ const [text2, setText] = (0, import_react24.useState)(() => (0, import_records11.durationText)(value) ?? "");
5086
+ const [wrong, setWrong] = (0, import_react24.useState)(false);
5087
+ (0, import_react24.useEffect)(() => {
5039
5088
  setText((0, import_records11.durationText)(value) ?? "");
5040
5089
  }, [value]);
5041
5090
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "flex flex-col gap-1", children: [
@@ -5108,8 +5157,8 @@ function barcodeDetector() {
5108
5157
  return typeof ctor === "function" ? ctor : null;
5109
5158
  }
5110
5159
  function BarcodeControl({ value, onChange, disabled, id }) {
5111
- const file = (0, import_react23.useRef)(null);
5112
- const [said2, setSaid] = (0, import_react23.useState)(null);
5160
+ const file = (0, import_react24.useRef)(null);
5161
+ const [said2, setSaid] = (0, import_react24.useState)(null);
5113
5162
  const Detect = barcodeDetector();
5114
5163
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "flex flex-col gap-1", children: [
5115
5164
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "flex items-center gap-1.5", children: [
@@ -5165,9 +5214,9 @@ function BarcodeControl({ value, onChange, disabled, id }) {
5165
5214
  }
5166
5215
 
5167
5216
  // src/RelationPicker.tsx
5168
- var import_react24 = require("react");
5217
+ var import_react25 = require("react");
5169
5218
  var import_records12 = require("@ai-matrx/records");
5170
- var import_react25 = require("@ai-matrx/records/react");
5219
+ var import_react26 = require("@ai-matrx/records/react");
5171
5220
  var import_design_system13 = require("@ai-matrx/design-system");
5172
5221
 
5173
5222
  // src/tellApart.ts
@@ -5214,29 +5263,29 @@ var import_jsx_runtime15 = (
5214
5263
  );
5215
5264
  var NO_STORE_ON_THIS_SCREEN_REASON = "This question points at a record in somebody's own data, and a page answered without an account is never allowed to search that. Leave it blank \u2014 whoever receives your answer will fill it in.";
5216
5265
  function RelationPicker({ field: field2, value, onChange, disabled, id, className, allowCreate = true, onPicked, autoOpen, onClose, onCancel }) {
5217
- const client = (0, import_react25.useOptionalRecordsClient)();
5218
- const [rows, setRows] = (0, import_react24.useState)(null);
5219
- const [words2, setWords] = (0, import_react24.useState)({});
5220
- const [refusal4, setRefusal] = (0, import_react24.useState)(null);
5221
- const [search, setSearch] = (0, import_react24.useState)("");
5222
- const [open, setOpenState] = (0, import_react24.useState)(autoOpen === true);
5223
- const onCloseRef = (0, import_react24.useRef)(onClose);
5266
+ const client = (0, import_react26.useOptionalRecordsClient)();
5267
+ const [rows, setRows] = (0, import_react25.useState)(null);
5268
+ const [words2, setWords] = (0, import_react25.useState)({});
5269
+ const [refusal4, setRefusal] = (0, import_react25.useState)(null);
5270
+ const [search, setSearch] = (0, import_react25.useState)("");
5271
+ const [open, setOpenState] = (0, import_react25.useState)(autoOpen === true);
5272
+ const onCloseRef = (0, import_react25.useRef)(onClose);
5224
5273
  onCloseRef.current = onClose;
5225
- const setOpen = (0, import_react24.useCallback)((next) => {
5274
+ const setOpen = (0, import_react25.useCallback)((next) => {
5226
5275
  setOpenState(next);
5227
5276
  if (!next) onCloseRef.current?.();
5228
5277
  }, []);
5229
- const [target, setTarget] = (0, import_react24.useState)(null);
5230
- const [targetRefusal, setTargetRefusal] = (0, import_react24.useState)(null);
5231
- const [creating, setCreating] = (0, import_react24.useState)(false);
5232
- const [newTitle, setNewTitle] = (0, import_react24.useState)("");
5233
- const [busy, setBusy] = (0, import_react24.useState)(false);
5234
- const [createRefusal, setCreateRefusal] = (0, import_react24.useState)(null);
5235
- const picked = (0, import_react24.useMemo)(
5278
+ const [target, setTarget] = (0, import_react25.useState)(null);
5279
+ const [targetRefusal, setTargetRefusal] = (0, import_react25.useState)(null);
5280
+ const [creating, setCreating] = (0, import_react25.useState)(false);
5281
+ const [newTitle, setNewTitle] = (0, import_react25.useState)("");
5282
+ const [busy, setBusy] = (0, import_react25.useState)(false);
5283
+ const [createRefusal, setCreateRefusal] = (0, import_react25.useState)(null);
5284
+ const picked = (0, import_react25.useMemo)(
5236
5285
  () => Array.isArray(value) ? value.map(String) : value === null || value === void 0 ? [] : [String(value)],
5237
5286
  [value]
5238
5287
  );
5239
- (0, import_react24.useEffect)(() => {
5288
+ (0, import_react25.useEffect)(() => {
5240
5289
  const target2 = field2.relation_target;
5241
5290
  if (!target2 || !client) return;
5242
5291
  let cancelled = false;
@@ -5249,7 +5298,7 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
5249
5298
  cancelled = true;
5250
5299
  };
5251
5300
  }, [client, field2.relation_target]);
5252
- (0, import_react24.useEffect)(() => {
5301
+ (0, import_react25.useEffect)(() => {
5253
5302
  if (!rows || !client) return;
5254
5303
  const wanted = [.../* @__PURE__ */ new Set([...rows.map((row) => row.id), ...picked])].filter(
5255
5304
  (id2) => words2[id2] === void 0
@@ -5269,7 +5318,7 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
5269
5318
  cancelled = true;
5270
5319
  };
5271
5320
  }, [client, field2.id, rows, picked, words2]);
5272
- (0, import_react24.useEffect)(() => {
5321
+ (0, import_react25.useEffect)(() => {
5273
5322
  if (!open || !allowCreate || target || targetRefusal || !client) return;
5274
5323
  const id2 = field2.relation_target;
5275
5324
  if (!id2) return;
@@ -5476,12 +5525,12 @@ function RelationPicker({ field: field2, value, onChange, disabled, id, classNam
5476
5525
  }
5477
5526
 
5478
5527
  // src/gridAttachments.tsx
5479
- var import_react27 = require("react");
5480
- var import_react28 = require("@ai-matrx/records/react");
5528
+ var import_react28 = require("react");
5529
+ var import_react29 = require("@ai-matrx/records/react");
5481
5530
  var import_design_system15 = require("@ai-matrx/design-system");
5482
5531
 
5483
5532
  // src/FilePicker.tsx
5484
- var import_react26 = require("react");
5533
+ var import_react27 = require("react");
5485
5534
  var import_design_system14 = require("@ai-matrx/design-system");
5486
5535
  var import_jsx_runtime16 = require("react/jsx-runtime");
5487
5536
  function FilePicker({
@@ -5495,17 +5544,17 @@ function FilePicker({
5495
5544
  chosenName,
5496
5545
  className
5497
5546
  }) {
5498
- const inputId = (0, import_react26.useId)();
5499
- const input = (0, import_react26.useRef)(null);
5500
- const [over, setOver] = (0, import_react26.useState)(false);
5501
- const take = (0, import_react26.useCallback)(
5547
+ const inputId = (0, import_react27.useId)();
5548
+ const input = (0, import_react27.useRef)(null);
5549
+ const [over, setOver] = (0, import_react27.useState)(false);
5550
+ const take = (0, import_react27.useCallback)(
5502
5551
  (file) => {
5503
5552
  if (!file || disabled) return;
5504
5553
  onFile(file);
5505
5554
  },
5506
5555
  [disabled, onFile]
5507
5556
  );
5508
- const onDrop = (0, import_react26.useCallback)(
5557
+ const onDrop = (0, import_react27.useCallback)(
5509
5558
  (e) => {
5510
5559
  e.preventDefault();
5511
5560
  setOver(false);
@@ -5598,10 +5647,10 @@ function rememberHostFileIds(ids) {
5598
5647
  var FILE_CHIP_UNREAD = "File";
5599
5648
  var FILE_CHIP_NO_PAGE = "This screen has no way to open files yet.";
5600
5649
  function AttachmentChip({ id, onRemove }) {
5601
- const client = (0, import_react28.useOptionalRecordsClient)();
5650
+ const client = (0, import_react29.useOptionalRecordsClient)();
5602
5651
  const host = useRecordsUi();
5603
- const [read, setRead] = (0, import_react27.useState)(null);
5604
- (0, import_react27.useEffect)(() => {
5652
+ const [read, setRead] = (0, import_react28.useState)(null);
5653
+ (0, import_react28.useEffect)(() => {
5605
5654
  let cancelled = false;
5606
5655
  if (!client) {
5607
5656
  setRead({ name: null, fileId: null, why: null });
@@ -5676,9 +5725,9 @@ function AttachmentControl({
5676
5725
  onClose
5677
5726
  }) {
5678
5727
  const host = useRecordsUi();
5679
- const [busy, setBusy] = (0, import_react27.useState)(false);
5680
- const [why, setWhy] = (0, import_react27.useState)(null);
5681
- const latest = (0, import_react27.useRef)(value);
5728
+ const [busy, setBusy] = (0, import_react28.useState)(false);
5729
+ const [why, setWhy] = (0, import_react28.useState)(null);
5730
+ const latest = (0, import_react28.useRef)(value);
5682
5731
  latest.current = value;
5683
5732
  const multiple = Boolean(field2.multi);
5684
5733
  const pick = async () => {
@@ -5699,8 +5748,8 @@ function AttachmentControl({
5699
5748
  setBusy(false);
5700
5749
  onClose?.();
5701
5750
  };
5702
- const opened = (0, import_react27.useRef)(false);
5703
- (0, import_react27.useEffect)(() => {
5751
+ const opened = (0, import_react28.useRef)(false);
5752
+ (0, import_react28.useEffect)(() => {
5704
5753
  if (!autoOpen || opened.current || !host.pickFiles) return;
5705
5754
  opened.current = true;
5706
5755
  void pick();
@@ -5743,9 +5792,9 @@ function AttachmentControl({
5743
5792
  }
5744
5793
 
5745
5794
  // src/EntityReferenceControl.tsx
5746
- var import_react29 = require("react");
5795
+ var import_react30 = require("react");
5747
5796
  var import_records13 = require("@ai-matrx/records");
5748
- var import_react30 = require("@ai-matrx/records/react");
5797
+ var import_react31 = require("@ai-matrx/records/react");
5749
5798
  var import_design_system16 = require("@ai-matrx/design-system");
5750
5799
  var import_jsx_runtime18 = require("react/jsx-runtime");
5751
5800
  var WITHHELD_ENTITY_LABEL = "Something you have not been given access to";
@@ -5761,19 +5810,19 @@ function allowedKindsOf(field2) {
5761
5810
  return kinds.map((k) => String(k).trim().toLowerCase()).filter(Boolean);
5762
5811
  }
5763
5812
  function EntityReferenceControl(props) {
5764
- const client = (0, import_react30.useOptionalRecordsClient)();
5813
+ const client = (0, import_react31.useOptionalRecordsClient)();
5765
5814
  return client ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(WithWords, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Chips, { ...props, words: null, picker: null });
5766
5815
  }
5767
5816
  function WithWords(props) {
5768
- const refs = (0, import_react29.useMemo)(() => (0, import_records13.entityRefsOf)(props.value), [props.value]);
5769
- const [known, setKnown] = (0, import_react29.useState)([]);
5817
+ const refs = (0, import_react30.useMemo)(() => (0, import_records13.entityRefsOf)(props.value), [props.value]);
5818
+ const [known, setKnown] = (0, import_react30.useState)([]);
5770
5819
  const withKnown = refs.map((r) => r.label === null ? known.find((k) => k.token === r.token && k.id === r.id) ?? r : r);
5771
- const unlabelled = (0, import_react29.useMemo)(
5820
+ const unlabelled = (0, import_react30.useMemo)(
5772
5821
  () => withKnown.filter((r) => r.label === null).map((r) => ({ token: r.token, id: r.id })),
5773
5822
  // eslint-disable-next-line react-hooks/exhaustive-deps
5774
5823
  [JSON.stringify(withKnown)]
5775
5824
  );
5776
- const words2 = (0, import_react30.useEntityReferenceWords)(unlabelled);
5825
+ const words2 = (0, import_react31.useEntityReferenceWords)(unlabelled);
5777
5826
  const picker = props.disabled ? null : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5778
5827
  EntityReferencePicker,
5779
5828
  {
@@ -5795,13 +5844,13 @@ function EntityReferencePicker({
5795
5844
  onPick
5796
5845
  }) {
5797
5846
  const allowed = allowedKindsOf(field2);
5798
- const kinds = (0, import_react30.useEntityReferenceKinds)();
5847
+ const kinds = (0, import_react31.useEntityReferenceKinds)();
5799
5848
  const labelOfKind = (token) => kinds.data?.find((k) => k.token === token)?.label ?? token.replace(/_/g, " ");
5800
- const [open, setOpen] = (0, import_react29.useState)(false);
5801
- const [search, setSearch] = (0, import_react29.useState)("");
5802
- const [only, setOnly] = (0, import_react29.useState)(null);
5849
+ const [open, setOpen] = (0, import_react30.useState)(false);
5850
+ const [search, setSearch] = (0, import_react30.useState)("");
5851
+ const [only, setOnly] = (0, import_react30.useState)(null);
5803
5852
  const tokens = only ? [only] : allowed;
5804
- const found = (0, import_react30.useEntityReferenceSearch)(tokens, search, open);
5853
+ const found = (0, import_react31.useEntityReferenceSearch)(tokens, search, open);
5805
5854
  const multi = Boolean(field2.multi);
5806
5855
  const items = (found.data ?? []).map((r) => ({
5807
5856
  id: `${r.token}:${r.id}`,
@@ -5872,7 +5921,7 @@ function Chips({
5872
5921
  words: words2,
5873
5922
  picker
5874
5923
  }) {
5875
- const refs = (0, import_react29.useMemo)(() => (0, import_records13.entityRefsOf)(value), [value]);
5924
+ const refs = (0, import_react30.useMemo)(() => (0, import_records13.entityRefsOf)(value), [value]);
5876
5925
  const labelOf = (token, refId, own3) => {
5877
5926
  if (own3) return own3;
5878
5927
  const read = words2?.data?.find((w) => w.token === token && w.id === refId)?.label;
@@ -5908,7 +5957,7 @@ function Chips({
5908
5957
  }
5909
5958
 
5910
5959
  // src/FloatingRefusal.tsx
5911
- var import_react31 = require("react");
5960
+ var import_react32 = require("react");
5912
5961
  var import_react_dom = require("react-dom");
5913
5962
  var import_jsx_runtime19 = require("react/jsx-runtime");
5914
5963
  var GAP = 4;
@@ -5926,11 +5975,11 @@ function placeFor(anchor, note) {
5926
5975
  return { position: "fixed", top: a.top + (a.height - height) / 2, left: Math.max(a.left, a.right - width - 8) };
5927
5976
  }
5928
5977
  function FloatingRefusal({ text: text2, why }) {
5929
- const spot = (0, import_react31.useRef)(null);
5930
- const note = (0, import_react31.useRef)(null);
5931
- const [style, setStyle] = (0, import_react31.useState)(null);
5932
- const [floating, setFloating] = (0, import_react31.useState)(false);
5933
- (0, import_react31.useLayoutEffect)(() => {
5978
+ const spot = (0, import_react32.useRef)(null);
5979
+ const note = (0, import_react32.useRef)(null);
5980
+ const [style, setStyle] = (0, import_react32.useState)(null);
5981
+ const [floating, setFloating] = (0, import_react32.useState)(false);
5982
+ (0, import_react32.useLayoutEffect)(() => {
5934
5983
  const here = spot.current;
5935
5984
  if (!here) return;
5936
5985
  const anchor = here.closest("[data-matrx-cell-editor]");
@@ -5972,12 +6021,12 @@ function FloatingRefusal({ text: text2, why }) {
5972
6021
  }
5973
6022
 
5974
6023
  // src/formatControls.tsx
5975
- var import_react33 = require("react");
6024
+ var import_react34 = require("react");
5976
6025
  var import_design_system18 = require("@ai-matrx/design-system");
5977
6026
  var import_field_formats4 = require("@ai-matrx/design-system/field-formats");
5978
6027
 
5979
6028
  // src/formattedValue.tsx
5980
- var import_react32 = require("react");
6029
+ var import_react33 = require("react");
5981
6030
  var import_data_table4 = require("@ai-matrx/design-system/data-table");
5982
6031
  var import_field_formats3 = require("@ai-matrx/design-system/field-formats");
5983
6032
  var import_design_system17 = require("@ai-matrx/design-system");
@@ -5999,7 +6048,7 @@ function RatingStars({
5999
6048
  label,
6000
6049
  selectFirst
6001
6050
  }) {
6002
- const armed = (0, import_react32.useRef)(true);
6051
+ const armed = (0, import_react33.useRef)(true);
6003
6052
  const score = numberOf(value) ?? 0;
6004
6053
  const shown4 = Math.round(score);
6005
6054
  const said2 = `${shown4} out of ${max}`;
@@ -6148,9 +6197,9 @@ function keptValue(format, raw) {
6148
6197
  return parsed;
6149
6198
  }
6150
6199
  function NumberInFormat({ format, value, onChange, disabled, id }) {
6151
- const [text2, setText] = (0, import_react33.useState)(() => typedText(format, value));
6152
- const lastSent = (0, import_react33.useRef)(void 0);
6153
- (0, import_react33.useEffect)(() => {
6200
+ const [text2, setText] = (0, import_react34.useState)(() => typedText(format, value));
6201
+ const lastSent = (0, import_react34.useRef)(void 0);
6202
+ (0, import_react34.useEffect)(() => {
6154
6203
  if (value === lastSent.current) return;
6155
6204
  setText(typedText(format, value));
6156
6205
  }, [value, format]);
@@ -6227,56 +6276,6 @@ function formatControl(args) {
6227
6276
  var import_react35 = require("react");
6228
6277
  var import_design_system19 = require("@ai-matrx/design-system");
6229
6278
  var import_records14 = require("@ai-matrx/records");
6230
-
6231
- // src/personTime.ts
6232
- var import_react34 = require("react");
6233
- var zone = null;
6234
- var listeners = /* @__PURE__ */ new Set();
6235
- function valid(z) {
6236
- if (typeof z !== "string" || !z.trim()) return false;
6237
- try {
6238
- new Intl.DateTimeFormat("en-US", { timeZone: z });
6239
- return true;
6240
- } catch {
6241
- return false;
6242
- }
6243
- }
6244
- function setPersonTimeZone(next) {
6245
- const clean = valid(next) ? next : null;
6246
- if (clean === zone) return;
6247
- zone = clean;
6248
- listeners.forEach((l) => l());
6249
- }
6250
- function getPersonTimeZone() {
6251
- return zone;
6252
- }
6253
- function usePersonTimeZone() {
6254
- return (0, import_react34.useSyncExternalStore)(
6255
- (cb) => {
6256
- listeners.add(cb);
6257
- return () => listeners.delete(cb);
6258
- },
6259
- () => zone,
6260
- () => null
6261
- );
6262
- }
6263
- function personWallNow(at = /* @__PURE__ */ new Date()) {
6264
- if (!zone) return at;
6265
- const parts = new Intl.DateTimeFormat("en-US", {
6266
- timeZone: zone,
6267
- year: "numeric",
6268
- month: "2-digit",
6269
- day: "2-digit",
6270
- hour: "2-digit",
6271
- minute: "2-digit",
6272
- second: "2-digit",
6273
- hourCycle: "h23"
6274
- }).formatToParts(at);
6275
- const n = (t) => Number(parts.find((p) => p.type === t)?.value ?? 0);
6276
- return new Date(n("year"), n("month") - 1, n("day"), n("hour"), n("minute"), n("second"));
6277
- }
6278
-
6279
- // src/typedDateHelper.tsx
6280
6279
  var import_jsx_runtime22 = require("react/jsx-runtime");
6281
6280
  var WEEK = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
6282
6281
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
@@ -7589,6 +7588,473 @@ var import_design_system25 = require("@ai-matrx/design-system");
7589
7588
 
7590
7589
  // src/embeddedLook.tsx
7591
7590
  var import_react42 = require("react");
7591
+
7592
+ // src/firstPage.ts
7593
+ var import_core4 = require("@ai-matrx/records/core");
7594
+
7595
+ // src/viewKeys.ts
7596
+ var STORE_KEEPS_TIMELINE = true;
7597
+ var ALL = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
7598
+ var HIDES = ["grid", "gallery", "kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
7599
+ var GRIDS = ["grid"];
7600
+ var VIEW_KEYS = [
7601
+ { path: "layout", shape: "kind", layouts: ALL, writer: "caller" },
7602
+ { path: "filters", shape: "filter", layouts: ALL, writer: "caller" },
7603
+ { path: "where", shape: "rule", layouts: ALL, writer: "caller" },
7604
+ { path: "group_field", shape: "field", layouts: ["kanban", ...STORE_KEEPS_TIMELINE ? ["timeline"] : []], writer: "caller" },
7605
+ { path: "swimlane_field", shape: "field:lane", layouts: ["kanban"], writer: "caller" },
7606
+ { path: "collapsed_columns", shape: "values", layouts: ["kanban"], writer: "caller" },
7607
+ { path: "measure", shape: "field:number", layouts: ["kanban"], writer: "caller" },
7608
+ { path: "date_field", shape: "field:date", layouts: ["calendar"], writer: "caller" },
7609
+ ...STORE_KEEPS_TIMELINE ? [
7610
+ { path: "start_field", shape: "field:date", layouts: ["timeline"], writer: "caller" },
7611
+ { path: "end_field", shape: "field:date", layouts: ["calendar", "timeline"], writer: "caller" }
7612
+ ] : [],
7613
+ { path: "image_field", shape: "field", layouts: ["gallery"], writer: "caller" },
7614
+ { path: "sorts", shape: "sorts", layouts: ALL, writer: "caller" },
7615
+ { path: "rule_id", shape: "uuid", layouts: ALL, writer: "caller" },
7616
+ { path: "is_default", shape: "boolean", layouts: ALL, writer: "caller" },
7617
+ { path: "presentation", shape: "presentation", layouts: ALL, writer: "caller" },
7618
+ { path: "presentation.style", shape: "style", layouts: ALL, writer: "caller" },
7619
+ { path: "presentation.formats", shape: "object", layouts: GRIDS, writer: "caller" },
7620
+ { path: "presentation.frozen", shape: "fields", layouts: GRIDS, writer: "caller" },
7621
+ { path: "presentation.grouping", shape: "grouping", layouts: ["grid", "gallery", "list"], writer: "caller" },
7622
+ { path: "presentation.widths", shape: "widths", layouts: GRIDS, writer: "caller" },
7623
+ { path: "presentation.rowHeight", shape: "row_height", layouts: GRIDS, writer: "caller" },
7624
+ { path: "presentation.hiddenFields", shape: "fields", layouts: HIDES, writer: "caller" },
7625
+ { path: "presentation.cardHidden", shape: "fields", layouts: ["kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list", "gallery"], writer: "caller" },
7626
+ { path: "presentation.columnOrder", shape: "fields", layouts: GRIDS, writer: "caller" },
7627
+ { path: "presentation.gallerySize", shape: "gallery_size", layouts: ["gallery"], writer: "caller" },
7628
+ { path: "presentation.wrap", shape: "boolean", layouts: GRIDS, writer: "caller" },
7629
+ { path: "presentation.wrapColumns", shape: "fields", layouts: GRIDS, writer: "caller" },
7630
+ { path: "presentation.fit", shape: "fit", layouts: GRIDS, writer: "caller" },
7631
+ { path: "presentation.freezeFirst", shape: "boolean", layouts: GRIDS, writer: "caller" },
7632
+ { path: "presentation.footer", shape: "footer", layouts: GRIDS, writer: "caller" },
7633
+ { path: "presentation.summaries", shape: "summaries", layouts: GRIDS, writer: "caller" },
7634
+ { path: "grid", shape: "grid", layouts: GRIDS, writer: "caller" },
7635
+ { path: "hidden_fields", shape: "input", layouts: HIDES, writer: "input" },
7636
+ { path: "table_id", shape: "server", layouts: ALL, writer: "server" },
7637
+ { path: "order", shape: "server", layouts: GRIDS, writer: "server" },
7638
+ { path: "moved_from", shape: "server", layouts: ALL, writer: "server" }
7639
+ ];
7640
+ var STORE_KEPT_LAYOUTS = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
7641
+ function storeKeepsLayout(layout) {
7642
+ return STORE_KEPT_LAYOUTS.includes(layout);
7643
+ }
7644
+ function viewKeysFor(layout) {
7645
+ return VIEW_KEYS.filter((k) => k.layouts.includes(layout)).map((k) => k.path);
7646
+ }
7647
+ var KINDS = STORE_KEPT_LAYOUTS;
7648
+ function viewSettings(definition, rowFilters) {
7649
+ const data = definition ?? {};
7650
+ const text2 = (key) => {
7651
+ const v = data[key];
7652
+ return typeof v === "string" && v !== "" ? v : null;
7653
+ };
7654
+ const layout = String(data["layout"] ?? "grid");
7655
+ const flat = rowFilters ?? (isObject2(data["filters"]) ? data["filters"] : null);
7656
+ const moved = data["moved_from"];
7657
+ return {
7658
+ layout: KINDS.includes(layout) ? layout : "grid",
7659
+ filters: flat && Object.keys(flat).length > 0 ? flat : null,
7660
+ where: isRule(data["where"]) ? data["where"] : null,
7661
+ groupField: text2("group_field"),
7662
+ swimlaneField: text2("swimlane_field"),
7663
+ collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
7664
+ measure: text2("measure"),
7665
+ dateField: text2("date_field"),
7666
+ startField: text2("start_field"),
7667
+ endField: text2("end_field"),
7668
+ imageField: text2("image_field"),
7669
+ sorts: parseSorts(data["sorts"]),
7670
+ ruleId: text2("rule_id"),
7671
+ isDefault: data["is_default"] === true || data["is_default"] === "true",
7672
+ presentation: parseGridPresentation(data["presentation"]),
7673
+ movedFrom: isObject2(moved) ? moved : null
7674
+ };
7675
+ }
7676
+ function viewSettingsFor(settings, layout) {
7677
+ const reads = new Set(viewKeysFor(layout));
7678
+ const out = { layout: settings.layout };
7679
+ const take = (key, path) => {
7680
+ if (reads.has(path)) out[key] = settings[key];
7681
+ };
7682
+ take("filters", "filters");
7683
+ take("where", "where");
7684
+ take("groupField", "group_field");
7685
+ take("swimlaneField", "swimlane_field");
7686
+ take("collapsedColumns", "collapsed_columns");
7687
+ take("measure", "measure");
7688
+ take("dateField", "date_field");
7689
+ take("startField", "start_field");
7690
+ take("endField", "end_field");
7691
+ take("imageField", "image_field");
7692
+ take("sorts", "sorts");
7693
+ take("ruleId", "rule_id");
7694
+ take("isDefault", "is_default");
7695
+ const p = settings.presentation;
7696
+ const look = {};
7697
+ for (const [key, value] of Object.entries(p)) {
7698
+ if (reads.has(`presentation.${key}`)) look[key] = value;
7699
+ }
7700
+ out.presentation = look;
7701
+ return out;
7702
+ }
7703
+ function viewSettingsPatch(patch) {
7704
+ const out = {};
7705
+ const field2 = (key, path) => {
7706
+ if (patch[key] !== void 0) out[path] = patch[key] || null;
7707
+ };
7708
+ if (patch.layout !== void 0 && storeKeepsLayout(patch.layout)) out["layout"] = patch.layout;
7709
+ field2("groupField", "group_field");
7710
+ field2("swimlaneField", "swimlane_field");
7711
+ field2("measure", "measure");
7712
+ field2("dateField", "date_field");
7713
+ if (STORE_KEEPS_TIMELINE) {
7714
+ field2("startField", "start_field");
7715
+ field2("endField", "end_field");
7716
+ }
7717
+ field2("imageField", "image_field");
7718
+ field2("ruleId", "rule_id");
7719
+ if (patch.collapsedColumns !== void 0) out["collapsed_columns"] = patch.collapsedColumns ?? [];
7720
+ if (patch.sorts !== void 0) out["sorts"] = patch.sorts ?? [];
7721
+ if (patch.where !== void 0) out["where"] = patch.where ?? null;
7722
+ if (patch.isDefault !== void 0) out["is_default"] = patch.isDefault === true;
7723
+ if (patch.presentation !== void 0) {
7724
+ out["presentation"] = !patch.presentation || presentationIsEmpty(patch.presentation) ? null : JSON.parse(presentationDocument(patch.presentation));
7725
+ }
7726
+ return out;
7727
+ }
7728
+ function isObject2(raw) {
7729
+ return Boolean(raw) && typeof raw === "object" && !Array.isArray(raw);
7730
+ }
7731
+ function isRule(raw) {
7732
+ if (!isObject2(raw)) return false;
7733
+ const node = raw;
7734
+ return typeof node.op === "string" && Array.isArray(node.args);
7735
+ }
7736
+ function parseSorts(raw) {
7737
+ let list = raw;
7738
+ if (typeof raw === "string") {
7739
+ try {
7740
+ list = raw.trim() === "" ? [] : JSON.parse(raw);
7741
+ } catch {
7742
+ return [];
7743
+ }
7744
+ }
7745
+ if (!Array.isArray(list)) return [];
7746
+ return list.filter((s) => isObject2(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
7747
+ }
7748
+
7749
+ // src/views.ts
7750
+ var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
7751
+ var LAYOUT_LABEL = {
7752
+ grid: "Grid",
7753
+ kanban: "Kanban",
7754
+ calendar: "Calendar",
7755
+ gallery: "Gallery",
7756
+ timeline: "Timeline",
7757
+ list: "List"
7758
+ };
7759
+ function wordsList(words2) {
7760
+ const clean = words2.map((w) => w.trim()).filter((w) => w !== "");
7761
+ if (clean.length <= 1) return clean.join("");
7762
+ return `${clean.slice(0, -1).join(", ")} and ${clean[clean.length - 1]}`;
7763
+ }
7764
+ var VIEW_NEEDS = {
7765
+ grid: null,
7766
+ // A list reads nothing a table can lack: rows, titled, grouped only when the person chooses.
7767
+ list: null,
7768
+ kanban: {
7769
+ kind: "choice",
7770
+ viewKey: "groupField",
7771
+ blocking: true,
7772
+ starter: { label: "Status", type: "select", options: ["To do", "In progress", "Done"] },
7773
+ pick: "Pick the choice column the board's columns come from.",
7774
+ missing: "This table has no choice column to make the board's columns from.",
7775
+ does: (label) => `Make it work adds a ${label} column with the choices below and groups the board by it.`,
7776
+ ask: (label, options) => `Add a choice column called ${label} to this table${options.length > 0 ? ` with the choices ${wordsList(options)}` : ""}, then group the Kanban board by it.`
7777
+ },
7778
+ calendar: {
7779
+ kind: "date",
7780
+ viewKey: "dateField",
7781
+ blocking: true,
7782
+ starter: { label: "Date", type: "datetime" },
7783
+ pick: "Pick the date column the calendar places records by.",
7784
+ missing: "This table has no date column to place records on.",
7785
+ does: (label) => `Make it work adds a ${label} column and lays the calendar out by it.`,
7786
+ ask: (label) => `Add a date column called ${label} to this table, then lay the Calendar out by it.`
7787
+ },
7788
+ gallery: {
7789
+ kind: "file",
7790
+ viewKey: "imageField",
7791
+ blocking: false,
7792
+ starter: { label: "Photo", type: "attachment" },
7793
+ pick: "Pick the file column each card shows as its picture.",
7794
+ missing: "The cards have no picture because this table has no file column.",
7795
+ does: (label) => `Make it work adds a ${label} column and shows it on each card.`,
7796
+ ask: (label) => `Add a file column called ${label} to this table, then show it as the picture on each Gallery card.`
7797
+ },
7798
+ timeline: {
7799
+ kind: "date",
7800
+ viewKey: "dateField",
7801
+ blocking: true,
7802
+ starter: { label: "Start", type: "datetime" },
7803
+ pick: "Pick the date column each bar starts on.",
7804
+ missing: "This table has no date column to place records on.",
7805
+ does: (label) => `Make it work adds a ${label} column and lays the timeline out by it.`,
7806
+ ask: (label) => `Add a date column called ${label} to this table, then lay the Timeline out by it.`
7807
+ }
7808
+ };
7809
+ function freeColumnName(wanted, taken) {
7810
+ const held = new Set(taken.map((t) => t.trim().toLowerCase()));
7811
+ const base = wanted.trim() === "" ? "Column" : wanted.trim();
7812
+ if (!held.has(base.toLowerCase())) return base;
7813
+ for (let n = 2; n < 100; n += 1) {
7814
+ const next = `${base} ${n}`;
7815
+ if (!held.has(next.toLowerCase())) return next;
7816
+ }
7817
+ return base;
7818
+ }
7819
+ function viewOrderOf(definition) {
7820
+ const raw = definition?.["order"];
7821
+ return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
7822
+ }
7823
+ function defaultViewOf(views) {
7824
+ return views.find((v) => v.isDefault);
7825
+ }
7826
+ var LAYOUT_FIELD_KIND = {
7827
+ grid: null,
7828
+ kanban: "choice",
7829
+ calendar: "date",
7830
+ gallery: "file",
7831
+ timeline: "date",
7832
+ list: null
7833
+ };
7834
+ var PAGE_VIEWS = [...VIEW_LAYOUTS, "dashboards", "archived"];
7835
+ var PAGE_VIEW_LABEL = {
7836
+ ...LAYOUT_LABEL,
7837
+ dashboards: "Dashboards",
7838
+ archived: "Archived"
7839
+ };
7840
+ var PAGE_VIEW_SPELLINGS = {
7841
+ grid: "grid",
7842
+ table: "grid",
7843
+ rows: "grid",
7844
+ list: "list",
7845
+ kanban: "kanban",
7846
+ board: "kanban",
7847
+ pipeline: "kanban",
7848
+ calendar: "calendar",
7849
+ month: "calendar",
7850
+ schedule: "calendar",
7851
+ gallery: "gallery",
7852
+ cards: "gallery",
7853
+ timeline: "timeline",
7854
+ gantt: "timeline",
7855
+ dashboards: "dashboards",
7856
+ dashboard: "dashboards",
7857
+ charts: "dashboards",
7858
+ archived: "archived",
7859
+ archive: "archived",
7860
+ // The grid's row action says "Delete" and the store soft-deletes, so the word
7861
+ // a person types is as likely to be the one the button used as the one this
7862
+ // view is called. Both land in the same place; neither dies.
7863
+ deleted: "archived",
7864
+ trash: "archived",
7865
+ removed: "archived"
7866
+ };
7867
+ function pageViewFromParam(raw) {
7868
+ if (typeof raw !== "string") return null;
7869
+ const token = raw.trim().toLowerCase();
7870
+ if (token === "") return null;
7871
+ return PAGE_VIEW_SPELLINGS[token] ?? null;
7872
+ }
7873
+ function unknownViewLine(raw) {
7874
+ return `The link asked for a view called \u201C${raw}\u201D, which this table has no view for, so you are looking at ${PAGE_VIEW_LABEL.grid}. The views this table has are ${PAGE_VIEWS.map((v) => PAGE_VIEW_LABEL[v]).join(", ")} \u2014 pick one above and the address follows it.`;
7875
+ }
7876
+ function viewDocument(spec) {
7877
+ const out = {
7878
+ // A layout the store does not keep yet is not sent: the view is saved as a grid (`STORE_KEPT_LAYOUTS`).
7879
+ layout: storeKeepsLayout(spec.layout) ? spec.layout : "grid",
7880
+ sorts: spec.sorts ?? [],
7881
+ is_default: spec.isDefault === true
7882
+ };
7883
+ if (spec.groupField) out["group_field"] = spec.groupField;
7884
+ if (spec.swimlaneField) out["swimlane_field"] = spec.swimlaneField;
7885
+ if (spec.collapsedColumns && spec.collapsedColumns.length > 0) out["collapsed_columns"] = spec.collapsedColumns;
7886
+ if (spec.measure) out["measure"] = spec.measure;
7887
+ if (spec.dateField) out["date_field"] = spec.dateField;
7888
+ if (STORE_KEEPS_TIMELINE && spec.startField) out["start_field"] = spec.startField;
7889
+ if (STORE_KEEPS_TIMELINE && spec.endField) out["end_field"] = spec.endField;
7890
+ if (spec.imageField) out["image_field"] = spec.imageField;
7891
+ if (spec.ruleId) out["rule_id"] = spec.ruleId;
7892
+ if (spec.where) out["where"] = spec.where;
7893
+ if (spec.presentation && !presentationIsEmpty(spec.presentation)) {
7894
+ out["presentation"] = JSON.parse(presentationDocument(spec.presentation));
7895
+ }
7896
+ return out;
7897
+ }
7898
+ function viewFromRow(row) {
7899
+ const data = row.definition ?? {};
7900
+ const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null);
7901
+ const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
7902
+ return {
7903
+ id: row.view_id,
7904
+ name: row.name || "Untitled view",
7905
+ subject: row.table_id ?? tableFromDefinition ?? "",
7906
+ layout: k.layout,
7907
+ groupField: k.groupField,
7908
+ swimlaneField: k.swimlaneField,
7909
+ collapsedColumns: k.collapsedColumns,
7910
+ measure: k.measure,
7911
+ dateField: k.dateField,
7912
+ startField: k.startField,
7913
+ endField: k.endField,
7914
+ imageField: k.imageField,
7915
+ sorts: k.sorts,
7916
+ order: viewOrderOf(data),
7917
+ ruleId: k.ruleId,
7918
+ ...k.filters ? { filters: k.filters } : {},
7919
+ where: k.where,
7920
+ // The older table's own default view, carried in by the mover, IS this table's default —
7921
+ // the mover wrote the row's column, which `custom.views` does not return. Read as anything
7922
+ // else, the page would seed a second "All records" beside it and open on that.
7923
+ isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
7924
+ presentation: k.presentation,
7925
+ movedFrom: k.movedFrom
7926
+ };
7927
+ }
7928
+ async function declareView(client, spec) {
7929
+ return client.viewDeclare({
7930
+ table_id: spec.subject,
7931
+ spec: {
7932
+ name: spec.name,
7933
+ ...spec.filters ? { filters: spec.filters } : {},
7934
+ definition: viewDocument(spec)
7935
+ }
7936
+ });
7937
+ }
7938
+ async function saveViewPatch(client, tableId, viewId, patch) {
7939
+ const definition = viewPatchDocument(patch);
7940
+ const renamed = patch.name !== void 0 && patch.name.trim() !== "";
7941
+ const refiltered = patch.filters !== void 0;
7942
+ return client.viewDeclare({
7943
+ table_id: tableId,
7944
+ spec: {
7945
+ view_id: viewId,
7946
+ ...renamed ? { name: patch.name.trim() } : {},
7947
+ ...refiltered ? { filters: patch.filters ?? null } : {},
7948
+ definition
7949
+ }
7950
+ });
7951
+ }
7952
+ function viewPatchDocument(patch) {
7953
+ const { name: _name, subject: _subject, filters: _filters, ...keys } = patch;
7954
+ return viewSettingsPatch(keys);
7955
+ }
7956
+ function viewPatchFor(view, patch) {
7957
+ if (!view.isDefault) return patch;
7958
+ const { layout: _layout, isDefault: _isDefault, ...kept } = patch;
7959
+ return kept;
7960
+ }
7961
+ async function designateView(client, tableId, viewId, layout) {
7962
+ return client.viewDesignate({ table_id: tableId, view_id: viewId, layout });
7963
+ }
7964
+
7965
+ // src/viewLook.ts
7966
+ var LOOK_KEYS = [
7967
+ "layout",
7968
+ "groupField",
7969
+ "swimlaneField",
7970
+ "collapsedColumns",
7971
+ "measure",
7972
+ "dateField",
7973
+ "startField",
7974
+ "endField",
7975
+ "imageField",
7976
+ "sorts",
7977
+ "where",
7978
+ "presentation"
7979
+ ];
7980
+ function lookPart(patch) {
7981
+ const out = {};
7982
+ for (const key of LOOK_KEYS) {
7983
+ if (patch[key] !== void 0) out[key] = patch[key];
7984
+ }
7985
+ return out;
7986
+ }
7987
+ function lookDocument(look) {
7988
+ return viewSettingsPatch(look);
7989
+ }
7990
+ function lookFromDocument(doc) {
7991
+ const data = doc ?? {};
7992
+ const read = viewSettings(data);
7993
+ const out = {};
7994
+ const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
7995
+ if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
7996
+ out.layout = data["layout"];
7997
+ }
7998
+ if (has("group_field")) out.groupField = read.groupField;
7999
+ if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
8000
+ if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
8001
+ if (has("measure")) out.measure = read.measure;
8002
+ if (has("date_field")) out.dateField = read.dateField;
8003
+ if (has("start_field")) out.startField = read.startField;
8004
+ if (has("end_field")) out.endField = read.endField;
8005
+ if (has("image_field")) out.imageField = read.imageField;
8006
+ if (has("sorts")) out.sorts = read.sorts;
8007
+ if (has("where")) out.where = read.where;
8008
+ if (has("presentation")) out.presentation = parseGridPresentation(data["presentation"]);
8009
+ return out;
8010
+ }
8011
+ function applyLook(view, look) {
8012
+ if (!look) return view;
8013
+ return { ...view, ...look };
8014
+ }
8015
+ function lookDiffers(view, look) {
8016
+ if (!look) return false;
8017
+ const shown4 = applyLook(view, look);
8018
+ return LOOK_KEYS.some(
8019
+ (key) => look[key] !== void 0 && JSON.stringify(shown4[key] ?? null) !== JSON.stringify(view[key] ?? null)
8020
+ );
8021
+ }
8022
+ function saveToViewPlan(view, look) {
8023
+ const patch = viewPatchFor(view, look);
8024
+ const left = {};
8025
+ if (look.layout !== void 0 && patch.layout === void 0 && look.layout !== view.layout) left.layout = look.layout;
8026
+ return { patch, left: Object.keys(left).length > 0 ? left : null };
8027
+ }
8028
+ async function readLooks(client, tableId) {
8029
+ const answered = await client.viewLookRead({ table_id: tableId });
8030
+ if (!answered.ok) return answered;
8031
+ const out = {};
8032
+ for (const [viewId, row] of Object.entries(answered.data ?? {})) {
8033
+ out[viewId] = lookFromDocument(row?.look ?? null);
8034
+ }
8035
+ return { ok: true, data: out };
8036
+ }
8037
+ async function keepLook(client, tableId, viewId, look) {
8038
+ const doc = look ? lookDocument(look) : null;
8039
+ return client.viewLookSet({ table_id: tableId, view_id: viewId, look: doc && Object.keys(doc).length > 0 ? doc : null });
8040
+ }
8041
+ var LOOK_WORDS = {
8042
+ /** The reason, for a tooltip or a screen reader — never a line on the page (interface-text). */
8043
+ yours: "You changed how this view looks. Only you see it.",
8044
+ /** The visible label for the same fact. */
8045
+ yoursLabel: "Only you see this",
8046
+ saveToView: "Save to view",
8047
+ saveAsNew: "Save as new view",
8048
+ reset: "Reset to view",
8049
+ /** The one button your look's doors fold into when the toolbar row has no room for three. */
8050
+ folded: "Your look",
8051
+ newName: "Name for the new view"
8052
+ };
8053
+
8054
+ // src/firstPage.ts
8055
+ var EMBEDDED_PAGE_SIZE = 50;
8056
+
8057
+ // src/embeddedLook.tsx
7592
8058
  var EMBEDDED_LOOK = { blankEmpty: true, choiceDot: true, plainRelation: true };
7593
8059
  var EmbeddedLookContext = (0, import_react42.createContext)(null);
7594
8060
  var EmbeddedLookProvider = EmbeddedLookContext.Provider;
@@ -7606,7 +8072,6 @@ var EMBEDDED_TABLE_CLASS = [
7606
8072
  "[&_thead_th:last-child]:border-r-0"
7607
8073
  ].join(" ");
7608
8074
  var EMBEDDED_PLAIN_FOOTER_CLASS = "[&_tfoot]:bg-transparent [&_tfoot]:border-t-0";
7609
- var EMBEDDED_PAGE_SIZE = 50;
7610
8075
 
7611
8076
  // src/enumLabels.ts
7612
8077
  function exhaustiveValuesOf() {
@@ -7745,16 +8210,16 @@ var ABSENCE_WORD_LABEL = {
7745
8210
  };
7746
8211
 
7747
8212
  // src/values.tsx
7748
- var import_core5 = require("@ai-matrx/records/core");
8213
+ var import_core6 = require("@ai-matrx/records/core");
7749
8214
 
7750
8215
  // src/WholeValue.tsx
7751
8216
  var import_react43 = require("react");
7752
- var import_core4 = require("@ai-matrx/records/core");
8217
+ var import_core5 = require("@ai-matrx/records/core");
7753
8218
  var import_design_system21 = require("@ai-matrx/design-system");
7754
8219
  var import_jsx_runtime26 = require("react/jsx-runtime");
7755
8220
  var WHOLE_VALUE_UNBOUND = "The whole text is kept as a file, and this screen has no way to open files yet.";
7756
8221
  function wholeValueLine(pointer) {
7757
- return `Open the whole text (${(0, import_core4.wholeValueSize)(pointer)})`;
8222
+ return `Open the whole text (${(0, import_core5.wholeValueSize)(pointer)})`;
7758
8223
  }
7759
8224
  function WholeValueCell({ words: words2, pointer }) {
7760
8225
  const host = useRecordsUi();
@@ -7765,12 +8230,12 @@ function WholeValueCell({ words: words2, pointer }) {
7765
8230
  words2,
7766
8231
  "\u2026"
7767
8232
  ] }),
7768
- href ? host.Link ? host.Link({ href, children: line, className: "shrink-0 text-xs text-primary underline-offset-2 hover:underline" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("a", { className: "shrink-0 text-xs text-primary underline-offset-2 hover:underline", href, target: "_blank", rel: "noreferrer", children: line }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0 text-xs italic text-muted-foreground", title: WHOLE_VALUE_UNBOUND, children: `${(0, import_core4.wholeValueSize)(pointer)} in a file` })
8233
+ href ? host.Link ? host.Link({ href, children: line, className: "shrink-0 text-xs text-primary underline-offset-2 hover:underline" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("a", { className: "shrink-0 text-xs text-primary underline-offset-2 hover:underline", href, target: "_blank", rel: "noreferrer", children: line }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0 text-xs italic text-muted-foreground", title: WHOLE_VALUE_UNBOUND, children: `${(0, import_core5.wholeValueSize)(pointer)} in a file` })
7769
8234
  ] });
7770
8235
  }
7771
8236
  var WHOLE_VALUE_NOT_EDITABLE_HERE = "The whole text is kept as a file. Open it to read it; this screen cannot load it to edit.";
7772
8237
  function wholeValueOpening(pointer) {
7773
- return `Opening the whole text (${(0, import_core4.wholeValueSize)(pointer)})\u2026`;
8238
+ return `Opening the whole text (${(0, import_core5.wholeValueSize)(pointer)})\u2026`;
7774
8239
  }
7775
8240
  function useWholeText(pointer) {
7776
8241
  const host = useRecordsUi();
@@ -8466,7 +8931,7 @@ function renderValue(field2, value, document2, labels, stillWaitingFor, look) {
8466
8931
  if (isSignatureField(field2)) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SignatureValue, { value, fieldKey: field2.key, document: document2 });
8467
8932
  const newer = newerKindValue(field2, value);
8468
8933
  if (newer !== void 0) return newer;
8469
- const whole = typeof value === "string" ? (0, import_core5.wholeValueOf)(document2, field2.key) : null;
8934
+ const whole = typeof value === "string" ? (0, import_core6.wholeValueOf)(document2, field2.key) : null;
8470
8935
  if (whole) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(WholeValueCell, { words: value, pointer: whole });
8471
8936
  const kind = editorKindFor(field2);
8472
8937
  if (kind === "relation" || kind === "entity_reference") {
@@ -8589,7 +9054,7 @@ function scalarText(field2, value, labels, stillWaitingFor) {
8589
9054
  function ProvenanceBadge({ document: document2, fieldKey }) {
8590
9055
  const envelope = envelopeFor(document2, fieldKey);
8591
9056
  if (!envelope?.src) return null;
8592
- if ((0, import_core5.wholeValueOf)(document2, fieldKey)) return null;
9057
+ if ((0, import_core6.wholeValueOf)(document2, fieldKey)) return null;
8593
9058
  const sources = document2?._sources;
8594
9059
  const source = sources?.[envelope.src];
8595
9060
  const label = source ? Object.values(source).map(String).join(" \xB7 ") : envelope.src;
@@ -8624,7 +9089,7 @@ function RecordValue({
8624
9089
  const newer = newerKindValue(field2, value, { inCell });
8625
9090
  if (newer !== void 0) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, { children: newer });
8626
9091
  }
8627
- if (inCell && ui.grid === "merged" && ui.renderText && typeof value === "string" && value.trim() !== "" && editorKindFor(field2) === "long_text" && !shownAsOf(field2) && !(0, import_core5.wholeValueOf)(document2, field2.key) && !envelopeFor(document2, field2.key)?.absent && // A long-text cell holding a kind is drawn by the kind system below, not as markdown.
9092
+ if (inCell && ui.grid === "merged" && ui.renderText && typeof value === "string" && value.trim() !== "" && editorKindFor(field2) === "long_text" && !shownAsOf(field2) && !(0, import_core6.wholeValueOf)(document2, field2.key) && !envelopeFor(document2, field2.key)?.absent && // A long-text cell holding a kind is drawn by the kind system below, not as markdown.
8628
9093
  !kindValueOf(value)) {
8629
9094
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "block h-[1.5em] min-w-0 overflow-hidden whitespace-normal", "data-records-cell-text": "", children: ui.renderText(value, "cell") });
8630
9095
  }
@@ -8837,7 +9302,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
8837
9302
  }
8838
9303
  const held = optimistic[cellKey(address.rowId, address.key)];
8839
9304
  const document2 = rows.find((r) => r.id === address.rowId)?.document;
8840
- const pointer = held === void 0 && typeof current === "string" ? (0, import_core6.wholeValueOf)(document2, address.key) : null;
9305
+ const pointer = held === void 0 && typeof current === "string" ? (0, import_core7.wholeValueOf)(document2, address.key) : null;
8841
9306
  if (pointer) {
8842
9307
  const read = host.readFileText;
8843
9308
  if (!read) return;
@@ -8948,7 +9413,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
8948
9413
  delete next[id];
8949
9414
  return next;
8950
9415
  });
8951
- const conflict = (0, import_core6.asWriteConflict)(written.error, rowId);
9416
+ const conflict = (0, import_core7.asWriteConflict)(written.error, rowId);
8952
9417
  if (written.error.code === "stale_write") {
8953
9418
  if (conflict) rememberVersion(versions.current, rowId, conflict.current_version);
8954
9419
  else versions.current.delete(rowId);
@@ -9036,7 +9501,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
9036
9501
  }
9037
9502
  const starting = shownValue2(next.rowId, next.key);
9038
9503
  const nextDocument = rows.find((r) => r.id === next.rowId)?.document;
9039
- if (typeof starting === "string" && optimistic[cellKey(next.rowId, next.key)] === void 0 && (0, import_core6.wholeValueOf)(nextDocument, next.key)) {
9504
+ if (typeof starting === "string" && optimistic[cellKey(next.rowId, next.key)] === void 0 && (0, import_core7.wholeValueOf)(nextDocument, next.key)) {
9040
9505
  setEditing(null);
9041
9506
  setDraft(null);
9042
9507
  typed2.current = null;
@@ -10057,7 +10522,7 @@ var import_react122 = require("react");
10057
10522
  var import_react123 = require("@ai-matrx/records/react");
10058
10523
  var import_records36 = require("@ai-matrx/records");
10059
10524
  var import_data_table13 = require("@ai-matrx/design-system/data-table");
10060
- var import_core16 = require("@ai-matrx/records/core");
10525
+ var import_core17 = require("@ai-matrx/records/core");
10061
10526
 
10062
10527
  // src/archiveWords.ts
10063
10528
  var import_format2 = require("@ai-matrx/kit/format");
@@ -10203,7 +10668,7 @@ function columnNameTakenLine(taken, noun = "column") {
10203
10668
  // src/FieldEditor.tsx
10204
10669
  var import_react65 = require("react");
10205
10670
  var import_react66 = require("@ai-matrx/records/react");
10206
- var import_core7 = require("@ai-matrx/records/core");
10671
+ var import_core8 = require("@ai-matrx/records/core");
10207
10672
  var import_design_system35 = require("@ai-matrx/design-system");
10208
10673
 
10209
10674
  // src/EntityReferenceKindPicker.tsx
@@ -11891,7 +12356,7 @@ function FieldEditor(props) {
11891
12356
  return;
11892
12357
  }
11893
12358
  (0, import_react66.tableShapeChanged)(tableId);
11894
- for (const c of done.data.undo.cells_back) (0, import_core7.announceRecordChanged)(c.record_id);
12359
+ for (const c of done.data.undo.cells_back) (0, import_core8.announceRecordChanged)(c.record_id);
11895
12360
  const n = done.data.rehomed.reduce((sum, r) => sum + r.records, 0);
11896
12361
  setRehome({});
11897
12362
  setRehomed({ said: `Saved. ${n} ${n === 1 ? "record was" : "records were"} changed with the choices.`, undo: done.data.undo });
@@ -12313,7 +12778,7 @@ function FieldEditor(props) {
12313
12778
  return;
12314
12779
  }
12315
12780
  (0, import_react66.tableShapeChanged)(tableId);
12316
- for (const c of undo.cells_back) (0, import_core7.announceRecordChanged)(c.record_id);
12781
+ for (const c of undo.cells_back) (0, import_core8.announceRecordChanged)(c.record_id);
12317
12782
  setChoiceList(null);
12318
12783
  setChoiceListStart(null);
12319
12784
  setRehomed({ said: "Undone. The choices and the records that held them are back as they were.", undo: null });
@@ -15004,7 +15469,7 @@ function WholeTextDialog({
15004
15469
  }
15005
15470
 
15006
15471
  // src/pasteValues.ts
15007
- var import_core8 = require("@ai-matrx/records/core");
15472
+ var import_core9 = require("@ai-matrx/records/core");
15008
15473
  var import_records29 = require("@ai-matrx/records");
15009
15474
  function wordForStoredChoice(options, value) {
15010
15475
  if (options === void 0 || typeof value !== "string" || value === "") return null;
@@ -15083,7 +15548,7 @@ function planPastedBlock(args) {
15083
15548
  });
15084
15549
  accepted[key] = judged.value;
15085
15550
  }
15086
- const predicted = (0, import_core8.predictValueRefusals)(args.fields, accepted);
15551
+ const predicted = (0, import_core9.predictValueRefusals)(args.fields, accepted);
15087
15552
  for (const refusal4 of predicted) {
15088
15553
  const key = refusal4.field_key;
15089
15554
  if (key === void 0) continue;
@@ -15604,9 +16069,17 @@ function useMergedGridControls(args) {
15604
16069
  const row = rows.find((r) => r.id === rowId);
15605
16070
  if (row) args.duplicate(row);
15606
16071
  },
16072
+ // ARCHIVE FROM THE ROW MENU NEVER FAILS SILENTLY (Spaces round 33): the confirm opens once the menu
16073
+ // layer has closed — opened from inside the menu's own select callback, the closing menu's focus
16074
+ // return dismissed the dialog the moment it opened (inside a contenteditable host every time), so the
16075
+ // press did nothing. A row the page no longer holds says so.
15607
16076
  archiveRow: (rowId) => {
15608
16077
  const row = rows.find((r) => r.id === rowId);
15609
- if (row) args.askDelete(row);
16078
+ if (!row) {
16079
+ notify?.error("This record is no longer on the page. Open it to archive it.");
16080
+ return;
16081
+ }
16082
+ afterMenuLayerCloses(() => args.askDelete(row));
15610
16083
  },
15611
16084
  ...args.onOpenRecord ? { openRecord: (rowId) => args.onOpenRecord?.(rowId) } : {},
15612
16085
  ...args.onAskWhoChanged ? { askWhoChanged: (columnId2, rowId) => args.onAskWhoChanged?.(columnId2, rowId) } : {},
@@ -15965,6 +16438,10 @@ function backLinkSentence(column, readers = [], tableName2 = null) {
15965
16438
  if (readers.length === 0) return base;
15966
16439
  return `${readersSentence(readers.length, tableName2)} ${base}`;
15967
16440
  }
16441
+ function afterMenuLayerCloses(next) {
16442
+ if (typeof window === "undefined") return next();
16443
+ requestAnimationFrame(() => requestAnimationFrame(next));
16444
+ }
15968
16445
  function selectOpenCellText() {
15969
16446
  if (typeof window === "undefined") return;
15970
16447
  requestAnimationFrame(
@@ -15988,7 +16465,7 @@ var import_design_system51 = require("@ai-matrx/design-system");
15988
16465
  // src/RecordForm.tsx
15989
16466
  var import_react92 = require("react");
15990
16467
  var import_react93 = require("@ai-matrx/records/react");
15991
- var import_core10 = require("@ai-matrx/records/core");
16468
+ var import_core11 = require("@ai-matrx/records/core");
15992
16469
  var import_design_system50 = require("@ai-matrx/design-system");
15993
16470
  var import_text_case6 = require("@ai-matrx/kit/text-case");
15994
16471
 
@@ -16001,7 +16478,7 @@ var import_design_system49 = require("@ai-matrx/design-system");
16001
16478
  var import_react88 = require("react");
16002
16479
  var import_react89 = require("@ai-matrx/records/react");
16003
16480
  var import_design_system48 = require("@ai-matrx/design-system");
16004
- var import_core9 = require("@ai-matrx/records/core");
16481
+ var import_core10 = require("@ai-matrx/records/core");
16005
16482
  var import_jsx_runtime55 = require("react/jsx-runtime");
16006
16483
  function isEmptyValue(value) {
16007
16484
  return value === null || value === void 0 || value === "" || Array.isArray(value) && value.length === 0;
@@ -16073,7 +16550,7 @@ async function writeStandardRowValues(client, args) {
16073
16550
  { schema: config.schema ?? "custom" }
16074
16551
  );
16075
16552
  if (!old.error) return { ok: true };
16076
- const error = (0, import_core9.mapPgError)(old.error, "entityValueWrite");
16553
+ const error = (0, import_core10.mapPgError)(old.error, "entityValueWrite");
16077
16554
  return { ok: false, error: doorIsAbsent(error) && first && first.error.code !== "door_absent" ? first.error : error };
16078
16555
  }
16079
16556
  function doorIsAbsent(error) {
@@ -16644,7 +17121,7 @@ function CustomRecordForm({
16644
17121
  return out;
16645
17122
  }, [draft]);
16646
17123
  const predicted = (0, import_react92.useMemo)(
16647
- () => fields.data ? (0, import_core10.predictWriteRefusals)({ fields: fields.data, document: document2, ...recordType ? { recordType } : {} }) : [],
17124
+ () => fields.data ? (0, import_core11.predictWriteRefusals)({ fields: fields.data, document: document2, ...recordType ? { recordType } : {} }) : [],
16648
17125
  [fields.data, document2, recordType]
16649
17126
  );
16650
17127
  if (fields.error) return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(RefusalNotice, { error: fields.error, className });
@@ -16694,7 +17171,7 @@ function CustomRecordForm({
16694
17171
  setEdit({
16695
17172
  saving: false,
16696
17173
  error: answered2.ok ? null : answered2.error,
16697
- conflict: answered2.ok ? null : (0, import_core10.asWriteConflict)(answered2.error, recordId)
17174
+ conflict: answered2.ok ? null : (0, import_core11.asWriteConflict)(answered2.error, recordId)
16698
17175
  });
16699
17176
  const moved = answered2.ok ? answered2.data : null;
16700
17177
  if (moved !== null) {
@@ -16803,7 +17280,7 @@ function FieldRow({
16803
17280
  }) {
16804
17281
  const id = `field-${field2.id}`;
16805
17282
  const storedWords = document2?.[field2.key];
16806
- const whole = typeof storedWords === "string" ? (0, import_core10.wholeValueOf)(document2, field2.key) : null;
17283
+ const whole = typeof storedWords === "string" ? (0, import_core11.wholeValueOf)(document2, field2.key) : null;
16807
17284
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: (0, import_design_system50.cn)("flex min-w-0 flex-col gap-1", whole && "sm:col-span-2"), children: [
16808
17285
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(FieldLabel, { field: field2, htmlFor: id, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ProvenanceBadge, { document: document2, fieldKey: field2.key }) }),
16809
17286
  whole ? (
@@ -18852,12 +19329,12 @@ function withOpenRecord(columns, onOpen, nameOf2, place = "end", hrefOf) {
18852
19329
  // src/ImportWizard.tsx
18853
19330
  var import_react105 = require("react");
18854
19331
  var import_react106 = require("@ai-matrx/records/react");
18855
- var import_core12 = require("@ai-matrx/records/core");
19332
+ var import_core13 = require("@ai-matrx/records/core");
18856
19333
  var import_design_system56 = require("@ai-matrx/design-system");
18857
19334
  var import_records33 = require("@ai-matrx/records");
18858
19335
 
18859
19336
  // src/importRuleCheck.ts
18860
- var import_core11 = require("@ai-matrx/records/core");
19337
+ var import_core12 = require("@ai-matrx/records/core");
18861
19338
  function checkImportRules(fields, rows, mapping, choiceOptions, relationNames) {
18862
19339
  const byKey = new Map(fields.map((f) => [f.key, f]));
18863
19340
  const verdicts = [];
@@ -18883,7 +19360,7 @@ function checkImportRules(fields, rows, mapping, choiceOptions, relationNames) {
18883
19360
  if ("unmatchedNames" in meant) return;
18884
19361
  if ("refusal" in meant) why = meant.refusal;
18885
19362
  else {
18886
- const predicted = (0, import_core11.predictValueRefusals)([field2], { [key]: meant.value }).filter(
19363
+ const predicted = (0, import_core12.predictValueRefusals)([field2], { [key]: meant.value }).filter(
18887
19364
  (p) => p.field_key === void 0 || p.field_key === key
18888
19365
  );
18889
19366
  if (predicted.length > 0) why = predicted[0].message;
@@ -19387,7 +19864,7 @@ function ImportWizard({ tableId, source, onDone, onWrote, className }) {
19387
19864
  try {
19388
19865
  const xlsx = file.name.toLowerCase().endsWith(".xlsx");
19389
19866
  const bytes = await file.arrayBuffer();
19390
- const result = xlsx ? await (0, import_core12.importXlsx)(bytes) : (0, import_core12.importCsv)(new TextDecoder().decode(bytes));
19867
+ const result = xlsx ? await (0, import_core13.importXlsx)(bytes) : (0, import_core13.importCsv)(new TextDecoder().decode(bytes));
19391
19868
  await planFrom(result, { name: file.name, bytes: file.size, hash: await sha256(bytes), format: xlsx ? "xlsx" : "csv" });
19392
19869
  } catch (thrown) {
19393
19870
  setProblem(
@@ -21405,7 +21882,7 @@ function useGroupLabel(fields, groupKey) {
21405
21882
  // src/gridUndo.tsx
21406
21883
  var import_react113 = require("react");
21407
21884
  var import_react114 = require("@ai-matrx/records/react");
21408
- var import_core13 = require("@ai-matrx/records/core");
21885
+ var import_core14 = require("@ai-matrx/records/core");
21409
21886
  var import_design_system58 = require("@ai-matrx/design-system");
21410
21887
  var import_data_table12 = require("@ai-matrx/design-system/data-table");
21411
21888
  var import_jsx_runtime68 = require("react/jsx-runtime");
@@ -21499,7 +21976,7 @@ function useGridUndo(args) {
21499
21976
  }
21500
21977
  forget(step2.cells.map((c) => ({ rowId: c.rowId, key: c.key })));
21501
21978
  for (const id of /* @__PURE__ */ new Set([...step2.cells.map((c) => c.rowId), ...step2.created ?? [], ...step2.archived ?? []])) {
21502
- (0, import_core13.announceRecordChanged)(id);
21979
+ (0, import_core14.announceRecordChanged)(id);
21503
21980
  }
21504
21981
  setHeld(() => {
21505
21982
  let stack = taken.stack;
@@ -21784,7 +22261,7 @@ function holdKeys() {
21784
22261
  // src/gridAssist.tsx
21785
22262
  var import_clipboard2 = require("@ai-matrx/kit/clipboard");
21786
22263
  var import_react116 = require("react");
21787
- var import_core14 = require("@ai-matrx/records/core");
22264
+ var import_core15 = require("@ai-matrx/records/core");
21788
22265
  var import_workspace = require("@ai-matrx/alchemy/react/workspace");
21789
22266
 
21790
22267
  // src/gridAgentContext.ts
@@ -21914,7 +22391,7 @@ function useGridAssist(args) {
21914
22391
  const copyRecordReference = (0, import_react116.useCallback)(
21915
22392
  (rowId) => {
21916
22393
  void (async () => {
21917
- const text2 = JSON.stringify({ __kind: (0, import_core14.tableKindSlug)(tableId), _record_id: rowId });
22394
+ const text2 = JSON.stringify({ __kind: (0, import_core15.tableKindSlug)(tableId), _record_id: rowId });
21918
22395
  if (!await (0, import_clipboard2.copyText)(text2)) {
21919
22396
  say2(false, "This browser did not let the page write to the clipboard.");
21920
22397
  return;
@@ -21970,7 +22447,7 @@ function useGridAssist(args) {
21970
22447
  if (!row) return;
21971
22448
  const document2 = row.document ?? {};
21972
22449
  const value = editing.valueFor(row, fieldOf2(key));
21973
- const pointer = typeof document2[key] === "string" ? (0, import_core14.wholeValueOf)(document2, key) : null;
22450
+ const pointer = typeof document2[key] === "string" ? (0, import_core15.wholeValueOf)(document2, key) : null;
21974
22451
  setWhole({ rowId, key, rowTitle: titleOf(row), value, pointer });
21975
22452
  },
21976
22453
  [rowOf, fieldOf2, titleOf, editing]
@@ -22066,7 +22543,7 @@ function useGridAssist(args) {
22066
22543
  // src/gridBulk.tsx
22067
22544
  var import_react117 = require("react");
22068
22545
  var import_react118 = require("@ai-matrx/records/react");
22069
- var import_core15 = require("@ai-matrx/records/core");
22546
+ var import_core16 = require("@ai-matrx/records/core");
22070
22547
  var import_design_system59 = require("@ai-matrx/design-system");
22071
22548
  var import_jsx_runtime70 = require("react/jsx-runtime");
22072
22549
  function countOf(n, one, many) {
@@ -22132,7 +22609,7 @@ function useGridBulk(args) {
22132
22609
  return null;
22133
22610
  }
22134
22611
  for (const result of done.data ?? []) if (result.op === "update") versions.wrote(result.id, result.version);
22135
- for (const change of changes) if ("record_id" in change && change.record_id) (0, import_core15.announceRecordChanged)(change.record_id);
22612
+ for (const change of changes) if ("record_id" in change && change.record_id) (0, import_core16.announceRecordChanged)(change.record_id);
22136
22613
  return done.data;
22137
22614
  },
22138
22615
  [client, tableId, versions, reload]
@@ -22297,378 +22774,6 @@ var import_react119 = require("react");
22297
22774
  var import_react120 = require("@ai-matrx/records/react");
22298
22775
  var import_records35 = require("@ai-matrx/records");
22299
22776
  var import_design_system60 = require("@ai-matrx/design-system");
22300
-
22301
- // src/viewKeys.ts
22302
- var STORE_KEEPS_TIMELINE = true;
22303
- var ALL = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
22304
- var HIDES = ["grid", "gallery", "kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
22305
- var GRIDS = ["grid"];
22306
- var VIEW_KEYS = [
22307
- { path: "layout", shape: "kind", layouts: ALL, writer: "caller" },
22308
- { path: "filters", shape: "filter", layouts: ALL, writer: "caller" },
22309
- { path: "where", shape: "rule", layouts: ALL, writer: "caller" },
22310
- { path: "group_field", shape: "field", layouts: ["kanban", ...STORE_KEEPS_TIMELINE ? ["timeline"] : []], writer: "caller" },
22311
- { path: "swimlane_field", shape: "field:lane", layouts: ["kanban"], writer: "caller" },
22312
- { path: "collapsed_columns", shape: "values", layouts: ["kanban"], writer: "caller" },
22313
- { path: "measure", shape: "field:number", layouts: ["kanban"], writer: "caller" },
22314
- { path: "date_field", shape: "field:date", layouts: ["calendar"], writer: "caller" },
22315
- ...STORE_KEEPS_TIMELINE ? [
22316
- { path: "start_field", shape: "field:date", layouts: ["timeline"], writer: "caller" },
22317
- { path: "end_field", shape: "field:date", layouts: ["calendar", "timeline"], writer: "caller" }
22318
- ] : [],
22319
- { path: "image_field", shape: "field", layouts: ["gallery"], writer: "caller" },
22320
- { path: "sorts", shape: "sorts", layouts: ALL, writer: "caller" },
22321
- { path: "rule_id", shape: "uuid", layouts: ALL, writer: "caller" },
22322
- { path: "is_default", shape: "boolean", layouts: ALL, writer: "caller" },
22323
- { path: "presentation", shape: "presentation", layouts: ALL, writer: "caller" },
22324
- { path: "presentation.style", shape: "style", layouts: ALL, writer: "caller" },
22325
- { path: "presentation.formats", shape: "object", layouts: GRIDS, writer: "caller" },
22326
- { path: "presentation.frozen", shape: "fields", layouts: GRIDS, writer: "caller" },
22327
- { path: "presentation.grouping", shape: "grouping", layouts: ["grid", "gallery", "list"], writer: "caller" },
22328
- { path: "presentation.widths", shape: "widths", layouts: GRIDS, writer: "caller" },
22329
- { path: "presentation.rowHeight", shape: "row_height", layouts: GRIDS, writer: "caller" },
22330
- { path: "presentation.hiddenFields", shape: "fields", layouts: HIDES, writer: "caller" },
22331
- { path: "presentation.cardHidden", shape: "fields", layouts: ["kanban", "calendar", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list", "gallery"], writer: "caller" },
22332
- { path: "presentation.columnOrder", shape: "fields", layouts: GRIDS, writer: "caller" },
22333
- { path: "presentation.gallerySize", shape: "gallery_size", layouts: ["gallery"], writer: "caller" },
22334
- { path: "presentation.wrap", shape: "boolean", layouts: GRIDS, writer: "caller" },
22335
- { path: "presentation.wrapColumns", shape: "fields", layouts: GRIDS, writer: "caller" },
22336
- { path: "presentation.fit", shape: "fit", layouts: GRIDS, writer: "caller" },
22337
- { path: "presentation.freezeFirst", shape: "boolean", layouts: GRIDS, writer: "caller" },
22338
- { path: "presentation.footer", shape: "footer", layouts: GRIDS, writer: "caller" },
22339
- { path: "presentation.summaries", shape: "summaries", layouts: GRIDS, writer: "caller" },
22340
- { path: "grid", shape: "grid", layouts: GRIDS, writer: "caller" },
22341
- { path: "hidden_fields", shape: "input", layouts: HIDES, writer: "input" },
22342
- { path: "table_id", shape: "server", layouts: ALL, writer: "server" },
22343
- { path: "order", shape: "server", layouts: GRIDS, writer: "server" },
22344
- { path: "moved_from", shape: "server", layouts: ALL, writer: "server" }
22345
- ];
22346
- var STORE_KEPT_LAYOUTS = ["grid", "kanban", "calendar", "gallery", ...STORE_KEEPS_TIMELINE ? ["timeline"] : [], "list"];
22347
- function storeKeepsLayout(layout) {
22348
- return STORE_KEPT_LAYOUTS.includes(layout);
22349
- }
22350
- function viewKeysFor(layout) {
22351
- return VIEW_KEYS.filter((k) => k.layouts.includes(layout)).map((k) => k.path);
22352
- }
22353
- var KINDS = STORE_KEPT_LAYOUTS;
22354
- function viewSettings(definition, rowFilters) {
22355
- const data = definition ?? {};
22356
- const text2 = (key) => {
22357
- const v = data[key];
22358
- return typeof v === "string" && v !== "" ? v : null;
22359
- };
22360
- const layout = String(data["layout"] ?? "grid");
22361
- const flat = rowFilters ?? (isObject2(data["filters"]) ? data["filters"] : null);
22362
- const moved = data["moved_from"];
22363
- return {
22364
- layout: KINDS.includes(layout) ? layout : "grid",
22365
- filters: flat && Object.keys(flat).length > 0 ? flat : null,
22366
- where: isRule(data["where"]) ? data["where"] : null,
22367
- groupField: text2("group_field"),
22368
- swimlaneField: text2("swimlane_field"),
22369
- collapsedColumns: Array.isArray(data["collapsed_columns"]) ? data["collapsed_columns"].filter((v) => ["string", "number", "boolean"].includes(typeof v)).map(String) : [],
22370
- measure: text2("measure"),
22371
- dateField: text2("date_field"),
22372
- startField: text2("start_field"),
22373
- endField: text2("end_field"),
22374
- imageField: text2("image_field"),
22375
- sorts: parseSorts(data["sorts"]),
22376
- ruleId: text2("rule_id"),
22377
- isDefault: data["is_default"] === true || data["is_default"] === "true",
22378
- presentation: parseGridPresentation(data["presentation"]),
22379
- movedFrom: isObject2(moved) ? moved : null
22380
- };
22381
- }
22382
- function viewSettingsFor(settings, layout) {
22383
- const reads = new Set(viewKeysFor(layout));
22384
- const out = { layout: settings.layout };
22385
- const take = (key, path) => {
22386
- if (reads.has(path)) out[key] = settings[key];
22387
- };
22388
- take("filters", "filters");
22389
- take("where", "where");
22390
- take("groupField", "group_field");
22391
- take("swimlaneField", "swimlane_field");
22392
- take("collapsedColumns", "collapsed_columns");
22393
- take("measure", "measure");
22394
- take("dateField", "date_field");
22395
- take("startField", "start_field");
22396
- take("endField", "end_field");
22397
- take("imageField", "image_field");
22398
- take("sorts", "sorts");
22399
- take("ruleId", "rule_id");
22400
- take("isDefault", "is_default");
22401
- const p = settings.presentation;
22402
- const look = {};
22403
- for (const [key, value] of Object.entries(p)) {
22404
- if (reads.has(`presentation.${key}`)) look[key] = value;
22405
- }
22406
- out.presentation = look;
22407
- return out;
22408
- }
22409
- function viewSettingsPatch(patch) {
22410
- const out = {};
22411
- const field2 = (key, path) => {
22412
- if (patch[key] !== void 0) out[path] = patch[key] || null;
22413
- };
22414
- if (patch.layout !== void 0 && storeKeepsLayout(patch.layout)) out["layout"] = patch.layout;
22415
- field2("groupField", "group_field");
22416
- field2("swimlaneField", "swimlane_field");
22417
- field2("measure", "measure");
22418
- field2("dateField", "date_field");
22419
- if (STORE_KEEPS_TIMELINE) {
22420
- field2("startField", "start_field");
22421
- field2("endField", "end_field");
22422
- }
22423
- field2("imageField", "image_field");
22424
- field2("ruleId", "rule_id");
22425
- if (patch.collapsedColumns !== void 0) out["collapsed_columns"] = patch.collapsedColumns ?? [];
22426
- if (patch.sorts !== void 0) out["sorts"] = patch.sorts ?? [];
22427
- if (patch.where !== void 0) out["where"] = patch.where ?? null;
22428
- if (patch.isDefault !== void 0) out["is_default"] = patch.isDefault === true;
22429
- if (patch.presentation !== void 0) {
22430
- out["presentation"] = !patch.presentation || presentationIsEmpty(patch.presentation) ? null : JSON.parse(presentationDocument(patch.presentation));
22431
- }
22432
- return out;
22433
- }
22434
- function isObject2(raw) {
22435
- return Boolean(raw) && typeof raw === "object" && !Array.isArray(raw);
22436
- }
22437
- function isRule(raw) {
22438
- if (!isObject2(raw)) return false;
22439
- const node = raw;
22440
- return typeof node.op === "string" && Array.isArray(node.args);
22441
- }
22442
- function parseSorts(raw) {
22443
- let list = raw;
22444
- if (typeof raw === "string") {
22445
- try {
22446
- list = raw.trim() === "" ? [] : JSON.parse(raw);
22447
- } catch {
22448
- return [];
22449
- }
22450
- }
22451
- if (!Array.isArray(list)) return [];
22452
- return list.filter((s) => isObject2(s) && typeof s.field === "string").map((s) => ({ field: s.field, direction: s.direction === "desc" ? "desc" : "asc" }));
22453
- }
22454
-
22455
- // src/views.ts
22456
- var VIEW_LAYOUTS = ["grid", "kanban", "calendar", "gallery", "timeline", "list"];
22457
- var LAYOUT_LABEL = {
22458
- grid: "Grid",
22459
- kanban: "Kanban",
22460
- calendar: "Calendar",
22461
- gallery: "Gallery",
22462
- timeline: "Timeline",
22463
- list: "List"
22464
- };
22465
- function wordsList(words2) {
22466
- const clean = words2.map((w) => w.trim()).filter((w) => w !== "");
22467
- if (clean.length <= 1) return clean.join("");
22468
- return `${clean.slice(0, -1).join(", ")} and ${clean[clean.length - 1]}`;
22469
- }
22470
- var VIEW_NEEDS = {
22471
- grid: null,
22472
- // A list reads nothing a table can lack: rows, titled, grouped only when the person chooses.
22473
- list: null,
22474
- kanban: {
22475
- kind: "choice",
22476
- viewKey: "groupField",
22477
- blocking: true,
22478
- starter: { label: "Status", type: "select", options: ["To do", "In progress", "Done"] },
22479
- pick: "Pick the choice column the board's columns come from.",
22480
- missing: "This table has no choice column to make the board's columns from.",
22481
- does: (label) => `Make it work adds a ${label} column with the choices below and groups the board by it.`,
22482
- ask: (label, options) => `Add a choice column called ${label} to this table${options.length > 0 ? ` with the choices ${wordsList(options)}` : ""}, then group the Kanban board by it.`
22483
- },
22484
- calendar: {
22485
- kind: "date",
22486
- viewKey: "dateField",
22487
- blocking: true,
22488
- starter: { label: "Date", type: "datetime" },
22489
- pick: "Pick the date column the calendar places records by.",
22490
- missing: "This table has no date column to place records on.",
22491
- does: (label) => `Make it work adds a ${label} column and lays the calendar out by it.`,
22492
- ask: (label) => `Add a date column called ${label} to this table, then lay the Calendar out by it.`
22493
- },
22494
- gallery: {
22495
- kind: "file",
22496
- viewKey: "imageField",
22497
- blocking: false,
22498
- starter: { label: "Photo", type: "attachment" },
22499
- pick: "Pick the file column each card shows as its picture.",
22500
- missing: "The cards have no picture because this table has no file column.",
22501
- does: (label) => `Make it work adds a ${label} column and shows it on each card.`,
22502
- ask: (label) => `Add a file column called ${label} to this table, then show it as the picture on each Gallery card.`
22503
- },
22504
- timeline: {
22505
- kind: "date",
22506
- viewKey: "dateField",
22507
- blocking: true,
22508
- starter: { label: "Start", type: "datetime" },
22509
- pick: "Pick the date column each bar starts on.",
22510
- missing: "This table has no date column to place records on.",
22511
- does: (label) => `Make it work adds a ${label} column and lays the timeline out by it.`,
22512
- ask: (label) => `Add a date column called ${label} to this table, then lay the Timeline out by it.`
22513
- }
22514
- };
22515
- function freeColumnName(wanted, taken) {
22516
- const held = new Set(taken.map((t) => t.trim().toLowerCase()));
22517
- const base = wanted.trim() === "" ? "Column" : wanted.trim();
22518
- if (!held.has(base.toLowerCase())) return base;
22519
- for (let n = 2; n < 100; n += 1) {
22520
- const next = `${base} ${n}`;
22521
- if (!held.has(next.toLowerCase())) return next;
22522
- }
22523
- return base;
22524
- }
22525
- function viewOrderOf(definition) {
22526
- const raw = definition?.["order"];
22527
- return raw === "manual" ? "manual" : raw === "sorted" ? "sorted" : null;
22528
- }
22529
- function defaultViewOf(views) {
22530
- return views.find((v) => v.isDefault);
22531
- }
22532
- var LAYOUT_FIELD_KIND = {
22533
- grid: null,
22534
- kanban: "choice",
22535
- calendar: "date",
22536
- gallery: "file",
22537
- timeline: "date",
22538
- list: null
22539
- };
22540
- var PAGE_VIEWS = [...VIEW_LAYOUTS, "dashboards", "archived"];
22541
- var PAGE_VIEW_LABEL = {
22542
- ...LAYOUT_LABEL,
22543
- dashboards: "Dashboards",
22544
- archived: "Archived"
22545
- };
22546
- var PAGE_VIEW_SPELLINGS = {
22547
- grid: "grid",
22548
- table: "grid",
22549
- rows: "grid",
22550
- list: "list",
22551
- kanban: "kanban",
22552
- board: "kanban",
22553
- pipeline: "kanban",
22554
- calendar: "calendar",
22555
- month: "calendar",
22556
- schedule: "calendar",
22557
- gallery: "gallery",
22558
- cards: "gallery",
22559
- timeline: "timeline",
22560
- gantt: "timeline",
22561
- dashboards: "dashboards",
22562
- dashboard: "dashboards",
22563
- charts: "dashboards",
22564
- archived: "archived",
22565
- archive: "archived",
22566
- // The grid's row action says "Delete" and the store soft-deletes, so the word
22567
- // a person types is as likely to be the one the button used as the one this
22568
- // view is called. Both land in the same place; neither dies.
22569
- deleted: "archived",
22570
- trash: "archived",
22571
- removed: "archived"
22572
- };
22573
- function pageViewFromParam(raw) {
22574
- if (typeof raw !== "string") return null;
22575
- const token = raw.trim().toLowerCase();
22576
- if (token === "") return null;
22577
- return PAGE_VIEW_SPELLINGS[token] ?? null;
22578
- }
22579
- function unknownViewLine(raw) {
22580
- return `The link asked for a view called \u201C${raw}\u201D, which this table has no view for, so you are looking at ${PAGE_VIEW_LABEL.grid}. The views this table has are ${PAGE_VIEWS.map((v) => PAGE_VIEW_LABEL[v]).join(", ")} \u2014 pick one above and the address follows it.`;
22581
- }
22582
- function viewDocument(spec) {
22583
- const out = {
22584
- // A layout the store does not keep yet is not sent: the view is saved as a grid (`STORE_KEPT_LAYOUTS`).
22585
- layout: storeKeepsLayout(spec.layout) ? spec.layout : "grid",
22586
- sorts: spec.sorts ?? [],
22587
- is_default: spec.isDefault === true
22588
- };
22589
- if (spec.groupField) out["group_field"] = spec.groupField;
22590
- if (spec.swimlaneField) out["swimlane_field"] = spec.swimlaneField;
22591
- if (spec.collapsedColumns && spec.collapsedColumns.length > 0) out["collapsed_columns"] = spec.collapsedColumns;
22592
- if (spec.measure) out["measure"] = spec.measure;
22593
- if (spec.dateField) out["date_field"] = spec.dateField;
22594
- if (STORE_KEEPS_TIMELINE && spec.startField) out["start_field"] = spec.startField;
22595
- if (STORE_KEEPS_TIMELINE && spec.endField) out["end_field"] = spec.endField;
22596
- if (spec.imageField) out["image_field"] = spec.imageField;
22597
- if (spec.ruleId) out["rule_id"] = spec.ruleId;
22598
- if (spec.where) out["where"] = spec.where;
22599
- if (spec.presentation && !presentationIsEmpty(spec.presentation)) {
22600
- out["presentation"] = JSON.parse(presentationDocument(spec.presentation));
22601
- }
22602
- return out;
22603
- }
22604
- function viewFromRow(row) {
22605
- const data = row.definition ?? {};
22606
- const k = viewSettings(data, row.filters && Object.keys(row.filters).length > 0 ? row.filters : null);
22607
- const tableFromDefinition = typeof data["table_id"] === "string" && data["table_id"] !== "" ? data["table_id"] : null;
22608
- return {
22609
- id: row.view_id,
22610
- name: row.name || "Untitled view",
22611
- subject: row.table_id ?? tableFromDefinition ?? "",
22612
- layout: k.layout,
22613
- groupField: k.groupField,
22614
- swimlaneField: k.swimlaneField,
22615
- collapsedColumns: k.collapsedColumns,
22616
- measure: k.measure,
22617
- dateField: k.dateField,
22618
- startField: k.startField,
22619
- endField: k.endField,
22620
- imageField: k.imageField,
22621
- sorts: k.sorts,
22622
- order: viewOrderOf(data),
22623
- ruleId: k.ruleId,
22624
- ...k.filters ? { filters: k.filters } : {},
22625
- where: k.where,
22626
- // The older table's own default view, carried in by the mover, IS this table's default —
22627
- // the mover wrote the row's column, which `custom.views` does not return. Read as anything
22628
- // else, the page would seed a second "All records" beside it and open on that.
22629
- isDefault: k.isDefault || k.movedFrom?.["kind"] === "default_view",
22630
- presentation: k.presentation,
22631
- movedFrom: k.movedFrom
22632
- };
22633
- }
22634
- async function declareView(client, spec) {
22635
- return client.viewDeclare({
22636
- table_id: spec.subject,
22637
- spec: {
22638
- name: spec.name,
22639
- ...spec.filters ? { filters: spec.filters } : {},
22640
- definition: viewDocument(spec)
22641
- }
22642
- });
22643
- }
22644
- async function saveViewPatch(client, tableId, viewId, patch) {
22645
- const definition = viewPatchDocument(patch);
22646
- const renamed = patch.name !== void 0 && patch.name.trim() !== "";
22647
- const refiltered = patch.filters !== void 0;
22648
- return client.viewDeclare({
22649
- table_id: tableId,
22650
- spec: {
22651
- view_id: viewId,
22652
- ...renamed ? { name: patch.name.trim() } : {},
22653
- ...refiltered ? { filters: patch.filters ?? null } : {},
22654
- definition
22655
- }
22656
- });
22657
- }
22658
- function viewPatchDocument(patch) {
22659
- const { name: _name, subject: _subject, filters: _filters, ...keys } = patch;
22660
- return viewSettingsPatch(keys);
22661
- }
22662
- function viewPatchFor(view, patch) {
22663
- if (!view.isDefault) return patch;
22664
- const { layout: _layout, isDefault: _isDefault, ...kept } = patch;
22665
- return kept;
22666
- }
22667
- async function designateView(client, tableId, viewId, layout) {
22668
- return client.viewDesignate({ table_id: tableId, view_id: viewId, layout });
22669
- }
22670
-
22671
- // src/handOrder.tsx
22672
22777
  var import_jsx_runtime71 = require("react/jsx-runtime");
22673
22778
  function sortArrow(direction) {
22674
22779
  return direction === "asc" ? "\u2191" : "\u2193";
@@ -23641,7 +23746,7 @@ function GridBody({
23641
23746
  }))
23642
23747
  );
23643
23748
  editing.forget(cells);
23644
- for (const u of updates) (0, import_core16.announceRecordChanged)(u.row.recordId);
23749
+ for (const u of updates) (0, import_core17.announceRecordChanged)(u.row.recordId);
23645
23750
  const lines = updates.length + creates.length;
23646
23751
  undo.push({ label: `Pasted ${lines} ${lines === 1 ? "row" : "rows"}`, cells, created });
23647
23752
  const expected = [
@@ -25114,10 +25219,10 @@ var import_react_query = require("@tanstack/react-query");
25114
25219
  var import_react125 = require("@ai-matrx/records/data/react");
25115
25220
 
25116
25221
  // ../entity-data/src/core/client.ts
25117
- var import_core18 = require("@ai-matrx/records/core");
25222
+ var import_core19 = require("@ai-matrx/records/core");
25118
25223
 
25119
25224
  // ../entity-data/src/core/errors.ts
25120
- var import_core17 = require("@ai-matrx/records/core");
25225
+ var import_core18 = require("@ai-matrx/records/core");
25121
25226
  var ENTITY_REFUSALS = {
25122
25227
  /** conflict_version: somebody else's write won. */
25123
25228
  MX001: "stale_write",
@@ -25141,7 +25246,7 @@ var ENTITY_REFUSALS = {
25141
25246
  MX016: "invalid_argument"
25142
25247
  };
25143
25248
  function mapEntityError(error, where) {
25144
- const mapped = (0, import_core17.mapPgError)(error, where);
25249
+ const mapped = (0, import_core18.mapPgError)(error, where);
25145
25250
  const state = mapped.sqlstate;
25146
25251
  if (state && /^MX\d{3}$/.test(state)) {
25147
25252
  const code = ENTITY_REFUSALS[state];
@@ -25163,7 +25268,7 @@ function refusal2(code, message, hint) {
25163
25268
  var OP_ID_HEADER = "x-matrx-op-id";
25164
25269
  var ENTITY_DOOR_SCHEMA = "platform";
25165
25270
  function createEntityClient(options) {
25166
- const source = (0, import_core18.asRecordsDataSource)(options.dataSource ?? options.supabase);
25271
+ const source = (0, import_core19.asRecordsDataSource)(options.dataSource ?? options.supabase);
25167
25272
  let warnedHeaderless = false;
25168
25273
  function withHeaders(pending, headers) {
25169
25274
  if (!headers) return;
@@ -26086,7 +26191,7 @@ function ConnectedRecordsTableCard({
26086
26191
  var import_download2 = require("@ai-matrx/kit/download");
26087
26192
  var import_react130 = require("react");
26088
26193
  var import_react131 = require("@ai-matrx/records/react");
26089
- var import_core19 = require("@ai-matrx/records/core");
26194
+ var import_core20 = require("@ai-matrx/records/core");
26090
26195
 
26091
26196
  // src/viewExport.ts
26092
26197
  var import_format5 = require("@ai-matrx/kit/format");
@@ -26153,7 +26258,7 @@ function toRows(fields, records, labels) {
26153
26258
  absent_reason: envelope?.absent ?? null,
26154
26259
  // A VALUE KEPT AS A FILE carries its pointer, so the export writes the whole text
26155
26260
  // (`withWholeValues`), never the first words passed off as the value.
26156
- source: (0, import_core19.wholeValueOf)(document2, field2.key)
26261
+ source: (0, import_core20.wholeValueOf)(document2, field2.key)
26157
26262
  };
26158
26263
  }
26159
26264
  return row;
@@ -26184,7 +26289,7 @@ async function rowsForFile(args) {
26184
26289
  );
26185
26290
  const lookup = ((field2, id) => labels(field2, id) ?? learned.get(`${field2.id}:${id}`) ?? null);
26186
26291
  const read = host.readFileText;
26187
- return (0, import_core19.withWholeValues)(toRows(all, records, lookup), read ? (fileId) => read({ fileId }) : null);
26292
+ return (0, import_core20.withWholeValues)(toRows(all, records, lookup), read ? (fileId) => read({ fileId }) : null);
26188
26293
  }
26189
26294
  function ExportMenu({ tableId, rows, label, className, view }) {
26190
26295
  const client = (0, import_react131.useRecordsClient)();
@@ -26223,7 +26328,7 @@ function ExportMenu({ tableId, rows, label, className, view }) {
26223
26328
  {
26224
26329
  size: "sm",
26225
26330
  variant: "outline",
26226
- onClick: () => void exported().then((rows2) => download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core19.exportCsv)(columns, rows2))).catch(
26331
+ onClick: () => void exported().then((rows2) => download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core20.exportCsv)(columns, rows2))).catch(
26227
26332
  (thrown) => setFailure(refusalFromThrown(thrown, "The CSV could not be written.", "Try again in a moment."))
26228
26333
  ),
26229
26334
  children: "CSV"
@@ -26244,7 +26349,7 @@ function ExportMenu({ tableId, rows, label, className, view }) {
26244
26349
  );
26245
26350
  setFailure(null);
26246
26351
  try {
26247
- exported().then((rows2) => (0, import_core19.exportXlsx)(columns, rows2, name)).then(
26352
+ exported().then((rows2) => (0, import_core20.exportXlsx)(columns, rows2, name)).then(
26248
26353
  (bytes) => download(
26249
26354
  `${name}.xlsx`,
26250
26355
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -26265,7 +26370,7 @@ function ExportMenu({ tableId, rows, label, className, view }) {
26265
26370
  sourceId: `records:${tableId}`,
26266
26371
  size: "xs",
26267
26372
  json: () => records.map((r) => r.document),
26268
- human: () => (0, import_core19.exportCsv)(columns, toRows(columns, records, labels))
26373
+ human: () => (0, import_core20.exportCsv)(columns, toRows(columns, records, labels))
26269
26374
  }
26270
26375
  ),
26271
26376
  viewHeld && "rows" in viewHeld && viewHeld.cut ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-xs text-muted-foreground", children: cutWords(viewHeld.rows.length) }) : null,
@@ -26385,7 +26490,7 @@ var import_design_system74 = require("@ai-matrx/design-system");
26385
26490
  // src/TablesHome.tsx
26386
26491
  var import_react144 = require("react");
26387
26492
  var import_react145 = require("@ai-matrx/records/react");
26388
- var import_core20 = require("@ai-matrx/records/core");
26493
+ var import_core21 = require("@ai-matrx/records/core");
26389
26494
  var import_records43 = require("@ai-matrx/records");
26390
26495
  var import_design_system73 = require("@ai-matrx/design-system");
26391
26496
 
@@ -28121,7 +28226,7 @@ function TablesHome({ onOpenTable, organizationName, makingOnly = false, askedBy
28121
28226
  };
28122
28227
  }, [client]);
28123
28228
  const listed = facts.phase === "read" ? (0, import_records43.withTablePlacement)(
28124
- (0, import_core20.withTableFacts)(tables.data ?? [], facts.rows, me),
28229
+ (0, import_core21.withTableFacts)(tables.data ?? [], facts.rows, me),
28125
28230
  facts.rows
28126
28231
  ) : tables.data ?? [];
28127
28232
  const [showEverything, setShowEverything] = (0, import_react144.useState)(false);
@@ -30696,95 +30801,6 @@ function useSystemTable(spec) {
30696
30801
  return state;
30697
30802
  }
30698
30803
 
30699
- // src/viewLook.ts
30700
- var LOOK_KEYS = [
30701
- "layout",
30702
- "groupField",
30703
- "swimlaneField",
30704
- "collapsedColumns",
30705
- "measure",
30706
- "dateField",
30707
- "startField",
30708
- "endField",
30709
- "imageField",
30710
- "sorts",
30711
- "where",
30712
- "presentation"
30713
- ];
30714
- function lookPart(patch) {
30715
- const out = {};
30716
- for (const key of LOOK_KEYS) {
30717
- if (patch[key] !== void 0) out[key] = patch[key];
30718
- }
30719
- return out;
30720
- }
30721
- function lookDocument(look) {
30722
- return viewSettingsPatch(look);
30723
- }
30724
- function lookFromDocument(doc) {
30725
- const data = doc ?? {};
30726
- const read = viewSettings(data);
30727
- const out = {};
30728
- const has = (key) => Object.prototype.hasOwnProperty.call(data, key);
30729
- if (has("layout") && VIEW_LAYOUTS.includes(String(data["layout"]))) {
30730
- out.layout = data["layout"];
30731
- }
30732
- if (has("group_field")) out.groupField = read.groupField;
30733
- if (has("swimlane_field")) out.swimlaneField = read.swimlaneField;
30734
- if (has("collapsed_columns")) out.collapsedColumns = read.collapsedColumns;
30735
- if (has("measure")) out.measure = read.measure;
30736
- if (has("date_field")) out.dateField = read.dateField;
30737
- if (has("start_field")) out.startField = read.startField;
30738
- if (has("end_field")) out.endField = read.endField;
30739
- if (has("image_field")) out.imageField = read.imageField;
30740
- if (has("sorts")) out.sorts = read.sorts;
30741
- if (has("where")) out.where = read.where;
30742
- if (has("presentation")) out.presentation = parseGridPresentation(data["presentation"]);
30743
- return out;
30744
- }
30745
- function applyLook(view, look) {
30746
- if (!look) return view;
30747
- return { ...view, ...look };
30748
- }
30749
- function lookDiffers(view, look) {
30750
- if (!look) return false;
30751
- const shown4 = applyLook(view, look);
30752
- return LOOK_KEYS.some(
30753
- (key) => look[key] !== void 0 && JSON.stringify(shown4[key] ?? null) !== JSON.stringify(view[key] ?? null)
30754
- );
30755
- }
30756
- function saveToViewPlan(view, look) {
30757
- const patch = viewPatchFor(view, look);
30758
- const left = {};
30759
- if (look.layout !== void 0 && patch.layout === void 0 && look.layout !== view.layout) left.layout = look.layout;
30760
- return { patch, left: Object.keys(left).length > 0 ? left : null };
30761
- }
30762
- async function readLooks(client, tableId) {
30763
- const answered = await client.viewLookRead({ table_id: tableId });
30764
- if (!answered.ok) return answered;
30765
- const out = {};
30766
- for (const [viewId, row] of Object.entries(answered.data ?? {})) {
30767
- out[viewId] = lookFromDocument(row?.look ?? null);
30768
- }
30769
- return { ok: true, data: out };
30770
- }
30771
- async function keepLook(client, tableId, viewId, look) {
30772
- const doc = look ? lookDocument(look) : null;
30773
- return client.viewLookSet({ table_id: tableId, view_id: viewId, look: doc && Object.keys(doc).length > 0 ? doc : null });
30774
- }
30775
- var LOOK_WORDS = {
30776
- /** The reason, for a tooltip or a screen reader — never a line on the page (interface-text). */
30777
- yours: "You changed how this view looks. Only you see it.",
30778
- /** The visible label for the same fact. */
30779
- yoursLabel: "Only you see this",
30780
- saveToView: "Save to view",
30781
- saveAsNew: "Save as new view",
30782
- reset: "Reset to view",
30783
- /** The one button your look's doors fold into when the toolbar row has no room for three. */
30784
- folded: "Your look",
30785
- newName: "Name for the new view"
30786
- };
30787
-
30788
30804
  // src/ViewSwitcher.tsx
30789
30805
  var import_react190 = require("react");
30790
30806
  var import_react191 = require("@ai-matrx/records/react");
@@ -35498,16 +35514,20 @@ function seedIsSatisfied(seed, views) {
35498
35514
  if (views.some((v) => v.name === seed.name)) return true;
35499
35515
  return seed.isDefault === true && views.some((v) => v.isDefault);
35500
35516
  }
35501
- function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, className }) {
35517
+ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, initialViews, className }) {
35502
35518
  const client = (0, import_react198.useRecordsClient)();
35503
35519
  const claimSeed = useSeedGuard();
35504
35520
  const table = (0, import_react199.useTable)(tableId);
35505
35521
  const rights = useTableRights(table.data);
35506
35522
  const notify = useRecordsUi().notify;
35507
- const [views, setViews] = (0, import_react197.useState)(null);
35523
+ const [views, setViews] = (0, import_react197.useState)(() => initialViews ?? null);
35508
35524
  const [error, setError] = (0, import_react197.useState)(null);
35509
35525
  const [unavailable, setUnavailable] = (0, import_react197.useState)(false);
35510
- const [active, setActive] = (0, import_react197.useState)(activeViewId ?? null);
35526
+ const [active, setActive] = (0, import_react197.useState)(() => {
35527
+ if (!initialViews || initialViews.length === 0) return activeViewId ?? null;
35528
+ return (initialViews.find((v) => v.id === activeViewId) ?? defaultViewOf(initialViews) ?? initialViews[0]).id;
35529
+ });
35530
+ const readOnMount = (0, import_react197.useRef)(initialViews === void 0);
35511
35531
  const [naming, setNaming] = (0, import_react197.useState)(false);
35512
35532
  const [draftName, setDraftName] = (0, import_react197.useState)("");
35513
35533
  const [open, setOpen] = (0, import_react197.useState)(false);
@@ -35554,6 +35574,10 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
35554
35574
  onViews?.(mine);
35555
35575
  }, [client, readViews, tableId, seedKey]);
35556
35576
  (0, import_react197.useEffect)(() => {
35577
+ if (!readOnMount.current) {
35578
+ readOnMount.current = true;
35579
+ return;
35580
+ }
35557
35581
  void load();
35558
35582
  }, [load]);
35559
35583
  (0, import_react197.useEffect)(() => {
@@ -38514,7 +38538,7 @@ var import_design_system105 = require("@ai-matrx/design-system");
38514
38538
  var import_react217 = require("react");
38515
38539
  var import_recharts = require("recharts");
38516
38540
  var import_records51 = require("@ai-matrx/records");
38517
- var import_core21 = require("@ai-matrx/records/core");
38541
+ var import_core22 = require("@ai-matrx/records/core");
38518
38542
  var import_design_system104 = require("@ai-matrx/design-system");
38519
38543
  var import_format10 = require("@ai-matrx/kit/format");
38520
38544
 
@@ -38976,7 +39000,7 @@ function pretty(n) {
38976
39000
  return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(void 0, { maximumFractionDigits: 2 });
38977
39001
  }
38978
39002
  function asRefusal2(block) {
38979
- return (0, import_core21.mapPgError)(
39003
+ return (0, import_core22.mapPgError)(
38980
39004
  {
38981
39005
  message: block.refused ?? "",
38982
39006
  ...block.sqlstate ? { code: block.sqlstate } : {}
@@ -41884,7 +41908,7 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
41884
41908
  var import_clipboard9 = require("@ai-matrx/kit/clipboard");
41885
41909
  var import_design_system117 = require("@ai-matrx/design-system");
41886
41910
  var import_react235 = require("react");
41887
- var import_core22 = require("@dnd-kit/core");
41911
+ var import_core23 = require("@dnd-kit/core");
41888
41912
  var import_sortable = require("@dnd-kit/sortable");
41889
41913
  var import_utilities = require("@dnd-kit/utilities");
41890
41914
  var import_react236 = require("@ai-matrx/records/react");
@@ -43511,9 +43535,9 @@ function QuestionList({
43511
43535
  onQuestions,
43512
43536
  onQuestion
43513
43537
  }) {
43514
- const sensors = (0, import_core22.useSensors)(
43515
- (0, import_core22.useSensor)(import_core22.PointerSensor, { activationConstraint: { distance: 4 } }),
43516
- (0, import_core22.useSensor)(import_core22.KeyboardSensor, { coordinateGetter: import_sortable.sortableKeyboardCoordinates })
43538
+ const sensors = (0, import_core23.useSensors)(
43539
+ (0, import_core23.useSensor)(import_core23.PointerSensor, { activationConstraint: { distance: 4 } }),
43540
+ (0, import_core23.useSensor)(import_core23.KeyboardSensor, { coordinateGetter: import_sortable.sortableKeyboardCoordinates })
43517
43541
  );
43518
43542
  const askable = askableFields([...fields]);
43519
43543
  const unasked = askable.filter((f) => !draft.questions.some((q) => q.field === f.key));
@@ -43535,7 +43559,7 @@ function QuestionList({
43535
43559
  /* @__PURE__ */ (0, import_jsx_runtime133.jsx)("span", { className: "font-medium text-foreground", children: "Questions" }),
43536
43560
  /* @__PURE__ */ (0, import_jsx_runtime133.jsx)("span", { className: "tabular-nums", children: draft.questions.length })
43537
43561
  ] }),
43538
- /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(import_core22.DndContext, { sensors, collisionDetection: import_core22.closestCenter, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(import_sortable.SortableContext, { items: draft.questions.map((q) => q.field), strategy: import_sortable.verticalListSortingStrategy, children: draft.questions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(
43562
+ /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(import_core23.DndContext, { sensors, collisionDetection: import_core23.closestCenter, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(import_sortable.SortableContext, { items: draft.questions.map((q) => q.field), strategy: import_sortable.verticalListSortingStrategy, children: draft.questions.map((question, index) => /* @__PURE__ */ (0, import_jsx_runtime133.jsx)(
43539
43563
  QuestionRow,
43540
43564
  {
43541
43565
  index,
@@ -44531,7 +44555,7 @@ var import_react253 = require("@ai-matrx/records/react");
44531
44555
  var import_design_system126 = require("@ai-matrx/design-system");
44532
44556
 
44533
44557
  // src/DashboardGrid.tsx
44534
- var import_core23 = require("@dnd-kit/core");
44558
+ var import_core24 = require("@dnd-kit/core");
44535
44559
  var import_sortable2 = require("@dnd-kit/sortable");
44536
44560
  var import_utilities2 = require("@dnd-kit/utilities");
44537
44561
  var import_design_system123 = require("@ai-matrx/design-system");
@@ -44587,7 +44611,7 @@ function withBlockIds(blocks) {
44587
44611
  // src/DashboardGrid.tsx
44588
44612
  var import_jsx_runtime138 = require("react/jsx-runtime");
44589
44613
  var dashboardCollision = (args) => {
44590
- const under = (0, import_core23.pointerWithin)(args);
44614
+ const under = (0, import_core24.pointerWithin)(args);
44591
44615
  if (under.length > 0) return under;
44592
44616
  const at = args.collisionRect;
44593
44617
  return args.droppableContainers.flatMap((container) => {
@@ -44597,9 +44621,9 @@ var dashboardCollision = (args) => {
44597
44621
  }).sort((a, b) => a.data.value - b.data.value);
44598
44622
  };
44599
44623
  function DashboardGrid({ items, arranging, onMove, onSpan }) {
44600
- const sensors = (0, import_core23.useSensors)(
44601
- (0, import_core23.useSensor)(import_core23.PointerSensor, { activationConstraint: { distance: 4 } }),
44602
- (0, import_core23.useSensor)(import_core23.KeyboardSensor, { coordinateGetter: import_sortable2.sortableKeyboardCoordinates })
44624
+ const sensors = (0, import_core24.useSensors)(
44625
+ (0, import_core24.useSensor)(import_core24.PointerSensor, { activationConstraint: { distance: 4 } }),
44626
+ (0, import_core24.useSensor)(import_core24.KeyboardSensor, { coordinateGetter: import_sortable2.sortableKeyboardCoordinates })
44603
44627
  );
44604
44628
  const ids = items.map((item) => item.id);
44605
44629
  function dragEnd(event) {
@@ -44609,7 +44633,7 @@ function DashboardGrid({ items, arranging, onMove, onSpan }) {
44609
44633
  }
44610
44634
  const grid = /* @__PURE__ */ (0, import_jsx_runtime138.jsx)("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-12", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(GridCell2, { item, index, arranging, onSpan }, item.id)) });
44611
44635
  if (!arranging) return grid;
44612
- return /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_core23.DndContext, { sensors, collisionDetection: dashboardCollision, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_sortable2.SortableContext, { items: ids, strategy: import_sortable2.rectSortingStrategy, children: grid }) });
44636
+ return /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_core24.DndContext, { sensors, collisionDetection: dashboardCollision, onDragEnd: dragEnd, children: /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_sortable2.SortableContext, { items: ids, strategy: import_sortable2.rectSortingStrategy, children: grid }) });
44613
44637
  }
44614
44638
  function GridCell2({
44615
44639
  item,
@@ -45822,7 +45846,7 @@ var import_react255 = require("@ai-matrx/records/react");
45822
45846
 
45823
45847
  // src/question.ts
45824
45848
  var import_records59 = require("@ai-matrx/records");
45825
- var import_core24 = require("@ai-matrx/records/core");
45849
+ var import_core25 = require("@ai-matrx/records/core");
45826
45850
  var QUESTION_OPS = ["count", "sum", "avg", "min", "max"];
45827
45851
  var QUESTION_LIMIT_DEFAULT = 25;
45828
45852
  var QUESTION_GROUP_CEILING = 200;
@@ -46074,7 +46098,7 @@ async function askAsOf(client, tableId, spec, fields, measures, keys) {
46074
46098
  },
46075
46099
  { schema: config.schema ?? "custom" }
46076
46100
  );
46077
- if (response.error) return { ok: false, error: (0, import_core24.mapPgError)(response.error, "askQuestion.asOf") };
46101
+ if (response.error) return { ok: false, error: (0, import_core25.mapPgError)(response.error, "askQuestion.asOf") };
46078
46102
  const rows2 = Array.isArray(response.data) ? response.data : [];
46079
46103
  const bad = rows2.find((r) => Number(r.not_numbers ?? 0) > 0);
46080
46104
  if (bad && m.op !== "count") {
@@ -46145,7 +46169,7 @@ function savedOf(row) {
46145
46169
  }
46146
46170
  async function questionsOf(client, tableId) {
46147
46171
  const response = await client.config.dataSource.schema("platform").from("saved_view").select("id, name, definition, visibility, version, created_by").eq("surface_key", QUESTION_SURFACE).eq("subject_id", tableId).is("deleted_at", null).order("name", { ascending: true });
46148
- if (response.error) return { ok: false, error: (0, import_core24.mapPgError)(response.error, "questionsOf") };
46172
+ if (response.error) return { ok: false, error: (0, import_core25.mapPgError)(response.error, "questionsOf") };
46149
46173
  const me = client.config.actor?.user_id ?? null;
46150
46174
  return {
46151
46175
  ok: true,
@@ -46174,7 +46198,7 @@ async function questionSave(client, args) {
46174
46198
  if (response.error.code === "23505") {
46175
46199
  return { ok: false, error: { code: "already_exists", message: `You already have a question called \u201C${name}\u201D.` } };
46176
46200
  }
46177
- return { ok: false, error: (0, import_core24.mapPgError)(response.error, "questionSave") };
46201
+ return { ok: false, error: (0, import_core25.mapPgError)(response.error, "questionSave") };
46178
46202
  }
46179
46203
  return { ok: true, data: response.data ? savedOf(response.data) : null };
46180
46204
  }
@@ -46184,7 +46208,7 @@ async function questionArchive(client, id, version) {
46184
46208
  { p_surface_key: QUESTION_SURFACE, p_id: id, ...version !== void 0 ? { p_expected_version: version } : {} },
46185
46209
  { schema: "public" }
46186
46210
  );
46187
- if (response.error) return { ok: false, error: (0, import_core24.mapPgError)(response.error, "questionArchive") };
46211
+ if (response.error) return { ok: false, error: (0, import_core25.mapPgError)(response.error, "questionArchive") };
46188
46212
  return { ok: true, data: response.data !== null };
46189
46213
  }
46190
46214
 
@@ -47043,7 +47067,7 @@ function TableAsk({ tableId, onOpenInQuestions }) {
47043
47067
  // src/PageScreen.tsx
47044
47068
  var import_react258 = require("react");
47045
47069
  var import_react259 = require("@ai-matrx/records/react");
47046
- var import_core25 = require("@ai-matrx/records/core");
47070
+ var import_core26 = require("@ai-matrx/records/core");
47047
47071
  var import_design_system129 = require("@ai-matrx/design-system");
47048
47072
  var import_jsx_runtime145 = require("react/jsx-runtime");
47049
47073
  var EDIT_LEVELS = /* @__PURE__ */ new Set(["edit_content", "editor", "admin", "owner"]);
@@ -47459,7 +47483,7 @@ function ListBlockView({
47459
47483
  ...sort.length > 0 ? { sort } : {}
47460
47484
  });
47461
47485
  const reload = page.reload;
47462
- (0, import_react258.useEffect)(() => (0, import_core25.onRecordChanged)(() => reload()), [reload]);
47486
+ (0, import_react258.useEffect)(() => (0, import_core26.onRecordChanged)(() => reload()), [reload]);
47463
47487
  const rows = nobodyIsMe ? [] : page.data?.rows ?? [];
47464
47488
  const columns = block.columns && block.columns.length > 0 ? block.columns.map((k) => all.find((f) => f.key === k)).filter((f) => !!f) : [...all].sort((a, b) => (a.sort ?? 100) - (b.sort ?? 100)).slice(0, DEFAULT_COLUMNS);
47465
47489
  const firstId = rows[0]?.id ?? null;
@@ -48994,7 +49018,7 @@ var import_design_system142 = require("@ai-matrx/design-system");
48994
49018
  var import_text_case19 = require("@ai-matrx/kit/text-case");
48995
49019
 
48996
49020
  // src/viewShare.ts
48997
- var import_core26 = require("@ai-matrx/records/core");
49021
+ var import_core27 = require("@ai-matrx/records/core");
48998
49022
  var NO_VIEW_REASON = "No saved view yet";
48999
49023
  function viewLink(tableId, viewId, origin) {
49000
49024
  return `${tableLink(tableId, origin)}?view=${encodeURIComponent(viewId)}`;
@@ -49030,7 +49054,7 @@ async function downloadViewCsv(args) {
49030
49054
  const columns = viewColumns(fields, view.presentation);
49031
49055
  const rows = await rowsForFile({ client, host, fields: columns, records: read.rows, labels });
49032
49056
  const name = fileNameOf(args.tableName) || "records";
49033
- download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core26.exportCsv)(columns, rows));
49057
+ download(`${name}.csv`, "text/csv;charset=utf-8", (0, import_core27.exportCsv)(columns, rows));
49034
49058
  host.notify?.success(read.cut ? cutWords(read.rows.length) : "CSV downloaded");
49035
49059
  }
49036
49060
 
@@ -50010,9 +50034,29 @@ function TablePage({
50010
50034
  const askedInWords = filter ? filterInWords(filter, pageFields.data ?? []) : null;
50011
50035
  const organizationId = (0, import_react283.useRecordsClient)().config.organizationId;
50012
50036
  const publicReadOnly = usePublicReadOnly(client, organizationId, tableId, table.data, rights);
50013
- const [view, setView] = (0, import_react282.useState)(null);
50014
- const [looks, setLooks] = (0, import_react282.useState)(void 0);
50037
+ const seededOpening = (0, import_react283.useSeededAnswer)(
50038
+ `table-page-opening:${tableId}`,
50039
+ async (c) => {
50040
+ const [listed, looked] = await Promise.all([c.views({ table_id: tableId }), readLooks(c, tableId)]);
50041
+ if (!listed.ok) return listed;
50042
+ if (!looked.ok) return looked;
50043
+ const mine = listed.data.map(viewFromRow).filter((v) => v.subject === tableId);
50044
+ return { ok: true, data: { views: mine, looks: looked.data } };
50045
+ }
50046
+ );
50047
+ const seededViews = seededOpening && (seedViews ?? [defaultView(tableId)]).every((spec) => seedIsSatisfied(spec, seededOpening.views)) ? seededOpening.views : void 0;
50048
+ const [view, setView] = (0, import_react282.useState)(() => {
50049
+ if (!seededViews || seededViews.length === 0) return null;
50050
+ const asked3 = savedViewFromParam(activeView);
50051
+ return seededViews.find((v) => v.id === asked3) ?? defaultViewOf(seededViews) ?? seededViews[0];
50052
+ });
50053
+ const [looks, setLooks] = (0, import_react282.useState)(() => seededViews ? seededOpening?.looks : void 0);
50054
+ const looksSeededFor = (0, import_react282.useRef)(seededViews && seededOpening ? tableId : null);
50015
50055
  (0, import_react282.useEffect)(() => {
50056
+ if (looksSeededFor.current === tableId) {
50057
+ looksSeededFor.current = null;
50058
+ return;
50059
+ }
50016
50060
  let live = true;
50017
50061
  setLooks(void 0);
50018
50062
  void readLooks(client, tableId).then((answered) => {
@@ -50032,7 +50076,7 @@ function TablePage({
50032
50076
  const questionsFromLink = questionsFromParam(activeView);
50033
50077
  const openedByPackage = openingView(savedFromLink || questionsFromLink ? null : activeView, activeDashboardId);
50034
50078
  const opened = questionsFromLink ? { ...openedByPackage, main: "questions" } : openedByPackage;
50035
- const [views, setViews] = (0, import_react282.useState)(void 0);
50079
+ const [views, setViews] = (0, import_react282.useState)(() => seededViews);
50036
50080
  const [pickedViewId, setPickedViewId] = (0, import_react282.useState)(savedFromLink);
50037
50081
  const viewSeen = (0, import_react282.useRef)(null);
50038
50082
  const [viewLinkMissed, setViewLinkMissed] = (0, import_react282.useState)(false);
@@ -50568,6 +50612,7 @@ function TablePage({
50568
50612
  }
50569
50613
  },
50570
50614
  onViews: setViews,
50615
+ ...seededViews && viewsEpoch === 0 ? { initialViews: seededViews } : {},
50571
50616
  seed: seedViews ?? [defaultView(tableId)],
50572
50617
  settings: view && main === "records" && shownLayout === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime158.jsxs)("div", { className: "flex flex-col gap-0.5 px-1 py-1", role: "radiogroup", "aria-label": FOOTER_WORDS.label, children: [
50573
50618
  /* @__PURE__ */ (0, import_jsx_runtime158.jsx)("span", { className: "px-1 pb-0.5 text-[11px] font-medium text-muted-foreground", children: FOOTER_WORDS.label }),