@standhigher/puck-page-builder 0.12.7 → 0.12.9

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/README.md CHANGED
@@ -65,7 +65,7 @@ const notice = {
65
65
  />
66
66
  ```
67
67
 
68
- Built-in field controls are `text` (single line), `textarea` (multi-line), `url`, `color`, and `products`. `products` only renders the selected snapshot and a host picker button; Shopify search stays in the host `productPicker` adapter. Their validation runs in the editor before save or publish; custom fields may continue using a block's `validate` function. `validateFieldValue` is exported from `/extensions` when a host needs the same validation outside the editor.
68
+ Built-in field controls are `text` (single line), `textarea` (multi-line), `url`, `color`, and `products`. `products` only renders the selected snapshot and a host picker button; Shopify search stays in the host `productPicker` adapter. A product snapshot may include catalog display money as `{ amount, currencyCode }` minor units; formatted price strings are dropped. Their validation runs in the editor before save or publish; custom fields may continue using a block's `validate` function. `validateFieldValue` is exported from `/extensions` when a host needs the same validation outside the editor.
69
69
 
70
70
  Theme values remain deliberately token-based: template theme → page theme → variant theme → block style. A block resets an inherited token by setting its local token explicitly (for example `{ radius: "0" }`), so no incompatible persisted style-reset shape is needed.
71
71
 
@@ -7,6 +7,13 @@ function isHttpUrl(value) {
7
7
  return false;
8
8
  }
9
9
  }
10
+ function isProductMoney(value) {
11
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
12
+ const candidate = value;
13
+ const amount = candidate.amount;
14
+ const currencyCode = candidate.currencyCode;
15
+ return typeof amount === "number" && Number.isInteger(amount) && amount >= 0 && typeof currencyCode === "string" && Boolean(currencyCode.trim());
16
+ }
10
17
  function isProductReference(value) {
11
18
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
12
19
  const candidate = value;
@@ -14,6 +21,7 @@ function isProductReference(value) {
14
21
  if (candidate.title !== void 0 && typeof candidate.title !== "string") return false;
15
22
  if (candidate.handle !== void 0 && typeof candidate.handle !== "string") return false;
16
23
  if (candidate.imageUrl !== void 0 && (typeof candidate.imageUrl !== "string" || !isHttpUrl(candidate.imageUrl))) return false;
24
+ if (candidate.price !== void 0 && !isProductMoney(candidate.price)) return false;
17
25
  return true;
18
26
  }
19
27
  function parseProductReferences(value) {
@@ -27,7 +35,8 @@ function parseProductReferences(value) {
27
35
  id: candidate.id.trim(),
28
36
  ...typeof candidate.title === "string" && candidate.title.trim() ? { title: candidate.title.trim() } : {},
29
37
  ...typeof candidate.handle === "string" && candidate.handle.trim() ? { handle: candidate.handle.trim() } : {},
30
- ...typeof candidate.imageUrl === "string" && isHttpUrl(candidate.imageUrl) ? { imageUrl: candidate.imageUrl } : {}
38
+ ...typeof candidate.imageUrl === "string" && isHttpUrl(candidate.imageUrl) ? { imageUrl: candidate.imageUrl } : {},
39
+ ...isProductMoney(candidate.price) ? { price: { amount: candidate.price.amount, currencyCode: candidate.price.currencyCode } } : {}
31
40
  });
32
41
  }
33
42
  return products;
@@ -37,7 +46,8 @@ function toProductReferenceJson(product) {
37
46
  id: product.id,
38
47
  ...product.title ? { title: product.title } : {},
39
48
  ...product.handle ? { handle: product.handle } : {},
40
- ...product.imageUrl ? { imageUrl: product.imageUrl } : {}
49
+ ...product.imageUrl ? { imageUrl: product.imageUrl } : {},
50
+ ...isProductMoney(product.price) ? { price: { amount: product.price.amount, currencyCode: product.price.currencyCode } } : {}
41
51
  };
42
52
  }
43
53
 
@@ -14,13 +14,19 @@ declare function validatePageDocumentWithRegistry(document: PageDocument, regist
14
14
 
15
15
  /**
16
16
  * JSON-only product snapshot persisted in PageDocument props.
17
- * Hosts may add a stable id plus display fields; never store tokens or prices as secrets.
17
+ * Hosts may add a stable id plus display fields. Catalog display money may be
18
+ * stored as minor units; never persist tokens, secrets, or formatted price strings.
18
19
  */
20
+ type ProductReferenceMoney = {
21
+ amount: number;
22
+ currencyCode: string;
23
+ };
19
24
  type ProductReference = {
20
25
  id: string;
21
26
  title?: string;
22
27
  imageUrl?: string;
23
28
  handle?: string;
29
+ price?: ProductReferenceMoney;
24
30
  };
25
31
  declare function isProductReference(value: unknown): value is ProductReference;
26
32
  declare function parseProductReferences(value: unknown): ProductReference[];
@@ -34,4 +40,4 @@ declare function mergeBlockPolicies(...policies: Array<BlockPolicy | undefined>)
34
40
  declare function minimumBlockInstances(policy: BlockPolicy | undefined): number;
35
41
  declare function maximumBlockInstances(policy: BlockPolicy | undefined): number;
36
42
 
37
- export { BlockPolicy, ExtensionRegistry, FieldConfig, type ProductReference, ValidationIssue, isProductReference, maximumBlockInstances, mergeBlockPolicies, minimumBlockInstances, parseProductReferences, toProductReferenceJson, validateBlockPolicy, validateFieldValue, validatePageDocumentWithRegistry };
43
+ export { BlockPolicy, ExtensionRegistry, FieldConfig, type ProductReference, type ProductReferenceMoney, ValidationIssue, isProductReference, maximumBlockInstances, mergeBlockPolicies, minimumBlockInstances, parseProductReferences, toProductReferenceJson, validateBlockPolicy, validateFieldValue, validatePageDocumentWithRegistry };
@@ -13,7 +13,7 @@ import {
13
13
  validateBlockPolicy,
14
14
  validateFieldValue,
15
15
  validatePageDocumentWithRegistry
16
- } from "./chunk-RLKWR5JM.js";
16
+ } from "./chunk-UWS3OP2P.js";
17
17
  export {
18
18
  ExtensionRegistry,
19
19
  ExtensionRegistryError,
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, d as
5
5
  import { PageDocument, BlockNode, JsonValue } from './schema.js';
6
6
  export { BlockStyleOverrides, DataBinding, PageDocumentIssue, PageDocumentMigration, PageDocumentSchemaVersion, PageSettings, RenderTarget, createPageDocument, migratePageDocument, validatePageDocument } from './schema.js';
7
7
  import { ProductReference } from './extensions.js';
8
- export { isProductReference, maximumBlockInstances, mergeBlockPolicies, minimumBlockInstances, parseProductReferences, toProductReferenceJson, validateBlockPolicy, validateFieldValue, validatePageDocumentWithRegistry } from './extensions.js';
8
+ export { ProductReferenceMoney, isProductReference, maximumBlockInstances, mergeBlockPolicies, minimumBlockInstances, parseProductReferences, toProductReferenceJson, validateBlockPolicy, validateFieldValue, validatePageDocumentWithRegistry } from './extensions.js';
9
9
  export { ThemeTokenName, ThemeTokens, mergeThemeTokens, normalizeThemeTokens, systemThemeTokens, toThemeStyle } from './theme.js';
10
10
  import { Data } from '@puckeditor/core';
11
11
  export { WebRenderer, WebRendererProps } from './renderer.js';