@bettercms-ai/ui 0.17.1 → 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/blocks.js CHANGED
@@ -592,6 +592,8 @@ function pullQuoteHref(link) {
592
592
  }
593
593
  return "";
594
594
  }
595
+ var isPortableTextBlock = (n) => !!n && typeof n === "object" && n._type === "block";
596
+ var isPortableTextSpan = (n) => !!n && typeof n === "object" && n._type === "span";
595
597
  var PT_TYPES = {
596
598
  /** A generic embedded block: `{schemaKey, schemaLabel, fields}`, the successor to Lexical's BlockNode. */
597
599
  block: "bcmsBlock",
@@ -813,7 +815,9 @@ function normalizeCell(raw, at, mint, read) {
813
815
  ...raw.header === true ? { header: true } : {},
814
816
  ...span === void 0 ? {} : { span },
815
817
  ...rowSpan === void 0 ? {} : { rowSpan },
816
- ...typeof raw.group === "string" ? { group: raw.group } : {}
818
+ ...typeof raw.group === "string" ? { group: raw.group } : {},
819
+ ...raw.highlight === true ? { highlight: true } : {},
820
+ ...raw.sortable === true ? { sortable: true } : {}
817
821
  };
818
822
  }
819
823
  function normalizeRow(raw, at, mint, read) {
@@ -822,7 +826,10 @@ function normalizeRow(raw, at, mint, read) {
822
826
  _key: isRecord(raw) && isValidKey(raw._key) ? raw._key : mint("r", at),
823
827
  cells: cells.map((c, col) => normalizeCell(c, [at, col], mint, read)),
824
828
  ...isRecord(raw) && raw.head === true ? { head: true } : {},
825
- ...isRecord(raw) && typeof raw.group === "string" ? { group: raw.group } : {}
829
+ ...isRecord(raw) && typeof raw.group === "string" ? { group: raw.group } : {},
830
+ // The V2 table's two row flags ("Totals row", "Highlight this row"); see `PortableTextTableRow`.
831
+ ...isRecord(raw) && raw.footer === true ? { footer: true } : {},
832
+ ...isRecord(raw) && raw.highlight === true ? { highlight: true } : {}
826
833
  };
827
834
  }
828
835
  function builtInTableToTable(node, key = randomKey) {
@@ -879,9 +886,53 @@ function tableExtras(node) {
879
886
  ...typeof node.caption === "string" ? { caption: node.caption } : {},
880
887
  ...typeof node.notes === "string" ? { notes: node.notes } : {},
881
888
  ...rowGroups ? { rowGroups } : {},
882
- ...columnGroups ? { columnGroups } : {}
889
+ ...columnGroups ? { columnGroups } : {},
890
+ ...node.filterable === true ? { filterable: true } : {},
891
+ ...jsonLdOf(node.jsonLd) ? { jsonLd: jsonLdOf(node.jsonLd) } : {},
892
+ ...designOf(node.design) ? { design: designOf(node.design) } : {}
883
893
  };
884
894
  }
895
+ function designOf(v) {
896
+ if (!isRecord(v)) return void 0;
897
+ const d = {
898
+ ...v.responsive === "stack" || v.responsive === "cards" ? { responsive: v.responsive } : {},
899
+ ...v.sticky === true ? { sticky: true } : {}
900
+ };
901
+ return Object.keys(d).length ? d : void 0;
902
+ }
903
+ var JSONLD_TYPES = ["ItemList", "Dataset", "Offers"];
904
+ function jsonLdOf(v) {
905
+ if (!isRecord(v) || !JSONLD_TYPES.includes(v.type)) return void 0;
906
+ return {
907
+ type: v.type,
908
+ ...v.axis === "rows" || v.axis === "columns" ? { axis: v.axis } : {},
909
+ ...typeof v.priceRow === "string" && v.priceRow ? { priceRow: v.priceRow } : {}
910
+ };
911
+ }
912
+ function tableSections(table) {
913
+ const rows = Array.isArray(table.rows) ? table.rows : [];
914
+ const headCount = rows.findIndex((r) => !isRecord(r) || r.head !== true);
915
+ const head = rows.slice(0, headCount === -1 ? rows.length : headCount);
916
+ let footFrom = rows.length;
917
+ while (footFrom > head.length && isRecord(rows[footFrom - 1]) && rows[footFrom - 1].footer === true) footFrom -= 1;
918
+ return { head, body: rows.slice(head.length, footFrom), foot: rows.slice(footFrom) };
919
+ }
920
+ function highlightedColumns(table) {
921
+ return markedColumns(table, "highlight");
922
+ }
923
+ function sortableColumns(table) {
924
+ return markedColumns(table, "sortable");
925
+ }
926
+ function markedColumns(table, flag) {
927
+ const out = /* @__PURE__ */ new Set();
928
+ const first = Array.isArray(table.rows) ? table.rows[0] : void 0;
929
+ let at = 0;
930
+ for (const cell of isRecord(first) && Array.isArray(first.cells) ? first.cells : []) {
931
+ if (isRecord(cell) && cell[flag] === true) out.add(at);
932
+ at += isRecord(cell) && typeof cell.span === "number" && Number.isInteger(cell.span) && cell.span > 1 ? cell.span : 1;
933
+ }
934
+ return out;
935
+ }
885
936
  function tableGroupLayout(table) {
886
937
  const rows = Array.isArray(table.rows) ? table.rows : [];
887
938
  const labels = (list) => new Map(
@@ -899,8 +950,7 @@ function tableGroupLayout(table) {
899
950
  else columns.push({ width: spanOf2(cell), ...key === void 0 ? {} : { key, label: colLabels.get(key) } });
900
951
  }
901
952
  const rowLabels = labels(table.rowGroups);
902
- const headCount = rows.findIndex((r) => !isRecord(r) || r.head !== true);
903
- const body = headCount === -1 ? [] : rows.slice(headCount);
953
+ const { body } = tableSections(table);
904
954
  const runs = [];
905
955
  for (const row of body) {
906
956
  const key = isRecord(row) && typeof row.group === "string" && rowLabels.has(row.group) ? row.group : void 0;
@@ -939,6 +989,74 @@ function detachedComponentCopy(value) {
939
989
  ...typeof f.variant === "string" ? { variant: f.variant } : {}
940
990
  };
941
991
  }
992
+ function componentCopyLines(copy) {
993
+ const line = (v) => {
994
+ if (typeof v === "number" && Number.isFinite(v)) return String(v);
995
+ if (typeof v === "string") {
996
+ const t = v.replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/\s+/g, " ").trim();
997
+ return t || null;
998
+ }
999
+ if (isRecord3(v)) return line(v.label ?? v.text ?? v.title);
1000
+ return null;
1001
+ };
1002
+ return Object.values(copy.props).map(line).filter((s) => !!s);
1003
+ }
1004
+
1005
+ // ../richtext/src/plain.ts
1006
+ function portableTextToPlainText(value) {
1007
+ if (!Array.isArray(value)) return "";
1008
+ const lines = [];
1009
+ for (const node of value) {
1010
+ if (isPortableTextBlock(node)) {
1011
+ lines.push(node.children.map((c) => isPortableTextSpan(c) ? c.text : "").join(""));
1012
+ continue;
1013
+ }
1014
+ if (node._type === PT_TYPES.code && typeof node.code === "string") {
1015
+ lines.push(node.code);
1016
+ }
1017
+ if (node._type === PT_TYPES.pullQuote) {
1018
+ lines.push(...pullQuoteLines(node));
1019
+ continue;
1020
+ }
1021
+ if (node._type === PT_TYPES.keyTakeaways) {
1022
+ const { title, points } = keyTakeawaysView(node);
1023
+ lines.push(...title ? [title] : [], ...points);
1024
+ continue;
1025
+ }
1026
+ const table = migrateTable(node);
1027
+ if (table) {
1028
+ lines.push(...tableLines(table));
1029
+ continue;
1030
+ }
1031
+ const copy = detachedComponentCopy(node);
1032
+ if (copy) {
1033
+ lines.push(...componentCopyLines(copy));
1034
+ continue;
1035
+ }
1036
+ }
1037
+ return lines.join("\n");
1038
+ }
1039
+ var tableLines = (table) => {
1040
+ const rows = Array.isArray(table.rows) ? table.rows : [];
1041
+ const rowLine = (row) => (Array.isArray(row?.cells) ? row.cells : []).map((cell) => portableTextToPlainText(cell?.content).replace(/\s+/g, " ").trim()).join(" ").trim();
1042
+ const layout = tableGroupLayout(table);
1043
+ const one = (s) => typeof s === "string" ? s.replace(/\s+/g, " ").trim() : "";
1044
+ const head = layout.rows.length ? rows.slice(0, rows.length - layout.rows.reduce((n, r) => n + r.rows.length, 0)) : rows;
1045
+ const lines = [
1046
+ one(table.caption),
1047
+ layout.columns.map((r) => one(r.label)).filter(Boolean).join(" "),
1048
+ ...head.map(rowLine),
1049
+ ...layout.rows.flatMap((run) => [...run.label === void 0 ? [] : [one(run.label)], ...run.rows.map(rowLine)]),
1050
+ one(table.notes)
1051
+ ];
1052
+ const extras = /* @__PURE__ */ new Set([0, 1, lines.length - 1]);
1053
+ return lines.filter((l, i) => l !== "" || !extras.has(i));
1054
+ };
1055
+ var pullQuoteLines = (v) => {
1056
+ const text = (x) => typeof x === "string" ? x.trim() : "";
1057
+ const by = [text(v.name), text(v.role)].filter(Boolean).join(", ");
1058
+ return [text(v.quote), ...by ? [`\u2014 ${by}`] : []].filter(Boolean);
1059
+ };
942
1060
 
943
1061
  // ../richtext/src/read.ts
944
1062
  var isRecord4 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
@@ -1000,41 +1118,71 @@ function Table({ value }) {
1000
1118
  );
1001
1119
  const rows = Array.isArray(value?.rows) ? value.rows : [];
1002
1120
  if (rows.length === 0) return null;
1003
- const cells = (row) => (Array.isArray(row?.cells) ? row.cells : []).map((cell) => {
1004
- const Tag = cell?.header === true ? "th" : "td";
1005
- const span2 = typeof cell?.span === "number" && cell.span > 1 ? cell.span : void 0;
1006
- const rowSpan = typeof cell?.rowSpan === "number" && cell.rowSpan > 1 ? cell.rowSpan : void 0;
1007
- const content = Array.isArray(cell?.content) ? cell.content : [];
1008
- const lone = content.length === 1 && content[0]._type === "block" && content[0].style === "normal" && !content[0].listItem;
1009
- return /* @__PURE__ */ jsx14(Tag, { ...span2 ? { colSpan: span2 } : {}, ...rowSpan ? { rowSpan } : {}, children: /* @__PURE__ */ jsx14(PT, { value: content, components: lone ? inline : components }) }, cell?._key);
1010
- });
1011
- const rowEl = (row) => /* @__PURE__ */ jsx14("tr", { children: cells(row) }, row?._key);
1012
- const headCount = rows.findIndex((r) => r?.head !== true);
1013
- const head = headCount === -1 ? rows.length : headCount;
1121
+ const marked = highlightedColumns(value);
1122
+ const sortable = sortableColumns(value);
1123
+ const design = designOf(value.design);
1124
+ const stacked = design?.responsive === "stack" || design?.responsive === "cards";
1125
+ const role = (r) => stacked ? { role: r } : {};
1126
+ const labels = [];
1127
+ if (stacked) {
1128
+ const headRows = tableSections(value).head;
1129
+ let at = 0;
1130
+ for (const c of Array.isArray(headRows[headRows.length - 1]?.cells) ? headRows[headRows.length - 1].cells : []) {
1131
+ const text = portableTextToPlainText(Array.isArray(c?.content) ? c.content : []).replace(/\s+/g, " ").trim();
1132
+ const w = typeof c?.span === "number" && c.span > 1 ? c.span : 1;
1133
+ for (let i = 0; i < w; i += 1) labels[at + i] = text;
1134
+ at += w;
1135
+ }
1136
+ }
1137
+ const cells = (row) => {
1138
+ let col = 0;
1139
+ return (Array.isArray(row?.cells) ? row.cells : []).map((cell) => {
1140
+ const Tag = cell?.header === true ? "th" : "td";
1141
+ const span2 = typeof cell?.span === "number" && cell.span > 1 ? cell.span : void 0;
1142
+ const at = col;
1143
+ col += span2 ?? 1;
1144
+ const rowSpan = typeof cell?.rowSpan === "number" && cell.rowSpan > 1 ? cell.rowSpan : void 0;
1145
+ const content = Array.isArray(cell?.content) ? cell.content : [];
1146
+ const lone = content.length === 1 && content[0]._type === "block" && content[0].style === "normal" && !content[0].listItem;
1147
+ return /* @__PURE__ */ jsx14(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__ */ jsx14(PT, { value: content, components: lone ? inline : components }) }, cell?._key);
1148
+ });
1149
+ };
1150
+ const rowEl = (row) => /* @__PURE__ */ jsx14("tr", { ...role("row"), ...row?.highlight === true ? { "data-highlight": "true" } : {}, children: cells(row) }, row?._key);
1151
+ const sections = tableSections(value);
1152
+ const head = sections.head.length;
1153
+ const foot = sections.foot;
1014
1154
  const layout = tableGroupLayout(value);
1015
1155
  const caption = typeof value.caption === "string" ? value.caption.trim() : "";
1016
1156
  const notes = typeof value.notes === "string" ? value.notes.trim() : "";
1017
1157
  const notesId = notes && typeof value._key === "string" && value._key ? `${value._key}-notes` : void 0;
1018
1158
  const span = (n) => n > 1 ? n : void 0;
1019
- const groupRow = layout.columns.length ? /* @__PURE__ */ jsx14("tr", { children: layout.columns.flatMap(
1020
- (run, i) => run.label === void 0 ? Array.from({ length: run.width }, (_, k) => /* @__PURE__ */ jsx14("td", {}, `${i}-${k}`)) : [/* @__PURE__ */ jsx14("th", { scope: "colgroup", colSpan: span(run.width), "data-group": run.key, children: run.label }, i)]
1159
+ const groupRow = layout.columns.length ? /* @__PURE__ */ jsx14("tr", { ...role("row"), children: layout.columns.flatMap(
1160
+ (run, i) => run.label === void 0 ? Array.from({ length: run.width }, (_, k) => /* @__PURE__ */ jsx14("td", { ...role("cell") }, `${i}-${k}`)) : [/* @__PURE__ */ jsx14("th", { ...role("columnheader"), scope: "colgroup", colSpan: span(run.width), "data-group": run.key, children: run.label }, i)]
1021
1161
  ) }) : null;
1022
- const bodies = layout.rows.length ? layout.rows.map((run, i) => /* @__PURE__ */ jsxs11("tbody", { "data-key": run.key, children: [
1023
- run.label !== void 0 && /* @__PURE__ */ jsx14("tr", { children: /* @__PURE__ */ jsx14("th", { scope: "rowgroup", colSpan: span(layout.width), children: run.label }) }),
1162
+ const bodies = layout.rows.length ? layout.rows.map((run, i) => /* @__PURE__ */ jsxs11("tbody", { ...role("rowgroup"), "data-key": run.key, children: [
1163
+ run.label !== void 0 && /* @__PURE__ */ jsx14("tr", { ...role("row"), children: /* @__PURE__ */ jsx14("th", { ...role("rowheader"), scope: "rowgroup", colSpan: span(layout.width), children: run.label }) }),
1024
1164
  run.rows.map(rowEl)
1025
- ] }, i)) : head < rows.length && /* @__PURE__ */ jsx14("tbody", { children: rows.slice(head).map(rowEl) });
1026
- const table = /* @__PURE__ */ jsxs11("table", { ...value.legacy === true ? { className: "bcms-table" } : {}, ...notesId ? { "aria-describedby": notesId } : {}, children: [
1165
+ ] }, i)) : sections.body.length > 0 && /* @__PURE__ */ jsx14("tbody", { ...role("rowgroup"), children: sections.body.map(rowEl) });
1166
+ const table = /* @__PURE__ */ jsxs11("table", { ...role("table"), ...value.legacy === true ? { className: "bcms-table" } : {}, ...notesId ? { "aria-describedby": notesId } : {}, children: [
1027
1167
  caption && /* @__PURE__ */ jsx14("caption", { children: caption }),
1028
- layout.columns.map((run, i) => /* @__PURE__ */ jsx14("colgroup", { span: span(run.width) }, i)),
1029
- (groupRow || head > 0) && /* @__PURE__ */ jsxs11("thead", { children: [
1168
+ sortable.size ? (layout.columns.length ? layout.columns.map((run) => run.width) : [layout.width]).map((w, i, all) => {
1169
+ const from = all.slice(0, i).reduce((n, x) => n + x, 0);
1170
+ return /* @__PURE__ */ jsx14("colgroup", { children: Array.from({ length: w }, (_, k) => /* @__PURE__ */ jsx14("col", { ...sortable.has(from + k) ? { "data-sortable": "true" } : {} }, k)) }, i);
1171
+ }) : layout.columns.map((run, i) => /* @__PURE__ */ jsx14("colgroup", { span: span(run.width) }, i)),
1172
+ (groupRow || head > 0) && /* @__PURE__ */ jsxs11("thead", { ...role("rowgroup"), children: [
1030
1173
  groupRow,
1031
1174
  rows.slice(0, head).map(rowEl)
1032
1175
  ] }),
1033
- bodies
1176
+ bodies,
1177
+ foot.length > 0 && /* @__PURE__ */ jsx14("tfoot", { ...role("rowgroup"), children: foot.map(rowEl) })
1034
1178
  ] });
1035
- return notes ? /* @__PURE__ */ jsxs11("figure", { "data-rt": "table", children: [
1179
+ const filter = value.filterable === true;
1180
+ const ld = jsonLdOf(value.jsonLd);
1181
+ const ldAttrs = ld ? { "data-jsonld": ld.type, ...ld.axis ? { "data-jsonld-axis": ld.axis } : {}, ...ld.priceRow ? { "data-jsonld-price": ld.priceRow } : {} } : {};
1182
+ const designAttrs = design ? { ...design.responsive ? { "data-responsive": design.responsive } : {}, ...design.sticky ? { "data-sticky": "true" } : {} } : {};
1183
+ return notes || filter || ld || design ? /* @__PURE__ */ jsxs11("figure", { "data-rt": "table", ...designAttrs, ...filter ? { "data-filter": "true" } : {}, ...ldAttrs, children: [
1036
1184
  table,
1037
- /* @__PURE__ */ jsx14("p", { "data-notes": "", id: notesId, children: notes })
1185
+ notes ? /* @__PURE__ */ jsx14("p", { "data-notes": "", id: notesId, children: notes }) : null
1038
1186
  ] }) : table;
1039
1187
  }
1040
1188
  function buildComponents(renderBlock) {