@bettercms-ai/kit 2.0.0 → 2.0.2

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.
Files changed (120) hide show
  1. package/dist/adapters/lossy.d.ts +14 -6
  2. package/dist/adapters/lossy.js +23 -11
  3. package/dist/adapters/lossy.js.map +1 -1
  4. package/dist/adapters/prod-types.d.ts +46 -14
  5. package/dist/adapters/prod-types.js +37 -35
  6. package/dist/adapters/prod-types.js.map +1 -1
  7. package/dist/adapters/schema.d.ts +39 -0
  8. package/dist/adapters/schema.js +281 -82
  9. package/dist/adapters/schema.js.map +1 -1
  10. package/dist/context.d.ts +39 -0
  11. package/dist/context.js +40 -1
  12. package/dist/context.js.map +1 -1
  13. package/dist/controls/form-picker-register.d.ts +7 -1
  14. package/dist/controls/form-picker-register.js +1 -5
  15. package/dist/controls/form-picker-register.js.map +1 -1
  16. package/dist/controls/icon.d.ts +1 -1
  17. package/dist/controls/icon.js +1 -1
  18. package/dist/controls/icon.js.map +1 -1
  19. package/dist/controls/link.d.ts +11 -4
  20. package/dist/controls/link.js +120 -202
  21. package/dist/controls/link.js.map +1 -1
  22. package/dist/controls/location.js +3 -8
  23. package/dist/controls/location.js.map +1 -1
  24. package/dist/controls/media.d.ts +0 -14
  25. package/dist/controls/media.js +52 -95
  26. package/dist/controls/media.js.map +1 -1
  27. package/dist/controls/reference-services.d.ts +23 -2
  28. package/dist/controls/reference.d.ts +2 -2
  29. package/dist/controls/reference.js +79 -28
  30. package/dist/controls/reference.js.map +1 -1
  31. package/dist/controls/rich-text/article-shell.d.ts +145 -0
  32. package/dist/controls/rich-text/article-shell.js +514 -0
  33. package/dist/controls/rich-text/article-shell.js.map +1 -0
  34. package/dist/controls/rich-text/author.d.ts +25 -0
  35. package/dist/controls/rich-text/author.js +107 -0
  36. package/dist/controls/rich-text/author.js.map +1 -0
  37. package/dist/controls/rich-text/blocks.d.ts +19 -2
  38. package/dist/controls/rich-text/blocks.js +275 -638
  39. package/dist/controls/rich-text/blocks.js.map +1 -1
  40. package/dist/controls/rich-text/button.d.ts +23 -0
  41. package/dist/controls/rich-text/button.js +81 -0
  42. package/dist/controls/rich-text/button.js.map +1 -0
  43. package/dist/controls/rich-text/catalog.d.ts +2 -5
  44. package/dist/controls/rich-text/catalog.js +121 -7
  45. package/dist/controls/rich-text/catalog.js.map +1 -1
  46. package/dist/controls/rich-text/checklist.d.ts +24 -0
  47. package/dist/controls/rich-text/checklist.js +115 -0
  48. package/dist/controls/rich-text/checklist.js.map +1 -0
  49. package/dist/controls/rich-text/codec.d.ts +15 -1
  50. package/dist/controls/rich-text/codec.js +11 -1
  51. package/dist/controls/rich-text/codec.js.map +1 -1
  52. package/dist/controls/rich-text/columns.d.ts +41 -0
  53. package/dist/controls/rich-text/columns.js +181 -0
  54. package/dist/controls/rich-text/columns.js.map +1 -0
  55. package/dist/controls/rich-text/control.js +1 -0
  56. package/dist/controls/rich-text/control.js.map +1 -1
  57. package/dist/controls/rich-text/dom.d.ts +84 -4
  58. package/dist/controls/rich-text/dom.js +171 -10
  59. package/dist/controls/rich-text/dom.js.map +1 -1
  60. package/dist/controls/rich-text/editor.d.ts +4 -2
  61. package/dist/controls/rich-text/editor.js +199 -26
  62. package/dist/controls/rich-text/editor.js.map +1 -1
  63. package/dist/controls/rich-text/embed.d.ts +28 -0
  64. package/dist/controls/rich-text/embed.js +210 -0
  65. package/dist/controls/rich-text/embed.js.map +1 -0
  66. package/dist/controls/rich-text/footnote.d.ts +41 -0
  67. package/dist/controls/rich-text/footnote.js +185 -0
  68. package/dist/controls/rich-text/footnote.js.map +1 -0
  69. package/dist/controls/rich-text/gallery.d.ts +28 -0
  70. package/dist/controls/rich-text/gallery.js +167 -0
  71. package/dist/controls/rich-text/gallery.js.map +1 -0
  72. package/dist/controls/rich-text/link-form.d.ts +13 -1
  73. package/dist/controls/rich-text/link-form.js +41 -7
  74. package/dist/controls/rich-text/link-form.js.map +1 -1
  75. package/dist/controls/rich-text/ops.js +6 -0
  76. package/dist/controls/rich-text/ops.js.map +1 -1
  77. package/dist/controls/rich-text/related.d.ts +49 -0
  78. package/dist/controls/rich-text/related.js +233 -0
  79. package/dist/controls/rich-text/related.js.map +1 -0
  80. package/dist/controls/rich-text/toc.d.ts +47 -0
  81. package/dist/controls/rich-text/toc.js +160 -0
  82. package/dist/controls/rich-text/toc.js.map +1 -0
  83. package/dist/controls/slot-register.d.ts +6 -1
  84. package/dist/controls/slot-register.js +1 -4
  85. package/dist/controls/slot-register.js.map +1 -1
  86. package/dist/core/core.d.ts +11 -3
  87. package/dist/core/core.js +24 -6
  88. package/dist/core/core.js.map +1 -1
  89. package/dist/core/facets.d.ts +16 -0
  90. package/dist/core/facets.js +17 -1
  91. package/dist/core/facets.js.map +1 -1
  92. package/dist/core/index.js +2 -2
  93. package/dist/index.js +16 -5
  94. package/dist/index.js.map +1 -1
  95. package/dist/ledgers/exclusions.v1.js +141 -0
  96. package/dist/ledgers/exclusions.v1.js.map +1 -0
  97. package/dist/library/coverage.d.ts +13 -1
  98. package/dist/library/coverage.js +12 -1
  99. package/dist/library/coverage.js.map +1 -1
  100. package/dist/library/kit-catalog.json +158 -154
  101. package/dist/schema/types.d.ts +17 -0
  102. package/dist/schema/types.js.map +1 -1
  103. package/dist/styles.css +1 -1
  104. package/dist/testing/coverage-extras.d.ts +8 -0
  105. package/dist/testing/coverage-extras.js +44 -0
  106. package/dist/testing/coverage-extras.js.map +1 -0
  107. package/dist/testing/exclusions.d.ts +30 -0
  108. package/dist/testing/exclusions.js +13 -0
  109. package/dist/testing/exclusions.js.map +1 -0
  110. package/dist/ui/autocomplete.d.ts +29 -1
  111. package/dist/ui/autocomplete.js +102 -47
  112. package/dist/ui/autocomplete.js.map +1 -1
  113. package/dist/ui/button.js +3 -5
  114. package/dist/ui/button.js.map +1 -1
  115. package/dist/ui/index.js +2 -2
  116. package/dist/ui/overlay.d.ts +4 -1
  117. package/dist/ui/overlay.js +2 -1
  118. package/dist/ui/overlay.js.map +1 -1
  119. package/dist/ui/toast.js +1 -1
  120. package/package.json +8 -2
@@ -31,8 +31,9 @@ var NON_ENTRY = /* @__PURE__ */ new Set([
31
31
  ]);
32
32
  var isEntryTarget = (t) => !NON_ENTRY.has(t);
33
33
  var targetsOf = (field) => field.reference?.to ?? [];
34
- /** The noun the picker uses (D48: "CMS item" where V2 says "entry"). */
35
- function referenceNoun(to) {
34
+ /** The noun the picker uses: the field's own (`reference.noun`), else D48's ("CMS item" where V2 says "entry"). */
35
+ function referenceNoun(to, noun) {
36
+ if (noun) return noun;
36
37
  if (to.length === 1) return to[0] === "page" ? "page" : to[0] === "form" ? "form" : to[0] === "collection" ? "collection" : to[0] === "shopify" ? "product" : "CMS item";
37
38
  return to.length && to.every(isEntryTarget) ? "CMS item" : "item";
38
39
  }
@@ -80,11 +81,13 @@ function RefThumb({ o, size = 28 }) {
80
81
  })
81
82
  });
82
83
  }
83
- function DraftChip({ status }) {
84
- return status === "draft" ? /* @__PURE__ */ jsx("span", {
84
+ function DraftChip({ status, missingRequired }) {
85
+ if (status !== "draft") return null;
86
+ const n = missingRequired ?? 0;
87
+ return /* @__PURE__ */ jsxs("span", {
85
88
  className: "shrink-0 rounded-kit-md bg-kit-muted px-1 text-kit-2xs text-kit-fg-3",
86
- children: "Draft"
87
- }) : null;
89
+ children: ["Draft", n > 0 ? ` · ${n} required field${n === 1 ? "" : "s"} empty` : ""]
90
+ });
88
91
  }
89
92
  /**
90
93
  * The records behind `ids`, read once per id through `lookupReferences`. An id the service does not hand back is
@@ -145,8 +148,8 @@ function useReferenceRecords(ids, to) {
145
148
  canLookup: !!lookupReferences
146
149
  };
147
150
  }
148
- function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, canCreate, onCreated }) {
149
- const { searchReferences, createReference } = useKitServices();
151
+ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, canCreate, noCreateWhy, onCreated, excludeId }) {
152
+ const { searchReferences, createReference, toast } = useKitServices();
150
153
  const env = useKitEnv();
151
154
  const [q, setQ] = React.useState("");
152
155
  const [query, setQuery] = React.useState("");
@@ -173,11 +176,11 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
173
176
  filter,
174
177
  q: query,
175
178
  limit: PAGE,
176
- excludeId: env.docId,
179
+ excludeId: excludeId ?? env.docId,
177
180
  signal: ctrl.signal
178
181
  }).then((r) => {
179
182
  if (ctrl.signal.aborted) return;
180
- setRows(r.options.filter((o) => o.id !== env.docId));
183
+ setRows(r.options.filter((o) => o.id !== env.docId && o.id !== excludeId));
181
184
  setTruncated(r.truncated);
182
185
  setError(null);
183
186
  setActive(0);
@@ -188,6 +191,7 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
188
191
  toKey,
189
192
  filter,
190
193
  env.docId,
194
+ excludeId,
191
195
  searchReferences
192
196
  ]);
193
197
  const none = onNone && !q;
@@ -200,8 +204,10 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
200
204
  else if (none) onNone();
201
205
  };
202
206
  const optionId = (i) => `${listId}-${i}`;
207
+ const createOut = React.useRef(false);
203
208
  const create = async (title) => {
204
- if (!createReference) return;
209
+ if (!createReference || createOut.current) return;
210
+ createOut.current = true;
205
211
  setCreateBusy(true);
206
212
  setCreateError(null);
207
213
  try {
@@ -211,9 +217,19 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
211
217
  });
212
218
  setCreating(false);
213
219
  onCreated(o);
220
+ const open = o.kind === "entry" && o.modelSlug && env.onOpenReference ? {
221
+ label: "Open",
222
+ onClick: () => env.onOpenReference({
223
+ collectionId: o.modelSlug,
224
+ entryId: o.id,
225
+ title: o.title
226
+ })
227
+ } : void 0;
228
+ toast?.success(o.created === false ? `Using existing ‘${o.title}’` : `Created ‘${o.title}’ as a draft`, open ? { action: open } : void 0);
214
229
  } catch (e) {
215
230
  setCreateError(`Not created: ${reasonOf(e)}`);
216
231
  } finally {
232
+ createOut.current = false;
217
233
  setCreateBusy(false);
218
234
  }
219
235
  };
@@ -318,7 +334,10 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
318
334
  children: o.subtitle
319
335
  }) : null]
320
336
  }),
321
- /* @__PURE__ */ jsx(DraftChip, { status: o.status }),
337
+ /* @__PURE__ */ jsx(DraftChip, {
338
+ status: o.status,
339
+ missingRequired: o.missingRequired
340
+ }),
322
341
  !multi && on ? /* @__PURE__ */ jsx(IconCheck, {
323
342
  className: "size-4 shrink-0 text-kit-fg",
324
343
  stroke: 2,
@@ -327,9 +346,13 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
327
346
  ]
328
347
  }, `${o.kind}:${o.id}`);
329
348
  }),
330
- !loading && !error && rows.length === 0 ? /* @__PURE__ */ jsx("div", {
349
+ !loading && !error && rows.length === 0 ? /* @__PURE__ */ jsxs("div", {
331
350
  className: "px-3 py-6 text-center text-kit-sm text-kit-fg-3",
332
- children: "No matches"
351
+ children: ["No matches", noCreateWhy ? /* @__PURE__ */ jsx("p", {
352
+ role: "note",
353
+ className: "mt-1 text-kit-xs",
354
+ children: noCreateWhy
355
+ }) : null]
333
356
  }) : null,
334
357
  loading && rows.length === 0 ? /* @__PURE__ */ jsx("div", {
335
358
  role: "status",
@@ -420,10 +443,28 @@ function PickerBody({ to, filter, selected, multi, max, noun, onPick, onNone, ca
420
443
  ]
421
444
  });
422
445
  }
423
- /** "Create new" only where the host can create a draft in the ONE entry model the field targets. */
424
- function useCanCreate(to) {
425
- const { createReference } = useKitServices();
426
- return !!createReference && to.length === 1 && isEntryTarget(to[0]);
446
+ var noCapability = (_to) => void 0;
447
+ /**
448
+ * "Create new" only where the host can create a draft in the ONE entry model the field targets, and, when the host
449
+ * answers per target (useReferenceCreate), only where that model takes one. Otherwise `why`, for the empty state:
450
+ * the target's own refusal, else the host's createDisabledReason. A capability not known yet shows neither.
451
+ */
452
+ function useCreate(to) {
453
+ const { createReference, createDisabledReason, useReferenceCreate } = useKitServices();
454
+ const one = to.length === 1 && isEntryTarget(to[0]) ? to[0] : null;
455
+ const cap = (useReferenceCreate ?? noCapability)(one);
456
+ if (!one) return { can: false };
457
+ if (useReferenceCreate) {
458
+ if (!cap) return { can: false };
459
+ if (!cap.ok) return {
460
+ can: false,
461
+ why: cap.reason
462
+ };
463
+ }
464
+ return createReference ? { can: true } : {
465
+ can: false,
466
+ why: createDisabledReason
467
+ };
427
468
  }
428
469
  /** Why the field cannot change its value here (no search service), in words. */
429
470
  function NoSearch({ title }) {
@@ -439,12 +480,13 @@ function NoSearch({ title }) {
439
480
  }
440
481
  function ReferenceControl({ field, value, onChange, readOnly, id }) {
441
482
  const env = useKitEnv();
442
- const { searchReferences, toast } = useKitServices();
483
+ const { searchReferences } = useKitServices();
443
484
  const to = targetsOf(field);
444
- const noun = referenceNoun(to);
485
+ const noun = referenceNoun(to, field.reference?.noun);
445
486
  const current = typeof value === "string" && value ? value : null;
446
487
  const rec = useReferenceRecords(React.useMemo(() => current ? [current] : [], [current]), to);
447
- const canCreate = useCanCreate(to) && !readOnly;
488
+ const createState = useCreate(to);
489
+ const canCreate = createState.can && !readOnly;
448
490
  const [open, setOpen] = React.useState(false);
449
491
  const pick = (o) => {
450
492
  rec.remember(o);
@@ -464,6 +506,7 @@ function ReferenceControl({ field, value, onChange, readOnly, id }) {
464
506
  children: /* @__PURE__ */ jsx(PickerBody, {
465
507
  to,
466
508
  filter: field.reference?.filter,
509
+ excludeId: field.reference?.excludeId,
467
510
  selected: current ? [current] : [],
468
511
  noun,
469
512
  onPick: pick,
@@ -472,10 +515,8 @@ function ReferenceControl({ field, value, onChange, readOnly, id }) {
472
515
  setOpen(false);
473
516
  } : void 0,
474
517
  canCreate,
475
- onCreated: (o) => {
476
- pick(o);
477
- toast?.success(`${noun.replace(/^./, (c) => c.toUpperCase())} created as a draft`, { description: `“${o.title}”` });
478
- }
518
+ noCreateWhy: createState.why,
519
+ onCreated: pick
479
520
  })
480
521
  });
481
522
  const missing = !!current && rec.missing.has(current);
@@ -510,7 +551,10 @@ function ReferenceControl({ field, value, onChange, readOnly, id }) {
510
551
  children: subtitle
511
552
  }) : null]
512
553
  }),
513
- /* @__PURE__ */ jsx(DraftChip, { status: o?.status })
554
+ /* @__PURE__ */ jsx(DraftChip, {
555
+ status: o?.status,
556
+ missingRequired: o?.missingRequired
557
+ })
514
558
  ]
515
559
  }), readOnly ? null : /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
516
560
  "aria-label": `${o?.title ?? field.title} actions`,
@@ -623,6 +667,10 @@ function RefChip({ id, o, canLookup, readOnly, sort, onRemove }) {
623
667
  className: "truncate",
624
668
  children: title
625
669
  }),
670
+ o?.missingRequired ? /* @__PURE__ */ jsx(DraftChip, {
671
+ status: o.status,
672
+ missingRequired: o.missingRequired
673
+ }) : null,
626
674
  readOnly ? null : /* @__PURE__ */ jsx("button", {
627
675
  type: "button",
628
676
  "aria-label": `Remove ${title}`,
@@ -644,10 +692,11 @@ function ReferencesControl({ field, value, onChange, readOnly, id }) {
644
692
  const item = Array.isArray(field.of) ? field.of[0] : void 0;
645
693
  const to = item?.reference?.to ?? field.reference?.to ?? [];
646
694
  const filter = item?.reference?.filter ?? field.reference?.filter;
647
- const noun = referenceNoun(to);
695
+ const noun = referenceNoun(to, item?.reference?.noun ?? field.reference?.noun);
648
696
  const ids = React.useMemo(() => (Array.isArray(value) ? value : []).filter((x) => typeof x === "string" && x !== ""), [value]);
649
697
  const rec = useReferenceRecords(ids, to);
650
- const canCreate = useCanCreate(to) && !readOnly;
698
+ const createState = useCreate(to);
699
+ const canCreate = createState.can && !readOnly;
651
700
  const max = field.validation?.max;
652
701
  const missingIds = ids.filter((x) => rec.missing.has(x));
653
702
  const shown = missingIds.length ? ids.filter((x) => !rec.missing.has(x)) : ids;
@@ -704,12 +753,14 @@ function ReferencesControl({ field, value, onChange, readOnly, id }) {
704
753
  }) : /* @__PURE__ */ jsx(PickerBody, {
705
754
  to,
706
755
  filter,
756
+ excludeId: item?.reference?.excludeId ?? field.reference?.excludeId,
707
757
  selected: ids,
708
758
  multi: true,
709
759
  max,
710
760
  noun,
711
761
  onPick: toggle,
712
762
  canCreate,
763
+ noCreateWhy: createState.why,
713
764
  onCreated: (o) => {
714
765
  rec.remember(o);
715
766
  onChange(max != null && ids.length >= max ? [...ids.slice(0, -1), o.id] : [...ids, o.id]);
@@ -1 +1 @@
1
- {"version":3,"file":"reference.js","names":[],"sources":["../../src/controls/reference.tsx"],"sourcesContent":["/**\n * REFERENCE — single: a select-like trigger (\"Select a CMS item\") → a 300px search popover with \"None\", result rows,\n * drafts labelled, and \"Create new\" inline when the host can create. Never lists the document being edited. No one-click\n * clear (⋯ → Remove). MULTI-REFERENCE — reorderable chips + \"+ Add\", \"n / max\"; at the limit the picker swaps in place.\n * (V2 HEAD 9829bf1 kit/controls/reference.tsx, DESIGN.md 6.8, 8.16, 9.6.)\n *\n * The rows come from the host (reference-services.ts): `searchReferences` is POST /content/reference-options, which\n * already applies the field's `reference.filter` and scope; `truncated` says its filter scan stopped early, and the\n * picker says so. The stored value is the target id (\"en_12\"; a list for many), exactly V2's shape.\n *\n * Kit deviations from V2: no seed rows (every row is a real record from the service); matching is the server's title /\n * slug search, so rows keep the server's order; a stored id the lookup cannot find shows as a \"Missing\" card, or in a\n * multi list one compact \"n missing\" chip with Remove (DESIGN 9.6's production rule), instead of disappearing; chips sort with the engine's `useDragReorder`\n * (@dnd-kit is not on the kit allow-list).\n */\nimport * as React from \"react\";\nimport { IconArrowUpRight, IconCheck, IconChevronDown, IconDatabase, IconDots, IconFileDatabase, IconFileText, IconForms, IconPlus, IconReplace, IconSearch, IconShoppingBag, IconTrash, IconX } from \"@tabler/icons-react\";\nimport type { KitReferenceKind, KitReferenceOption } from \"./reference-services\";\nimport { Button } from \"../ui/button\";\nimport { Avatar } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { cn } from \"../lib/cn\";\nimport { useDragReorder } from \"../engine/item-list\";\nimport { useKitEnv, useKitServices } from \"../context\";\nimport type { ControlProps } from \"../types\";\n\nconst NON_ENTRY = new Set([\"page\", \"form\", \"collection\", \"shopify\"]);\nconst isEntryTarget = (t: string) => !NON_ENTRY.has(t);\nconst targetsOf = (field: ControlProps[\"field\"]) => field.reference?.to ?? [];\n\n/** The noun the picker uses (D48: \"CMS item\" where V2 says \"entry\"). */\nexport function referenceNoun(to: string[]): string {\n if (to.length === 1) return to[0] === \"page\" ? \"page\" : to[0] === \"form\" ? \"form\" : to[0] === \"collection\" ? \"collection\" : to[0] === \"shopify\" ? \"product\" : \"CMS item\";\n return to.length && to.every(isEntryTarget) ? \"CMS item\" : \"item\";\n}\nconst plural = (noun: string) => (noun === \"CMS item\" ? \"CMS items\" : `${noun}s`);\nconst withArticle = (noun: string) => `${/^[aeiou]/i.test(noun) ? \"an\" : \"a\"} ${noun}`;\nconst reasonOf = (e: unknown) => (e instanceof Error ? e.message : String(e));\nconst PAGE = 25;\n/** V2 (Radix) slides a picker that would overflow along the edge, keeping it over the panel; Base UI would flip it to\n * end-aligned, which hangs it left over the preview */\nconst SHIFT = { align: \"shift\" } as const;\n\nconst KIND_ICON: Record<KitReferenceKind, React.ComponentType<{ className?: string; stroke?: number }>> = {\n entry: IconFileDatabase,\n page: IconFileText,\n form: IconForms,\n collection: IconDatabase,\n shopify: IconShoppingBag,\n};\n\nexport function RefThumb({ o, size = 28 }: { o: Pick<KitReferenceOption, \"kind\" | \"title\" | \"photo\" | \"avatar\" | \"cover\"> | null; size?: number }) {\n // V2 reference.tsx:152-156: a person is their round avatar (initials without a photo), a record with a cover its image\n if (o?.avatar || o?.photo) return <Avatar name={o.title} src={o.photo ?? undefined} size={size} decorative />;\n if (o?.cover) return <img src={o.cover} alt=\"\" style={{ width: size, height: size }} className=\"shrink-0 rounded-kit-md border border-kit-line object-cover\" />;\n const Icon = o ? KIND_ICON[o.kind] : IconFileDatabase;\n return (\n <span aria-hidden style={{ width: size, height: size }} className=\"flex shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-subtle text-kit-fg-3\">\n <Icon className={size > 24 ? \"size-4\" : \"size-3.5\"} stroke={1.5} />\n </span>\n );\n}\n\nfunction DraftChip({ status }: { status?: string | null }) {\n return status === \"draft\" ? <span className=\"shrink-0 rounded-kit-md bg-kit-muted px-1 text-kit-2xs text-kit-fg-3\">Draft</span> : null;\n}\n\n/* ── Lookup: stored ids → their records ────────────────────────────── */\n/**\n * The records behind `ids`, read once per id through `lookupReferences`. An id the service does not hand back is\n * `missing`; a failed read is `error` (in words). A row picked in the picker is `remember`ed, so it shows at once.\n */\nexport function useReferenceRecords(ids: string[], to: string[]) {\n const { lookupReferences } = useKitServices();\n const [known, setKnown] = React.useState<Record<string, KitReferenceOption>>({});\n const [missing, setMissing] = React.useState<ReadonlySet<string>>(new Set());\n const [error, setError] = React.useState<string | null>(null);\n const inflight = React.useRef(new Set<string>());\n const alive = React.useRef(true);\n // set on every mount: StrictMode mounts, unmounts and mounts again, and a flag only cleared would drop every read\n React.useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n const idsKey = ids.join(\"|\");\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!lookupReferences) return;\n const asked = ids.filter((x) => !known[x] && !missing.has(x) && !inflight.current.has(x));\n if (!asked.length) return;\n for (const x of asked) inflight.current.add(x);\n lookupReferences(asked, to)\n .then((rows) => {\n if (!alive.current) return;\n const found = new Set(rows.map((r) => r.id));\n setKnown((k) => ({ ...k, ...Object.fromEntries(rows.map((r) => [r.id, r])) }));\n setMissing((m) => new Set([...m, ...asked.filter((x) => !found.has(x))]));\n setError(null);\n })\n .catch((e: unknown) => alive.current && setError(`The saved ${plural(referenceNoun(to))} could not be read: ${reasonOf(e)}`))\n .finally(() => {\n for (const x of asked) inflight.current.delete(x);\n });\n }, [idsKey, toKey, lookupReferences, known, missing]); // eslint-disable-line react-hooks/exhaustive-deps\n const remember = React.useCallback((o: KitReferenceOption) => {\n setKnown((k) => ({ ...k, [o.id]: o }));\n setMissing((m) => (m.has(o.id) ? new Set([...m].filter((x) => x !== o.id)) : m));\n }, []);\n return { known, missing, loading: !!lookupReferences && ids.some((x) => !known[x] && !missing.has(x)) && !error, error, remember, canLookup: !!lookupReferences };\n}\n\n/* ── The search popover body, shared by single and multi ───────────── */\nfunction PickerBody({\n to,\n filter,\n selected,\n multi,\n max,\n noun,\n onPick,\n onNone,\n canCreate,\n onCreated,\n}: {\n to: string[];\n filter?: string;\n selected: string[];\n multi?: boolean;\n max?: number;\n noun: string;\n onPick: (o: KitReferenceOption) => void;\n onNone?: () => void;\n canCreate: boolean;\n onCreated: (o: KitReferenceOption) => void;\n}) {\n const { searchReferences, createReference } = useKitServices();\n const env = useKitEnv();\n const [q, setQ] = React.useState(\"\");\n const [query, setQuery] = React.useState(\"\");\n const [rows, setRows] = React.useState<KitReferenceOption[]>([]);\n const [truncated, setTruncated] = React.useState(false);\n const [loading, setLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n const [active, setActive] = React.useState(0);\n const [creating, setCreating] = React.useState(false);\n const [createBusy, setCreateBusy] = React.useState(false);\n const [createError, setCreateError] = React.useState<string | null>(null);\n const listId = React.useId();\n\n React.useEffect(() => {\n const t = window.setTimeout(() => setQuery(q.trim()), q.trim() ? 180 : 0);\n return () => window.clearTimeout(t);\n }, [q]);\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!searchReferences) return;\n const ctrl = new AbortController();\n setLoading(true);\n searchReferences({ to, filter, q: query, limit: PAGE, excludeId: env.docId, signal: ctrl.signal })\n .then((r) => {\n if (ctrl.signal.aborted) return;\n setRows(r.options.filter((o) => o.id !== env.docId));\n setTruncated(r.truncated);\n setError(null);\n setActive(0);\n })\n .catch((e: unknown) => !ctrl.signal.aborted && setError(reasonOf(e)))\n .finally(() => !ctrl.signal.aborted && setLoading(false));\n return () => ctrl.abort();\n }, [query, toKey, filter, env.docId, searchReferences]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const none = onNone && !q;\n const total = rows.length + (none ? 1 : 0);\n const at = (i: number) => (none ? (i === 0 ? null : rows[i - 1]) : rows[i]);\n const full = multi && max != null && selected.length >= max;\n const choose = (i: number) => {\n const o = at(i);\n if (o) onPick(o);\n else if (none) onNone!();\n };\n const optionId = (i: number) => `${listId}-${i}`;\n const create = async (title: string) => {\n if (!createReference) return;\n setCreateBusy(true);\n setCreateError(null);\n try {\n const o = await createReference({ to: to[0], title });\n setCreating(false);\n onCreated(o);\n } catch (e) {\n setCreateError(`Not created: ${reasonOf(e)}`);\n } finally {\n setCreateBusy(false);\n }\n };\n // V2's search copy: \"pages\" for a page picker, \"entries\" for every other one\n const searchLabel = `Search ${noun === \"page\" ? \"pages\" : \"entries\"}`;\n return (\n <div className=\"flex flex-col\">\n <label className=\"flex h-10 items-center gap-2 border-b border-kit-line px-3 text-kit-fg-3\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n value={q}\n onChange={(e) => {\n setQ(e.target.value);\n setActive(0);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(total - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n setActive(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n setActive(Math.max(0, total - 1));\n } else if (e.key === \"Enter\" && total) {\n e.preventDefault();\n choose(Math.min(active, total - 1));\n }\n }}\n placeholder={`${searchLabel}…`}\n role=\"combobox\"\n aria-expanded\n aria-autocomplete=\"list\"\n aria-controls={listId}\n aria-activedescendant={total ? optionId(Math.min(active, total - 1)) : undefined}\n aria-label={searchLabel}\n className=\"h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n </label>\n <div id={listId} className=\"max-h-72 overflow-y-auto p-1\" role=\"listbox\" aria-label={`${noun} results`} aria-multiselectable={multi || undefined} aria-busy={loading || undefined}>\n {none ? (\n <button\n type=\"button\"\n id={optionId(0)}\n role=\"option\"\n aria-selected={false}\n tabIndex={-1}\n onMouseEnter={() => setActive(0)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onNone}\n className={cn(\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-3 hover:bg-kit-hover\", active === 0 && \"bg-kit-hover\")}\n >\n None\n </button>\n ) : null}\n {rows.map((o, j) => {\n const i = j + (none ? 1 : 0);\n const on = selected.includes(o.id);\n return (\n <button\n type=\"button\"\n key={`${o.kind}:${o.id}`}\n id={optionId(i)}\n role=\"option\"\n aria-selected={on}\n tabIndex={-1}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(o)}\n className={cn(\"flex w-full items-center gap-2.5 rounded-kit-md p-1.5 text-left\", i === active && \"bg-kit-hover\")}\n >\n {multi ? (\n <span aria-hidden className={cn(\"flex size-4 shrink-0 items-center justify-center rounded-kit-md border\", on ? \"border-kit-accent bg-kit-accent text-kit-accent-on\" : \"border-kit-line-strong\", !on && full && \"opacity-40\")}>\n {on ? <IconCheck className=\"size-3\" stroke={3} /> : null}\n </span>\n ) : null}\n <RefThumb o={o} size={28} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-kit-sm text-kit-fg\">{o.title}</span>\n {o.subtitle ? <span className=\"block truncate text-kit-xs text-kit-fg-3\">{o.subtitle}</span> : null}\n </span>\n <DraftChip status={o.status} />\n {!multi && on ? <IconCheck className=\"size-4 shrink-0 text-kit-fg\" stroke={2} aria-hidden /> : null}\n </button>\n );\n })}\n {!loading && !error && rows.length === 0 ? <div className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">No matches</div> : null}\n {loading && rows.length === 0 ? (\n <div role=\"status\" className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">\n Searching…\n </div>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"px-3 py-3 text-kit-xs text-kit-danger-fg\">\n {plural(noun).replace(/^./, (c) => c.toUpperCase())} could not be listed: {error}\n </p>\n ) : null}\n </div>\n {truncated && !error ? (\n <p role=\"note\" className=\"border-t border-kit-line px-3 py-2 text-kit-xs text-kit-warning-fg\">\n Some {plural(noun)} were not checked against this field's filter, so the list may be incomplete. Search by name to narrow it.\n </p>\n ) : null}\n {multi ? (\n <div className={cn(\"border-t border-kit-line px-3 py-2 text-kit-xs\", full ? \"text-kit-warning-fg\" : \"text-kit-fg-3\")}>\n {selected.length}\n {max != null ? ` of ${max}` : \"\"} selected{full ? ` · Limit is ${max}. Picking another swaps out the last one.` : \"\"}\n </div>\n ) : null}\n {canCreate ? (\n <div className=\"border-t border-kit-line p-1.5\">\n {creating ? (\n <>\n <form\n className=\"flex items-center gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const t = String(new FormData(e.currentTarget).get(\"t\") ?? \"\").trim();\n if (t) void create(t);\n }}\n >\n <input\n name=\"t\"\n autoFocus\n defaultValue={q}\n aria-label={`New ${noun} name`}\n placeholder={`New ${noun} name`}\n className=\"h-8 min-w-0 flex-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none focus:bg-kit-field-bg focus:ring-1 focus:ring-kit-line-strong\"\n />\n <Button size=\"sm\" type=\"submit\" variant=\"primary\" loading={createBusy} disabled={createBusy}>\n Create\n </Button>\n </form>\n {createError ? (\n <p role=\"alert\" className=\"mt-1.5 px-1 text-kit-xs text-kit-danger-fg\">\n {createError}\n </p>\n ) : null}\n </>\n ) : (\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\n className=\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconPlus className=\"size-4\" stroke={1.5} aria-hidden />\n Create new {noun}\n {q ? <span className=\"truncate text-kit-fg-3\">“{q}”</span> : null}\n </button>\n )}\n </div>\n ) : null}\n </div>\n );\n}\n\n/** \"Create new\" only where the host can create a draft in the ONE entry model the field targets. */\nfunction useCanCreate(to: string[]) {\n const { createReference } = useKitServices();\n return !!createReference && to.length === 1 && isEntryTarget(to[0]);\n}\n\n/** Why the field cannot change its value here (no search service), in words. */\nfunction NoSearch({ title }: { title: string }) {\n return (\n <p role=\"note\" className=\"text-kit-xs text-kit-fg-3\">\n No reference search is connected to this editor, so {title} can't be changed here.\n </p>\n );\n}\n\n/* ── Single reference ──────────────────────────────────────────────── */\nexport function ReferenceControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const env = useKitEnv();\n const { searchReferences, toast } = useKitServices();\n const to = targetsOf(field);\n const noun = referenceNoun(to);\n const current = typeof value === \"string\" && value ? value : null;\n const ids = React.useMemo(() => (current ? [current] : []), [current]);\n const rec = useReferenceRecords(ids, to);\n const canCreate = useCanCreate(to) && !readOnly;\n const [open, setOpen] = React.useState(false);\n const pick = (o: KitReferenceOption) => {\n rec.remember(o);\n onChange(o.id);\n setOpen(false);\n };\n /* the trigger opens like V2's even with no search service; the popover then says why nothing can be picked */\n const editable = !readOnly;\n const body = !editable ? null : !searchReferences ? (\n <PopoverContent className=\"w-[300px] p-3\" align=\"start\" collisionAvoidance={SHIFT}>\n <NoSearch title={field.title} />\n </PopoverContent>\n ) : (\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n <PickerBody\n to={to}\n filter={field.reference?.filter}\n selected={current ? [current] : []}\n noun={noun}\n onPick={pick}\n onNone={\n current\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n canCreate={canCreate}\n onCreated={(o) => {\n pick(o);\n toast?.success(`${noun.replace(/^./, (c) => c.toUpperCase())} created as a draft`, { description: `“${o.title}”` });\n }}\n />\n </PopoverContent>\n );\n\n const missing = !!current && rec.missing.has(current);\n if (current && !missing) {\n const o = rec.known[current];\n const title = o?.title ?? (rec.loading ? \"Loading…\" : current);\n const subtitle = o ? o.subtitle : rec.error ?? (!rec.canLookup ? `Saved ${noun} id` : null);\n const openable = !!o && o.kind === \"entry\" && !!o.modelSlug && !!env.onOpenReference;\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <div data-slot=\"kit-reference-card\" className=\"group/ref flex items-center gap-2.5 rounded-kit-lg border border-kit-line bg-kit-control-bg p-1.5 pr-1 transition-colors hover:border-kit-line-strong\">\n <PopoverTrigger\n id={id}\n disabled={!editable}\n aria-label={`${field.title}: ${title}.${editable ? \" Change\" : \"\"}`}\n className=\"flex min-w-0 flex-1 items-center gap-2.5 text-left\"\n >\n <RefThumb o={o ?? null} size={32} />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate text-kit-sm font-medium text-kit-fg\", !o && !rec.canLookup && \"font-kit-mono text-kit-xs\")}>{title}</span>\n {subtitle ? <span className={cn(\"block truncate text-kit-xs\", rec.error && !o ? \"text-kit-danger-fg\" : \"text-kit-fg-3\")}>{subtitle}</span> : null}\n </span>\n <DraftChip status={o?.status} />\n </PopoverTrigger>\n {readOnly ? null : (\n <Menu>\n <MenuTrigger\n aria-label={`${o?.title ?? field.title} actions`}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover\"\n >\n <IconDots className=\"size-4\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n <MenuContent align=\"end\" className=\"w-48\">\n {openable ? (\n <MenuItem icon={<IconArrowUpRight stroke={1.5} />} onClick={() => env.onOpenReference!({ collectionId: o!.modelSlug!, entryId: o!.id, title: o!.title })}>\n Open {o!.title.length > 18 ? `${o!.title.slice(0, 16)}…` : o!.title}\n </MenuItem>\n ) : null}\n {editable ? (\n <MenuItem icon={<IconReplace stroke={1.5} />} onClick={() => window.setTimeout(() => setOpen(true), 0)}>\n Replace\n </MenuItem>\n ) : null}\n {openable || editable ? <MenuSeparator /> : null}\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => onChange(null)}>\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n )}\n </div>\n {body}\n </Popover>\n );\n }\n /* empty, or a saved id the lookup cannot find: V2's select trigger (V2 draws an unresolved id as no selection). Ours\n says \"Missing\" on it instead of hiding the saved id (DESIGN 9.6); the picker's None clears it, a row replaces it. */\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n id={id}\n disabled={!editable}\n data-slot={missing ? \"kit-reference-card\" : undefined}\n data-missing={missing || undefined}\n aria-label={missing ? `${field.title}: Missing ${noun}.${editable ? \" Change\" : \"\"}` : `${field.title}: select ${withArticle(noun)}`}\n className={cn(\n \"flex h-8 w-full items-center gap-2 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2.5 text-left text-kit-sm text-kit-fg-3 transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg\",\n missing && \"border-kit-warning-line text-kit-warning-fg hover:border-kit-warning-line data-[popup-open]:border-kit-warning-line\",\n )}\n >\n <IconFileDatabase className=\"size-4\" stroke={1.5} aria-hidden />\n {missing ? (\n <span className=\"flex-1 truncate\">\n Missing {noun}\n <span className=\"sr-only\">. Deleted, or not visible to you. The saved id stays until you replace or remove it.</span>\n </span>\n ) : (\n <span className=\"flex-1 truncate\">Select {withArticle(noun)}</span>\n )}\n <IconChevronDown className=\"size-3.5\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n {body}\n </Popover>\n );\n}\n\n/* ── Multi-reference: an array of ids ─────────────────────────────── */\nfunction RefChip({\n id,\n o,\n canLookup,\n readOnly,\n sort,\n onRemove,\n}: {\n id: string;\n o?: KitReferenceOption;\n /** false: no lookup service, so the saved id is all there is to show (never a \"Loading…\" that never ends) */\n canLookup: boolean;\n readOnly?: boolean;\n sort: ReturnType<typeof useDragReorder>;\n onRemove: () => void;\n}) {\n const handle = sort.handle(id);\n const register = sort.register(id);\n const title = o?.title ?? (canLookup ? \"Loading…\" : id);\n /* V2: the chip itself is the sortable item (thumb, title and remove button inside it) */\n return (\n <span\n {...(readOnly ? {} : handle)}\n ref={(el: HTMLElement | null) => {\n register(el);\n if (!readOnly) handle.ref(el);\n }}\n style={sort.style(id)}\n tabIndex={0}\n role=\"group\"\n aria-roledescription=\"sortable item\"\n aria-label={readOnly ? title : `${title}, drag to reorder`}\n onKeyDown={(e) => {\n // keys on the remove button are the button's own\n if (readOnly || e.target !== e.currentTarget) return;\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n e.preventDefault();\n onRemove();\n return;\n }\n handle.onKeyDown(e);\n }}\n className={cn(\n \"inline-flex h-6 max-w-full cursor-grab touch-none items-center gap-1.5 rounded-kit-md border border-kit-line bg-kit-control-bg pl-0.5 pr-1 text-kit-sm text-kit-fg shadow-kit-xs active:cursor-grabbing\",\n sort.active === id && \"z-10 shadow-kit-md\",\n )}\n >\n <RefThumb o={o ?? null} size={20} />\n <span className=\"truncate\">{title}</span>\n {readOnly ? null : (\n <button type=\"button\" aria-label={`Remove ${title}`} onPointerDown={(e) => e.stopPropagation()} onClick={onRemove} className=\"flex rounded-kit-md p-0.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n );\n}\n\n/** Multi-reference: an array of reference ids. `field` is the ARRAY field; the engine hands it the item's `reference`. */\nexport function ReferencesControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const { searchReferences } = useKitServices();\n const item = Array.isArray(field.of) ? field.of[0] : undefined;\n const to = item?.reference?.to ?? field.reference?.to ?? [];\n const filter = item?.reference?.filter ?? field.reference?.filter;\n const noun = referenceNoun(to);\n const ids = React.useMemo(() => (Array.isArray(value) ? value : []).filter((x): x is string => typeof x === \"string\" && x !== \"\"), [value]);\n const rec = useReferenceRecords(ids, to);\n const canCreate = useCanCreate(to) && !readOnly;\n const max = field.validation?.max;\n /* ids the lookup cannot find are drawn as ONE compact \"n missing\" chip after Add (V2 hides them; one row keeps V2's height),\n so the chips that sort are the rest; a reorder puts them back around the missing ids, which keep their places */\n const missingIds = ids.filter((x) => rec.missing.has(x));\n const shown = missingIds.length ? ids.filter((x) => !rec.missing.has(x)) : ids;\n const sort = useDragReorder(\n shown,\n (from, to2) => {\n const next = [...shown];\n const [moved] = next.splice(from, 1);\n next.splice(to2, 0, moved);\n let i = 0;\n onChange(ids.map((x) => (rec.missing.has(x) ? x : next[i++])));\n },\n { axis: \"grid\", disabled: readOnly },\n );\n const missingNoun = missingIds.length === 1 ? noun : plural(noun);\n const toggle = (o: KitReferenceOption) => {\n rec.remember(o);\n if (ids.includes(o.id)) return onChange(ids.filter((x) => x !== o.id));\n if (max != null && ids.length >= max) return onChange([...ids.slice(0, -1), o.id]); // swap in place at the limit\n onChange([...ids, o.id]);\n };\n return (\n <div className=\"flex flex-col gap-1\">\n {/* the field label points at the Add trigger; read-only there is none, so the box carries the id. The chips sit\n straight in the wrapping box, as V2's do (a wrapper would take them out of the box's flow). V2's box has no\n role or name while editing; read-only (no Add to label) it is named as a group. */}\n <div\n id={readOnly ? id : undefined}\n role={readOnly ? \"group\" : undefined}\n aria-label={readOnly ? field.title : undefined}\n className=\"flex min-h-8 flex-wrap items-center gap-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg p-1 transition-colors hover:border-kit-line-strong\"\n >\n {shown.map((x) => (\n <RefChip key={x} id={x} o={rec.known[x]} canLookup={rec.canLookup} readOnly={readOnly} sort={sort} onRemove={() => onChange(ids.filter((y) => y !== x))} />\n ))}\n {sort.a11y}\n {!readOnly ? (\n <Popover>\n <PopoverTrigger id={id} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md px-1.5 text-kit-sm text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconPlus className=\"size-3.5\" stroke={1.5} aria-hidden />\n Add\n </PopoverTrigger>\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n {/* no search service: the picker says why instead of listing anything */}\n {!searchReferences ? (\n <div className=\"p-3\">\n <NoSearch title={field.title} />\n </div>\n ) : (\n <PickerBody\n to={to}\n filter={filter}\n selected={ids}\n multi\n max={max}\n noun={noun}\n onPick={toggle}\n canCreate={canCreate}\n onCreated={(o) => {\n rec.remember(o);\n onChange(max != null && ids.length >= max ? [...ids.slice(0, -1), o.id] : [...ids, o.id]);\n }}\n />\n )}\n </PopoverContent>\n </Popover>\n ) : ids.length === 0 ? (\n <span className=\"px-1.5 text-kit-sm text-kit-fg-3\">None</span>\n ) : null}\n {/* after Add, so Add keeps V2's place (V2 draws nothing for these ids) */}\n {missingIds.length ? (\n <span\n data-missing\n data-slot=\"kit-reference-missing\"\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-kit-md border border-kit-warning-line bg-kit-control-bg pl-1.5 pr-1 text-kit-sm text-kit-warning-fg shadow-kit-xs\"\n >\n <span className=\"truncate tabular-nums\">\n {missingIds.length} missing\n <span className=\"sr-only\">\n {\" \"}\n {missingNoun}. Deleted, or not visible to you. The saved {missingIds.length === 1 ? \"id stays\" : \"ids stay\"} until you remove {missingIds.length === 1 ? \"it\" : \"them\"}.\n </span>\n </span>\n {readOnly ? null : (\n <button\n type=\"button\"\n aria-label={`Remove ${missingIds.length} missing ${missingNoun}`}\n onClick={() => onChange(ids.filter((y) => !rec.missing.has(y)))}\n className=\"flex rounded-kit-sm p-0.5 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n ) : null}\n </div>\n {rec.error ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {rec.error}\n </p>\n ) : null}\n {max != null ? (\n <span className=\"tabular-nums self-end text-kit-xs text-kit-fg-3\">\n {ids.length} / {max}\n </span>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reference.js","names":[],"sources":["../../src/controls/reference.tsx"],"sourcesContent":["/**\n * REFERENCE — single: a select-like trigger (\"Select a CMS item\") → a 300px search popover with \"None\", result rows,\n * drafts labelled, and \"Create new\" inline when the host can create. Never lists the document being edited. No one-click\n * clear (⋯ → Remove). MULTI-REFERENCE — reorderable chips + \"+ Add\", \"n / max\"; at the limit the picker swaps in place.\n * (V2 HEAD 9829bf1 kit/controls/reference.tsx, DESIGN.md 6.8, 8.16, 9.6.)\n *\n * The rows come from the host (reference-services.ts): `searchReferences` is POST /content/reference-options, which\n * already applies the field's `reference.filter` and scope; `truncated` says its filter scan stopped early, and the\n * picker says so. The stored value is the target id (\"en_12\"; a list for many), exactly V2's shape.\n *\n * Kit deviations from V2: no seed rows (every row is a real record from the service); matching is the server's title /\n * slug search, so rows keep the server's order; a stored id the lookup cannot find shows as a \"Missing\" card, or in a\n * multi list one compact \"n missing\" chip with Remove (DESIGN 9.6's production rule), instead of disappearing; chips sort with the engine's `useDragReorder`\n * (@dnd-kit is not on the kit allow-list).\n */\nimport * as React from \"react\";\nimport { IconArrowUpRight, IconCheck, IconChevronDown, IconDatabase, IconDots, IconFileDatabase, IconFileText, IconForms, IconPlus, IconReplace, IconSearch, IconShoppingBag, IconTrash, IconX } from \"@tabler/icons-react\";\nimport type { KitReferenceCreateCapability, KitReferenceKind, KitReferenceOption } from \"./reference-services\";\nimport { Button } from \"../ui/button\";\nimport { Avatar } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { cn } from \"../lib/cn\";\nimport { useDragReorder } from \"../engine/item-list\";\nimport { useKitEnv, useKitServices } from \"../context\";\nimport type { ControlProps } from \"../types\";\n\nconst NON_ENTRY = new Set([\"page\", \"form\", \"collection\", \"shopify\"]);\nconst isEntryTarget = (t: string) => !NON_ENTRY.has(t);\nconst targetsOf = (field: ControlProps[\"field\"]) => field.reference?.to ?? [];\n\n/** The noun the picker uses: the field's own (`reference.noun`), else D48's (\"CMS item\" where V2 says \"entry\"). */\nexport function referenceNoun(to: string[], noun?: string): string {\n if (noun) return noun;\n if (to.length === 1) return to[0] === \"page\" ? \"page\" : to[0] === \"form\" ? \"form\" : to[0] === \"collection\" ? \"collection\" : to[0] === \"shopify\" ? \"product\" : \"CMS item\";\n return to.length && to.every(isEntryTarget) ? \"CMS item\" : \"item\";\n}\nconst plural = (noun: string) => (noun === \"CMS item\" ? \"CMS items\" : `${noun}s`);\nconst withArticle = (noun: string) => `${/^[aeiou]/i.test(noun) ? \"an\" : \"a\"} ${noun}`;\nconst reasonOf = (e: unknown) => (e instanceof Error ? e.message : String(e));\nconst PAGE = 25;\n/** V2 (Radix) slides a picker that would overflow along the edge, keeping it over the panel; Base UI would flip it to\n * end-aligned, which hangs it left over the preview */\nconst SHIFT = { align: \"shift\" } as const;\n\nconst KIND_ICON: Record<KitReferenceKind, React.ComponentType<{ className?: string; stroke?: number }>> = {\n entry: IconFileDatabase,\n page: IconFileText,\n form: IconForms,\n collection: IconDatabase,\n shopify: IconShoppingBag,\n};\n\nexport function RefThumb({ o, size = 28 }: { o: Pick<KitReferenceOption, \"kind\" | \"title\" | \"photo\" | \"avatar\" | \"cover\"> | null; size?: number }) {\n // V2 reference.tsx:152-156: a person is their round avatar (initials without a photo), a record with a cover its image\n if (o?.avatar || o?.photo) return <Avatar name={o.title} src={o.photo ?? undefined} size={size} decorative />;\n if (o?.cover) return <img src={o.cover} alt=\"\" style={{ width: size, height: size }} className=\"shrink-0 rounded-kit-md border border-kit-line object-cover\" />;\n const Icon = o ? KIND_ICON[o.kind] : IconFileDatabase;\n return (\n <span aria-hidden style={{ width: size, height: size }} className=\"flex shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-subtle text-kit-fg-3\">\n <Icon className={size > 24 ? \"size-4\" : \"size-3.5\"} stroke={1.5} />\n </span>\n );\n}\n\nfunction DraftChip({ status, missingRequired }: { status?: string | null; missingRequired?: number }) {\n if (status !== \"draft\") return null;\n const n = missingRequired ?? 0;\n return (\n <span className=\"shrink-0 rounded-kit-md bg-kit-muted px-1 text-kit-2xs text-kit-fg-3\">\n Draft{n > 0 ? ` · ${n} required field${n === 1 ? \"\" : \"s\"} empty` : \"\"}\n </span>\n );\n}\n\n/* ── Lookup: stored ids → their records ────────────────────────────── */\n/**\n * The records behind `ids`, read once per id through `lookupReferences`. An id the service does not hand back is\n * `missing`; a failed read is `error` (in words). A row picked in the picker is `remember`ed, so it shows at once.\n */\nexport function useReferenceRecords(ids: string[], to: string[]) {\n const { lookupReferences } = useKitServices();\n const [known, setKnown] = React.useState<Record<string, KitReferenceOption>>({});\n const [missing, setMissing] = React.useState<ReadonlySet<string>>(new Set());\n const [error, setError] = React.useState<string | null>(null);\n const inflight = React.useRef(new Set<string>());\n const alive = React.useRef(true);\n // set on every mount: StrictMode mounts, unmounts and mounts again, and a flag only cleared would drop every read\n React.useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n const idsKey = ids.join(\"|\");\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!lookupReferences) return;\n const asked = ids.filter((x) => !known[x] && !missing.has(x) && !inflight.current.has(x));\n if (!asked.length) return;\n for (const x of asked) inflight.current.add(x);\n lookupReferences(asked, to)\n .then((rows) => {\n if (!alive.current) return;\n const found = new Set(rows.map((r) => r.id));\n setKnown((k) => ({ ...k, ...Object.fromEntries(rows.map((r) => [r.id, r])) }));\n setMissing((m) => new Set([...m, ...asked.filter((x) => !found.has(x))]));\n setError(null);\n })\n .catch((e: unknown) => alive.current && setError(`The saved ${plural(referenceNoun(to))} could not be read: ${reasonOf(e)}`))\n .finally(() => {\n for (const x of asked) inflight.current.delete(x);\n });\n }, [idsKey, toKey, lookupReferences, known, missing]); // eslint-disable-line react-hooks/exhaustive-deps\n const remember = React.useCallback((o: KitReferenceOption) => {\n setKnown((k) => ({ ...k, [o.id]: o }));\n setMissing((m) => (m.has(o.id) ? new Set([...m].filter((x) => x !== o.id)) : m));\n }, []);\n return { known, missing, loading: !!lookupReferences && ids.some((x) => !known[x] && !missing.has(x)) && !error, error, remember, canLookup: !!lookupReferences };\n}\n\n/* ── The search popover body, shared by single and multi ───────────── */\nfunction PickerBody({\n to,\n filter,\n selected,\n multi,\n max,\n noun,\n onPick,\n onNone,\n canCreate,\n noCreateWhy,\n onCreated,\n excludeId,\n}: {\n to: string[];\n filter?: string;\n /** a record never listed besides the document being edited (the field's `reference.excludeId`) */\n excludeId?: string;\n selected: string[];\n multi?: boolean;\n max?: number;\n noun: string;\n onPick: (o: KitReferenceOption) => void;\n onNone?: () => void;\n canCreate: boolean;\n /** why \"Create new\" isn't offered here, for the empty state (useCreate) */\n noCreateWhy?: string;\n onCreated: (o: KitReferenceOption) => void;\n}) {\n const { searchReferences, createReference, toast } = useKitServices();\n const env = useKitEnv();\n const [q, setQ] = React.useState(\"\");\n const [query, setQuery] = React.useState(\"\");\n const [rows, setRows] = React.useState<KitReferenceOption[]>([]);\n const [truncated, setTruncated] = React.useState(false);\n const [loading, setLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n const [active, setActive] = React.useState(0);\n const [creating, setCreating] = React.useState(false);\n const [createBusy, setCreateBusy] = React.useState(false);\n const [createError, setCreateError] = React.useState<string | null>(null);\n const listId = React.useId();\n\n React.useEffect(() => {\n const t = window.setTimeout(() => setQuery(q.trim()), q.trim() ? 180 : 0);\n return () => window.clearTimeout(t);\n }, [q]);\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!searchReferences) return;\n const ctrl = new AbortController();\n setLoading(true);\n searchReferences({ to, filter, q: query, limit: PAGE, excludeId: excludeId ?? env.docId, signal: ctrl.signal })\n .then((r) => {\n if (ctrl.signal.aborted) return;\n setRows(r.options.filter((o) => o.id !== env.docId && o.id !== excludeId));\n setTruncated(r.truncated);\n setError(null);\n setActive(0);\n })\n .catch((e: unknown) => !ctrl.signal.aborted && setError(reasonOf(e)))\n .finally(() => !ctrl.signal.aborted && setLoading(false));\n return () => ctrl.abort();\n }, [query, toKey, filter, env.docId, excludeId, searchReferences]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const none = onNone && !q;\n const total = rows.length + (none ? 1 : 0);\n const at = (i: number) => (none ? (i === 0 ? null : rows[i - 1]) : rows[i]);\n const full = multi && max != null && selected.length >= max;\n const choose = (i: number) => {\n const o = at(i);\n if (o) onPick(o);\n else if (none) onNone!();\n };\n const optionId = (i: number) => `${listId}-${i}`;\n // one create at a time: a second Enter or click while the first is out is the same request, not another draft\n const createOut = React.useRef(false);\n const create = async (title: string) => {\n if (!createReference || createOut.current) return;\n createOut.current = true;\n setCreateBusy(true);\n setCreateError(null);\n try {\n const o = await createReference({ to: to[0], title });\n setCreating(false);\n onCreated(o);\n const open =\n o.kind === \"entry\" && o.modelSlug && env.onOpenReference\n ? { label: \"Open\", onClick: () => env.onOpenReference!({ collectionId: o.modelSlug!, entryId: o.id, title: o.title }) }\n : undefined;\n toast?.success(o.created === false ? `Using existing ‘${o.title}’` : `Created ‘${o.title}’ as a draft`, open ? { action: open } : undefined);\n } catch (e) {\n setCreateError(`Not created: ${reasonOf(e)}`);\n } finally {\n createOut.current = false;\n setCreateBusy(false);\n }\n };\n // V2's search copy: \"pages\" for a page picker, \"entries\" for every other one\n const searchLabel = `Search ${noun === \"page\" ? \"pages\" : \"entries\"}`;\n return (\n <div className=\"flex flex-col\">\n <label className=\"flex h-10 items-center gap-2 border-b border-kit-line px-3 text-kit-fg-3\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n value={q}\n onChange={(e) => {\n setQ(e.target.value);\n setActive(0);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(total - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n setActive(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n setActive(Math.max(0, total - 1));\n } else if (e.key === \"Enter\" && total) {\n e.preventDefault();\n choose(Math.min(active, total - 1));\n }\n }}\n placeholder={`${searchLabel}…`}\n role=\"combobox\"\n aria-expanded\n aria-autocomplete=\"list\"\n aria-controls={listId}\n aria-activedescendant={total ? optionId(Math.min(active, total - 1)) : undefined}\n aria-label={searchLabel}\n className=\"h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n </label>\n <div id={listId} className=\"max-h-72 overflow-y-auto p-1\" role=\"listbox\" aria-label={`${noun} results`} aria-multiselectable={multi || undefined} aria-busy={loading || undefined}>\n {none ? (\n <button\n type=\"button\"\n id={optionId(0)}\n role=\"option\"\n aria-selected={false}\n tabIndex={-1}\n onMouseEnter={() => setActive(0)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onNone}\n className={cn(\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-3 hover:bg-kit-hover\", active === 0 && \"bg-kit-hover\")}\n >\n None\n </button>\n ) : null}\n {rows.map((o, j) => {\n const i = j + (none ? 1 : 0);\n const on = selected.includes(o.id);\n return (\n <button\n type=\"button\"\n key={`${o.kind}:${o.id}`}\n id={optionId(i)}\n role=\"option\"\n aria-selected={on}\n tabIndex={-1}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(o)}\n className={cn(\"flex w-full items-center gap-2.5 rounded-kit-md p-1.5 text-left\", i === active && \"bg-kit-hover\")}\n >\n {multi ? (\n <span aria-hidden className={cn(\"flex size-4 shrink-0 items-center justify-center rounded-kit-md border\", on ? \"border-kit-accent bg-kit-accent text-kit-accent-on\" : \"border-kit-line-strong\", !on && full && \"opacity-40\")}>\n {on ? <IconCheck className=\"size-3\" stroke={3} /> : null}\n </span>\n ) : null}\n <RefThumb o={o} size={28} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-kit-sm text-kit-fg\">{o.title}</span>\n {o.subtitle ? <span className=\"block truncate text-kit-xs text-kit-fg-3\">{o.subtitle}</span> : null}\n </span>\n <DraftChip status={o.status} missingRequired={o.missingRequired} />\n {!multi && on ? <IconCheck className=\"size-4 shrink-0 text-kit-fg\" stroke={2} aria-hidden /> : null}\n </button>\n );\n })}\n {!loading && !error && rows.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">\n No matches\n {noCreateWhy ? (\n <p role=\"note\" className=\"mt-1 text-kit-xs\">\n {noCreateWhy}\n </p>\n ) : null}\n </div>\n ) : null}\n {loading && rows.length === 0 ? (\n <div role=\"status\" className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">\n Searching…\n </div>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"px-3 py-3 text-kit-xs text-kit-danger-fg\">\n {plural(noun).replace(/^./, (c) => c.toUpperCase())} could not be listed: {error}\n </p>\n ) : null}\n </div>\n {truncated && !error ? (\n <p role=\"note\" className=\"border-t border-kit-line px-3 py-2 text-kit-xs text-kit-warning-fg\">\n Some {plural(noun)} were not checked against this field's filter, so the list may be incomplete. Search by name to narrow it.\n </p>\n ) : null}\n {multi ? (\n <div className={cn(\"border-t border-kit-line px-3 py-2 text-kit-xs\", full ? \"text-kit-warning-fg\" : \"text-kit-fg-3\")}>\n {selected.length}\n {max != null ? ` of ${max}` : \"\"} selected{full ? ` · Limit is ${max}. Picking another swaps out the last one.` : \"\"}\n </div>\n ) : null}\n {canCreate ? (\n <div className=\"border-t border-kit-line p-1.5\">\n {creating ? (\n <>\n <form\n className=\"flex items-center gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const t = String(new FormData(e.currentTarget).get(\"t\") ?? \"\").trim();\n if (t) void create(t);\n }}\n >\n <input\n name=\"t\"\n autoFocus\n defaultValue={q}\n aria-label={`New ${noun} name`}\n placeholder={`New ${noun} name`}\n className=\"h-8 min-w-0 flex-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none focus:bg-kit-field-bg focus:ring-1 focus:ring-kit-line-strong\"\n />\n <Button size=\"sm\" type=\"submit\" variant=\"primary\" loading={createBusy} disabled={createBusy}>\n Create\n </Button>\n </form>\n {createError ? (\n <p role=\"alert\" className=\"mt-1.5 px-1 text-kit-xs text-kit-danger-fg\">\n {createError}\n </p>\n ) : null}\n </>\n ) : (\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\n className=\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconPlus className=\"size-4\" stroke={1.5} aria-hidden />\n Create new {noun}\n {q ? <span className=\"truncate text-kit-fg-3\">“{q}”</span> : null}\n </button>\n )}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst noCapability = (_to: string | null): KitReferenceCreateCapability | undefined => undefined;\n\n/**\n * \"Create new\" only where the host can create a draft in the ONE entry model the field targets, and, when the host\n * answers per target (useReferenceCreate), only where that model takes one. Otherwise `why`, for the empty state:\n * the target's own refusal, else the host's createDisabledReason. A capability not known yet shows neither.\n */\nfunction useCreate(to: string[]): { can: boolean; why?: string } {\n const { createReference, createDisabledReason, useReferenceCreate } = useKitServices();\n const one = to.length === 1 && isEntryTarget(to[0]) ? to[0] : null;\n const useCapability = useReferenceCreate ?? noCapability;\n const cap = useCapability(one);\n if (!one) return { can: false };\n if (useReferenceCreate) {\n if (!cap) return { can: false };\n if (!cap.ok) return { can: false, why: cap.reason };\n }\n return createReference ? { can: true } : { can: false, why: createDisabledReason };\n}\n\n/** Why the field cannot change its value here (no search service), in words. */\nfunction NoSearch({ title }: { title: string }) {\n return (\n <p role=\"note\" className=\"text-kit-xs text-kit-fg-3\">\n No reference search is connected to this editor, so {title} can't be changed here.\n </p>\n );\n}\n\n/* ── Single reference ──────────────────────────────────────────────── */\nexport function ReferenceControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const env = useKitEnv();\n const { searchReferences } = useKitServices();\n const to = targetsOf(field);\n const noun = referenceNoun(to, field.reference?.noun);\n const current = typeof value === \"string\" && value ? value : null;\n const ids = React.useMemo(() => (current ? [current] : []), [current]);\n const rec = useReferenceRecords(ids, to);\n const createState = useCreate(to);\n const canCreate = createState.can && !readOnly;\n const [open, setOpen] = React.useState(false);\n const pick = (o: KitReferenceOption) => {\n rec.remember(o);\n onChange(o.id);\n setOpen(false);\n };\n /* the trigger opens like V2's even with no search service; the popover then says why nothing can be picked */\n const editable = !readOnly;\n const body = !editable ? null : !searchReferences ? (\n <PopoverContent className=\"w-[300px] p-3\" align=\"start\" collisionAvoidance={SHIFT}>\n <NoSearch title={field.title} />\n </PopoverContent>\n ) : (\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n <PickerBody\n to={to}\n filter={field.reference?.filter}\n excludeId={field.reference?.excludeId}\n selected={current ? [current] : []}\n noun={noun}\n onPick={pick}\n onNone={\n current\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n canCreate={canCreate}\n noCreateWhy={createState.why}\n onCreated={pick}\n />\n </PopoverContent>\n );\n\n const missing = !!current && rec.missing.has(current);\n if (current && !missing) {\n const o = rec.known[current];\n const title = o?.title ?? (rec.loading ? \"Loading…\" : current);\n const subtitle = o ? o.subtitle : rec.error ?? (!rec.canLookup ? `Saved ${noun} id` : null);\n const openable = !!o && o.kind === \"entry\" && !!o.modelSlug && !!env.onOpenReference;\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <div data-slot=\"kit-reference-card\" className=\"group/ref flex items-center gap-2.5 rounded-kit-lg border border-kit-line bg-kit-control-bg p-1.5 pr-1 transition-colors hover:border-kit-line-strong\">\n <PopoverTrigger\n id={id}\n disabled={!editable}\n aria-label={`${field.title}: ${title}.${editable ? \" Change\" : \"\"}`}\n className=\"flex min-w-0 flex-1 items-center gap-2.5 text-left\"\n >\n <RefThumb o={o ?? null} size={32} />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate text-kit-sm font-medium text-kit-fg\", !o && !rec.canLookup && \"font-kit-mono text-kit-xs\")}>{title}</span>\n {subtitle ? <span className={cn(\"block truncate text-kit-xs\", rec.error && !o ? \"text-kit-danger-fg\" : \"text-kit-fg-3\")}>{subtitle}</span> : null}\n </span>\n <DraftChip status={o?.status} missingRequired={o?.missingRequired} />\n </PopoverTrigger>\n {readOnly ? null : (\n <Menu>\n <MenuTrigger\n aria-label={`${o?.title ?? field.title} actions`}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover\"\n >\n <IconDots className=\"size-4\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n <MenuContent align=\"end\" className=\"w-48\">\n {openable ? (\n <MenuItem icon={<IconArrowUpRight stroke={1.5} />} onClick={() => env.onOpenReference!({ collectionId: o!.modelSlug!, entryId: o!.id, title: o!.title })}>\n Open {o!.title.length > 18 ? `${o!.title.slice(0, 16)}…` : o!.title}\n </MenuItem>\n ) : null}\n {editable ? (\n <MenuItem icon={<IconReplace stroke={1.5} />} onClick={() => window.setTimeout(() => setOpen(true), 0)}>\n Replace\n </MenuItem>\n ) : null}\n {openable || editable ? <MenuSeparator /> : null}\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => onChange(null)}>\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n )}\n </div>\n {body}\n </Popover>\n );\n }\n /* empty, or a saved id the lookup cannot find: V2's select trigger (V2 draws an unresolved id as no selection). Ours\n says \"Missing\" on it instead of hiding the saved id (DESIGN 9.6); the picker's None clears it, a row replaces it. */\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n id={id}\n disabled={!editable}\n data-slot={missing ? \"kit-reference-card\" : undefined}\n data-missing={missing || undefined}\n aria-label={missing ? `${field.title}: Missing ${noun}.${editable ? \" Change\" : \"\"}` : `${field.title}: select ${withArticle(noun)}`}\n className={cn(\n \"flex h-8 w-full items-center gap-2 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2.5 text-left text-kit-sm text-kit-fg-3 transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg\",\n missing && \"border-kit-warning-line text-kit-warning-fg hover:border-kit-warning-line data-[popup-open]:border-kit-warning-line\",\n )}\n >\n <IconFileDatabase className=\"size-4\" stroke={1.5} aria-hidden />\n {missing ? (\n <span className=\"flex-1 truncate\">\n Missing {noun}\n <span className=\"sr-only\">. Deleted, or not visible to you. The saved id stays until you replace or remove it.</span>\n </span>\n ) : (\n <span className=\"flex-1 truncate\">Select {withArticle(noun)}</span>\n )}\n <IconChevronDown className=\"size-3.5\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n {body}\n </Popover>\n );\n}\n\n/* ── Multi-reference: an array of ids ─────────────────────────────── */\nfunction RefChip({\n id,\n o,\n canLookup,\n readOnly,\n sort,\n onRemove,\n}: {\n id: string;\n o?: KitReferenceOption;\n /** false: no lookup service, so the saved id is all there is to show (never a \"Loading…\" that never ends) */\n canLookup: boolean;\n readOnly?: boolean;\n sort: ReturnType<typeof useDragReorder>;\n onRemove: () => void;\n}) {\n const handle = sort.handle(id);\n const register = sort.register(id);\n const title = o?.title ?? (canLookup ? \"Loading…\" : id);\n /* V2: the chip itself is the sortable item (thumb, title and remove button inside it) */\n return (\n <span\n {...(readOnly ? {} : handle)}\n ref={(el: HTMLElement | null) => {\n register(el);\n if (!readOnly) handle.ref(el);\n }}\n style={sort.style(id)}\n tabIndex={0}\n role=\"group\"\n aria-roledescription=\"sortable item\"\n aria-label={readOnly ? title : `${title}, drag to reorder`}\n onKeyDown={(e) => {\n // keys on the remove button are the button's own\n if (readOnly || e.target !== e.currentTarget) return;\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n e.preventDefault();\n onRemove();\n return;\n }\n handle.onKeyDown(e);\n }}\n className={cn(\n \"inline-flex h-6 max-w-full cursor-grab touch-none items-center gap-1.5 rounded-kit-md border border-kit-line bg-kit-control-bg pl-0.5 pr-1 text-kit-sm text-kit-fg shadow-kit-xs active:cursor-grabbing\",\n sort.active === id && \"z-10 shadow-kit-md\",\n )}\n >\n <RefThumb o={o ?? null} size={20} />\n <span className=\"truncate\">{title}</span>\n {/* a picker-made draft says what is left to fill, as the single card does; other chips stay V2's */}\n {o?.missingRequired ? <DraftChip status={o.status} missingRequired={o.missingRequired} /> : null}\n {readOnly ? null : (\n <button type=\"button\" aria-label={`Remove ${title}`} onPointerDown={(e) => e.stopPropagation()} onClick={onRemove} className=\"flex rounded-kit-md p-0.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n );\n}\n\n/** Multi-reference: an array of reference ids. `field` is the ARRAY field; the engine hands it the item's `reference`. */\nexport function ReferencesControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const { searchReferences } = useKitServices();\n const item = Array.isArray(field.of) ? field.of[0] : undefined;\n const to = item?.reference?.to ?? field.reference?.to ?? [];\n const filter = item?.reference?.filter ?? field.reference?.filter;\n const noun = referenceNoun(to, item?.reference?.noun ?? field.reference?.noun);\n const ids = React.useMemo(() => (Array.isArray(value) ? value : []).filter((x): x is string => typeof x === \"string\" && x !== \"\"), [value]);\n const rec = useReferenceRecords(ids, to);\n const createState = useCreate(to);\n const canCreate = createState.can && !readOnly;\n const max = field.validation?.max;\n /* ids the lookup cannot find are drawn as ONE compact \"n missing\" chip after Add (V2 hides them; one row keeps V2's height),\n so the chips that sort are the rest; a reorder puts them back around the missing ids, which keep their places */\n const missingIds = ids.filter((x) => rec.missing.has(x));\n const shown = missingIds.length ? ids.filter((x) => !rec.missing.has(x)) : ids;\n const sort = useDragReorder(\n shown,\n (from, to2) => {\n const next = [...shown];\n const [moved] = next.splice(from, 1);\n next.splice(to2, 0, moved);\n let i = 0;\n onChange(ids.map((x) => (rec.missing.has(x) ? x : next[i++])));\n },\n { axis: \"grid\", disabled: readOnly },\n );\n const missingNoun = missingIds.length === 1 ? noun : plural(noun);\n const toggle = (o: KitReferenceOption) => {\n rec.remember(o);\n if (ids.includes(o.id)) return onChange(ids.filter((x) => x !== o.id));\n if (max != null && ids.length >= max) return onChange([...ids.slice(0, -1), o.id]); // swap in place at the limit\n onChange([...ids, o.id]);\n };\n return (\n <div className=\"flex flex-col gap-1\">\n {/* the field label points at the Add trigger; read-only there is none, so the box carries the id. The chips sit\n straight in the wrapping box, as V2's do (a wrapper would take them out of the box's flow). V2's box has no\n role or name while editing; read-only (no Add to label) it is named as a group. */}\n <div\n id={readOnly ? id : undefined}\n role={readOnly ? \"group\" : undefined}\n aria-label={readOnly ? field.title : undefined}\n className=\"flex min-h-8 flex-wrap items-center gap-1 rounded-kit-md border border-kit-line-strong bg-kit-field-bg p-1 transition-colors hover:border-kit-line-strong\"\n >\n {shown.map((x) => (\n <RefChip key={x} id={x} o={rec.known[x]} canLookup={rec.canLookup} readOnly={readOnly} sort={sort} onRemove={() => onChange(ids.filter((y) => y !== x))} />\n ))}\n {sort.a11y}\n {!readOnly ? (\n <Popover>\n <PopoverTrigger id={id} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md px-1.5 text-kit-sm text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconPlus className=\"size-3.5\" stroke={1.5} aria-hidden />\n Add\n </PopoverTrigger>\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n {/* no search service: the picker says why instead of listing anything */}\n {!searchReferences ? (\n <div className=\"p-3\">\n <NoSearch title={field.title} />\n </div>\n ) : (\n <PickerBody\n to={to}\n filter={filter}\n excludeId={item?.reference?.excludeId ?? field.reference?.excludeId}\n selected={ids}\n multi\n max={max}\n noun={noun}\n onPick={toggle}\n canCreate={canCreate}\n noCreateWhy={createState.why}\n onCreated={(o) => {\n rec.remember(o);\n onChange(max != null && ids.length >= max ? [...ids.slice(0, -1), o.id] : [...ids, o.id]);\n }}\n />\n )}\n </PopoverContent>\n </Popover>\n ) : ids.length === 0 ? (\n <span className=\"px-1.5 text-kit-sm text-kit-fg-3\">None</span>\n ) : null}\n {/* after Add, so Add keeps V2's place (V2 draws nothing for these ids) */}\n {missingIds.length ? (\n <span\n data-missing\n data-slot=\"kit-reference-missing\"\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-kit-md border border-kit-warning-line bg-kit-control-bg pl-1.5 pr-1 text-kit-sm text-kit-warning-fg shadow-kit-xs\"\n >\n <span className=\"truncate tabular-nums\">\n {missingIds.length} missing\n <span className=\"sr-only\">\n {\" \"}\n {missingNoun}. Deleted, or not visible to you. The saved {missingIds.length === 1 ? \"id stays\" : \"ids stay\"} until you remove {missingIds.length === 1 ? \"it\" : \"them\"}.\n </span>\n </span>\n {readOnly ? null : (\n <button\n type=\"button\"\n aria-label={`Remove ${missingIds.length} missing ${missingNoun}`}\n onClick={() => onChange(ids.filter((y) => !rec.missing.has(y)))}\n className=\"flex rounded-kit-sm p-0.5 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n ) : null}\n </div>\n {rec.error ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {rec.error}\n </p>\n ) : null}\n {max != null ? (\n <span className=\"tabular-nums self-end text-kit-xs text-kit-fg-3\">\n {ids.length} / {max}\n </span>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * RICH TEXT · the article-block shell (V2 article-blocks.tsx ArticleBlock), shared by every article block: the one-open
3
+ * store (one panel or popover open at a time), the card the block draws in (a focusable group: Enter opens it, Escape
4
+ * closes it then leaves, ⌘Z / ⌘⇧Z, ⌘D, ⌥↑/↓, Backspace), the edit / remove chip on its top edge, the empty state, the
5
+ * schema form a panel or popover holds, and the floating properties panel (D54).
6
+ *
7
+ * surface "panel" ArticlePanelBlock: ArticleCard + useArticleOpen + ArticlePanel(ArticleForm) (pull quote, gallery,
8
+ * related posts)
9
+ * surface "popover" ArticlePopoverBlock: ArticleCard + useArticleOpen + a Popover of ArticleForm (embed, table of
10
+ * contents, author bio)
11
+ * surface "inline" ArticleCard without onOpen: the block edits in the text itself (key takeaways)
12
+ */
13
+ import * as React from "react";
14
+ import type { TypeSchema } from "../../schema/types";
15
+ import type { IslandEl } from "./dom";
16
+ import type { IslandCtx } from "./blocks";
17
+ export interface OpenArticle {
18
+ id: string;
19
+ /** the field the panel focuses when it opens (a click on the preview's `data-field`), null = the first */
20
+ focusKey: string | null;
21
+ /** bumps on every open, so re-opening the open block refocuses */
22
+ nonce: number;
23
+ }
24
+ /** The article block open now, if any. */
25
+ export declare const currentOpenArticle: () => OpenArticle | null;
26
+ export declare function useOpenArticle(): OpenArticle | null;
27
+ /**
28
+ * One block's place in the one-open store: `open(field?)` opens it (closing any other), `close()` closes it if it is
29
+ * the open one. It closes when the block unmounts, and a fresh insert (`autoFocus`) opens its form.
30
+ */
31
+ export declare function useArticleOpen({ ro, autoFocus }: {
32
+ ro: boolean;
33
+ autoFocus: boolean;
34
+ }): {
35
+ open: OpenArticle | null;
36
+ editing: boolean;
37
+ openPanel: (k?: string | null) => void;
38
+ close: () => void;
39
+ };
40
+ /** Focus the form row `key` names (`data-field-key`), else the first row. */
41
+ export declare function focusField(root: HTMLElement | null, key: string | null): void;
42
+ /**
43
+ * V2 ArticleBlock onKeyDown, on the card itself (its own fields handle their own keys). With `onOpen` (a panel or
44
+ * popover block) Enter / Space open it and Escape closes it first; without (an inline block) Escape leaves the block.
45
+ */
46
+ export declare function articleCardKeyDown({ card, ctx, el, ro, editing, onOpen, onClose, focusCard, }: {
47
+ card: React.RefObject<HTMLElement | null>;
48
+ ctx: IslandCtx;
49
+ el: IslandEl;
50
+ ro: boolean;
51
+ editing?: boolean;
52
+ onOpen?: () => void;
53
+ onClose?: () => void;
54
+ focusCard: () => void;
55
+ }): (e: React.KeyboardEvent) => void;
56
+ /** The chip on the block's top edge (so it never covers the block's own text): Edit (with `onEdit`) and Remove. */
57
+ export declare function ArticleActions({ label, ctx, el, editing, onEdit, tooltips, }: {
58
+ label: string;
59
+ ctx: IslandCtx;
60
+ el: IslandEl;
61
+ editing?: boolean;
62
+ /** toggles the block's panel or popover; absent on an inline block */
63
+ onEdit?: () => void;
64
+ /** each button also says what it does in a tooltip */
65
+ tooltips?: boolean;
66
+ }): import("react/jsx-runtime").JSX.Element | null;
67
+ /**
68
+ * The card an article block draws in. With `onOpen` (panel / popover) it is pressable: a click opens it on the field
69
+ * clicked (`data-field`), and it shows the open ring while `editing`. Without, it is the inline block's quiet group.
70
+ */
71
+ export declare const ArticleCard: React.ForwardRefExoticComponent<{
72
+ label: string;
73
+ kind: string;
74
+ ro: boolean;
75
+ editing?: boolean;
76
+ onOpen?: (field: string | null) => void;
77
+ onKeyDown: (e: React.KeyboardEvent) => void;
78
+ children: React.ReactNode;
79
+ } & React.RefAttributes<HTMLDivElement>>;
80
+ /** The block's settings, built from its schema (V2 ArticleForm: the kit SchemaForm, flush to the panel's top). */
81
+ export declare function ArticleForm({ schema, label, value, onChange, ro, }: {
82
+ schema: TypeSchema;
83
+ label: string;
84
+ value: Record<string, unknown>;
85
+ onChange: (v: Record<string, unknown>) => void;
86
+ ro: boolean;
87
+ }): import("react/jsx-runtime").JSX.Element;
88
+ /** V2 article-blocks.tsx Empty: a block with nothing to show yet. */
89
+ export declare const ArticleEmpty: ({ icon, title, action, onAction, ro }: {
90
+ icon: React.ReactNode;
91
+ title: string;
92
+ action: string;
93
+ onAction: () => void;
94
+ ro: boolean;
95
+ }) => import("react/jsx-runtime").JSX.Element;
96
+ export declare function ArticlePanel({ label, anchor, nonce, focusKey, onClose, focusBack, ctx, el, children, }: {
97
+ label: string;
98
+ anchor: HTMLElement | null;
99
+ nonce: number;
100
+ focusKey: string | null;
101
+ onClose: () => void;
102
+ focusBack: () => void;
103
+ ctx: IslandCtx;
104
+ el: IslandEl;
105
+ children: React.ReactNode;
106
+ }): import("react/jsx-runtime").JSX.Element;
107
+ /**
108
+ * A panel article block (V2 ArticleBlock surface "panel": Gallery, Related posts): the shell's card + chip, its
109
+ * settings in the floating properties panel, one undo step per field edit.
110
+ */
111
+ export declare function ArticlePanelBlock<M extends object>({ label, kind, schema, m, set, el, ctx, autoFocus, openOnInsert, toForm, fromForm, children, }: {
112
+ label: string;
113
+ kind: string;
114
+ schema: TypeSchema;
115
+ m: M;
116
+ set: (fn: (m: M) => M, label?: string) => void;
117
+ el: IslandEl;
118
+ ctx: IslandCtx;
119
+ autoFocus: boolean;
120
+ /** V2 article-blocks.tsx:127-133: a fresh insert opens the panel, except Related posts, which focuses the card */
121
+ openOnInsert?: boolean;
122
+ toForm: (m: M) => Record<string, unknown>;
123
+ fromForm: (v: Record<string, unknown>, prev: M) => M;
124
+ children: (open: (field?: string | null) => void, ro: boolean) => React.ReactNode;
125
+ }): import("react/jsx-runtime").JSX.Element;
126
+ /**
127
+ * A popover article block (V2 ArticleBlock surface "popover": TOC, Embed, Author bio): the shell's card + chip, its
128
+ * settings in a popover from the card's top-right corner, one undo step per field edit.
129
+ */
130
+ export declare function ArticlePopoverBlock<M extends object>({ label, kind, schema, m, set, el, ctx, autoFocus, openOnInsert, toForm, fromForm, children, }: {
131
+ label: string;
132
+ kind: string;
133
+ schema: TypeSchema;
134
+ m: M;
135
+ set: (fn: (m: M) => M, label?: string) => void;
136
+ el: IslandEl;
137
+ ctx: IslandCtx;
138
+ autoFocus: boolean;
139
+ /** V2 article-blocks.tsx:127-133: a fresh insert opens the form, except TOC and Related, which focus the card */
140
+ openOnInsert?: boolean;
141
+ toForm: (m: M) => Record<string, unknown>;
142
+ fromForm: (v: Record<string, unknown>, prev: M) => M;
143
+ /** the preview; `open(field)` opens the popover on that field (the empty state's action) */
144
+ children: (open: (field?: string | null) => void, ro: boolean) => React.ReactNode;
145
+ }): import("react/jsx-runtime").JSX.Element;