@standhigher/puck-page-builder 0.12.0 → 0.12.2

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.
@@ -72,7 +72,7 @@ function validateFieldValue(config, value) {
72
72
  if (control === "text" && /[\r\n]/.test(value)) issues.push({ path: "", message: "\u5FC5\u987B\u4E3A\u5355\u884C\u6587\u672C\u3002" });
73
73
  if (config.validation?.minLength !== void 0 && stringLength(value) < config.validation.minLength) issues.push({ path: "", message: `\u81F3\u5C11\u9700\u8981 ${config.validation.minLength} \u4E2A\u5B57\u7B26\u3002` });
74
74
  if (config.validation?.maxLength !== void 0 && stringLength(value) > config.validation.maxLength) issues.push({ path: "", message: `\u6700\u591A\u5141\u8BB8 ${config.validation.maxLength} \u4E2A\u5B57\u7B26\u3002` });
75
- if (value && control === "url" && !isSafeUrl(value, config)) issues.push({ path: "", message: "\u5FC5\u987B\u662F\u7AD9\u5185\u76F8\u5BF9\u8DEF\u5F84\u6216\u5141\u8BB8\u7684 HTTP(S) URL\u3002" });
75
+ if (value && (control === "url" || control === "asset") && !isSafeUrl(value, config)) issues.push({ path: "", message: "\u5FC5\u987B\u662F\u7AD9\u5185\u76F8\u5BF9\u8DEF\u5F84\u6216\u5141\u8BB8\u7684 HTTP(S) URL\u3002" });
76
76
  if (value && control === "color" && !hexColor.test(value)) issues.push({ path: "", message: "\u5FC5\u987B\u662F\u5341\u516D\u8FDB\u5236\u989C\u8272\uFF0C\u4F8B\u5982 #005BD3\u3002" });
77
77
  return issues;
78
78
  }
@@ -327,11 +327,12 @@ function validateBlock(document, index, registry) {
327
327
  if (block.version !== definition.version) issues.push({ path: `${path}.version`, message: `\u533A\u5757\u7248\u672C\u5FC5\u987B\u4E3A ${definition.version}\u3002` });
328
328
  if (!supportsTarget(definition, document.target)) issues.push({ path, message: `\u533A\u5757\u4E0D\u652F\u6301 ${document.target} target\u3002` });
329
329
  if (definition.variants?.length && !definition.variants.some((variant) => variant.id === block.variant)) issues.push({ path: `${path}.variant`, message: `\u4E0D\u652F\u6301\u7684 variant\uFF1A${block.variant}\u3002` });
330
- const allowedProps = /* @__PURE__ */ new Set([...Object.keys(definition.defaultProps), ...Object.keys(definition.fields)]);
330
+ const allowedProps = /* @__PURE__ */ new Set([...Object.keys(definition.defaultProps), ...Object.entries(definition.fields).filter(([, field]) => field.persist !== false).map(([name]) => name)]);
331
331
  for (const key of Object.keys(block.props)) {
332
332
  if (!allowedProps.has(key)) issues.push({ path: `${path}.props.${key}`, message: "\u4E0D\u5141\u8BB8\u4FDD\u5B58\u672A\u77E5\u5B57\u6BB5\u3002" });
333
333
  }
334
334
  for (const [name, field] of Object.entries(definition.fields)) {
335
+ if (field.persist === false) continue;
335
336
  for (const issue of validateFieldValue(field, block.props[name])) {
336
337
  issues.push({ ...issue, path: issue.path ? `${path}.props.${name}.${issue.path}` : `${path}.props.${name}` });
337
338
  }
@@ -1,5 +1,5 @@
1
- import { h as ExtensionRegistry, V as ValidationIssue, c as BlockPolicy, F as FieldConfig } from './registry-CXJdOya3.js';
2
- export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, f as EditorOperationPolicy, g as ExtensionActionContext, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-CXJdOya3.js';
1
+ import { h as ExtensionRegistry, V as ValidationIssue, c as BlockPolicy, F as FieldConfig } from './registry-BkqtMP-A.js';
2
+ export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, f as EditorOperationPolicy, g as ExtensionActionContext, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-BkqtMP-A.js';
3
3
  import { PageDocument, JsonValue } from './schema.js';
4
4
  import 'react';
5
5
  import './theme.js';
@@ -13,7 +13,7 @@ import {
13
13
  validateBlockPolicy,
14
14
  validateFieldValue,
15
15
  validatePageDocumentWithRegistry
16
- } from "./chunk-YXBTNYPR.js";
16
+ } from "./chunk-RLKWR5JM.js";
17
17
  export {
18
18
  ExtensionRegistry,
19
19
  ExtensionRegistryError,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { f as EditorOperationPolicy, c as BlockPolicy, V as ValidationIssue, h as ExtensionRegistry } from './registry-CXJdOya3.js';
4
- export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, g as ExtensionActionContext, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, F as FieldConfig, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-CXJdOya3.js';
3
+ import { f as EditorOperationPolicy, c as BlockPolicy, V as ValidationIssue, h as ExtensionRegistry } from './registry-BkqtMP-A.js';
4
+ export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, g as ExtensionActionContext, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, F as FieldConfig, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-BkqtMP-A.js';
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';
@@ -238,7 +238,7 @@ type PageDocumentEditorShellProps = {
238
238
  /** Host-owned single-editor lock. Without this adapter the package stays backwards-compatible and editable. */
239
239
  sessionAdapter?: EditorSessionAdapter;
240
240
  onSessionStateChange?: (state: EditorSessionState) => void;
241
- /** Host-owned draft persistence shared by the manual-save and 800ms autosave paths. */
241
+ /** Host-owned draft persistence used by the 800ms autosave path. */
242
242
  draftPersistence?: DraftPersistenceAdapter;
243
243
  draftRevision?: number;
244
244
  autoSave?: boolean;
@@ -247,6 +247,13 @@ type PageDocumentEditorShellProps = {
247
247
  publishAction?: PublishAction;
248
248
  /** Host-owned picker/uploader for shop-scoped assets. */
249
249
  assetPicker?: AssetPickerAdapter;
250
+ /** External settings, keyed by block id (or block type for shared settings), outside document history and persistence. */
251
+ inspectorSettings?: Record<string, {
252
+ values: Record<string, JsonValue>;
253
+ disabled?: boolean;
254
+ onChange: (fieldName: string, value: JsonValue) => void;
255
+ footer?: ReactNode;
256
+ }>;
250
257
  /** Host-owned product picker. The shell only shows the selected snapshot and a button. */
251
258
  productPicker?: ProductPickerAdapter;
252
259
  /** Optional reusable page lifecycle summary. */
@@ -316,6 +323,9 @@ declare const messages: {
316
323
  readonly offline: "当前离线,恢复网络后将自动保存";
317
324
  readonly publishFailed: "发布失败";
318
325
  readonly published: "已发布";
326
+ readonly publishSuccessTitle: "发布成功";
327
+ readonly publishSuccessMessage: "页面已发布,消费者将看到当前版本。";
328
+ readonly publishSuccessClose: "完成";
319
329
  readonly back: "返回";
320
330
  readonly confirmLeaveTitle: "离开编辑器?";
321
331
  readonly leave: "离开";
@@ -341,6 +351,11 @@ declare const messages: {
341
351
  readonly selectProductsFailed: "无法选择商品,请重试。";
342
352
  readonly emptyProducts: "未选择商品";
343
353
  readonly productCountSuffix: "件商品";
354
+ readonly selectAsset: "选择图片";
355
+ readonly selectingAsset: "正在上传图片…";
356
+ readonly selectAssetFailed: "无法上传图片,请重试。";
357
+ readonly emptyAsset: "未设置图片";
358
+ readonly removeAsset: "移除图片";
344
359
  };
345
360
  readonly en: {
346
361
  readonly blocks: "Blocks";
@@ -374,6 +389,9 @@ declare const messages: {
374
389
  readonly offline: "Offline — changes will save when connection returns";
375
390
  readonly publishFailed: "Could not publish";
376
391
  readonly published: "Published";
392
+ readonly publishSuccessTitle: "Published";
393
+ readonly publishSuccessMessage: "This page is live. Shoppers will see the current version.";
394
+ readonly publishSuccessClose: "Done";
377
395
  readonly back: "Back";
378
396
  readonly confirmLeaveTitle: "Leave the editor?";
379
397
  readonly leave: "Leave";
@@ -399,13 +417,18 @@ declare const messages: {
399
417
  readonly selectProductsFailed: "Could not select products. Try again.";
400
418
  readonly emptyProducts: "No products selected";
401
419
  readonly productCountSuffix: "products";
420
+ readonly selectAsset: "Select image";
421
+ readonly selectingAsset: "Uploading image…";
422
+ readonly selectAssetFailed: "Could not upload the image. Try again.";
423
+ readonly emptyAsset: "No image selected";
424
+ readonly removeAsset: "Remove image";
402
425
  };
403
426
  };
404
427
  type AdminMessageKey = keyof typeof messages["zh-CN"];
405
428
  /** Minimal, dependency-free Admin copy catalog. Product locale remains PageDocument.settings.locale. */
406
429
  declare function createAdminI18n(locale?: string): {
407
430
  locale: AdminLocale;
408
- t: (key: AdminMessageKey) => "Desktop" | "Tablet" | "Mobile" | "未保存变更" | "Outline" | "Preview" | "缩放" | "区块" | "结构" | "撤销" | "恢复" | "收起左侧面板" | "收起属性面板" | "Delete" | "Duplicate" | "products" | "编辑锁已失效" | "属性" | "添加区块" | "复制" | "删除" | "确认删除区块?" | "删除后可使用撤销恢复。" | "取消" | "确认删除" | "上移" | "下移" | "正在加载编辑器…" | "页面还没有区块" | "编辑器无法加载" | "编辑器当前不可编辑" | "操作已完成" | "所有更改已保留在当前会话中" | "保存草稿" | "历史记录" | "正在保存…" | "发布" | "正在发布…" | "保存草稿失败" | "重试保存" | "当前离线,恢复网络后将自动保存" | "发布失败" | "已发布" | "返回" | "离开编辑器?" | "离开" | "自动缩放" | "正式预览" | "添加到店铺" | "正在获取编辑锁…" | "该页面正在被编辑" | "页面为只读状态" | "你有未保存的更改。确定要离开吗?" | "选择一个区块以编辑。" | "桌面" | "平板" | "手机" | "打开区块面板" | "打开属性面板" | "从 Shopify 选择商品" | "正在选择商品…" | "无法选择商品,请重试。" | "未选择商品" | "件商品" | "Blocks" | "Properties" | "Add block" | "Undo" | "Redo" | "Delete this block?" | "You can restore it with Undo after deleting." | "Cancel" | "Delete block" | "Move up" | "Move down" | "Loading editor…" | "This page has no blocks" | "The editor could not load" | "The editor is currently read-only" | "Action completed" | "Unsaved changes" | "Changes are kept in this session" | "Save draft" | "History" | "Saving…" | "Publish" | "Publishing…" | "Could not save draft" | "Retry save" | "Offline — changes will save when connection returns" | "Could not publish" | "Published" | "Back" | "Leave the editor?" | "Leave" | "Zoom" | "Auto zoom" | "Add to store" | "Acquiring edit lock…" | "This page is being edited" | "The edit lock has expired" | "This page is read-only" | "You have unsaved changes. Are you sure you want to leave?" | "Select a block to edit it." | "Collapse blocks panel" | "Collapse properties panel" | "Open blocks panel" | "Open properties panel" | "Select from Shopify" | "Selecting products…" | "Could not select products. Try again." | "No products selected";
431
+ t: (key: AdminMessageKey) => "Desktop" | "Tablet" | "Mobile" | "未保存变更" | "Outline" | "Preview" | "缩放" | "区块" | "结构" | "撤销" | "恢复" | "收起左侧面板" | "收起属性面板" | "Delete" | "Duplicate" | "products" | "编辑锁已失效" | "属性" | "添加区块" | "复制" | "删除" | "确认删除区块?" | "删除后可使用撤销恢复。" | "取消" | "确认删除" | "上移" | "下移" | "正在加载编辑器…" | "页面还没有区块" | "编辑器无法加载" | "编辑器当前不可编辑" | "操作已完成" | "所有更改已保留在当前会话中" | "保存草稿" | "历史记录" | "正在保存…" | "发布" | "正在发布…" | "保存草稿失败" | "重试保存" | "当前离线,恢复网络后将自动保存" | "发布失败" | "已发布" | "发布成功" | "页面已发布,消费者将看到当前版本。" | "完成" | "返回" | "离开编辑器?" | "离开" | "自动缩放" | "正式预览" | "添加到店铺" | "正在获取编辑锁…" | "该页面正在被编辑" | "页面为只读状态" | "你有未保存的更改。确定要离开吗?" | "选择一个区块以编辑。" | "桌面" | "平板" | "手机" | "打开区块面板" | "打开属性面板" | "从 Shopify 选择商品" | "正在选择商品…" | "无法选择商品,请重试。" | "未选择商品" | "件商品" | "选择图片" | "正在上传图片…" | "无法上传图片,请重试。" | "未设置图片" | "移除图片" | "Blocks" | "Properties" | "Add block" | "Undo" | "Redo" | "Delete this block?" | "You can restore it with Undo after deleting." | "Cancel" | "Delete block" | "Move up" | "Move down" | "Loading editor…" | "This page has no blocks" | "The editor could not load" | "The editor is currently read-only" | "Action completed" | "Unsaved changes" | "Changes are kept in this session" | "Save draft" | "History" | "Saving…" | "Publish" | "Publishing…" | "Could not save draft" | "Retry save" | "Offline — changes will save when connection returns" | "Could not publish" | "Published" | "This page is live. Shoppers will see the current version." | "Done" | "Back" | "Leave the editor?" | "Leave" | "Zoom" | "Auto zoom" | "Add to store" | "Acquiring edit lock…" | "This page is being edited" | "The edit lock has expired" | "This page is read-only" | "You have unsaved changes. Are you sure you want to leave?" | "Select a block to edit it." | "Collapse blocks panel" | "Collapse properties panel" | "Open blocks panel" | "Open properties panel" | "Select from Shopify" | "Selecting products…" | "Could not select products. Try again." | "No products selected" | "Select image" | "Uploading image…" | "Could not upload the image. Try again." | "No image selected" | "Remove image";
409
432
  };
410
433
 
411
434
  declare function toEngineData(document: PageDocument, registry?: ExtensionRegistry): Data;
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  validateBlockPolicy,
14
14
  validateFieldValue,
15
15
  validatePageDocumentWithRegistry
16
- } from "./chunk-YXBTNYPR.js";
16
+ } from "./chunk-RLKWR5JM.js";
17
17
  import {
18
18
  WebRenderer
19
19
  } from "./chunk-KYXIXIWK.js";
@@ -351,7 +351,7 @@ function PropertyPanel({
351
351
 
352
352
  // src/editor/shell/PageDocumentEditorShell.tsx
353
353
  import { Puck as Puck2, usePuck } from "@puckeditor/core";
354
- import { Badge as Badge3, Banner, Button as Button2, ButtonGroup as ButtonGroup2, InlineStack as InlineStack3, Select as Select2, Text as Text3, TextField } from "@shopify/polaris";
354
+ import { Badge as Badge3, Banner, Button as Button2, ButtonGroup as ButtonGroup2, InlineStack as InlineStack3, Modal as Modal2, Select as Select2, Text as Text3, TextField } from "@shopify/polaris";
355
355
  import { DragHandleIcon as DragHandleIcon2, LayoutSectionIcon as LayoutSectionIcon2, MenuIcon as MenuIcon2, ProductIcon, RedoIcon as RedoIcon2, UndoIcon as UndoIcon2, XIcon as XIcon2 } from "@shopify/polaris-icons";
356
356
  import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef4, useState as useState3 } from "react";
357
357
 
@@ -798,6 +798,9 @@ var messages = {
798
798
  offline: "\u5F53\u524D\u79BB\u7EBF\uFF0C\u6062\u590D\u7F51\u7EDC\u540E\u5C06\u81EA\u52A8\u4FDD\u5B58",
799
799
  publishFailed: "\u53D1\u5E03\u5931\u8D25",
800
800
  published: "\u5DF2\u53D1\u5E03",
801
+ publishSuccessTitle: "\u53D1\u5E03\u6210\u529F",
802
+ publishSuccessMessage: "\u9875\u9762\u5DF2\u53D1\u5E03\uFF0C\u6D88\u8D39\u8005\u5C06\u770B\u5230\u5F53\u524D\u7248\u672C\u3002",
803
+ publishSuccessClose: "\u5B8C\u6210",
801
804
  back: "\u8FD4\u56DE",
802
805
  confirmLeaveTitle: "\u79BB\u5F00\u7F16\u8F91\u5668\uFF1F",
803
806
  leave: "\u79BB\u5F00",
@@ -822,7 +825,12 @@ var messages = {
822
825
  selectingProducts: "\u6B63\u5728\u9009\u62E9\u5546\u54C1\u2026",
823
826
  selectProductsFailed: "\u65E0\u6CD5\u9009\u62E9\u5546\u54C1\uFF0C\u8BF7\u91CD\u8BD5\u3002",
824
827
  emptyProducts: "\u672A\u9009\u62E9\u5546\u54C1",
825
- productCountSuffix: "\u4EF6\u5546\u54C1"
828
+ productCountSuffix: "\u4EF6\u5546\u54C1",
829
+ selectAsset: "\u9009\u62E9\u56FE\u7247",
830
+ selectingAsset: "\u6B63\u5728\u4E0A\u4F20\u56FE\u7247\u2026",
831
+ selectAssetFailed: "\u65E0\u6CD5\u4E0A\u4F20\u56FE\u7247\uFF0C\u8BF7\u91CD\u8BD5\u3002",
832
+ emptyAsset: "\u672A\u8BBE\u7F6E\u56FE\u7247",
833
+ removeAsset: "\u79FB\u9664\u56FE\u7247"
826
834
  },
827
835
  en: {
828
836
  blocks: "Blocks",
@@ -856,6 +864,9 @@ var messages = {
856
864
  offline: "Offline \u2014 changes will save when connection returns",
857
865
  publishFailed: "Could not publish",
858
866
  published: "Published",
867
+ publishSuccessTitle: "Published",
868
+ publishSuccessMessage: "This page is live. Shoppers will see the current version.",
869
+ publishSuccessClose: "Done",
859
870
  back: "Back",
860
871
  confirmLeaveTitle: "Leave the editor?",
861
872
  leave: "Leave",
@@ -880,7 +891,12 @@ var messages = {
880
891
  selectingProducts: "Selecting products\u2026",
881
892
  selectProductsFailed: "Could not select products. Try again.",
882
893
  emptyProducts: "No products selected",
883
- productCountSuffix: "products"
894
+ productCountSuffix: "products",
895
+ selectAsset: "Select image",
896
+ selectingAsset: "Uploading image\u2026",
897
+ selectAssetFailed: "Could not upload the image. Try again.",
898
+ emptyAsset: "No image selected",
899
+ removeAsset: "Remove image"
884
900
  }
885
901
  };
886
902
  function createAdminI18n(locale) {
@@ -960,7 +976,7 @@ function PageDocumentEditorShell(props) {
960
976
  }, [managedSession.state, onSessionStateChange]);
961
977
  return /* @__PURE__ */ jsx7(EditorProvider, { initialDocument: props.initialDocument, registry: props.registry, policy: props.policy, loadState: props.loadState, sessionState: managedSession.state, session: managedSession.session, sessionMessage: managedSession.message, leaveWarning: createAdminI18n(props.adminLocale).t("leaveWarning"), onDocumentChange: props.onDocumentChange, children: /* @__PURE__ */ jsx7(PageDocumentEditor, { ...props }) });
962
978
  }
963
- function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onPublish, draftPersistence, draftRevision: initialDraftRevision, autoSave = true, autoSaveDelayMs = 800, publishAction, assetPicker, productPicker, pageStatus, onBack, onHistory, onPreview, onAddToStore, deleteConfirmation, availableBlockTypes, appearanceControls = false }) {
979
+ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onPublish, draftPersistence, draftRevision: initialDraftRevision, autoSave = true, autoSaveDelayMs = 800, publishAction, assetPicker, inspectorSettings, productPicker, pageStatus, onBack, onHistory, onPreview, onAddToStore, deleteConfirmation, availableBlockTypes, appearanceControls = false }) {
964
980
  const editor = useEditorContext();
965
981
  const [blockView, setBlockView] = useState3("blocks");
966
982
  const [leftRailOpen, setLeftRailOpen] = useState3(true);
@@ -978,6 +994,10 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
978
994
  const [confirmBack, setConfirmBack] = useState3(false);
979
995
  const i18n = createAdminI18n(adminLocale);
980
996
  const engineData = useMemo2(() => toEngineData(editor.document, registry), [editor.document, registry]);
997
+ const canvasThemeStyle = useMemo2(() => {
998
+ const template = editor.document.templateId ? registry?.getTemplate(editor.document.templateId) : void 0;
999
+ return toThemeStyle(mergeThemeTokens(template?.theme, editor.document.theme));
1000
+ }, [editor.document, registry]);
981
1001
  const validationIssues = useMemo2(() => validateDocumentBlocks(editor.document, registry), [editor.document, registry]);
982
1002
  const { confirmCanvasSelection, selectedBlockId, updateBlockProps, updateBlockPresentation } = editor;
983
1003
  const updateFromCanvasInput = useCallback2((id, props, preserveCanvasValue = false) => {
@@ -1006,7 +1026,7 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1006
1026
  const document = editor.document;
1007
1027
  setRequest("saving");
1008
1028
  setSaveState("saving");
1009
- setNotice(null);
1029
+ setNotice((current) => current === "published" ? current : null);
1010
1030
  try {
1011
1031
  const result = draftPersistence ? await draftPersistence.saveDraft({ document, expectedRevision: draftRevision, session: editor.session }) : await onSave?.(document);
1012
1032
  if (result?.revision !== void 0) setDraftRevision(result.revision);
@@ -1020,7 +1040,7 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1020
1040
  }
1021
1041
  }, [canPersistDraft, draftPersistence, draftRevision, editor, isOnline, onSave, request, validationIssues.length]);
1022
1042
  useEffect3(() => {
1023
- if (!autoSave || !canPersistDraft || !editor.isDirty || resolvedSaveState !== "dirty" || !isOnline || request !== "idle" || validationIssues.length > 0 || editor.sessionState !== "active") return;
1043
+ if (!autoSave || !canPersistDraft || !editor.isDirty || resolvedSaveState !== "dirty" && resolvedSaveState !== "failed" || !isOnline || request !== "idle" || validationIssues.length > 0 || editor.sessionState !== "active") return;
1024
1044
  const timer = window.setTimeout(() => {
1025
1045
  void save();
1026
1046
  }, autoSaveDelayMs);
@@ -1084,7 +1104,6 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1084
1104
  };
1085
1105
  const saveBadgeTone = resolvedSaveState === "failed" ? "critical" : resolvedSaveState === "offline" || resolvedSaveState === "dirty" ? "attention" : "success";
1086
1106
  const saveBadgeLabel = resolvedSaveState === "saving" ? i18n.t("saving") : resolvedSaveState === "failed" ? i18n.t("saveFailed") : resolvedSaveState === "offline" ? i18n.t("offline") : resolvedSaveState === "dirty" ? i18n.t("unsaved") : i18n.t("saved");
1087
- const saveButtonLabel = request === "saving" ? i18n.t("saving") : resolvedSaveState === "failed" ? i18n.t("retrySave") : i18n.t("save");
1088
1107
  const requestBack = () => {
1089
1108
  if (!onBack) return;
1090
1109
  if (editor.isDirty || request === "saving") setConfirmBack(true);
@@ -1114,18 +1133,17 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1114
1133
  /* @__PURE__ */ jsx7("div", { className: "pb-zoom-control", children: /* @__PURE__ */ jsx7(Select2, { label: i18n.t("zoom"), labelHidden: true, options: [{ label: i18n.t("zoomAuto"), value: "auto" }, { label: "50%", value: "50" }, { label: "70%", value: "70" }, { label: "100%", value: "100" }], value: zoom, onChange: (value) => setZoom(value) }) })
1115
1134
  ] }) }),
1116
1135
  /* @__PURE__ */ jsx7("div", { className: "pb-header-actions", children: /* @__PURE__ */ jsxs5(InlineStack3, { gap: "150", blockAlign: "center", wrap: true, children: [
1136
+ /* @__PURE__ */ jsx7(Button2, { accessibilityLabel: i18n.t("undo"), icon: UndoIcon2, variant: "tertiary", disabled: !editor.actionState.canUndo, onClick: editor.undo }),
1137
+ /* @__PURE__ */ jsx7(Button2, { accessibilityLabel: i18n.t("redo"), icon: RedoIcon2, variant: "tertiary", disabled: !editor.actionState.canRedo, onClick: editor.redo }),
1117
1138
  /* @__PURE__ */ jsx7(Badge3, { tone: saveBadgeTone, children: saveBadgeLabel }),
1118
1139
  onHistory ? /* @__PURE__ */ jsx7("span", { "data-editor-history": "", children: /* @__PURE__ */ jsx7(Button2, { disabled: request !== "idle", onClick: () => onHistory({ document: editor.document, draftRevision, session: editor.session }), children: i18n.t("history") }) }) : null,
1119
- /* @__PURE__ */ jsx7(Button2, { disabled: !canPersistDraft || !editor.isDirty || request !== "idle" || validationIssues.length > 0 || !isOnline, onClick: () => void save(), children: saveButtonLabel }),
1120
1140
  onPreview ? /* @__PURE__ */ jsx7(Button2, { disabled: request !== "idle" || !isOnline, onClick: () => void onPreview({ document: editor.document, draftRevision, session: editor.session }), children: i18n.t("preview") }) : null,
1121
1141
  onAddToStore ? /* @__PURE__ */ jsx7(Button2, { disabled: request !== "idle" || pageStatus?.publicationStatus === "unpublished", onClick: () => void onAddToStore({ document: editor.document, session: editor.session }), children: i18n.t("addToStore") }) : null,
1122
- /* @__PURE__ */ jsx7(Button2, { variant: "primary", disabled: !publishAction && !onPublish || request !== "idle" || validationIssues.length > 0 || !isOnline, onClick: () => void publish(), children: request === "publishing" ? i18n.t("publishing") : i18n.t("publish") }),
1123
- /* @__PURE__ */ jsx7(Button2, { accessibilityLabel: i18n.t("undo"), icon: UndoIcon2, variant: "tertiary", disabled: !editor.actionState.canUndo, onClick: editor.undo }),
1124
- /* @__PURE__ */ jsx7(Button2, { accessibilityLabel: i18n.t("redo"), icon: RedoIcon2, variant: "tertiary", disabled: !editor.actionState.canRedo, onClick: editor.redo })
1142
+ /* @__PURE__ */ jsx7(Button2, { variant: "primary", disabled: !publishAction && !onPublish || request !== "idle" || validationIssues.length > 0 || !isOnline, onClick: () => void publish(), children: request === "publishing" ? i18n.t("publishing") : i18n.t("publish") })
1125
1143
  ] }) })
1126
1144
  ] }) }),
1127
1145
  editor.loadState === "success" ? /* @__PURE__ */ jsx7(Banner, { tone: "success", children: i18n.t("success") }) : null,
1128
- notice ? /* @__PURE__ */ jsx7(Banner, { tone: notice === "published" ? "success" : "critical", children: i18n.t(notice) }) : null,
1146
+ notice && notice !== "published" ? /* @__PURE__ */ jsx7("div", { className: `pb-editor-notice pb-editor-notice--${notice}`, "data-testid": "editor-notice", "data-notice": notice, children: /* @__PURE__ */ jsx7(Banner, { tone: "critical", children: i18n.t(notice) }) }) : null,
1129
1147
  validationIssues.length > 0 ? /* @__PURE__ */ jsx7(Banner, { tone: "critical", title: "\u533A\u5757\u5C5E\u6027\u672A\u901A\u8FC7\u6821\u9A8C", children: /* @__PURE__ */ jsx7("ul", { children: validationIssues.map((issue) => /* @__PURE__ */ jsxs5("li", { children: [
1130
1148
  issue.path,
1131
1149
  ": ",
@@ -1168,7 +1186,7 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1168
1186
  ] }),
1169
1187
  /* @__PURE__ */ jsxs5("main", { className: "pb-canvas-area", children: [
1170
1188
  /* @__PURE__ */ jsxs5("div", { className: "pb-canvas-stage", children: [
1171
- /* @__PURE__ */ jsx7("div", { ref: canvasFrameRef, className: `pb-canvas-frame pb-canvas-frame--${editor.device}${zoom === "auto" ? "" : ` pb-canvas-frame--zoom-${zoom}`}`, "data-device": editor.device, "data-zoom": zoom, children: /* @__PURE__ */ jsx7(Puck2.Preview, {}) }),
1189
+ /* @__PURE__ */ jsx7("div", { ref: canvasFrameRef, className: `pb-canvas-frame pb-canvas-frame--${editor.device}${zoom === "auto" ? "" : ` pb-canvas-frame--zoom-${zoom}`}`, "data-device": editor.device, "data-zoom": zoom, style: canvasThemeStyle, children: /* @__PURE__ */ jsx7(Puck2.Preview, {}) }),
1172
1190
  draggingLibraryType ? /* @__PURE__ */ jsxs5("div", { className: "pb-canvas-drop-target", "data-testid": "canvas-drop-target", role: "region", "aria-label": "\u533A\u5757\u6295\u653E\u533A", onDragOver: (event) => event.preventDefault(), onDrop: dropFromLibrary, children: [
1173
1191
  "\u677E\u5F00\u4EE5\u6DFB\u52A0 ",
1174
1192
  blockTypeLabel(draggingLibraryType, registry)
@@ -1189,11 +1207,12 @@ function PageDocumentEditor({ iframe = false, registry, adminLocale, onSave, onP
1189
1207
  /* @__PURE__ */ jsx7(Button2, { accessibilityLabel: i18n.t("collapseRight"), icon: XIcon2, variant: "tertiary", onClick: () => setRightPanelOpen(false) })
1190
1208
  ] }),
1191
1209
  editor.selectedBlock ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1192
- /* @__PURE__ */ jsx7(DocumentInspector, { pageId: editor.document.pageId, assetPicker, productPicker, i18n, block: editor.selectedBlock, registry, disabled: !editor.actionState.canEdit, appearanceControls, onChange: (props) => editor.updateBlockProps(editor.selectedBlock.id, props), onPresentationChange: (presentation) => updateBlockPresentation(editor.selectedBlock.id, presentation) }),
1210
+ /* @__PURE__ */ jsx7(DocumentInspector, { settings: inspectorSettings?.[editor.selectedBlock.id] ?? inspectorSettings?.[editor.selectedBlock.type], pageId: editor.document.pageId, assetPicker, productPicker, i18n, block: editor.selectedBlock, registry, disabled: !editor.actionState.canEdit, appearanceControls, onChange: (props) => editor.updateBlockProps(editor.selectedBlock.id, props), onPresentationChange: (presentation) => updateBlockPresentation(editor.selectedBlock.id, presentation) }, editor.selectedBlock.id),
1193
1211
  /* @__PURE__ */ jsx7(InspectorActions, { block: editor.selectedBlock, canDuplicate: editor.actionState.canDuplicate, canDelete: editor.actionState.canDelete, canMove: editor.actionState.canReorder, canMoveUp: editor.document.blocks[0]?.id !== editor.selectedBlock.id, canMoveDown: editor.document.blocks.at(-1)?.id !== editor.selectedBlock.id, i18n, onDuplicate: () => editor.duplicateBlock(editor.selectedBlock.id), onDelete: () => editor.requestDeleteBlock(editor.selectedBlock.id), onMove: (direction) => editor.moveBlock(editor.selectedBlock.id, direction) })
1194
1212
  ] }) : /* @__PURE__ */ jsx7(Text3, { as: "p", tone: "subdued", children: i18n.t("selectBlock") })
1195
1213
  ] })
1196
1214
  ] }),
1215
+ /* @__PURE__ */ jsx7(Modal2, { instant: true, open: notice === "published", onClose: () => setNotice(null), title: i18n.t("publishSuccessTitle"), primaryAction: { content: i18n.t("publishSuccessClose"), onAction: () => setNotice(null) }, children: /* @__PURE__ */ jsx7(Modal2.Section, { children: /* @__PURE__ */ jsx7("div", { className: "pb-publish-success", "data-testid": "editor-notice", "data-notice": "published", children: /* @__PURE__ */ jsx7(Text3, { as: "p", children: i18n.t("publishSuccessMessage") }) }) }) }),
1197
1216
  editor.pendingDeleteBlock ? /* @__PURE__ */ jsx7(DeleteConfirmation, { block: editor.pendingDeleteBlock, config: deleteConfirmation, i18n, onCancel: editor.cancelDeleteBlock, onConfirm: editor.confirmDeleteBlock }) : null,
1198
1217
  confirmBack ? /* @__PURE__ */ jsx7(LeaveConfirmation, { i18n, onCancel: () => setConfirmBack(false), onConfirm: () => {
1199
1218
  setConfirmBack(false);
@@ -1260,6 +1279,39 @@ function InspectorTextControl({ label, value, control, disabled, onChange }) {
1260
1279
  if (control === "color") return /* @__PURE__ */ jsx7("input", { "aria-label": label, type: "color", value: /^#[\da-f]{6}$/i.test(stringValue) ? stringValue : "#000000", disabled, onChange: (event) => onChange(event.currentTarget.value) });
1261
1280
  return /* @__PURE__ */ jsx7(TextField, { label, labelHidden: true, value: stringValue, onChange, autoComplete: "off", disabled, multiline: control === "textarea" ? 4 : false, type: control === "url" ? "url" : "text" });
1262
1281
  }
1282
+ function InspectorAssetControl({ value, disabled, picker, pageId, blockId, i18n, onChange }) {
1283
+ const [busy, setBusy] = useState3(false);
1284
+ const [error, setError] = useState3(null);
1285
+ const active = useRef4(true);
1286
+ useEffect3(() => {
1287
+ active.current = !disabled;
1288
+ return () => {
1289
+ active.current = false;
1290
+ };
1291
+ }, [disabled]);
1292
+ const url = typeof value === "string" && validateFieldValue({ field: "", control: "asset" }, value).length === 0 ? value : "";
1293
+ return /* @__PURE__ */ jsxs5("div", { className: "pb-asset-picker", "data-testid": "asset-picker", children: [
1294
+ url ? /* @__PURE__ */ jsx7("img", { src: url, alt: "", className: "pb-asset-picker__preview" }) : /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "subdued", children: i18n.t("emptyAsset") }),
1295
+ url ? /* @__PURE__ */ jsx7(Button2, { fullWidth: true, variant: "tertiary", disabled: disabled || busy, onClick: () => onChange(""), children: i18n.t("removeAsset") }) : null,
1296
+ /* @__PURE__ */ jsx7(Button2, { fullWidth: true, disabled: disabled || busy || !picker, onClick: () => void (async () => {
1297
+ if (!picker) return;
1298
+ setBusy(true);
1299
+ setError(null);
1300
+ try {
1301
+ const asset = await picker.selectAsset({ pageId, blockId, current: { url } });
1302
+ if (asset && active.current) {
1303
+ if (validateFieldValue({ field: "", control: "asset", required: true }, asset.url).length) throw new Error("Invalid image URL");
1304
+ onChange(asset.url);
1305
+ }
1306
+ } catch {
1307
+ setError(i18n.t("selectAssetFailed"));
1308
+ } finally {
1309
+ setBusy(false);
1310
+ }
1311
+ })(), children: busy ? i18n.t("selectingAsset") : i18n.t("selectAsset") }),
1312
+ error ? /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "critical", children: error }) : null
1313
+ ] });
1314
+ }
1263
1315
  function InspectorProductsControl({ value, disabled, picker, pageId, blockId, i18n, onChange }) {
1264
1316
  const products = parseProductReferences(value);
1265
1317
  const [busy, setBusy] = useState3(false);
@@ -1286,7 +1338,7 @@ function InspectorProductsControl({ value, disabled, picker, pageId, blockId, i1
1286
1338
  error ? /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "critical", children: error }) : null
1287
1339
  ] });
1288
1340
  }
1289
- function InspectorField({ name, field, value, registry, disabled, productPicker, pageId, blockId, i18n, onChange }) {
1341
+ function InspectorField({ name, field, value, registry, disabled, assetPicker, productPicker, pageId, blockId, i18n, onChange }) {
1290
1342
  const label = field.label ?? name;
1291
1343
  const issues = validateFieldValue(field, value);
1292
1344
  const Field = registry?.getField(field.field)?.component;
@@ -1295,7 +1347,7 @@ function InspectorField({ name, field, value, registry, disabled, productPicker,
1295
1347
  /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", fontWeight: "semibold", children: label }),
1296
1348
  field.description ? /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "subdued", children: field.description }) : null
1297
1349
  ] }),
1298
- field.control === "products" ? /* @__PURE__ */ jsx7(InspectorProductsControl, { value, disabled, picker: productPicker, pageId, blockId, i18n, onChange }) : field.control ? /* @__PURE__ */ jsx7(InspectorTextControl, { label, value, control: field.control, disabled, onChange: (next) => onChange(next) }) : Field ? /* @__PURE__ */ jsx7(Field, { value, onChange }) : null,
1350
+ field.control === "products" ? /* @__PURE__ */ jsx7(InspectorProductsControl, { value, disabled, picker: productPicker, pageId, blockId, i18n, onChange }) : field.control === "asset" ? /* @__PURE__ */ jsx7(InspectorAssetControl, { value, disabled, picker: assetPicker, pageId, blockId, i18n, onChange }) : field.control ? /* @__PURE__ */ jsx7(InspectorTextControl, { label, value, control: field.control, disabled, onChange: (next) => onChange(next) }) : Field ? /* @__PURE__ */ jsx7(Field, { value, onChange }) : null,
1299
1351
  issues.map((issue) => /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "critical", children: issue.message }, issue.message))
1300
1352
  ] });
1301
1353
  }
@@ -1334,7 +1386,7 @@ function inspectorFieldConfig(name, field) {
1334
1386
  return { ...field, group: field.group ?? group, description };
1335
1387
  }
1336
1388
  var appearanceTokens = [["color.primary", "\u4E3B\u8272"], ["color.surface", "\u8868\u9762\u8272"], ["radius", "\u5706\u89D2"], ["spacing", "\u95F4\u8DDD"]];
1337
- function DocumentInspector({ pageId, assetPicker, productPicker, i18n, block, registry, disabled, appearanceControls, onChange, onPresentationChange }) {
1389
+ function DocumentInspector({ settings, pageId, assetPicker, productPicker, i18n, block, registry, disabled, appearanceControls, onChange, onPresentationChange }) {
1338
1390
  const [assetError, setAssetError] = useState3(null);
1339
1391
  const [selectingAsset, setSelectingAsset] = useState3(false);
1340
1392
  const definition = registry?.getBlock(block.type);
@@ -1373,7 +1425,8 @@ function DocumentInspector({ pageId, assetPicker, productPicker, i18n, block, re
1373
1425
  assetError ? /* @__PURE__ */ jsx7(Text3, { as: "p", variant: "bodySm", tone: "critical", children: assetError }) : null
1374
1426
  ] }) : null
1375
1427
  ] }) : null,
1376
- Object.entries(groupedFields).map(([group, fields]) => /* @__PURE__ */ jsx7(InspectorSection, { title: group, defaultOpen: group !== "Advanced", children: fields.map(([name, field]) => /* @__PURE__ */ jsx7(InspectorField, { name, field, value: block.props[name], registry, disabled, productPicker, pageId, blockId: block.id, i18n, onChange: (value) => onChange({ ...block.props, [name]: value }) }, name)) }, group)),
1428
+ Object.entries(groupedFields).map(([group, fields]) => /* @__PURE__ */ jsx7(InspectorSection, { title: group, defaultOpen: group !== "Advanced", children: fields.map(([name, field]) => /* @__PURE__ */ jsx7(InspectorField, { name, field, value: field.persist === false ? settings?.values[name] : block.props[name], registry, disabled: disabled || field.persist === false && (!settings || Boolean(settings.disabled)), assetPicker, productPicker, pageId, blockId: block.id, i18n, onChange: (value) => field.persist === false ? settings?.onChange(name, value) : onChange({ [name]: value }) }, name)) }, group)),
1429
+ Object.values(definition?.fields ?? {}).some((field) => field.persist === false) ? settings?.footer : null,
1377
1430
  appearanceControls && definition?.variants?.length ? /* @__PURE__ */ jsx7(InspectorSection, { title: "\u5916\u89C2", children: /* @__PURE__ */ jsx7(Select2, { label: "\u6837\u5F0F\u53D8\u4F53", options: definition.variants.map((variant) => ({ label: variant.label, value: variant.id })), value: block.variant, disabled, onChange: (variant) => onPresentationChange({ variant, style: block.style }) }) }) : null,
1378
1431
  appearanceControls && definition ? /* @__PURE__ */ jsx7(InspectorSection, { title: "\u6837\u5F0F\u8986\u76D6", defaultOpen: false, children: appearanceTokens.map(([token, label]) => /* @__PURE__ */ jsx7(TextField, { label, value: block.style[token] ?? "", placeholder: "\u7EE7\u627F\u9875\u9762\u6216\u6A21\u677F\u8BBE\u7F6E", autoComplete: "off", disabled, onChange: (value) => {
1379
1432
  const style = { ...block.style };
@@ -42,9 +42,11 @@ type FieldConfig = {
42
42
  field: string;
43
43
  label?: string;
44
44
  /** Product-facing editor metadata. Custom field components remain supported. */
45
- control?: "text" | "textarea" | "url" | "color" | "products";
45
+ control?: "text" | "textarea" | "url" | "color" | "products" | "asset";
46
46
  description?: string;
47
47
  group?: string;
48
+ /** Host-owned setting; never written to PageDocument props. */
49
+ persist?: boolean;
48
50
  /** Kept for compatibility; it participates in the built-in validation. */
49
51
  required?: boolean;
50
52
  validation?: FieldValidation;
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { h as ExtensionRegistry } from './registry-CXJdOya3.js';
2
+ import { h as ExtensionRegistry } from './registry-BkqtMP-A.js';
3
3
  import { PageDocument } from './schema.js';
4
4
  import './theme.js';
5
5
 
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { WebRenderer, WebRendererProps } from './renderer.js';
2
- export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, c as BlockPolicy, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, f as EditorOperationPolicy, g as ExtensionActionContext, h as ExtensionRegistry, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, F as FieldConfig, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, V as ValidationIssue, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-CXJdOya3.js';
2
+ export { B as BlockDefinition, a as BlockEditorProps, b as BlockOperation, c as BlockPolicy, d as BlockVariantDefinition, D as DataSourceDefinition, E as EditorAction, e as EditorActionPosition, f as EditorOperationPolicy, g as ExtensionActionContext, h as ExtensionRegistry, i as ExtensionRegistryError, j as ExtensionRegistryErrorCode, k as ExtensionRegistryOptions, l as ExtensionTarget, F as FieldConfig, m as FieldDefinition, n as FieldProps, o as FieldValidation, L as LifecycleHooks, P as PageBuilderExtension, R as RendererDefinition, T as TemplateDefinition, p as TemplateRegistry, q as TemplateSource, U as UISlotContribution, r as UISlotName, V as ValidationIssue, s as createExtensionRegistry, t as createTemplateRegistry } from './registry-BkqtMP-A.js';
3
3
  export { ProductReference, isProductReference, maximumBlockInstances, mergeBlockPolicies, minimumBlockInstances, parseProductReferences, toProductReferenceJson, validateBlockPolicy, validateFieldValue, validatePageDocumentWithRegistry } from './extensions.js';
4
4
  export { BlockNode, BlockStyleOverrides, DataBinding, JsonPrimitive, JsonValue, PageDocument, PageDocumentIssue, PageDocumentMigration, PageDocumentSchemaVersion, PageDocumentValidation, PageSettings, RenderTarget, createPageDocument, migratePageDocument, validatePageDocument } from './schema.js';
5
5
  export { ThemeTokenName, ThemeTokenValidation, ThemeTokens, mergeThemeTokens, normalizeThemeTokens, systemThemeTokens, toThemeStyle } from './theme.js';
package/dist/runtime.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  validateBlockPolicy,
14
14
  validateFieldValue,
15
15
  validatePageDocumentWithRegistry
16
- } from "./chunk-YXBTNYPR.js";
16
+ } from "./chunk-RLKWR5JM.js";
17
17
  import {
18
18
  WebRenderer
19
19
  } from "./chunk-KYXIXIWK.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standhigher/puck-page-builder",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "React PageDocument editor, extension registry, and web renderer for BestTrack page experiences.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/styles.css CHANGED
@@ -52,6 +52,7 @@ button:focus-visible, [role="button"]:focus-visible { outline: 2px solid var(--b
52
52
  .pb-inspector-field input:hover, .pb-inspector-field textarea:hover { border-color: #94a3b8; }
53
53
  .pb-inspector-field input:focus, .pb-inspector-field textarea:focus { border-color: #2563eb; box-shadow: 0 0 0 3px rgb(37 99 235 / 12%); }
54
54
  .pb-inspector-field input:disabled, .pb-inspector-field textarea:disabled { color: #94a3b8; background: #f8fafc; cursor: not-allowed; }
55
+ .pb-inspector-field input[type="color"] { width: 52px; padding: 4px; cursor: pointer; }
55
56
  .pb-product-picker { display: grid; gap: 8px; }
56
57
  .pb-product-picker__summary { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 10px 12px; border: 1px solid #e2e8f0; border-radius: 10px; background: #fff; }
57
58
  .pb-product-picker__summary p { margin: 0; color: #334155; }
@@ -60,6 +61,8 @@ button:focus-visible, [role="button"]:focus-visible { outline: 2px solid var(--b
60
61
  .pb-product-picker__thumb:first-child { margin-left: 0; }
61
62
  .pb-product-picker__thumb img, .pb-product-picker__thumb-fallback { display: block; width: 100%; height: 100%; object-fit: cover; }
62
63
  .pb-product-picker__thumb-fallback { background: #cbd5e1; }
64
+ .pb-asset-picker { display: grid; gap: 8px; }
65
+ .pb-asset-picker__preview { display: block; width: 100%; max-height: 180px; object-fit: cover; border: 1px solid #e2e8f0; border-radius: 10px; background: #f8fafc; }
63
66
  .pb-inspector__hint { margin: 0; padding: 0 var(--builder-space-2); color: #64748b; font-size: 12px; line-height: 1.5; }
64
67
  .pb-inspector-actions { padding-top: var(--builder-space-2); border-top: 1px solid #e2e8f0; }
65
68
  .pb-delete-confirmation-backdrop { position: fixed; z-index: 1000; inset: 0; display: grid; place-items: center; padding: var(--builder-space-4); background: rgb(15 23 42 / 42%); }
@@ -110,7 +113,12 @@ button:focus-visible, [role="button"]:focus-visible { outline: 2px solid var(--b
110
113
  .pb-document-block-row--selected { border-color: var(--builder-accent); background: var(--builder-accent-subtle); }
111
114
  .pb-editor-status { display: grid; place-items: center; box-sizing: border-box; width: 100%; min-height: 100dvh; padding: var(--builder-space-6); }
112
115
  .pb-editor-status > * { width: min(100%, 28rem); justify-self: center; }
113
- .pb-shell--v04 > .Polaris-Banner { margin: var(--builder-space-3) var(--builder-space-4) 0; }
116
+ .pb-shell--v04 > .Polaris-Banner,
117
+ .pb-editor-notice { margin: var(--builder-space-3) var(--builder-space-4) 0; }
118
+ body:has([data-notice="published"]) .Polaris-Modal-Dialog__Modal {
119
+ width: 620px;
120
+ max-width: min(620px, calc(100vw - 32px));
121
+ }
114
122
  .pb-document-canvas__text, .pb-document-canvas__image { max-width: 760px; margin: 0 auto; padding: 48px; color: #1d2939; background: #fff; cursor: pointer; }
115
123
  .pb-document-canvas__text { font-size: clamp(32px, 4vw, 52px); font-weight: 650; line-height: 1.1; letter-spacing: -.03em; }
116
124
  .pb-document-canvas__text p { margin: 0; }