@bettercms-ai/ui 0.17.0 → 0.18.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
@@ -159,6 +159,8 @@ function pullQuoteHref(link) {
159
159
  }
160
160
  return "";
161
161
  }
162
+ var isPortableTextBlock = (n) => !!n && typeof n === "object" && n._type === "block";
163
+ var isPortableTextSpan = (n) => !!n && typeof n === "object" && n._type === "span";
162
164
  var PT_TYPES = {
163
165
  /** A generic embedded block: `{schemaKey, schemaLabel, fields}`, the successor to Lexical's BlockNode. */
164
166
  block: "bcmsBlock",
@@ -380,7 +382,9 @@ function normalizeCell(raw, at, mint, read) {
380
382
  ...raw.header === true ? { header: true } : {},
381
383
  ...span === void 0 ? {} : { span },
382
384
  ...rowSpan === void 0 ? {} : { rowSpan },
383
- ...typeof raw.group === "string" ? { group: raw.group } : {}
385
+ ...typeof raw.group === "string" ? { group: raw.group } : {},
386
+ ...raw.highlight === true ? { highlight: true } : {},
387
+ ...raw.sortable === true ? { sortable: true } : {}
384
388
  };
385
389
  }
386
390
  function normalizeRow(raw, at, mint, read) {
@@ -389,7 +393,10 @@ function normalizeRow(raw, at, mint, read) {
389
393
  _key: isRecord(raw) && isValidKey(raw._key) ? raw._key : mint("r", at),
390
394
  cells: cells.map((c, col) => normalizeCell(c, [at, col], mint, read)),
391
395
  ...isRecord(raw) && raw.head === true ? { head: true } : {},
392
- ...isRecord(raw) && typeof raw.group === "string" ? { group: raw.group } : {}
396
+ ...isRecord(raw) && typeof raw.group === "string" ? { group: raw.group } : {},
397
+ // The V2 table's two row flags ("Totals row", "Highlight this row"); see `PortableTextTableRow`.
398
+ ...isRecord(raw) && raw.footer === true ? { footer: true } : {},
399
+ ...isRecord(raw) && raw.highlight === true ? { highlight: true } : {}
393
400
  };
394
401
  }
395
402
  function builtInTableToTable(node, key = randomKey) {
@@ -446,9 +453,53 @@ function tableExtras(node) {
446
453
  ...typeof node.caption === "string" ? { caption: node.caption } : {},
447
454
  ...typeof node.notes === "string" ? { notes: node.notes } : {},
448
455
  ...rowGroups ? { rowGroups } : {},
449
- ...columnGroups ? { columnGroups } : {}
456
+ ...columnGroups ? { columnGroups } : {},
457
+ ...node.filterable === true ? { filterable: true } : {},
458
+ ...jsonLdOf(node.jsonLd) ? { jsonLd: jsonLdOf(node.jsonLd) } : {},
459
+ ...designOf(node.design) ? { design: designOf(node.design) } : {}
450
460
  };
451
461
  }
462
+ function designOf(v) {
463
+ if (!isRecord(v)) return void 0;
464
+ const d = {
465
+ ...v.responsive === "stack" || v.responsive === "cards" ? { responsive: v.responsive } : {},
466
+ ...v.sticky === true ? { sticky: true } : {}
467
+ };
468
+ return Object.keys(d).length ? d : void 0;
469
+ }
470
+ var JSONLD_TYPES = ["ItemList", "Dataset", "Offers"];
471
+ function jsonLdOf(v) {
472
+ if (!isRecord(v) || !JSONLD_TYPES.includes(v.type)) return void 0;
473
+ return {
474
+ type: v.type,
475
+ ...v.axis === "rows" || v.axis === "columns" ? { axis: v.axis } : {},
476
+ ...typeof v.priceRow === "string" && v.priceRow ? { priceRow: v.priceRow } : {}
477
+ };
478
+ }
479
+ function tableSections(table) {
480
+ const rows = Array.isArray(table.rows) ? table.rows : [];
481
+ const headCount = rows.findIndex((r) => !isRecord(r) || r.head !== true);
482
+ const head = rows.slice(0, headCount === -1 ? rows.length : headCount);
483
+ let footFrom = rows.length;
484
+ while (footFrom > head.length && isRecord(rows[footFrom - 1]) && rows[footFrom - 1].footer === true) footFrom -= 1;
485
+ return { head, body: rows.slice(head.length, footFrom), foot: rows.slice(footFrom) };
486
+ }
487
+ function highlightedColumns(table) {
488
+ return markedColumns(table, "highlight");
489
+ }
490
+ function sortableColumns(table) {
491
+ return markedColumns(table, "sortable");
492
+ }
493
+ function markedColumns(table, flag) {
494
+ const out = /* @__PURE__ */ new Set();
495
+ const first = Array.isArray(table.rows) ? table.rows[0] : void 0;
496
+ let at = 0;
497
+ for (const cell of isRecord(first) && Array.isArray(first.cells) ? first.cells : []) {
498
+ if (isRecord(cell) && cell[flag] === true) out.add(at);
499
+ at += isRecord(cell) && typeof cell.span === "number" && Number.isInteger(cell.span) && cell.span > 1 ? cell.span : 1;
500
+ }
501
+ return out;
502
+ }
452
503
  function tableGroupLayout(table) {
453
504
  const rows = Array.isArray(table.rows) ? table.rows : [];
454
505
  const labels = (list) => new Map(
@@ -466,8 +517,7 @@ function tableGroupLayout(table) {
466
517
  else columns.push({ width: spanOf2(cell), ...key === void 0 ? {} : { key, label: colLabels.get(key) } });
467
518
  }
468
519
  const rowLabels = labels(table.rowGroups);
469
- const headCount = rows.findIndex((r) => !isRecord(r) || r.head !== true);
470
- const body = headCount === -1 ? [] : rows.slice(headCount);
520
+ const { body } = tableSections(table);
471
521
  const runs = [];
472
522
  for (const row of body) {
473
523
  const key = isRecord(row) && typeof row.group === "string" && rowLabels.has(row.group) ? row.group : void 0;
@@ -506,6 +556,74 @@ function detachedComponentCopy(value) {
506
556
  ...typeof f.variant === "string" ? { variant: f.variant } : {}
507
557
  };
508
558
  }
559
+ function componentCopyLines(copy) {
560
+ const line = (v) => {
561
+ if (typeof v === "number" && Number.isFinite(v)) return String(v);
562
+ if (typeof v === "string") {
563
+ const t = v.replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/\s+/g, " ").trim();
564
+ return t || null;
565
+ }
566
+ if (isRecord3(v)) return line(v.label ?? v.text ?? v.title);
567
+ return null;
568
+ };
569
+ return Object.values(copy.props).map(line).filter((s) => !!s);
570
+ }
571
+
572
+ // ../richtext/src/plain.ts
573
+ function portableTextToPlainText(value) {
574
+ if (!Array.isArray(value)) return "";
575
+ const lines = [];
576
+ for (const node of value) {
577
+ if (isPortableTextBlock(node)) {
578
+ lines.push(node.children.map((c) => isPortableTextSpan(c) ? c.text : "").join(""));
579
+ continue;
580
+ }
581
+ if (node._type === PT_TYPES.code && typeof node.code === "string") {
582
+ lines.push(node.code);
583
+ }
584
+ if (node._type === PT_TYPES.pullQuote) {
585
+ lines.push(...pullQuoteLines(node));
586
+ continue;
587
+ }
588
+ if (node._type === PT_TYPES.keyTakeaways) {
589
+ const { title, points } = keyTakeawaysView(node);
590
+ lines.push(...title ? [title] : [], ...points);
591
+ continue;
592
+ }
593
+ const table = migrateTable(node);
594
+ if (table) {
595
+ lines.push(...tableLines(table));
596
+ continue;
597
+ }
598
+ const copy = detachedComponentCopy(node);
599
+ if (copy) {
600
+ lines.push(...componentCopyLines(copy));
601
+ continue;
602
+ }
603
+ }
604
+ return lines.join("\n");
605
+ }
606
+ var tableLines = (table) => {
607
+ const rows = Array.isArray(table.rows) ? table.rows : [];
608
+ const rowLine = (row) => (Array.isArray(row?.cells) ? row.cells : []).map((cell) => portableTextToPlainText(cell?.content).replace(/\s+/g, " ").trim()).join(" ").trim();
609
+ const layout = tableGroupLayout(table);
610
+ const one = (s) => typeof s === "string" ? s.replace(/\s+/g, " ").trim() : "";
611
+ const head = layout.rows.length ? rows.slice(0, rows.length - layout.rows.reduce((n, r) => n + r.rows.length, 0)) : rows;
612
+ const lines = [
613
+ one(table.caption),
614
+ layout.columns.map((r) => one(r.label)).filter(Boolean).join(" "),
615
+ ...head.map(rowLine),
616
+ ...layout.rows.flatMap((run) => [...run.label === void 0 ? [] : [one(run.label)], ...run.rows.map(rowLine)]),
617
+ one(table.notes)
618
+ ];
619
+ const extras = /* @__PURE__ */ new Set([0, 1, lines.length - 1]);
620
+ return lines.filter((l, i) => l !== "" || !extras.has(i));
621
+ };
622
+ var pullQuoteLines = (v) => {
623
+ const text = (x) => typeof x === "string" ? x.trim() : "";
624
+ const by = [text(v.name), text(v.role)].filter(Boolean).join(", ");
625
+ return [text(v.quote), ...by ? [`\u2014 ${by}`] : []].filter(Boolean);
626
+ };
509
627
 
510
628
  // ../richtext/src/read.ts
511
629
  var isRecord4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
@@ -567,41 +685,71 @@ function Table({ value }) {
567
685
  );
568
686
  const rows = Array.isArray(value?.rows) ? value.rows : [];
569
687
  if (rows.length === 0) return null;
570
- const cells = (row) => (Array.isArray(row?.cells) ? row.cells : []).map((cell) => {
571
- const Tag = cell?.header === true ? "th" : "td";
572
- const span2 = typeof cell?.span === "number" && cell.span > 1 ? cell.span : void 0;
573
- const rowSpan = typeof cell?.rowSpan === "number" && cell.rowSpan > 1 ? cell.rowSpan : void 0;
574
- const content = Array.isArray(cell?.content) ? cell.content : [];
575
- const lone = content.length === 1 && content[0]._type === "block" && content[0].style === "normal" && !content[0].listItem;
576
- return /* @__PURE__ */ jsx3(Tag, { ...span2 ? { colSpan: span2 } : {}, ...rowSpan ? { rowSpan } : {}, children: /* @__PURE__ */ jsx3(PT, { value: content, components: lone ? inline : components }) }, cell?._key);
577
- });
578
- const rowEl = (row) => /* @__PURE__ */ jsx3("tr", { children: cells(row) }, row?._key);
579
- const headCount = rows.findIndex((r) => r?.head !== true);
580
- const head = headCount === -1 ? rows.length : headCount;
688
+ const marked = highlightedColumns(value);
689
+ const sortable = sortableColumns(value);
690
+ const design = designOf(value.design);
691
+ const stacked = design?.responsive === "stack" || design?.responsive === "cards";
692
+ const role = (r) => stacked ? { role: r } : {};
693
+ const labels = [];
694
+ if (stacked) {
695
+ const headRows = tableSections(value).head;
696
+ let at = 0;
697
+ for (const c of Array.isArray(headRows[headRows.length - 1]?.cells) ? headRows[headRows.length - 1].cells : []) {
698
+ const text = portableTextToPlainText(Array.isArray(c?.content) ? c.content : []).replace(/\s+/g, " ").trim();
699
+ const w = typeof c?.span === "number" && c.span > 1 ? c.span : 1;
700
+ for (let i = 0; i < w; i += 1) labels[at + i] = text;
701
+ at += w;
702
+ }
703
+ }
704
+ const cells = (row) => {
705
+ let col = 0;
706
+ return (Array.isArray(row?.cells) ? row.cells : []).map((cell) => {
707
+ const Tag = cell?.header === true ? "th" : "td";
708
+ const span2 = typeof cell?.span === "number" && cell.span > 1 ? cell.span : void 0;
709
+ const at = col;
710
+ col += span2 ?? 1;
711
+ const rowSpan = typeof cell?.rowSpan === "number" && cell.rowSpan > 1 ? cell.rowSpan : void 0;
712
+ const content = Array.isArray(cell?.content) ? cell.content : [];
713
+ 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);
715
+ });
716
+ };
717
+ const rowEl = (row) => /* @__PURE__ */ jsx3("tr", { ...role("row"), ...row?.highlight === true ? { "data-highlight": "true" } : {}, children: cells(row) }, row?._key);
718
+ const sections = tableSections(value);
719
+ const head = sections.head.length;
720
+ const foot = sections.foot;
581
721
  const layout = tableGroupLayout(value);
582
722
  const caption = typeof value.caption === "string" ? value.caption.trim() : "";
583
723
  const notes = typeof value.notes === "string" ? value.notes.trim() : "";
584
724
  const notesId = notes && typeof value._key === "string" && value._key ? `${value._key}-notes` : void 0;
585
725
  const span = (n) => n > 1 ? n : void 0;
586
- const groupRow = layout.columns.length ? /* @__PURE__ */ jsx3("tr", { children: layout.columns.flatMap(
587
- (run, i) => run.label === void 0 ? Array.from({ length: run.width }, (_, k) => /* @__PURE__ */ jsx3("td", {}, `${i}-${k}`)) : [/* @__PURE__ */ jsx3("th", { scope: "colgroup", colSpan: span(run.width), "data-group": run.key, children: run.label }, i)]
726
+ const groupRow = layout.columns.length ? /* @__PURE__ */ jsx3("tr", { ...role("row"), children: layout.columns.flatMap(
727
+ (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)]
588
728
  ) }) : null;
589
- const bodies = layout.rows.length ? layout.rows.map((run, i) => /* @__PURE__ */ jsxs2("tbody", { "data-key": run.key, children: [
590
- run.label !== void 0 && /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("th", { scope: "rowgroup", colSpan: span(layout.width), children: run.label }) }),
729
+ const bodies = layout.rows.length ? layout.rows.map((run, i) => /* @__PURE__ */ jsxs2("tbody", { ...role("rowgroup"), "data-key": run.key, children: [
730
+ run.label !== void 0 && /* @__PURE__ */ jsx3("tr", { ...role("row"), children: /* @__PURE__ */ jsx3("th", { ...role("rowheader"), scope: "rowgroup", colSpan: span(layout.width), children: run.label }) }),
591
731
  run.rows.map(rowEl)
592
- ] }, i)) : head < rows.length && /* @__PURE__ */ jsx3("tbody", { children: rows.slice(head).map(rowEl) });
593
- const table = /* @__PURE__ */ jsxs2("table", { ...value.legacy === true ? { className: "bcms-table" } : {}, ...notesId ? { "aria-describedby": notesId } : {}, children: [
732
+ ] }, i)) : sections.body.length > 0 && /* @__PURE__ */ jsx3("tbody", { ...role("rowgroup"), children: sections.body.map(rowEl) });
733
+ const table = /* @__PURE__ */ jsxs2("table", { ...role("table"), ...value.legacy === true ? { className: "bcms-table" } : {}, ...notesId ? { "aria-describedby": notesId } : {}, children: [
594
734
  caption && /* @__PURE__ */ jsx3("caption", { children: caption }),
595
- layout.columns.map((run, i) => /* @__PURE__ */ jsx3("colgroup", { span: span(run.width) }, i)),
596
- (groupRow || head > 0) && /* @__PURE__ */ jsxs2("thead", { children: [
735
+ sortable.size ? (layout.columns.length ? layout.columns.map((run) => run.width) : [layout.width]).map((w, i, all) => {
736
+ 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);
738
+ }) : layout.columns.map((run, i) => /* @__PURE__ */ jsx3("colgroup", { span: span(run.width) }, i)),
739
+ (groupRow || head > 0) && /* @__PURE__ */ jsxs2("thead", { ...role("rowgroup"), children: [
597
740
  groupRow,
598
741
  rows.slice(0, head).map(rowEl)
599
742
  ] }),
600
- bodies
743
+ bodies,
744
+ foot.length > 0 && /* @__PURE__ */ jsx3("tfoot", { ...role("rowgroup"), children: foot.map(rowEl) })
601
745
  ] });
602
- return notes ? /* @__PURE__ */ jsxs2("figure", { "data-rt": "table", children: [
746
+ const filter = value.filterable === true;
747
+ const ld = jsonLdOf(value.jsonLd);
748
+ const ldAttrs = ld ? { "data-jsonld": ld.type, ...ld.axis ? { "data-jsonld-axis": ld.axis } : {}, ...ld.priceRow ? { "data-jsonld-price": ld.priceRow } : {} } : {};
749
+ 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: [
603
751
  table,
604
- /* @__PURE__ */ jsx3("p", { "data-notes": "", id: notesId, children: notes })
752
+ notes ? /* @__PURE__ */ jsx3("p", { "data-notes": "", id: notesId, children: notes }) : null
605
753
  ] }) : table;
606
754
  }
607
755
  function buildComponents(renderBlock) {