@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.
- package/dist/{chunk-YXBTNYPR.js → chunk-RLKWR5JM.js} +3 -2
- package/dist/extensions.d.ts +2 -2
- package/dist/extensions.js +1 -1
- package/dist/index.d.ts +27 -4
- package/dist/index.js +72 -19
- package/dist/{registry-CXJdOya3.d.ts → registry-BkqtMP-A.d.ts} +3 -1
- package/dist/renderer.d.ts +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +1 -1
- package/src/styles.css +9 -1
|
@@ -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.
|
|
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
|
}
|
package/dist/extensions.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as ExtensionRegistry, V as ValidationIssue, c as BlockPolicy, F as FieldConfig } from './registry-
|
|
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-
|
|
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';
|
package/dist/extensions.js
CHANGED
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-
|
|
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-
|
|
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
|
|
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-
|
|
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(
|
|
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({
|
|
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;
|
package/dist/renderer.d.ts
CHANGED
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-
|
|
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
package/package.json
CHANGED
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
|
|
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; }
|