@propeller-commerce/propeller-v2-react-ui 0.4.17 → 0.4.18

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
@@ -6077,6 +6077,27 @@ interface ProductSpecificationsProps {
6077
6077
  * rendered above the attribute table. Omitted when empty.
6078
6078
  */
6079
6079
  packageDescription?: string;
6080
+ /**
6081
+ * Render arbitrary content at the START of the specifications, before the
6082
+ * fetched attribute rows. Receives the active `layout` so the consumer can
6083
+ * return markup that fits the container:
6084
+ * - `'table'` → return one or more `<tr>` (injected inside `<tbody>`), e.g.
6085
+ * a labelled "Unit of measure" row.
6086
+ * - `'list'` → return block element(s) (injected inside the list stack).
6087
+ * In grouped mode it renders once, above the first group. Return
6088
+ * `null`/`undefined` to render nothing.
6089
+ */
6090
+ beforeSpecs?: (ctx: {
6091
+ layout: 'table' | 'list';
6092
+ }) => React$1.ReactNode;
6093
+ /**
6094
+ * Render arbitrary content at the END of the specifications, after the
6095
+ * fetched attribute rows. Same `layout` contract as {@link beforeSpecs}.
6096
+ * In grouped mode it renders once, below the last group.
6097
+ */
6098
+ afterSpecs?: (ctx: {
6099
+ layout: 'table' | 'list';
6100
+ }) => React$1.ReactNode;
6080
6101
  /** Extra CSS class applied to the root element. */
6081
6102
  className?: string;
6082
6103
  }
@@ -6180,6 +6201,22 @@ interface ProductTabsProps {
6180
6201
  * ProductSpecifications.
6181
6202
  */
6182
6203
  specificationsPackageDescription?: string;
6204
+ /**
6205
+ * Render arbitrary content at the start of the specifications section (before
6206
+ * the attribute rows) — e.g. a labelled "Unit of measure" row. Passed as
6207
+ * `beforeSpecs` to ProductSpecifications; receives the active `layout` so the
6208
+ * consumer can return a `<tr>` (table) or block (list).
6209
+ */
6210
+ specificationsBeforeSpecs?: (ctx: {
6211
+ layout: 'table' | 'list';
6212
+ }) => React$1.ReactNode;
6213
+ /**
6214
+ * Render arbitrary content at the end of the specifications section (after the
6215
+ * attribute rows). Passed as `afterSpecs` to ProductSpecifications.
6216
+ */
6217
+ specificationsAfterSpecs?: (ctx: {
6218
+ layout: 'table' | 'list';
6219
+ }) => React$1.ReactNode;
6183
6220
  /**
6184
6221
  * Override UI strings for the Downloads section.
6185
6222
  * Available keys: title, download
package/dist/index.d.ts CHANGED
@@ -6077,6 +6077,27 @@ interface ProductSpecificationsProps {
6077
6077
  * rendered above the attribute table. Omitted when empty.
6078
6078
  */
6079
6079
  packageDescription?: string;
6080
+ /**
6081
+ * Render arbitrary content at the START of the specifications, before the
6082
+ * fetched attribute rows. Receives the active `layout` so the consumer can
6083
+ * return markup that fits the container:
6084
+ * - `'table'` → return one or more `<tr>` (injected inside `<tbody>`), e.g.
6085
+ * a labelled "Unit of measure" row.
6086
+ * - `'list'` → return block element(s) (injected inside the list stack).
6087
+ * In grouped mode it renders once, above the first group. Return
6088
+ * `null`/`undefined` to render nothing.
6089
+ */
6090
+ beforeSpecs?: (ctx: {
6091
+ layout: 'table' | 'list';
6092
+ }) => React$1.ReactNode;
6093
+ /**
6094
+ * Render arbitrary content at the END of the specifications, after the
6095
+ * fetched attribute rows. Same `layout` contract as {@link beforeSpecs}.
6096
+ * In grouped mode it renders once, below the last group.
6097
+ */
6098
+ afterSpecs?: (ctx: {
6099
+ layout: 'table' | 'list';
6100
+ }) => React$1.ReactNode;
6080
6101
  /** Extra CSS class applied to the root element. */
6081
6102
  className?: string;
6082
6103
  }
@@ -6180,6 +6201,22 @@ interface ProductTabsProps {
6180
6201
  * ProductSpecifications.
6181
6202
  */
6182
6203
  specificationsPackageDescription?: string;
6204
+ /**
6205
+ * Render arbitrary content at the start of the specifications section (before
6206
+ * the attribute rows) — e.g. a labelled "Unit of measure" row. Passed as
6207
+ * `beforeSpecs` to ProductSpecifications; receives the active `layout` so the
6208
+ * consumer can return a `<tr>` (table) or block (list).
6209
+ */
6210
+ specificationsBeforeSpecs?: (ctx: {
6211
+ layout: 'table' | 'list';
6212
+ }) => React$1.ReactNode;
6213
+ /**
6214
+ * Render arbitrary content at the end of the specifications section (after the
6215
+ * attribute rows). Passed as `afterSpecs` to ProductSpecifications.
6216
+ */
6217
+ specificationsAfterSpecs?: (ctx: {
6218
+ layout: 'table' | 'list';
6219
+ }) => React$1.ReactNode;
6183
6220
  /**
6184
6221
  * Override UI strings for the Downloads section.
6185
6222
  * Available keys: title, download
package/dist/index.js CHANGED
@@ -15095,7 +15095,11 @@ function ProductSpecifications(rawProps) {
15095
15095
  if (!props.productId || !props.graphqlClient) return;
15096
15096
  fetchSpecs(props.productId);
15097
15097
  }, [props.productId]);
15098
- return /* @__PURE__ */ jsx(Fragment, { children: !loading && (hasPublicAttributes() || props.packageDescription) ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
15098
+ const layoutMode = props.layout === "list" ? "list" : "table";
15099
+ const before = props.beforeSpecs?.({ layout: layoutMode });
15100
+ const after = props.afterSpecs?.({ layout: layoutMode });
15101
+ const hasSlotContent = before != null || after != null;
15102
+ return /* @__PURE__ */ jsx(Fragment, { children: !loading && (hasPublicAttributes() || props.packageDescription || hasSlotContent) ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
15099
15103
  "div",
15100
15104
  {
15101
15105
  className: `propeller-product-specifications ${props.className || ""}`,
@@ -15104,26 +15108,38 @@ function ProductSpecifications(rawProps) {
15104
15108
  children: [
15105
15109
  props.packageDescription ? /* @__PURE__ */ jsx("p", { className: "propeller-product-specifications__package-description mb-4 text-sm text-muted-foreground", children: props.packageDescription }) : null,
15106
15110
  !props.grouping ? /* @__PURE__ */ jsxs(Fragment, { children: [
15107
- props.layout !== "list" ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: getAttributes()?.map((attr, i) => /* @__PURE__ */ jsxs("tr", { className: "propeller-product-specifications__row odd:bg-card even:bg-muted/20", children: [
15108
- /* @__PURE__ */ jsx("td", { className: "px-4 py-2 font-medium text-foreground w-1/2", children: getAttributeLabel(attr) }),
15109
- /* @__PURE__ */ jsx("td", { className: "px-4 py-2 text-muted-foreground", children: getAttributeValue(attr) })
15110
- ] }, i)) }) }) }) : null,
15111
- props.layout === "list" ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: getAttributes()?.map((attr, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
15112
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: getAttributeLabel(attr) }),
15113
- /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: getAttributeValue(attr) })
15114
- ] }, i)) }) : null
15111
+ props.layout !== "list" ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsxs("tbody", { className: "divide-y divide-border", children: [
15112
+ before,
15113
+ getAttributes()?.map((attr, i) => /* @__PURE__ */ jsxs("tr", { className: "propeller-product-specifications__row odd:bg-card even:bg-muted/20", children: [
15114
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-2 font-medium text-foreground w-1/2", children: getAttributeLabel(attr) }),
15115
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-2 text-muted-foreground", children: getAttributeValue(attr) })
15116
+ ] }, i)),
15117
+ after
15118
+ ] }) }) }) : null,
15119
+ props.layout === "list" ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
15120
+ before,
15121
+ getAttributes()?.map((attr, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
15122
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: getAttributeLabel(attr) }),
15123
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: getAttributeValue(attr) })
15124
+ ] }, i)),
15125
+ after
15126
+ ] }) : null
15115
15127
  ] }) : null,
15116
- !!props.grouping ? /* @__PURE__ */ jsx(Fragment, { children: getGroups()?.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
15117
- !!group ? /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-muted-foreground uppercase tracking-wide mb-2", children: group }) : null,
15118
- props.layout !== "list" ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: getAttributesByGroup(group)?.map((attr, i) => /* @__PURE__ */ jsxs("tr", { className: "propeller-product-specifications__row odd:bg-card even:bg-muted/20", children: [
15119
- /* @__PURE__ */ jsx("td", { className: "px-4 py-2 font-medium text-foreground w-1/2", children: getAttributeLabel(attr) }),
15120
- /* @__PURE__ */ jsx("td", { className: "px-4 py-2 text-muted-foreground", children: getAttributeValue(attr) })
15121
- ] }, i)) }) }) }) : null,
15122
- props.layout === "list" ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: getAttributesByGroup(group)?.map((attr, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
15123
- /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: getAttributeLabel(attr) }),
15124
- /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: getAttributeValue(attr) })
15125
- ] }, i)) }) : null
15126
- ] }, group)) }) : null
15128
+ !!props.grouping ? /* @__PURE__ */ jsxs(Fragment, { children: [
15129
+ before ? layoutMode === "table" ? /* @__PURE__ */ jsx("div", { className: "mb-6 overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: before }) }) }) : /* @__PURE__ */ jsx("div", { className: "mb-6 space-y-3", children: before }) : null,
15130
+ getGroups()?.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
15131
+ !!group ? /* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-muted-foreground uppercase tracking-wide mb-2", children: group }) : null,
15132
+ props.layout !== "list" ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: getAttributesByGroup(group)?.map((attr, i) => /* @__PURE__ */ jsxs("tr", { className: "propeller-product-specifications__row odd:bg-card even:bg-muted/20", children: [
15133
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-2 font-medium text-foreground w-1/2", children: getAttributeLabel(attr) }),
15134
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-2 text-muted-foreground", children: getAttributeValue(attr) })
15135
+ ] }, i)) }) }) }) : null,
15136
+ props.layout === "list" ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: getAttributesByGroup(group)?.map((attr, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
15137
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: getAttributeLabel(attr) }),
15138
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: getAttributeValue(attr) })
15139
+ ] }, i)) }) : null
15140
+ ] }, group)),
15141
+ after ? layoutMode === "table" ? /* @__PURE__ */ jsx("div", { className: "mb-6 overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: after }) }) }) : /* @__PURE__ */ jsx("div", { className: "space-y-3", children: after }) : null
15142
+ ] }) : null
15127
15143
  ]
15128
15144
  }
15129
15145
  ) }) : null });
@@ -15332,7 +15348,9 @@ function ProductTabs(rawProps) {
15332
15348
  language: props.language,
15333
15349
  layout: props.specificationsLayout,
15334
15350
  grouping: props.specificationsGrouping,
15335
- packageDescription: props.specificationsPackageDescription
15351
+ packageDescription: props.specificationsPackageDescription,
15352
+ beforeSpecs: props.specificationsBeforeSpecs,
15353
+ afterSpecs: props.specificationsAfterSpecs
15336
15354
  }
15337
15355
  ) }) : null,
15338
15356
  isActive("downloads") && isTabVisible("downloads") ? /* @__PURE__ */ jsx(