@unlayer/react-elements 0.1.11 → 0.1.13

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/index.d.cts CHANGED
@@ -308,11 +308,16 @@ interface BaseItemComponentProps {
308
308
  className?: string;
309
309
  style?: React__default.CSSProperties;
310
310
  mode?: RenderMode;
311
+ /** Padding of the content wrapper around this item — a number (→ px) or a CSS
312
+ * string ("10px", "16px 24px"). Applied by the containing Column. */
313
+ containerPadding?: SizeInput;
311
314
  index?: number;
312
315
  colIndex?: number;
313
316
  cells?: any[];
314
317
  bodyValues?: any;
315
318
  rowValues?: any;
319
+ /** @internal - this column's values, threaded by Column for width-aware exporters */
320
+ columnValues?: any;
316
321
  /** @internal - Unlayer config threaded from UnlayerProvider */
317
322
  _config?: UnlayerConfig;
318
323
  }
@@ -508,7 +513,7 @@ interface ImageProps extends ItemComponentProps<ImageSemanticProps> {
508
513
  */
509
514
  declare const Image: React$1.FC<ItemComponentProps<ImageSemanticProps>>;
510
515
 
511
- type MenuSemanticProps = Omit<SemanticProps<MenuValues>, "padding"> & {
516
+ type MenuSemanticProps = Omit<SemanticProps<MenuValues>, "padding" | "fontFamily" | "fontWeight" | "fontSize" | "letterSpacing"> & Omit<TextStyleProps, "color" | "lineHeight"> & {
512
517
  /** Menu items shorthand */
513
518
  items?: MenuItem[];
514
519
  /** Inner padding — a number (→ px) or CSS string. */
package/dist/index.d.ts CHANGED
@@ -308,11 +308,16 @@ interface BaseItemComponentProps {
308
308
  className?: string;
309
309
  style?: React__default.CSSProperties;
310
310
  mode?: RenderMode;
311
+ /** Padding of the content wrapper around this item — a number (→ px) or a CSS
312
+ * string ("10px", "16px 24px"). Applied by the containing Column. */
313
+ containerPadding?: SizeInput;
311
314
  index?: number;
312
315
  colIndex?: number;
313
316
  cells?: any[];
314
317
  bodyValues?: any;
315
318
  rowValues?: any;
319
+ /** @internal - this column's values, threaded by Column for width-aware exporters */
320
+ columnValues?: any;
316
321
  /** @internal - Unlayer config threaded from UnlayerProvider */
317
322
  _config?: UnlayerConfig;
318
323
  }
@@ -508,7 +513,7 @@ interface ImageProps extends ItemComponentProps<ImageSemanticProps> {
508
513
  */
509
514
  declare const Image: React$1.FC<ItemComponentProps<ImageSemanticProps>>;
510
515
 
511
- type MenuSemanticProps = Omit<SemanticProps<MenuValues>, "padding"> & {
516
+ type MenuSemanticProps = Omit<SemanticProps<MenuValues>, "padding" | "fontFamily" | "fontWeight" | "fontSize" | "letterSpacing"> & Omit<TextStyleProps, "color" | "lineHeight"> & {
512
517
  /** Menu items shorthand */
513
518
  items?: MenuItem[];
514
519
  /** Inner padding — a number (→ px) or CSS string. */
package/dist/index.js CHANGED
@@ -466,6 +466,12 @@ var ErrorFallback = ({
466
466
  ]
467
467
  }
468
468
  ) });
469
+ function nextHtmlId(config, prefix) {
470
+ if (!config) return `${prefix}_1`;
471
+ const ids = config.__ids ?? (config.__ids = {});
472
+ ids[prefix] = (ids[prefix] || 0) + 1;
473
+ return `${prefix}_${ids[prefix]}`;
474
+ }
469
475
  function ensureMeta(values, type, index = 0) {
470
476
  return {
471
477
  ...values,
@@ -477,7 +483,7 @@ function ensureMeta(values, type, index = 0) {
477
483
  };
478
484
  }
479
485
  function renderComponent(config) {
480
- const { type, values, className, style, args = [], innerHTML, _config, exporter } = config;
486
+ const { type, values, className, style, args = [], innerHTML, _config, exporter, metaContext } = config;
481
487
  try {
482
488
  const cfg = _config ?? DEFAULT_CONFIG;
483
489
  const exporterConfig = {
@@ -492,7 +498,8 @@ function renderComponent(config) {
492
498
  } else {
493
499
  const meta = {
494
500
  exporterConfig,
495
- mergeTagState: cfg.mergeTagState
501
+ mergeTagState: cfg.mergeTagState,
502
+ ...metaContext ?? {}
496
503
  };
497
504
  html = exporter(values, ...args, void 0, meta);
498
505
  }
@@ -531,6 +538,7 @@ function createItemComponent(config) {
531
538
  cells = [],
532
539
  bodyValues = {},
533
540
  rowValues = {},
541
+ columnValues = {},
534
542
  _config,
535
543
  // Children
536
544
  children,
@@ -549,7 +557,7 @@ function createItemComponent(config) {
549
557
  index
550
558
  );
551
559
  const safeBodyValues = {
552
- contentWidth: 600,
560
+ contentWidth: "500px",
553
561
  ...bodyValues
554
562
  };
555
563
  const valuesForExporter = normalizeValuesForExporter(
@@ -563,6 +571,15 @@ function createItemComponent(config) {
563
571
  className,
564
572
  style,
565
573
  args: [index, colIndex, cells, safeBodyValues, rowValues],
574
+ // The 8th arg the exporters actually read: column/body context for
575
+ // width-aware rendering (Image's available-width calc), mirroring the editor.
576
+ metaContext: {
577
+ columnIndex: colIndex,
578
+ columnValues,
579
+ rowCells: cells,
580
+ rowValues,
581
+ bodyValues: safeBodyValues
582
+ },
566
583
  _config,
567
584
  exporter
568
585
  });
@@ -1098,7 +1115,7 @@ var Row = (props) => {
1098
1115
  ...values,
1099
1116
  cells,
1100
1117
  _meta: {
1101
- htmlID: `u_row_${index + 1}`,
1118
+ htmlID: nextHtmlId(_config, "u_row"),
1102
1119
  htmlClassNames: "u_row",
1103
1120
  ...values._meta || {}
1104
1121
  }
@@ -1160,7 +1177,7 @@ var Column = (props) => {
1160
1177
  const valuesWithMeta = {
1161
1178
  ...values,
1162
1179
  _meta: {
1163
- htmlID: `u_column_${index + 1}`,
1180
+ htmlID: nextHtmlId(_config, "u_column"),
1164
1181
  htmlClassNames: "u_column",
1165
1182
  ...values._meta || {}
1166
1183
  }
@@ -1176,17 +1193,26 @@ var Column = (props) => {
1176
1193
  if (typeof child.type === "function") {
1177
1194
  const ComponentType = child.type;
1178
1195
  const renderFn = ComponentType[UNLAYER_RENDER_KEY] || ComponentType;
1179
- const rendered = renderFn({ ...child.props, _config });
1196
+ const rendered = renderFn({
1197
+ ...child.props,
1198
+ _config,
1199
+ colIndex: index,
1200
+ cells,
1201
+ bodyValues,
1202
+ rowValues,
1203
+ columnValues: valuesWithMeta
1204
+ });
1180
1205
  if (rendered && typeof rendered === "object" && rendered.props && rendered.props.dangerouslySetInnerHTML) {
1181
1206
  const componentHTML = rendered.props.dangerouslySetInnerHTML.__html;
1182
1207
  const componentType = child.type;
1183
1208
  const componentName = (componentType?.displayName || componentType?.name || "component").toLowerCase();
1184
1209
  const childProps = child.props;
1185
- const containerPadding = childProps.containerPadding ?? childProps.values?.containerPadding ?? DEFAULT_CONTAINER_PADDING;
1210
+ const rawContainerPadding = childProps.containerPadding ?? childProps.values?.containerPadding ?? DEFAULT_CONTAINER_PADDING;
1211
+ const containerPadding = typeof rawContainerPadding === "number" ? `${rawContainerPadding}px` : rawContainerPadding;
1186
1212
  const contentValues = {
1187
1213
  containerPadding,
1188
1214
  _meta: {
1189
- htmlID: `u_content_${componentName}_${childIndex + 1}`,
1215
+ htmlID: nextHtmlId(_config, `u_content_${componentName}`),
1190
1216
  htmlClassNames: `u_content_${componentName}`
1191
1217
  }
1192
1218
  };
@@ -1271,6 +1297,7 @@ var Body = (props) => {
1271
1297
  const resolvedConfig = { ...DEFAULT_CONFIG, ...configProp };
1272
1298
  const mode = modeProp ?? resolvedConfig.mode ?? "web";
1273
1299
  const _config = { ...resolvedConfig, mode };
1300
+ _config.__ids = {};
1274
1301
  const values = mergeValues(
1275
1302
  DEFAULT_VALUES13,
1276
1303
  mapSemanticProps(semanticProps, DEFAULT_VALUES13, "Body")
@@ -1278,7 +1305,7 @@ var Body = (props) => {
1278
1305
  const valuesWithMeta = {
1279
1306
  ...values,
1280
1307
  _meta: {
1281
- htmlID: `u_body_${index + 1}`,
1308
+ htmlID: nextHtmlId(_config, "u_body"),
1282
1309
  htmlClassNames: "u_body",
1283
1310
  ...values._meta || {}
1284
1311
  }
@@ -1546,6 +1573,29 @@ function getDisplayName2(element) {
1546
1573
  const type = element.type;
1547
1574
  return type?.displayName || type?.name;
1548
1575
  }
1576
+ var VALID_ROOTS = /* @__PURE__ */ new Set(["Body", "Email", "Page", "Document"]);
1577
+ function unwrapRoot(element) {
1578
+ let current = element;
1579
+ for (let depth = 0; depth < 10; depth++) {
1580
+ const name = getDisplayName2(current);
1581
+ if (name && VALID_ROOTS.has(name)) break;
1582
+ const type = current.type;
1583
+ const isPlainFunctionComponent = typeof type === "function" && !type.prototype?.isReactComponent;
1584
+ if (!isPlainFunctionComponent) break;
1585
+ let produced;
1586
+ try {
1587
+ produced = type({ ...current.props });
1588
+ } catch (cause) {
1589
+ const detail = cause instanceof Error ? cause.message : String(cause);
1590
+ throw new Error(
1591
+ `[Unlayer] renderToJson: could not unwrap <${name || "wrapper"}>. A wrapper must be a plain component that synchronously returns a root (<Email>, <Page>, <Document>, or <Body>) and uses no React hooks. Pass the root element directly \u2014 e.g. renderToJson(<Email>\u2026</Email>). (${detail})`
1592
+ );
1593
+ }
1594
+ if (!React.isValidElement(produced)) break;
1595
+ current = produced;
1596
+ }
1597
+ return current;
1598
+ }
1549
1599
  function collectChildren2(node) {
1550
1600
  const result = [];
1551
1601
  React.Children.forEach(node, (child) => {
@@ -1762,9 +1812,9 @@ function renderRowToJson(element) {
1762
1812
  return processRow(element, counters);
1763
1813
  }
1764
1814
  function renderToJson(element) {
1815
+ element = unwrapRoot(element);
1765
1816
  const displayName = getDisplayName2(element);
1766
- const validRoots = /* @__PURE__ */ new Set(["Body", "Email", "Page", "Document"]);
1767
- if (!displayName || !validRoots.has(displayName)) {
1817
+ if (!displayName || !VALID_ROOTS.has(displayName)) {
1768
1818
  throw new Error(
1769
1819
  `[Unlayer] renderToJson: Root element must be <Body>, <Email>, <Page>, or <Document>, but got <${displayName || "unknown"}>. Wrap your content: <Body><Row><Column>...</Column></Row></Body>`
1770
1820
  );