@ai-matrx/records-ui 0.113.2 → 0.113.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/pickers.cjs CHANGED
@@ -107,7 +107,7 @@ function fieldOptionsOnce(client, fieldId) {
107
107
 
108
108
  // src/editors.tsx
109
109
  var import_react26 = require("react");
110
- var import_records10 = require("@ai-matrx/records");
110
+ var import_records11 = require("@ai-matrx/records");
111
111
  var import_react27 = require("@ai-matrx/records/react");
112
112
  var import_design_system15 = require("@ai-matrx/design-system");
113
113
 
@@ -469,6 +469,7 @@ function BarcodeControl({ value, onChange, disabled, id }) {
469
469
  }
470
470
 
471
471
  // src/choiceLooks.ts
472
+ var import_records2 = require("@ai-matrx/records");
472
473
  var import_data_table = require("@ai-matrx/design-system/data-table");
473
474
  function displayFormatOf(field) {
474
475
  const raw = field.display_format;
@@ -503,6 +504,20 @@ function choiceLooksOf(field) {
503
504
  function choiceWord(value) {
504
505
  return String(value ?? "").trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
505
506
  }
507
+ var STATUS_GROUP_COLOR = { todo: "gray", in_progress: "blue", done: "green" };
508
+ function statusGroupColor(field, value) {
509
+ if ((0, import_records2.newerKindOf)(field) !== "status" || value === null || value === void 0 || value === "") return void 0;
510
+ const word = choiceWord(value);
511
+ if (word === "") return void 0;
512
+ const groups = (field.config ?? {})["status_groups"];
513
+ if (groups && typeof groups === "object") {
514
+ for (const [key, group] of Object.entries(groups)) {
515
+ if (choiceWord(key) !== word) continue;
516
+ return group === "in_progress" ? STATUS_GROUP_COLOR.in_progress : group === "done" ? STATUS_GROUP_COLOR.done : STATUS_GROUP_COLOR.todo;
517
+ }
518
+ }
519
+ return STATUS_GROUP_COLOR.todo;
520
+ }
506
521
  function storedChoiceColor(field, value) {
507
522
  if (value === null || value === void 0 || value === "") return void 0;
508
523
  const word = choiceWord(value);
@@ -511,7 +526,7 @@ function storedChoiceColor(field, value) {
511
526
  if (!look.color) continue;
512
527
  if (choiceWord(look.value) === word || look.label && choiceWord(look.label) === word) return look.color;
513
528
  }
514
- return void 0;
529
+ return statusGroupColor(field, value);
515
530
  }
516
531
  function choiceChipLookOf(field, ...words) {
517
532
  for (const word of words) {
@@ -522,7 +537,7 @@ function choiceChipLookOf(field, ...words) {
522
537
  }
523
538
 
524
539
  // src/parity.ts
525
- var import_records2 = require("@ai-matrx/records");
540
+ var import_records3 = require("@ai-matrx/records");
526
541
  var import_text_case = require("@ai-matrx/kit/text-case");
527
542
 
528
543
  // src/docs.ts
@@ -531,15 +546,15 @@ function isSignatureField(field) {
531
546
  }
532
547
 
533
548
  // src/parity.ts
534
- var kernelId = (name) => import_records2.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
549
+ var kernelId = (name) => import_records3.KERNEL_TABLES.find((t) => t.name === name)?.id ?? "";
535
550
  var KERNEL_FILE_TABLE = kernelId("File");
536
551
  var KERNEL_PERSON_TABLE = kernelId("Person");
537
552
  var PARITY_MADE_OF = Object.fromEntries(
538
- import_records2.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
553
+ import_records3.PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of])
539
554
  );
540
555
  var KERNEL = { file: KERNEL_FILE_TABLE, person: KERNEL_PERSON_TABLE };
541
556
  function editorKindFor(field) {
542
- return (0, import_records2.fieldKindFor)(field, KERNEL);
557
+ return (0, import_records3.fieldKindFor)(field, KERNEL);
543
558
  }
544
559
 
545
560
  // src/names.ts
@@ -578,7 +593,7 @@ var UNREAD_RECORD_LABEL = "Couldn't load this name";
578
593
 
579
594
  // src/RelationPicker.tsx
580
595
  var import_react3 = require("react");
581
- var import_records3 = require("@ai-matrx/records");
596
+ var import_records4 = require("@ai-matrx/records");
582
597
  var import_react4 = require("@ai-matrx/records/react");
583
598
  var import_design_system5 = require("@ai-matrx/design-system");
584
599
 
@@ -1331,7 +1346,7 @@ function RelationPicker({ field, value, onChange, disabled, id, className, allow
1331
1346
  toggle(createdId);
1332
1347
  };
1333
1348
  const apart = tellApart(rows ?? [], titleOf);
1334
- const visible = (0, import_records3.rankTypedMatches)(rows ?? [], search, (row) => [titleOf(row.id), apart.get(row.id) ?? ""]);
1349
+ const visible = (0, import_records4.rankTypedMatches)(rows ?? [], search, (row) => [titleOf(row.id), apart.get(row.id) ?? ""]);
1335
1350
  const anchored = autoOpen === true;
1336
1351
  const cellChips = picked.map((recordId) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1337
1352
  RecordChip,
@@ -1460,7 +1475,7 @@ var import_react5 = require("react");
1460
1475
  var import_react6 = require("@ai-matrx/records/react");
1461
1476
 
1462
1477
  // src/rights.ts
1463
- var import_records4 = require("@ai-matrx/records");
1478
+ var import_records5 = require("@ai-matrx/records");
1464
1479
  var LEVEL_WORD = {
1465
1480
  viewer: "Viewer",
1466
1481
  commenter: "Commenter",
@@ -1503,7 +1518,7 @@ function sentenceFor(what, level) {
1503
1518
  return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;
1504
1519
  }
1505
1520
  function whatYouMayDo(level, known = true) {
1506
- const may = (what) => known && (0, import_records4.atLeast)(level, NEEDS[what]);
1521
+ const may = (what) => known && (0, import_records5.atLeast)(level, NEEDS[what]);
1507
1522
  return {
1508
1523
  level: known ? level : null,
1509
1524
  known,
@@ -1539,7 +1554,7 @@ function useRecordsUi() {
1539
1554
  // src/labels.tsx
1540
1555
  var import_react9 = require("react");
1541
1556
  var import_react10 = require("@ai-matrx/records/react");
1542
- var import_records5 = require("@ai-matrx/records");
1557
+ var import_records6 = require("@ai-matrx/records");
1543
1558
  var import_uuid2 = require("@ai-matrx/kit/uuid");
1544
1559
 
1545
1560
  // src/signature.tsx
@@ -1898,7 +1913,7 @@ function RecordLabelProvider({ children }) {
1898
1913
  for (const option of result.data ?? []) {
1899
1914
  const words = recordName(option.data, null, "Unnamed choice");
1900
1915
  next[option.id] = words;
1901
- const key = (0, import_records5.optionKey)(option);
1916
+ const key = (0, import_records6.optionKey)(option);
1902
1917
  if (key) next[choiceKeyName(field.id, key)] = words;
1903
1918
  }
1904
1919
  return next;
@@ -2275,7 +2290,7 @@ function AttachmentControl({
2275
2290
 
2276
2291
  // src/EntityReferenceControl.tsx
2277
2292
  var import_react15 = require("react");
2278
- var import_records6 = require("@ai-matrx/records");
2293
+ var import_records7 = require("@ai-matrx/records");
2279
2294
  var import_react16 = require("@ai-matrx/records/react");
2280
2295
  var import_design_system10 = require("@ai-matrx/design-system");
2281
2296
 
@@ -2371,7 +2386,7 @@ var import_jsx_runtime12 = require("react/jsx-runtime");
2371
2386
  var WITHHELD_ENTITY_LABEL = "Something you have not been given access to";
2372
2387
  var ENTITY_REFERENCE_EMPTY = "Nothing is pointed at yet.";
2373
2388
  function entityReferenceText(value) {
2374
- const refs = (0, import_records6.entityRefsOf)(value);
2389
+ const refs = (0, import_records7.entityRefsOf)(value);
2375
2390
  if (refs.length === 0) return "\u2014";
2376
2391
  return refs.map((r) => r.label ?? WITHHELD_ENTITY_LABEL).join(", ");
2377
2392
  }
@@ -2385,7 +2400,7 @@ function EntityReferenceControl(props) {
2385
2400
  return client ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(WithWords, { ...props }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Chips, { ...props, words: null, picker: null });
2386
2401
  }
2387
2402
  function WithWords(props) {
2388
- const refs = (0, import_react15.useMemo)(() => (0, import_records6.entityRefsOf)(props.value), [props.value]);
2403
+ const refs = (0, import_react15.useMemo)(() => (0, import_records7.entityRefsOf)(props.value), [props.value]);
2389
2404
  const [known, setKnown] = (0, import_react15.useState)([]);
2390
2405
  const withKnown = refs.map((r) => r.label === null ? known.find((k) => k.token === r.token && k.id === r.id) ?? r : r);
2391
2406
  const unlabelled = (0, import_react15.useMemo)(
@@ -2403,7 +2418,7 @@ function WithWords(props) {
2403
2418
  setKnown((k) => [...k.filter((x) => !(x.token === picked.token && x.id === picked.id)), picked]);
2404
2419
  const multi = Boolean(props.field.multi);
2405
2420
  const next = multi ? [...withKnown.filter((x) => !(x.token === picked.token && x.id === picked.id)), picked] : [picked];
2406
- props.onChange((0, import_records6.entityRefsToWrite)(next, multi));
2421
+ props.onChange((0, import_records7.entityRefsToWrite)(next, multi));
2407
2422
  }
2408
2423
  }
2409
2424
  );
@@ -2492,7 +2507,7 @@ function Chips({
2492
2507
  words,
2493
2508
  picker
2494
2509
  }) {
2495
- const refs = (0, import_react15.useMemo)(() => (0, import_records6.entityRefsOf)(value), [value]);
2510
+ const refs = (0, import_react15.useMemo)(() => (0, import_records7.entityRefsOf)(value), [value]);
2496
2511
  const labelOf = (token, refId, own3) => {
2497
2512
  if (own3) return own3;
2498
2513
  const read = words?.data?.find((w) => w.token === token && w.id === refId)?.label;
@@ -2516,7 +2531,7 @@ function Chips({
2516
2531
  "aria-label": `Take ${label} off`,
2517
2532
  onClick: () => {
2518
2533
  const rest = refs.filter((x) => !(x.token === r.token && x.id === r.id));
2519
- onChange((0, import_records6.entityRefsToWrite)(rest, multi));
2534
+ onChange((0, import_records7.entityRefsToWrite)(rest, multi));
2520
2535
  },
2521
2536
  children: "\xD7"
2522
2537
  }
@@ -2529,7 +2544,7 @@ function Chips({
2529
2544
 
2530
2545
  // src/PersonPicker.tsx
2531
2546
  var import_react17 = require("react");
2532
- var import_records7 = require("@ai-matrx/records");
2547
+ var import_records8 = require("@ai-matrx/records");
2533
2548
  var import_react18 = require("@ai-matrx/records/react");
2534
2549
  var import_design_system11 = require("@ai-matrx/design-system");
2535
2550
  var import_jsx_runtime13 = require("react/jsx-runtime");
@@ -2611,7 +2626,7 @@ function PersonPicker({ field, value, onChange, disabled, id, className, autoOpe
2611
2626
  cancelled = true;
2612
2627
  };
2613
2628
  }, [client, personTable, picked.length, people.length]);
2614
- const listed = (0, import_records7.rankTypedMatches)(members ?? [], search, memberName);
2629
+ const listed = (0, import_records8.rankTypedMatches)(members ?? [], search, memberName);
2615
2630
  if (!membersPort || !client) {
2616
2631
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: (0, import_design_system11.cn)("text-xs text-muted-foreground", className), children: NO_MEMBERS_REASON });
2617
2632
  }
@@ -2781,7 +2796,7 @@ function FloatingRefusal({ text, why }) {
2781
2796
  var import_table_style = require("@ai-matrx/design-system/data-table/table-style");
2782
2797
  var import_data_table2 = require("@ai-matrx/design-system/data-table");
2783
2798
  var import_field_formats2 = require("@ai-matrx/design-system/field-formats");
2784
- var import_records8 = require("@ai-matrx/records");
2799
+ var import_records9 = require("@ai-matrx/records");
2785
2800
  var DRAWN_KINDS = /* @__PURE__ */ new Set(["select", "multi_select", "relation", "member", "person", "attachment", "file", "entity_reference", "checkbox", "boolean", "signature", "json"]);
2786
2801
  function shownAsOf(field) {
2787
2802
  if (DRAWN_KINDS.has(String(editorKindFor(field)))) return void 0;
@@ -2794,8 +2809,8 @@ function shownAsOf(field) {
2794
2809
  }
2795
2810
  function formatForField(field) {
2796
2811
  const shownAs = shownAsOf(field);
2797
- if ((0, import_records8.newerKindOf)(field) === "rating" && (!shownAs || shownAs.id === "rating")) {
2798
- return { id: "rating", options: { ...shownAs?.options ?? {}, ratingMax: (0, import_records8.ratingMaxOf)(field) } };
2812
+ if ((0, import_records9.newerKindOf)(field) === "rating" && (!shownAs || shownAs.id === "rating")) {
2813
+ return { id: "rating", options: { ...shownAs?.options ?? {}, ratingMax: (0, import_records9.ratingMaxOf)(field) } };
2799
2814
  }
2800
2815
  if (shownAs) return shownAs;
2801
2816
  const stamp = dateFormatFor(field);
@@ -3095,7 +3110,7 @@ function formatControl(args) {
3095
3110
  // src/typedDateHelper.tsx
3096
3111
  var import_react23 = require("react");
3097
3112
  var import_design_system14 = require("@ai-matrx/design-system");
3098
- var import_records9 = require("@ai-matrx/records");
3113
+ var import_records10 = require("@ai-matrx/records");
3099
3114
 
3100
3115
  // src/personTime.ts
3101
3116
  var import_react22 = require("react");
@@ -3136,12 +3151,12 @@ function pad(n) {
3136
3151
  }
3137
3152
  function readBox(text, kind) {
3138
3153
  if (kind === "time") {
3139
- const t = (0, import_records9.readTypedTime)(text);
3154
+ const t = (0, import_records10.readTypedTime)(text);
3140
3155
  if (!t.ok) return { day: null, time: null };
3141
3156
  const [h, m] = t.value.split(":").map(Number);
3142
3157
  return { day: null, time: { h, m } };
3143
3158
  }
3144
- const read = (0, import_records9.readTypedDate)(text, { withTime: kind === "datetime" });
3159
+ const read = (0, import_records10.readTypedDate)(text, { withTime: kind === "datetime" });
3145
3160
  if (!read.ok) return { day: null, time: null };
3146
3161
  if (kind === "datetime" && read.instant) {
3147
3162
  const at = new Date(read.instant);
@@ -3150,10 +3165,10 @@ function readBox(text, kind) {
3150
3165
  return { day: read.day, time: null };
3151
3166
  }
3152
3167
  function wordsFor(kind, day, time) {
3153
- if (kind === "time") return time ? (0, import_records9.typedTimeText)(time.h, time.m) : "";
3168
+ if (kind === "time") return time ? (0, import_records10.typedTimeText)(time.h, time.m) : "";
3154
3169
  if (!day) return "";
3155
- const dayText = (0, import_records9.typedDateText)(day);
3156
- return kind === "datetime" && time ? `${dayText} ${(0, import_records9.typedTimeText)(time.h, time.m)}` : dayText;
3170
+ const dayText = (0, import_records10.typedDateText)(day);
3171
+ return kind === "datetime" && time ? `${dayText} ${(0, import_records10.typedTimeText)(time.h, time.m)}` : dayText;
3157
3172
  }
3158
3173
  var keepFocus = { onMouseDown: (e) => e.preventDefault(), tabIndex: -1 };
3159
3174
  function CalendarGlyph() {
@@ -3173,9 +3188,10 @@ function TypedDateHelper({
3173
3188
  text,
3174
3189
  onText,
3175
3190
  label,
3176
- onPicked
3191
+ onPicked,
3192
+ startOpen = false
3177
3193
  }) {
3178
- const [open, setOpen] = (0, import_react23.useState)(false);
3194
+ const [open, setOpen] = (0, import_react23.useState)(startOpen);
3179
3195
  const held = readBox(text, kind);
3180
3196
  usePersonTimeZone();
3181
3197
  const today = personWallNow();
@@ -3274,7 +3290,7 @@ function TypedDateHelper({
3274
3290
  held.time && held.time.h === t.h && held.time.m === t.m ? "bg-primary text-primary-foreground" : ""
3275
3291
  ),
3276
3292
  onClick: () => pickTime(t),
3277
- children: (0, import_records9.typedTimeText)(t.h, t.m)
3293
+ children: (0, import_records10.typedTimeText)(t.h, t.m)
3278
3294
  },
3279
3295
  `${t.h}:${t.m}`
3280
3296
  )) })
@@ -3375,21 +3391,21 @@ function judgeTyped(field, text, choices, nudge) {
3375
3391
  const format = formatForField(field);
3376
3392
  if (trimmed === "") return { value: null };
3377
3393
  if (format && format.id === "time") {
3378
- const read2 = (0, import_records10.readTypedTime)(trimmed);
3394
+ const read2 = (0, import_records11.readTypedTime)(trimmed);
3379
3395
  return read2.ok ? { value: read2.value } : { refusal: SHORT_REFUSAL.time, why: `${fieldName(field)} holds a time of day, and ${read2.why}` };
3380
3396
  }
3381
3397
  if (kind === "select" || kind === "multi_select") {
3382
3398
  if (!choices || nudge === null) return null;
3383
3399
  const several = field.multi || kind === "multi_select";
3384
3400
  const words = several ? trimmed.split(/\s*[,;\n]\s*/).filter(Boolean) : [trimmed];
3385
- const allowOther = (0, import_records10.allowsOtherValues)(field);
3401
+ const allowOther = (0, import_records11.allowsOtherValues)(field);
3386
3402
  const parts = [];
3387
3403
  const add = [];
3388
3404
  const ask = [];
3389
3405
  const notChoices = [];
3390
3406
  let keepOffered = allowOther;
3391
3407
  for (const word of words) {
3392
- const decided = (0, import_records10.decideTypedChoice)({ words: word, options: choices, allowOther, nudge });
3408
+ const decided = (0, import_records11.decideTypedChoice)({ words: word, options: choices, allowOther, nudge });
3393
3409
  if (decided.decision === "empty") continue;
3394
3410
  if (decided.decision === "chosen") parts.push(decided.key);
3395
3411
  else {
@@ -3422,7 +3438,7 @@ function judgeTyped(field, text, choices, nudge) {
3422
3438
  return usual && digits.length >= 7 && digits.length <= 20 ? { value: trimmed } : { refusal: SHORT_REFUSAL.phone };
3423
3439
  }
3424
3440
  const showsAsPercent = Boolean(format && (format.id === "percent" || format.id === "progress"));
3425
- const read = (0, import_records10.coerceTypedAnswer)(field, text, { label: fieldName(field), showsAsPercent });
3441
+ const read = (0, import_records11.coerceTypedAnswer)(field, text, { label: fieldName(field), showsAsPercent });
3426
3442
  if ("refusal" in read) {
3427
3443
  if (kind === "email" || kind === "url") return { refusal: SHORT_REFUSAL[kind] };
3428
3444
  const short = kind === "datetime" ? SHORT_REFUSAL.date : kind === "number" || kind === "currency" || kind === "percent" || showsAsPercent ? SHORT_REFUSAL.number : read.refusal.length <= 32 ? read.refusal : SHORT_REFUSAL.value;
@@ -3443,12 +3459,12 @@ function openingText(field, value) {
3443
3459
  if (value === null || value === void 0 || value === "") return "";
3444
3460
  const helper = dateHelperKind(field, value);
3445
3461
  if (helper === "time") {
3446
- const read = (0, import_records10.readTypedTime)(String(value));
3462
+ const read = (0, import_records11.readTypedTime)(String(value));
3447
3463
  if (!read.ok) return String(value);
3448
3464
  const [h, m] = read.value.split(":").map(Number);
3449
- return (0, import_records10.typedTimeText)(h, m);
3465
+ return (0, import_records11.typedTimeText)(h, m);
3450
3466
  }
3451
- if (helper) return (0, import_records10.typedDateText)(value, { withTime: helper === "datetime" });
3467
+ if (helper) return (0, import_records11.typedDateText)(value, { withTime: helper === "datetime" });
3452
3468
  const format = formatForField(field);
3453
3469
  return format ? typedText(format, value) : String(value);
3454
3470
  }
@@ -3506,7 +3522,7 @@ function TypedTextControl({ field, value, onChange, disabled, id, onCommit, onCa
3506
3522
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "flex flex-col gap-0.5", children: [
3507
3523
  helper && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "flex min-w-0 items-center gap-0.5", children: [
3508
3524
  box,
3509
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TypedDateHelper, { kind: helper, text: value.text, onText: retype, label: fieldName(field), onPicked: onCommit })
3525
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TypedDateHelper, { kind: helper, text: value.text, onText: retype, label: fieldName(field), onPicked: onCommit, startOpen: value.openedAs !== void 0 })
3510
3526
  ] }) : box,
3511
3527
  judged === null ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { "data-records-cell-note": "", className: "text-[10px] text-muted-foreground", children: [
3512
3528
  "Reading ",
@@ -3537,7 +3553,7 @@ function TypedTextControl({ field, value, onChange, disabled, id, onCommit, onCa
3537
3553
  " ",
3538
3554
  needsChoices ? String(
3539
3555
  (Array.isArray(withoutAddition(judged.value).value) ? withoutAddition(judged.value).value : [withoutAddition(judged.value).value]).map((k) => {
3540
- const option = choices?.find((o) => (0, import_records10.optionKey)(o) === k);
3556
+ const option = choices?.find((o) => (0, import_records11.optionKey)(o) === k);
3541
3557
  return option ? recordName(option.data, null, String(k)) : String(k);
3542
3558
  }).join(", ")
3543
3559
  ) : (() => {
@@ -3713,7 +3729,7 @@ function TypedWordsControl({ field, value, onChange, disabled, id }) {
3713
3729
  function typedDatePlaceholder(helper) {
3714
3730
  const time = "h:mm AM";
3715
3731
  if (helper === "time") return time;
3716
- const pattern = (0, import_records10.typedDateText)("2026-11-22").replace("2026", "YYYY").replace("11", "MM").replace("22", "DD");
3732
+ const pattern = (0, import_records11.typedDateText)("2026-11-22").replace("2026", "YYYY").replace("11", "MM").replace("22", "DD");
3717
3733
  return helper === "datetime" ? `${pattern} ${time}` : pattern;
3718
3734
  }
3719
3735
  function CheckboxControl({ field, value, onChange, disabled, id }) {
@@ -3852,15 +3868,15 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3852
3868
  ChoiceAnswer,
3853
3869
  {
3854
3870
  field,
3855
- choices: options.map((option) => ({ key: (0, import_records10.optionKey)(option), label: titled(option) })),
3871
+ choices: options.map((option) => ({ key: (0, import_records11.optionKey)(option), label: titled(option) })),
3856
3872
  value,
3857
3873
  onChange,
3858
3874
  disabled,
3859
3875
  id,
3860
3876
  onChosen,
3861
3877
  isChosen: (choice, v) => {
3862
- const option = options.find((o) => (0, import_records10.optionKey)(o) === choice.key);
3863
- return option ? (0, import_records10.isTheChosen)(option, v) : false;
3878
+ const option = options.find((o) => (0, import_records11.optionKey)(o) === choice.key);
3879
+ return option ? (0, import_records11.isTheChosen)(option, v) : false;
3864
3880
  }
3865
3881
  }
3866
3882
  );
@@ -3880,7 +3896,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3880
3896
  onCancel,
3881
3897
  initialSearch,
3882
3898
  addsChoices,
3883
- allowOther: (0, import_records10.allowsOtherValues)(field),
3899
+ allowOther: (0, import_records11.allowsOtherValues)(field),
3884
3900
  onChoicesChanged: () => {
3885
3901
  if (client) forgetAsked(client, `field_options:${field.id}`);
3886
3902
  setReread((n) => n + 1);
@@ -3893,19 +3909,19 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3893
3909
  }
3894
3910
  const titleOf = (option) => recordName(option.data, null, "Unnamed choice");
3895
3911
  if (field.multi) {
3896
- const chosen = options.filter((option) => (0, import_records10.choiceValuesOf)(value).some((v) => (0, import_records10.isTheChosen)(option, v)));
3897
- const picked = new Set(chosen.map((option) => (0, import_records10.optionKey)(option)));
3912
+ const chosen = options.filter((option) => (0, import_records11.choiceValuesOf)(value).some((v) => (0, import_records11.isTheChosen)(option, v)));
3913
+ const picked = new Set(chosen.map((option) => (0, import_records11.optionKey)(option)));
3898
3914
  const toggles = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { id: autoOpen ? void 0 : id, className: "flex flex-wrap gap-1", children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3899
3915
  import_design_system15.Button,
3900
3916
  {
3901
3917
  type: "button",
3902
3918
  size: "sm",
3903
- variant: picked.has((0, import_records10.optionKey)(option)) ? "default" : "outline",
3919
+ variant: picked.has((0, import_records11.optionKey)(option)) ? "default" : "outline",
3904
3920
  disabled,
3905
3921
  onClick: () => {
3906
3922
  const next = new Set(picked);
3907
- if (next.has((0, import_records10.optionKey)(option))) next.delete((0, import_records10.optionKey)(option));
3908
- else next.add((0, import_records10.optionKey)(option));
3923
+ if (next.has((0, import_records11.optionKey)(option))) next.delete((0, import_records11.optionKey)(option));
3924
+ else next.add((0, import_records11.optionKey)(option));
3909
3925
  onChange(next.size === 0 ? null : [...next]);
3910
3926
  },
3911
3927
  children: titleOf(option)
@@ -3927,11 +3943,11 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3927
3943
  }
3928
3944
  );
3929
3945
  }
3930
- const current = options.find((option) => (0, import_records10.isTheChosen)(option, value));
3946
+ const current = options.find((option) => (0, import_records11.isTheChosen)(option, value));
3931
3947
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3932
3948
  import_design_system15.Select,
3933
3949
  {
3934
- value: current ? (0, import_records10.optionKey)(current) : "",
3950
+ value: current ? (0, import_records11.optionKey)(current) : "",
3935
3951
  disabled: disabled ?? false,
3936
3952
  onValueChange: (next) => onChange(next === "" ? null : next),
3937
3953
  ...autoOpen ? {
@@ -3943,7 +3959,7 @@ function OptionControl({ field, value, onChange, disabled, id, autoOpen, onClose
3943
3959
  } : {},
3944
3960
  children: [
3945
3961
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectTrigger, { id, size: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectValue, { placeholder: "Choose" }) }),
3946
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectContent, { children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectItem, { value: (0, import_records10.optionKey)(option), children: titleOf(option) }, option.id)) })
3962
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectContent, { children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.SelectItem, { value: (0, import_records11.optionKey)(option), children: titleOf(option) }, option.id)) })
3947
3963
  ]
3948
3964
  }
3949
3965
  );
@@ -3977,23 +3993,23 @@ function OpenChoicePicker({
3977
3993
  const [addRefused, setAddRefused] = (0, import_react26.useState)(null);
3978
3994
  const titleOf = (option) => recordName(option.data, null, "Unnamed choice");
3979
3995
  const held = withoutAddition(value);
3980
- const current = (0, import_records10.choiceValuesOf)(held.value);
3996
+ const current = (0, import_records11.choiceValuesOf)(held.value);
3981
3997
  const pickedWords = current.map((v) => {
3982
- const option = options.find((o) => (0, import_records10.isTheChosen)(o, v));
3998
+ const option = options.find((o) => (0, import_records11.isTheChosen)(o, v));
3983
3999
  return option ? titleOf(option) : String(v);
3984
4000
  });
3985
- const chipOf = (option, word) => option ? choiceChipLookOf(field, (0, import_records10.optionKey)(option), titleOf(option)) : choiceChipLookOf(field, word);
4001
+ const chipOf = (option, word) => option ? choiceChipLookOf(field, (0, import_records11.optionKey)(option), titleOf(option)) : choiceChipLookOf(field, word);
3986
4002
  const q = search.trim();
3987
- const visible = (0, import_records10.rankTypedMatches)(options, q, titleOf);
3988
- const decided = (0, import_records10.decideTypedChoice)({ words: q, options, allowOther, nudge: nudge ?? "ask" });
4003
+ const visible = (0, import_records11.rankTypedMatches)(options, q, titleOf);
4004
+ const decided = (0, import_records11.decideTypedChoice)({ words: q, options, allowOther, nudge: nudge ?? "ask" });
3989
4005
  const choose = (word, addingIt = false) => {
3990
4006
  const pending = held.add.filter((w) => w.toLowerCase() !== word.toLowerCase());
3991
4007
  let next;
3992
4008
  let add2 = [...pending];
3993
4009
  if (field.multi) {
3994
4010
  const existing = current.map((v) => {
3995
- const option = options.find((o) => (0, import_records10.isTheChosen)(o, v));
3996
- return option ? (0, import_records10.optionKey)(option) : String(v);
4011
+ const option = options.find((o) => (0, import_records11.isTheChosen)(o, v));
4012
+ return option ? (0, import_records11.optionKey)(option) : String(v);
3997
4013
  });
3998
4014
  const has = existing.some((v) => v.toLowerCase() === word.toLowerCase());
3999
4015
  const list = has ? existing.filter((v) => v.toLowerCase() !== word.toLowerCase()) : [...existing, word];
@@ -4029,7 +4045,7 @@ function OpenChoicePicker({
4029
4045
  const foot = null;
4030
4046
  const add = offList && (decided.decision === "ask" || decided.decision === "add") ? { label: `Create \u201C${q}\u201D`, onAdd: addTyped, disabled: adding } : offList && decided.decision === "keep_as_typed" ? { label: `Use \u201C${q}\u201D`, onAdd: () => choose(q) } : null;
4031
4047
  const listed = visible;
4032
- const pickedOptions = current.map((v) => options.find((o) => (0, import_records10.isTheChosen)(o, v)));
4048
+ const pickedOptions = current.map((v) => options.find((o) => (0, import_records11.isTheChosen)(o, v)));
4033
4049
  const cellChips = pickedWords.map((word, i) => {
4034
4050
  const chip = chipOf(pickedOptions[i], word);
4035
4051
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_design_system15.Badge, { variant: "outline", className: (0, import_design_system15.cn)("text-[11px]", chip.className), "data-records-choice-chip": "", children: word }, word);
@@ -4041,7 +4057,7 @@ function OpenChoicePicker({
4041
4057
  label: word,
4042
4058
  chip: chipOf(option, word).className,
4043
4059
  onRemove: () => {
4044
- if (field.multi) choose(option ? (0, import_records10.optionKey)(option) : String(current[i]));
4060
+ if (field.multi) choose(option ? (0, import_records11.optionKey)(option) : String(current[i]));
4045
4061
  else onChange(null);
4046
4062
  }
4047
4063
  };
@@ -4072,11 +4088,11 @@ function OpenChoicePicker({
4072
4088
  id: option.id,
4073
4089
  label: titleOf(option),
4074
4090
  chip: chipOf(option, titleOf(option)).className,
4075
- picked: current.some((v) => (0, import_records10.isTheChosen)(option, v))
4091
+ picked: current.some((v) => (0, import_records11.isTheChosen)(option, v))
4076
4092
  })),
4077
4093
  onPick: (optionId) => {
4078
4094
  const option = options.find((o) => o.id === optionId);
4079
- if (option) choose((0, import_records10.optionKey)(option));
4095
+ if (option) choose((0, import_records11.optionKey)(option));
4080
4096
  },
4081
4097
  empty: q === "" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "p-2 text-xs text-muted-foreground", children: "No choices yet \u2014 type one to add it." }) : null,
4082
4098
  add,
@@ -4132,7 +4148,7 @@ function ChoiceAnswer({
4132
4148
  onChosen
4133
4149
  }) {
4134
4150
  const [search, setSearch] = (0, import_react26.useState)("");
4135
- const held = field.multi ? (0, import_records10.choiceValuesOf)(value) : value === null || value === void 0 || value === "" ? [] : [value];
4151
+ const held = field.multi ? (0, import_records11.choiceValuesOf)(value) : value === null || value === void 0 || value === "" ? [] : [value];
4136
4152
  const on = (choice) => held.some((v) => isChosen ? isChosen(choice, v) : String(v) === choice.key || String(v) === choice.label);
4137
4153
  const press = (choice) => {
4138
4154
  if (!field.multi) {
@@ -4243,17 +4259,17 @@ function personActor(userId) {
4243
4259
 
4244
4260
  // src/tablePicking.tsx
4245
4261
  var import_react30 = require("react");
4246
- var import_records11 = require("@ai-matrx/records");
4262
+ var import_records12 = require("@ai-matrx/records");
4247
4263
  var import_react31 = require("@ai-matrx/records/react");
4248
4264
  var import_design_system16 = require("@ai-matrx/design-system");
4249
4265
  var import_jsx_runtime20 = require("react/jsx-runtime");
4250
4266
  var PLATFORM_TABLE_PREFIX = "records_ui_";
4251
4267
  function isValueSet(table) {
4252
4268
  if (table.kept_for === "choices") return true;
4253
- return table.kept_for == null && table.kind === "list" && table.kept_by_the_app === true;
4269
+ return table.kept_for == null && table.kind === "list" && table.platform_owned === true;
4254
4270
  }
4255
4271
  function isKeptTable(table) {
4256
- return table.kept_by_the_app === true || isValueSet(table) || Boolean(table.work_kind) || (table.slug ?? "").startsWith(PLATFORM_TABLE_PREFIX);
4272
+ return table.platform_owned === true || isValueSet(table) || Boolean(table.work_kind) || (table.slug ?? "").startsWith(PLATFORM_TABLE_PREFIX);
4257
4273
  }
4258
4274
  var CHOICES_SUFFIX = / choices$/i;
4259
4275
  function tablePickerEntries(tables, options = {}) {
@@ -4516,7 +4532,7 @@ function RecordPicker({ tableId, value, onChange, disabled }) {
4516
4532
 
4517
4533
  // src/DataBindingPicker.tsx
4518
4534
  var import_react34 = require("react");
4519
- var import_records12 = require("@ai-matrx/records");
4535
+ var import_records13 = require("@ai-matrx/records");
4520
4536
  var import_react35 = require("@ai-matrx/records/react");
4521
4537
  var import_design_system18 = require("@ai-matrx/design-system");
4522
4538
  var import_jsx_runtime22 = require("react/jsx-runtime");
@@ -4550,7 +4566,7 @@ function isCompleteDataBinding(binding) {
4550
4566
  }
4551
4567
  function bindingPlaceholdersFor(field) {
4552
4568
  const label = fieldName(field);
4553
- if ((0, import_records12.isEntityReferenceConfig)(field.config)) {
4569
+ if ((0, import_records13.isEntityReferenceConfig)(field.config)) {
4554
4570
  return [
4555
4571
  { token: `{${field.key}.name}`, label: `${label} \xB7 name` },
4556
4572
  { token: `{${field.key}.id}`, label: `${label} \xB7 id` }
@@ -4841,7 +4857,7 @@ function WholeValueCell({ words, pointer }) {
4841
4857
  var import_field_formats6 = require("@ai-matrx/design-system/field-formats");
4842
4858
 
4843
4859
  // src/ReferenceChips.tsx
4844
- var import_records13 = require("@ai-matrx/records");
4860
+ var import_records14 = require("@ai-matrx/records");
4845
4861
  var import_design_system20 = require("@ai-matrx/design-system");
4846
4862
 
4847
4863
  // src/kindValues.ts
@@ -4913,7 +4929,7 @@ function iconOf(pair) {
4913
4929
  }
4914
4930
  function referencesOf(field, value, kind, labels) {
4915
4931
  if (kind === "entity_reference") {
4916
- return (0, import_records13.entityRefsOf)(value).map((r) => ({ token: r.token, id: r.id, label: r.label }));
4932
+ return (0, import_records14.entityRefsOf)(value).map((r) => ({ token: r.token, id: r.id, label: r.label }));
4917
4933
  }
4918
4934
  const ids = (Array.isArray(value) ? value : [value]).filter(isId).map(String);
4919
4935
  const tableId = typeof field.relation_target === "string" ? field.relation_target : void 0;
@@ -4999,20 +5015,20 @@ function KindValueCell({
4999
5015
  }
5000
5016
 
5001
5017
  // src/formulaNames.ts
5002
- var import_records14 = require("@ai-matrx/records");
5018
+ var import_records15 = require("@ai-matrx/records");
5003
5019
  var FORMULA_INPUT_KEYS = "__formula_input_keys";
5004
5020
  function formulaSourceArchived(field, document2) {
5005
5021
  const keys = (field.config ?? {})[FORMULA_INPUT_KEYS];
5006
5022
  if (!Array.isArray(keys) || !document2) return null;
5007
5023
  for (const key of keys) {
5008
- const state = (0, import_records14.sourceArchivedOf)(document2[String(key)]);
5024
+ const state = (0, import_records15.sourceArchivedOf)(document2[String(key)]);
5009
5025
  if (state) return state;
5010
5026
  }
5011
5027
  return null;
5012
5028
  }
5013
5029
 
5014
5030
  // src/values.tsx
5015
- var import_records15 = require("@ai-matrx/records");
5031
+ var import_records16 = require("@ai-matrx/records");
5016
5032
  var import_jsx_runtime25 = require("react/jsx-runtime");
5017
5033
  function statusMark(field, item, document2) {
5018
5034
  const mark = statusMarkOf(field, item, document2);
@@ -5066,7 +5082,7 @@ function SourceArchivedValue({ state }) {
5066
5082
  }
5067
5083
  var ABSENCE_WORDS = ABSENCE_WORD_LABEL;
5068
5084
  function renderValue(field, value, document2, labels, stillWaitingFor, look) {
5069
- const archivedSource = (0, import_records15.sourceArchivedOf)(value);
5085
+ const archivedSource = (0, import_records16.sourceArchivedOf)(value);
5070
5086
  if (archivedSource) return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SourceArchivedValue, { state: archivedSource });
5071
5087
  const envelope = envelopeFor(document2, field.key);
5072
5088
  if (envelope?.absent) {
@@ -5175,9 +5191,9 @@ function renderValue(field, value, document2, labels, stillWaitingFor, look) {
5175
5191
  }
5176
5192
  function scalarText(field, value, labels, stillWaitingFor) {
5177
5193
  if (value === null || value === void 0) return "\u2014";
5178
- if ((0, import_records15.sourceArchivedOf)(value)) return SOURCE_ARCHIVED_WORDS;
5194
+ if ((0, import_records16.sourceArchivedOf)(value)) return SOURCE_ARCHIVED_WORDS;
5179
5195
  if (isSignatureField(field)) return signatureWords(value) ?? "\u2014";
5180
- const newerWords = (0, import_records15.newerKindWords)(field, value);
5196
+ const newerWords = (0, import_records16.newerKindWords)(field, value);
5181
5197
  if (newerWords !== null) return newerWords;
5182
5198
  const kind = editorKindFor(field);
5183
5199
  if (kind === "entity_reference") return entityReferenceText(value);