@bettercms-ai/ui 0.18.0 → 0.20.0

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/registry.js CHANGED
@@ -152,6 +152,7 @@ function BlocksRenderer({
152
152
  }
153
153
 
154
154
  // ../richtext/src/types.ts
155
+ var PT_TABLE_COLUMN_TYPES = ["text", "number", "money", "boolean", "rating", "link"];
155
156
  function pullQuoteHref(link) {
156
157
  if (typeof link === "string") return link.trim();
157
158
  if (link && typeof link === "object" && typeof link.href === "string") {
@@ -384,7 +385,12 @@ function normalizeCell(raw, at, mint, read) {
384
385
  ...rowSpan === void 0 ? {} : { rowSpan },
385
386
  ...typeof raw.group === "string" ? { group: raw.group } : {},
386
387
  ...raw.highlight === true ? { highlight: true } : {},
387
- ...raw.sortable === true ? { sortable: true } : {}
388
+ ...raw.sortable === true ? { sortable: true } : {},
389
+ // The V2 table's typed cells: the column (first-row cell), the per-cell type, the typed value.
390
+ ...columnOf(raw.column) ? { column: columnOf(raw.column) } : {},
391
+ ...isColumnType(raw.type) ? { type: raw.type } : {},
392
+ ...typeof raw.value === "boolean" || typeof raw.value === "number" && Number.isFinite(raw.value) ? { value: raw.value } : {},
393
+ ...typeof raw.note === "string" && raw.note ? { note: raw.note } : {}
388
394
  };
389
395
  }
390
396
  function normalizeRow(raw, at, mint, read) {
@@ -396,7 +402,8 @@ function normalizeRow(raw, at, mint, read) {
396
402
  ...isRecord(raw) && typeof raw.group === "string" ? { group: raw.group } : {},
397
403
  // The V2 table's two row flags ("Totals row", "Highlight this row"); see `PortableTextTableRow`.
398
404
  ...isRecord(raw) && raw.footer === true ? { footer: true } : {},
399
- ...isRecord(raw) && raw.highlight === true ? { highlight: true } : {}
405
+ ...isRecord(raw) && raw.highlight === true ? { highlight: true } : {},
406
+ ...isRecord(raw) && isColumnType(raw.type) ? { type: raw.type } : {}
400
407
  };
401
408
  }
402
409
  function builtInTableToTable(node, key = randomKey) {
@@ -456,9 +463,18 @@ function tableExtras(node) {
456
463
  ...columnGroups ? { columnGroups } : {},
457
464
  ...node.filterable === true ? { filterable: true } : {},
458
465
  ...jsonLdOf(node.jsonLd) ? { jsonLd: jsonLdOf(node.jsonLd) } : {},
459
- ...designOf(node.design) ? { design: designOf(node.design) } : {}
466
+ ...designOf(node.design) ? { design: designOf(node.design) } : {},
467
+ ...footnotesOf(node.footnotes) ? { footnotes: footnotesOf(node.footnotes) } : {}
460
468
  };
461
469
  }
470
+ function footnotesOf(v) {
471
+ if (!Array.isArray(v)) return void 0;
472
+ const out = v.filter((f) => isRecord(f) && typeof f._key === "string" && f._key !== "").map((f) => ({ _key: f._key, text: typeof f.text === "string" ? f.text : "" }));
473
+ return out.length ? out : void 0;
474
+ }
475
+ function footnoteNumbers(table) {
476
+ return new Map((footnotesOf(table.footnotes) ?? []).map((f, i) => [f._key, i + 1]));
477
+ }
462
478
  function designOf(v) {
463
479
  if (!isRecord(v)) return void 0;
464
480
  const d = {
@@ -531,6 +547,133 @@ function tableGroupLayout(table) {
531
547
  width
532
548
  };
533
549
  }
550
+ var NUMERIC_TYPES = /* @__PURE__ */ new Set(["number", "money", "rating"]);
551
+ var isColumnType = (v) => PT_TABLE_COLUMN_TYPES.includes(v);
552
+ function columnOf(v) {
553
+ if (!isRecord(v)) return void 0;
554
+ const str = (x) => typeof x === "string" && x !== "" ? x : void 0;
555
+ const int = (x, lo, hi) => Number.isInteger(x) && x >= lo && x <= hi ? x : void 0;
556
+ const c = {
557
+ ...isColumnType(v.type) ? { type: v.type } : {},
558
+ ...str(v.description) ? { description: str(v.description) } : {},
559
+ ...str(v.unit) ? { unit: str(v.unit) } : {},
560
+ ...typeof v.currency === "string" && /^[A-Z]{3}$/.test(v.currency) ? { currency: v.currency } : {},
561
+ ...int(v.decimals, 0, 10) !== void 0 ? { decimals: int(v.decimals, 0, 10) } : {},
562
+ ...v.align === "start" || v.align === "center" || v.align === "end" ? { align: v.align } : {},
563
+ ...str(v.trueLabel) ? { trueLabel: str(v.trueLabel) } : {},
564
+ ...str(v.falseLabel) ? { falseLabel: str(v.falseLabel) } : {},
565
+ ...int(v.max, 1, 10) !== void 0 ? { max: int(v.max, 1, 10) } : {}
566
+ };
567
+ return Object.keys(c).length ? c : void 0;
568
+ }
569
+ function tableColumns(table) {
570
+ const out = [];
571
+ const first = Array.isArray(table.rows) ? table.rows[0] : void 0;
572
+ for (const cell of isRecord(first) && Array.isArray(first.cells) ? first.cells : []) {
573
+ const w = isRecord(cell) && typeof cell.span === "number" && Number.isInteger(cell.span) && cell.span > 1 ? cell.span : 1;
574
+ const col = isRecord(cell) ? columnOf(cell.column) : void 0;
575
+ for (let i = 0; i < w; i += 1) out.push(col);
576
+ }
577
+ return out;
578
+ }
579
+ function isTypedTable(table) {
580
+ if (tableColumns(table).some(Boolean)) return true;
581
+ return (Array.isArray(table.rows) ? table.rows : []).some(
582
+ (r) => isRecord(r) && (r.type !== void 0 || Array.isArray(r.cells) && r.cells.some((c) => isRecord(c) && (c.type !== void 0 || c.value !== void 0)))
583
+ );
584
+ }
585
+ var cellTypeOf = (col, row, cell) => (isRecord(cell) && isColumnType(cell.type) ? cell.type : void 0) ?? (isRecord(row) && isColumnType(row.type) ? row.type : void 0) ?? col?.type ?? "text";
586
+ var columnAlign = (col, type) => col?.align ?? (NUMERIC_TYPES.has(type) ? "end" : "start");
587
+ var TRUE_WORDS = /* @__PURE__ */ new Set(["\u2713", "\u2714", "\u2714\uFE0F", "\u2611", "\u2705", "yes", "y", "true", "included", "available", "supported", "x \u2713", "check", "\u25CF"]);
588
+ var FALSE_WORDS = /* @__PURE__ */ new Set(["\u2717", "\u2715", "\u2716", "\u274C", "\xD7", "x", "no", "n", "false", "not included", "unavailable", "not available", "unsupported", "\u2014", "\u2013", "-", "\u25CB"]);
589
+ function toBool(v) {
590
+ if (typeof v === "boolean") return v;
591
+ if (typeof v !== "string") return null;
592
+ const s = v.trim().toLowerCase();
593
+ return TRUE_WORDS.has(s) ? true : FALSE_WORDS.has(s) ? false : null;
594
+ }
595
+ function toNumber(v) {
596
+ if (typeof v === "number") return Number.isFinite(v) ? v : null;
597
+ if (typeof v !== "string") return null;
598
+ const s = v.replace(/[,\s]/g, "").replace(/[^\d.+-]/g, "");
599
+ if (!s || !/^[+-]?\d*\.?\d+$/.test(s)) return null;
600
+ return Number(s);
601
+ }
602
+ var formatNumber = (n, decimals) => new Intl.NumberFormat("en-US", decimals != null ? { minimumFractionDigits: decimals, maximumFractionDigits: decimals } : { maximumFractionDigits: 6 }).format(n);
603
+ function formatMoney(n, currency = "USD", decimals) {
604
+ try {
605
+ const whole = Number.isInteger(n) && decimals == null;
606
+ return new Intl.NumberFormat("en-US", { style: "currency", currency, minimumFractionDigits: whole ? 0 : decimals ?? 2, maximumFractionDigits: whole ? 0 : decimals ?? 2 }).format(n);
607
+ } catch {
608
+ return `${formatNumber(n, decimals)} ${currency}`;
609
+ }
610
+ }
611
+ var boolLabels = (col) => ({ yes: col?.trueLabel || "Included", no: col?.falseLabel || "Not included" });
612
+ function typedCellText(col, type, v) {
613
+ if (v == null || v === "") return "";
614
+ const words = String(v).replace(/\s+/g, " ").trim();
615
+ switch (type) {
616
+ case "boolean": {
617
+ const b = toBool(v);
618
+ return b == null ? words : b ? boolLabels(col).yes : boolLabels(col).no;
619
+ }
620
+ case "number": {
621
+ const n = toNumber(v);
622
+ return n == null ? words : `${formatNumber(n, col?.decimals)}${col?.unit ? /^[%°]/.test(col.unit) ? col.unit : ` ${col.unit}` : ""}`;
623
+ }
624
+ case "money": {
625
+ const n = toNumber(v);
626
+ return n == null ? words : formatMoney(n, col?.currency || "USD", col?.decimals);
627
+ }
628
+ case "rating": {
629
+ const n = toNumber(v);
630
+ return n == null ? words : `${formatNumber(n, 1).replace(/\.0$/, "")} out of ${col?.max ?? 5}`;
631
+ }
632
+ default:
633
+ return words;
634
+ }
635
+ }
636
+ var escHtml = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
637
+ function typedCellView(column, row, cell, inHead) {
638
+ if (inHead) {
639
+ const align2 = columnAlign(column, column?.type ?? "text");
640
+ return { lead: align2 !== "start" ? [["data-align", align2]] : [], tail: column?.description ? [["title", column.description]] : [] };
641
+ }
642
+ const type = cellTypeOf(column, row, cell);
643
+ const words = portableTextWords(cell.content);
644
+ const v = typeof cell.value === "number" || typeof cell.value === "boolean" ? cell.value : words;
645
+ const tail = isColumnType(cell.type) ? [["data-type", cell.type]] : [];
646
+ let inner;
647
+ if (v === "") {
648
+ inner = cell.header === true ? "" : '<span aria-hidden="true" class="bt-dash">\u2014</span><span class="bt-sr">No value</span>';
649
+ tail.push(["data-empty", ""]);
650
+ } else if (type === "boolean") {
651
+ const b = toBool(v);
652
+ if (b == null) inner = escHtml(words);
653
+ else {
654
+ const { yes, no } = boolLabels(column);
655
+ inner = `<span aria-hidden="true" class="bt-bool" data-bool="${b}">${b ? "\u2713" : "\u2013"}</span><span class="bt-sr">${escHtml(b ? yes : no)}</span>`;
656
+ tail.push(["data-value", String(b)]);
657
+ }
658
+ } else if (type === "rating") {
659
+ const n = toNumber(v);
660
+ if (n == null) inner = escHtml(words);
661
+ else {
662
+ inner = `<span aria-hidden="true" class="bt-star">\u2605</span> ${escHtml(formatNumber(n, 1).replace(/\.0$/, ""))}<span class="bt-dim"> / ${column?.max ?? 5}</span>`;
663
+ tail.push(["data-value", String(n)]);
664
+ }
665
+ } else if (type === "number" || type === "money") {
666
+ const n = toNumber(v);
667
+ inner = escHtml(typedCellText(column, type, v));
668
+ if (n != null) tail.push(["data-value", String(n)]);
669
+ }
670
+ const align = columnAlign(column, type);
671
+ if (align !== "start") tail.push(["data-align", align]);
672
+ return { lead: [], tail, ...inner === void 0 ? {} : { inner } };
673
+ }
674
+ function portableTextWords(content) {
675
+ return (Array.isArray(content) ? content : []).map((b) => isRecord(b) && Array.isArray(b.children) ? b.children.map((c) => isRecord(c) && typeof c.text === "string" ? c.text : "").join("") : "").join(" ").replace(/\s+/g, " ").trim();
676
+ }
534
677
 
535
678
  // ../richtext/src/key-takeaways.ts
536
679
  var isRecord2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
@@ -614,9 +757,12 @@ var tableLines = (table) => {
614
757
  layout.columns.map((r) => one(r.label)).filter(Boolean).join(" "),
615
758
  ...head.map(rowLine),
616
759
  ...layout.rows.flatMap((run) => [...run.label === void 0 ? [] : [one(run.label)], ...run.rows.map(rowLine)]),
617
- one(table.notes)
760
+ one(table.notes),
761
+ // footnotes, numbered as the html numbers them (V2 tableSearchText reads them too)
762
+ ...(Array.isArray(table.footnotes) ? table.footnotes : []).map((f, i) => one(`[${i + 1}] ${typeof f?.text === "string" ? f.text : ""}`))
618
763
  ];
619
- const extras = /* @__PURE__ */ new Set([0, 1, lines.length - 1]);
764
+ const fnCount = Array.isArray(table.footnotes) ? table.footnotes.length : 0;
765
+ const extras = /* @__PURE__ */ new Set([0, 1, lines.length - 1 - fnCount]);
620
766
  return lines.filter((l, i) => l !== "" || !extras.has(i));
621
767
  };
622
768
  var pullQuoteLines = (v) => {
@@ -701,6 +847,13 @@ function Table({ value }) {
701
847
  at += w;
702
848
  }
703
849
  }
850
+ const columns = tableColumns(value);
851
+ const typed = isTypedTable(value);
852
+ const headSet = new Set(tableSections(value).head);
853
+ const props = (list) => Object.fromEntries(list);
854
+ const fnNumber = footnoteNumbers(value);
855
+ const footnotes = footnotesOf(value.footnotes) ?? [];
856
+ const tableId = typeof value._key === "string" && value._key ? value._key : "tbl";
704
857
  const cells = (row) => {
705
858
  let col = 0;
706
859
  return (Array.isArray(row?.cells) ? row.cells : []).map((cell) => {
@@ -709,19 +862,27 @@ function Table({ value }) {
709
862
  const at = col;
710
863
  col += span2 ?? 1;
711
864
  const rowSpan = typeof cell?.rowSpan === "number" && cell.rowSpan > 1 ? cell.rowSpan : void 0;
865
+ const n = typeof cell?.note === "string" ? fnNumber.get(cell.note) : void 0;
712
866
  const content = Array.isArray(cell?.content) ? cell.content : [];
713
867
  const lone = content.length === 1 && content[0]._type === "block" && content[0].style === "normal" && !content[0].listItem;
714
- return /* @__PURE__ */ jsx3(Tag, { ...Tag === "td" ? role("cell") : {}, ...span2 ? { colSpan: span2 } : {}, ...rowSpan ? { rowSpan } : {}, ...stacked && Tag === "td" ? { "data-label": labels[at] || `Column ${at + 1}` } : {}, ...marked.has(at) ? { "data-highlight": "true" } : {}, children: /* @__PURE__ */ jsx3(PT, { value: content, components: lone ? inline : components }) }, cell?._key);
868
+ const view = typed ? typedCellView(columns[at], row, cell ?? {}, headSet.has(row)) : void 0;
869
+ const noteAttr = n ? [["data-note", cell.note]] : [];
870
+ const tail = [...(view?.tail ?? []).filter(([k]) => k !== "data-align"), ...noteAttr, ...(view?.tail ?? []).filter(([k]) => k === "data-align")];
871
+ const supHtml = n ? `<sup><a href="#${tableId}-fn-${n}" aria-label="Note ${n}">${n}</a></sup>` : "";
872
+ return /* @__PURE__ */ jsx3(Tag, { ...Tag === "td" ? role("cell") : {}, ...span2 ? { colSpan: span2 } : {}, ...rowSpan ? { rowSpan } : {}, ...props(view?.lead ?? []), ...stacked && Tag === "td" ? { "data-label": labels[at] || `Column ${at + 1}` } : {}, ...marked.has(at) ? { "data-highlight": "true" } : {}, ...props(tail), ...view?.inner !== void 0 ? { dangerouslySetInnerHTML: { __html: view.inner + supHtml } } : {}, children: view?.inner !== void 0 ? void 0 : /* @__PURE__ */ jsxs2(Fragment, { children: [
873
+ /* @__PURE__ */ jsx3(PT, { value: content, components: lone ? inline : components }),
874
+ n ? /* @__PURE__ */ jsx3("sup", { children: /* @__PURE__ */ jsx3("a", { href: `#${tableId}-fn-${n}`, "aria-label": `Note ${n}`, children: n }) }) : null
875
+ ] }) }, cell?._key);
715
876
  });
716
877
  };
717
- const rowEl = (row) => /* @__PURE__ */ jsx3("tr", { ...role("row"), ...row?.highlight === true ? { "data-highlight": "true" } : {}, children: cells(row) }, row?._key);
878
+ const rowEl = (row) => /* @__PURE__ */ jsx3("tr", { ...role("row"), ...typeof row?.type === "string" ? { "data-type": row.type } : {}, ...row?.highlight === true ? { "data-highlight": "true" } : {}, children: cells(row) }, row?._key);
718
879
  const sections = tableSections(value);
719
880
  const head = sections.head.length;
720
881
  const foot = sections.foot;
721
882
  const layout = tableGroupLayout(value);
722
883
  const caption = typeof value.caption === "string" ? value.caption.trim() : "";
723
884
  const notes = typeof value.notes === "string" ? value.notes.trim() : "";
724
- const notesId = notes && typeof value._key === "string" && value._key ? `${value._key}-notes` : void 0;
885
+ const notesId = (notes || footnotes.length) && typeof value._key === "string" && value._key ? `${value._key}-notes` : void 0;
725
886
  const span = (n) => n > 1 ? n : void 0;
726
887
  const groupRow = layout.columns.length ? /* @__PURE__ */ jsx3("tr", { ...role("row"), children: layout.columns.flatMap(
727
888
  (run, i) => run.label === void 0 ? Array.from({ length: run.width }, (_, k) => /* @__PURE__ */ jsx3("td", { ...role("cell") }, `${i}-${k}`)) : [/* @__PURE__ */ jsx3("th", { ...role("columnheader"), scope: "colgroup", colSpan: span(run.width), "data-group": run.key, children: run.label }, i)]
@@ -730,11 +891,26 @@ function Table({ value }) {
730
891
  run.label !== void 0 && /* @__PURE__ */ jsx3("tr", { ...role("row"), children: /* @__PURE__ */ jsx3("th", { ...role("rowheader"), scope: "rowgroup", colSpan: span(layout.width), children: run.label }) }),
731
892
  run.rows.map(rowEl)
732
893
  ] }, i)) : sections.body.length > 0 && /* @__PURE__ */ jsx3("tbody", { ...role("rowgroup"), children: sections.body.map(rowEl) });
894
+ const colProps = (i) => {
895
+ const c = columns[i];
896
+ return {
897
+ ...c ? { "data-type": c.type ?? "text" } : {},
898
+ ...c?.unit ? { "data-unit": c.unit } : {},
899
+ ...c?.currency ? { "data-currency": c.currency } : {},
900
+ ...c?.decimals != null ? { "data-decimals": String(c.decimals) } : {},
901
+ ...c?.align ? { "data-align": c.align } : {},
902
+ ...sortable.has(i) ? { "data-sortable": "true" } : {},
903
+ ...c?.trueLabel ? { "data-true": c.trueLabel } : {},
904
+ ...c?.falseLabel ? { "data-false": c.falseLabel } : {},
905
+ ...c?.max != null ? { "data-max": String(c.max) } : {},
906
+ ...c?.description ? { "data-description": c.description } : {}
907
+ };
908
+ };
733
909
  const table = /* @__PURE__ */ jsxs2("table", { ...role("table"), ...value.legacy === true ? { className: "bcms-table" } : {}, ...notesId ? { "aria-describedby": notesId } : {}, children: [
734
910
  caption && /* @__PURE__ */ jsx3("caption", { children: caption }),
735
- sortable.size ? (layout.columns.length ? layout.columns.map((run) => run.width) : [layout.width]).map((w, i, all) => {
911
+ sortable.size || columns.some(Boolean) ? (layout.columns.length ? layout.columns.map((run) => run.width) : [layout.width]).map((w, i, all) => {
736
912
  const from = all.slice(0, i).reduce((n, x) => n + x, 0);
737
- return /* @__PURE__ */ jsx3("colgroup", { children: Array.from({ length: w }, (_, k) => /* @__PURE__ */ jsx3("col", { ...sortable.has(from + k) ? { "data-sortable": "true" } : {} }, k)) }, i);
913
+ return /* @__PURE__ */ jsx3("colgroup", { children: Array.from({ length: w }, (_, k) => /* @__PURE__ */ jsx3("col", { ...colProps(from + k) }, k)) }, i);
738
914
  }) : layout.columns.map((run, i) => /* @__PURE__ */ jsx3("colgroup", { span: span(run.width) }, i)),
739
915
  (groupRow || head > 0) && /* @__PURE__ */ jsxs2("thead", { ...role("rowgroup"), children: [
740
916
  groupRow,
@@ -747,9 +923,12 @@ function Table({ value }) {
747
923
  const ld = jsonLdOf(value.jsonLd);
748
924
  const ldAttrs = ld ? { "data-jsonld": ld.type, ...ld.axis ? { "data-jsonld-axis": ld.axis } : {}, ...ld.priceRow ? { "data-jsonld-price": ld.priceRow } : {} } : {};
749
925
  const designAttrs = design ? { ...design.responsive ? { "data-responsive": design.responsive } : {}, ...design.sticky ? { "data-sticky": "true" } : {} } : {};
750
- return notes || filter || ld || design ? /* @__PURE__ */ jsxs2("figure", { "data-rt": "table", ...designAttrs, ...filter ? { "data-filter": "true" } : {}, ...ldAttrs, children: [
926
+ return notes || filter || ld || design || footnotes.length ? /* @__PURE__ */ jsxs2("figure", { "data-rt": "table", ...designAttrs, ...filter ? { "data-filter": "true" } : {}, ...ldAttrs, children: [
751
927
  table,
752
- notes ? /* @__PURE__ */ jsx3("p", { "data-notes": "", id: notesId, children: notes }) : null
928
+ footnotes.length ? /* @__PURE__ */ jsxs2("div", { className: "bt-notes", id: `${tableId}-notes`, children: [
929
+ notes ? /* @__PURE__ */ jsx3("p", { "data-notes": "", children: notes }) : null,
930
+ /* @__PURE__ */ jsx3("ol", { "data-footnotes": "", children: footnotes.map((f, i) => /* @__PURE__ */ jsx3("li", { id: `${tableId}-fn-${i + 1}`, "data-key": f._key, children: f.text }, f._key)) })
931
+ ] }) : notes ? /* @__PURE__ */ jsx3("p", { "data-notes": "", id: notesId, children: notes }) : null
753
932
  ] }) : table;
754
933
  }
755
934
  function buildComponents(renderBlock) {
@@ -772,6 +951,8 @@ function buildComponents(renderBlock) {
772
951
  [PT_TYPES.block]: ({ value }) => {
773
952
  const rendered = renderBlock?.(value);
774
953
  if (rendered !== void 0) return /* @__PURE__ */ jsx3(Fragment, { children: rendered });
954
+ const builtIn = calloutOrToggle(value);
955
+ if (builtIn) return builtIn;
775
956
  const copy = detachedComponentCopy(value);
776
957
  if (copy) {
777
958
  return /* @__PURE__ */ jsx3("div", { className: "bcms-block bcms-block--component", "data-bcms-component-copy": copy.componentId, "data-bcms-instance": copy.id, children: /* @__PURE__ */ jsx3(BlocksRenderer, { blocks: copy.blocks }) });
@@ -888,6 +1069,35 @@ function runsOf(blocks) {
888
1069
  }
889
1070
  return runs;
890
1071
  }
1072
+ function paragraphs(text) {
1073
+ return text.split(/\n\s*\n/).map((p) => p.trim()).filter(Boolean).map((p, i) => /* @__PURE__ */ jsx3("p", { children: p.split("\n").map((line, j) => j === 0 ? line : [/* @__PURE__ */ jsx3("br", {}, j), line]) }, i));
1074
+ }
1075
+ var CALLOUT_TONES = /* @__PURE__ */ new Set(["info", "tip", "warning"]);
1076
+ function calloutOrToggle(value) {
1077
+ const v = value ?? {};
1078
+ const f = v.fields && typeof v.fields === "object" ? v.fields : {};
1079
+ const text = (x) => typeof x === "string" ? x.trim() : "";
1080
+ if (v.schemaKey === "builtin:callout") {
1081
+ const tone = CALLOUT_TONES.has(text(f.tone)) ? text(f.tone) : "info";
1082
+ const title = text(f.title);
1083
+ const body = paragraphs(typeof f.message === "string" ? f.message : "");
1084
+ if (!title && !body.length) return /* @__PURE__ */ jsx3(Fragment, {});
1085
+ return /* @__PURE__ */ jsxs2("div", { className: `bcms-callout bcms-callout--${tone}`, "data-rt": "callout", "data-callout": tone, role: "note", children: [
1086
+ title ? /* @__PURE__ */ jsx3("p", { className: "bcms-callout__title", "data-title": "", children: title }) : null,
1087
+ /* @__PURE__ */ jsx3("div", { className: "bcms-callout__body", "data-body": "", children: body })
1088
+ ] });
1089
+ }
1090
+ if (v.schemaKey === "builtin:toggle") {
1091
+ const title = text(f.title);
1092
+ const body = paragraphs(typeof f.body === "string" ? f.body : "");
1093
+ if (!title && !body.length) return /* @__PURE__ */ jsx3(Fragment, {});
1094
+ return /* @__PURE__ */ jsxs2("details", { className: "bcms-toggle", "data-rt": "toggle", children: [
1095
+ /* @__PURE__ */ jsx3("summary", { className: "bcms-toggle__title", children: title }),
1096
+ /* @__PURE__ */ jsx3("div", { className: "bcms-toggle__body", "data-body": "", children: body })
1097
+ ] });
1098
+ }
1099
+ return null;
1100
+ }
891
1101
  function PortableText({ value, bindingBase, renderBlock }) {
892
1102
  const blocks = React2.useMemo(() => normalizePortableText(readValue(value)), [value]);
893
1103
  const components = React2.useMemo(() => buildComponents(renderBlock), [renderBlock]);