pagepilot-visual-editor 1.0.30 → 1.0.33
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/CHANGELOG.md +20 -0
- package/dist/blocks-internal/block-button/src/index.d.ts +6 -0
- package/dist/blocks-internal/block-heading/src/index.d.ts +2 -2
- package/dist/blocks-internal/block-list/src/index.d.ts +1 -1
- package/dist/editor-sample/App/InspectorDrawer/BehaviourPanel.d.ts +1 -1
- package/dist/editor-sample/App/InspectorDrawer/ConfigurationPanel/input-panels/MenuPickerSidebarPanel.d.ts +1 -1
- package/dist/editor-sample/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/VariableLinkHint.d.ts +22 -3
- package/dist/editor-sample/App/InspectorDrawer/LayersPanelStyles.d.ts +1 -1
- package/dist/editor-sample/App/InspectorDrawer/LayoutPanel/templateHelpers.d.ts +11 -39
- package/dist/editor-sample/App/InspectorDrawer/VariablesPanel/AiGenerateButton.d.ts +5 -1
- package/dist/editor-sample/App/InspectorDrawer/VariablesPanel/ItemsArrayRepeatSection.d.ts +2 -3
- package/dist/editor-sample/App/InspectorDrawer/VariablesPanel/aiFill.d.ts +42 -3
- package/dist/editor-sample/App/InspectorDrawer/VariablesPanel/useAutoRegisterTokenFields.d.ts +8 -0
- package/dist/editor-sample/App/InspectorDrawer/components/RichTextAiButton.d.ts +7 -0
- package/dist/editor-sample/App/TemplatePanel/pageGuide/iframeSrcDoc.d.ts +3 -6
- package/dist/editor-sample/App/shared/PagePreviewFrame.d.ts +17 -2
- package/dist/editor-sample/App/shared/editor.styles.d.ts +2 -2
- package/dist/editor-sample/documents/blocks/EmailLayout/EmailLayoutPropsSchema.d.ts +4 -0
- package/dist/editor-sample/documents/blocks/MenuPicker/MenuPropsSchema.d.ts +5 -0
- package/dist/editor-sample/documents/blocks/Table/TableImportDialog.styles.d.ts +6 -6
- package/dist/editor-sample/documents/blocks/helpers/InlineTextToolbar/popovers/TableResizeOverlay.d.ts +17 -0
- package/dist/editor-sample/documents/blocks/helpers/block-wrappers/saveAsTemplateUtils.d.ts +8 -6
- package/dist/editor-sample/documents/blocks/helpers/documentUtils.d.ts +22 -2
- package/dist/editor-sample/documents/blocks/helpers/responsiveStyle.d.ts +1 -1
- package/dist/editor-sample/documents/blocks/helpers/variableBinding.d.ts +0 -2
- package/dist/editor-sample/documents/editor/EditorContext.d.ts +10 -0
- package/dist/editor-sample/documents/editor/core.d.ts +20 -2
- package/dist/editor-sample/documents/editor/templateVariables.d.ts +29 -13
- package/dist/email-builder-core/blocks/Container/ContainerReader.d.ts +1 -1
- package/dist/email-builder-core/blocks/EmailLayout/EmailLayoutPropsSchema.d.ts +4 -0
- package/dist/email-builder-core/blocks/FlexColumns/FlexColumnsPropsSchema.d.ts +3 -0
- package/dist/email-builder-core/blocks/FlexColumns/flexColumnsHelpers.d.ts +4 -2
- package/dist/email-builder-core/blocks/MenuPicker/MenuColumns.d.ts +13 -0
- package/dist/email-builder-core/blocks/MenuPicker/MenuPropsSchema.d.ts +10 -0
- package/dist/email-builder-core/renderers/themeTokens.d.ts +100 -4
- package/dist/host-stubs/modules/allSlugs/allSlugsActions.d.ts +1 -0
- package/dist/host-stubs/modules/allSlugs/allSlugsSelectors.d.ts +1 -0
- package/dist/host-stubs/modules/shared/axios/authAxios.d.ts +1 -0
- package/dist/host-stubs/modules/websiteV2/propagateFromPage.d.ts +4 -0
- package/dist/host-stubs/view/shared/styles/Table.styles.d.ts +1 -1
- package/dist/{index-CStZQ7E0.js → index-BONR8bWR.js} +1 -1
- package/dist/{index-B8pdGALF.js → index-B_cb-ZLC.js} +32297 -30421
- package/dist/{index-DVx38kGU.cjs → index-BfIWhBCR.cjs} +321 -313
- package/dist/{index-C-KL2oQP.cjs → index-CFA3aG_U.cjs} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/render.cjs +157 -149
- package/dist/render.js +4332 -3948
- package/dist/{xlsx-DUs4Mvqq.cjs → xlsx-CBpoXUEM.cjs} +1 -1
- package/dist/{xlsx-bYU68TCR.js → xlsx-DSqBw3Em.js} +1 -1
- package/package.json +1 -1
- package/dist/editor-sample/App/InspectorDrawer/VariablesPanel/AiFillAllDialog.d.ts +0 -21
|
@@ -36,6 +36,13 @@ export declare const addRepeatRow: (documentTree: Record<string, any>, sourceBlo
|
|
|
36
36
|
* arrays. Used to delete a repeat row's cloned container subtree.
|
|
37
37
|
*/
|
|
38
38
|
export declare function removeSubtree(documentTree: Record<string, any>, idsToRemove: Set<string>): Record<string, any>;
|
|
39
|
+
/**
|
|
40
|
+
* removeSubtree for deleted repeat rows. Tabs are the exception to the
|
|
41
|
+
* "slot stays" rule: each repeat row owns a whole tab (label + panel), so
|
|
42
|
+
* deleting the row must drop the tab item itself — otherwise a blank-panel tab
|
|
43
|
+
* with a stale label is left behind. At least one tab is always kept.
|
|
44
|
+
*/
|
|
45
|
+
export declare function removeRepeatRowSubtrees(documentTree: Record<string, any>, cloneRootIds: string[], idsToRemove: Set<string>): Record<string, any>;
|
|
39
46
|
export type RepeatableSlot = {
|
|
40
47
|
childrenIds: string[];
|
|
41
48
|
};
|
|
@@ -69,6 +76,18 @@ export type ItemsArrayInfo = {
|
|
|
69
76
|
};
|
|
70
77
|
/** True if the block's repeatable content is a flat `props.items` array (no child blocks). */
|
|
71
78
|
export declare function isItemsArrayBlockType(type: string | undefined): boolean;
|
|
79
|
+
/** The `data.props` key an items-array block keeps its items under. */
|
|
80
|
+
export declare function getItemsArrayPropKey(type: string | undefined): string;
|
|
81
|
+
/** A block's current items array (empty when missing). */
|
|
82
|
+
export declare function readItemsArray(block: any): Record<string, any>[];
|
|
83
|
+
type ItemSubField = {
|
|
84
|
+
id: string;
|
|
85
|
+
mapsTo?: string;
|
|
86
|
+
};
|
|
87
|
+
/** Items → field rows: row keys are sub-field ids, read from each sub's `mapsTo` item key. */
|
|
88
|
+
export declare function itemsToRows(items: Record<string, any>[], itemFields: ItemSubField[] | null | undefined): Record<string, string>[];
|
|
89
|
+
/** Field rows → items: writes each row value onto its sub's `mapsTo` key, keeping other item keys. */
|
|
90
|
+
export declare function rowsToItems(rows: Record<string, any>[], existingItems: Record<string, any>[], itemFields: ItemSubField[] | null | undefined): Record<string, any>[];
|
|
72
91
|
/**
|
|
73
92
|
* Describe an items-array block's current items. Returns null when the block
|
|
74
93
|
* isn't a supported items-array type. Used by the Variables tab to decide
|
|
@@ -95,8 +114,8 @@ export type VariableGroup = {
|
|
|
95
114
|
*/
|
|
96
115
|
fieldNames: string[];
|
|
97
116
|
/**
|
|
98
|
-
* True when the block is a repeatable container
|
|
99
|
-
*
|
|
117
|
+
* True when the block is a repeatable container that owns no variables —
|
|
118
|
+
* no field and no row tokens (the Repeat toggle alone doesn't count). It owns nothing to edit,
|
|
100
119
|
* but its Repeat toggle is only reachable from its own screen, so it is
|
|
101
120
|
* listed separately rather than dropped. See `isVariableBoundBlock`.
|
|
102
121
|
*/
|
|
@@ -314,3 +333,4 @@ export declare function sanitizeAgainstKnownTypes(doc: Record<string, any>, know
|
|
|
314
333
|
removedTypes: string[];
|
|
315
334
|
changed: boolean;
|
|
316
335
|
};
|
|
336
|
+
export {};
|
|
@@ -31,7 +31,7 @@ export declare const RESPONSIVE_PROP_KEYS: readonly ["contentAlignment", "horizo
|
|
|
31
31
|
* {@link nativeKeysForBlock} to get the right set for a block type — never test
|
|
32
32
|
* against this flat list directly.
|
|
33
33
|
*/
|
|
34
|
-
export declare const NATIVE_DEVICE_PROP_KEYS: readonly ["columnsCount", "columnsCountTablet", "columnsCountMobile", "rowsCount", "rowsCountTablet", "rowsCountMobile", "columnsGap", "columnsGapTablet", "columnsGapMobile", "rowsGap", "desktopLayout", "tabletLayout", "mobileLayout", "columnShrink", "columnShrinkTablet", "columnShrinkMobile", "columnsDirection", "columnsDirectionTablet", "columnsDirectionMobile", "widthType", "widthTypeTablet", "widthTypeMobile", "size", "sizeTablet", "sizeMobile", "fixedWidths", "fixedWidthsTablet", "fixedWidthsMobile", "contentAlignmentTablet", "contentAlignmentMobile", "slidesPerView", "slidesPerViewTablet", "slidesPerViewMobile", "width", "widthTablet", "widthMobile", "widthUnit", "widthUnitTablet", "widthUnitMobile", "height", "heightTablet", "heightMobile", "url", "urlTablet", "urlMobile", "iconName", "iconNameTablet", "iconNameMobile", "iconFillColor", "iconFillColorTablet", "iconFillColorMobile", "enableScroll", "enableScrollTablet", "enableScrollMobile", "orientation", "orientationTablet", "orientationMobile", "dropdown", "dropdownTablet", "dropdownMobile", "direction", "directionTablet", "directionMobile", "gapTablet", "gapMobile", "alignmentTablet", "alignmentMobile", "rotation", "rotationTablet", "rotationMobile", "burgerDropdownBackgroundColor", "stickyNavTablet", "stickyNavMobile"];
|
|
34
|
+
export declare const NATIVE_DEVICE_PROP_KEYS: readonly ["columnsCount", "columnsCountTablet", "columnsCountMobile", "rowsCount", "rowsCountTablet", "rowsCountMobile", "columnsGap", "columnsGapTablet", "columnsGapMobile", "rowsGap", "desktopLayout", "tabletLayout", "mobileLayout", "columnShrink", "columnShrinkTablet", "columnShrinkMobile", "columnSpan", "columnSpanTablet", "columnSpanMobile", "columnsDirection", "columnsDirectionTablet", "columnsDirectionMobile", "widthType", "widthTypeTablet", "widthTypeMobile", "size", "sizeTablet", "sizeMobile", "fixedWidths", "fixedWidthsTablet", "fixedWidthsMobile", "contentAlignmentTablet", "contentAlignmentMobile", "slidesPerView", "slidesPerViewTablet", "slidesPerViewMobile", "width", "widthTablet", "widthMobile", "widthUnit", "widthUnitTablet", "widthUnitMobile", "height", "heightTablet", "heightMobile", "url", "urlTablet", "urlMobile", "iconName", "iconNameTablet", "iconNameMobile", "iconFillColor", "iconFillColorTablet", "iconFillColorMobile", "enableScroll", "enableScrollTablet", "enableScrollMobile", "orientation", "orientationTablet", "orientationMobile", "dropdown", "dropdownTablet", "dropdownMobile", "direction", "directionTablet", "directionMobile", "gapTablet", "gapMobile", "alignmentTablet", "alignmentMobile", "rotation", "rotationTablet", "rotationMobile", "burgerDropdownBackgroundColor", "stickyNavTablet", "stickyNavMobile"];
|
|
35
35
|
/**
|
|
36
36
|
* The native per-device prop keys that apply to `blockType`. Unambiguous keys
|
|
37
37
|
* are always native; ambiguous ones only for the block types that actually
|
|
@@ -8,7 +8,5 @@ export declare function getBlockScalarTokenIds(block: any): string[];
|
|
|
8
8
|
/** Every token-bearing string on a single block. */
|
|
9
9
|
export declare function blockTokenStrings(block: any): string[];
|
|
10
10
|
export declare function subtreeHasRowTokens(documentTree: Record<string, any>, rootId: string): boolean;
|
|
11
|
-
/** True if the author has switched the block's Repeat toggle on. */
|
|
12
|
-
export declare function hasRepeatEnabled(block: any): boolean;
|
|
13
11
|
export declare function isVariableBoundBlock(documentTree: Record<string, any>, blockId: string, fieldOwnerIds: Set<string>): boolean;
|
|
14
12
|
export declare function classifyVariableBlock(documentTree: Record<string, any>, blockId: string, fieldOwnerIds: Set<string>): 'bound' | 'candidate' | 'none';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PageTypes } from '../../App/hooks/constants';
|
|
2
2
|
import { TEditorConfiguration } from './core';
|
|
3
3
|
import { TemplateFormField, TemplateArrayRow } from './templateVariables';
|
|
4
|
+
export type PreviewHostTheme = 'light' | 'dark' | 'follow';
|
|
4
5
|
type TValue = {
|
|
5
6
|
document: TEditorConfiguration;
|
|
6
7
|
record: any | null;
|
|
@@ -8,6 +9,7 @@ type TValue = {
|
|
|
8
9
|
selectedSidebarTab: 'block-configuration' | 'styles' | 'behaviour' | 'layout' | 'settings' | 'background' | 'page-pilot-ai' | 'layers' | 'brand' | 'seo' | 'variables' | 'research';
|
|
9
10
|
selectedMainTab: 'editor' | 'preview' | 'json' | 'html';
|
|
10
11
|
selectedScreenSize: 'desktop' | 'mobile' | 'tablet';
|
|
12
|
+
previewHostTheme: PreviewHostTheme;
|
|
11
13
|
zoomLevel: number;
|
|
12
14
|
minimapVisible: boolean;
|
|
13
15
|
sidebarEditingDevice: 'desktop' | 'mobile' | 'tablet';
|
|
@@ -123,6 +125,8 @@ export declare function useSelectedBlockId(): string;
|
|
|
123
125
|
* re-renders A and B, not every other block on the canvas.
|
|
124
126
|
*/
|
|
125
127
|
export declare function useIsBlockSelected(id: string): boolean;
|
|
128
|
+
export declare function usePreviewHostTheme(): PreviewHostTheme;
|
|
129
|
+
export declare function setPreviewHostTheme(previewHostTheme: PreviewHostTheme): void;
|
|
126
130
|
export declare function useSelectedScreenSize(): "desktop" | "tablet" | "mobile";
|
|
127
131
|
export declare const ZOOM_MIN = 25;
|
|
128
132
|
export declare const ZOOM_MAX = 100;
|
|
@@ -194,6 +198,12 @@ export declare function useInlineEditing(): {
|
|
|
194
198
|
blockId: string | null;
|
|
195
199
|
draft: string;
|
|
196
200
|
};
|
|
201
|
+
/**
|
|
202
|
+
* Boolean selector — true only while THIS block is the one being inline-edited.
|
|
203
|
+
* Prefer over useInlineEditing() in per-block components so starting/stopping
|
|
204
|
+
* an edit doesn't re-render every Text/Heading/Button on the canvas.
|
|
205
|
+
*/
|
|
206
|
+
export declare function useIsBlockInlineEditing(id: string): boolean;
|
|
197
207
|
export declare function useHoveredBlockId(): string;
|
|
198
208
|
/**
|
|
199
209
|
* Boolean selector — returns true only when THIS block is the hovered one.
|
|
@@ -51,6 +51,12 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
51
51
|
normal: "normal";
|
|
52
52
|
bold: "bold";
|
|
53
53
|
}>>>;
|
|
54
|
+
textDecoration: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
55
|
+
none: "none";
|
|
56
|
+
underline: "underline";
|
|
57
|
+
"line-through": "line-through";
|
|
58
|
+
"underline line-through": "underline line-through";
|
|
59
|
+
}>>>;
|
|
54
60
|
textAlign: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
55
61
|
right: "right";
|
|
56
62
|
left: "left";
|
|
@@ -990,6 +996,9 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
990
996
|
columnShrink: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
991
997
|
columnShrinkTablet: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
992
998
|
columnShrinkMobile: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
999
|
+
columnSpan: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
1000
|
+
columnSpanTablet: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
1001
|
+
columnSpanMobile: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
993
1002
|
equalColumns: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
994
1003
|
columns: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
995
1004
|
childrenIds: z.ZodArray<z.ZodString>;
|
|
@@ -1134,8 +1143,8 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
1134
1143
|
h6: "h6";
|
|
1135
1144
|
}>>>;
|
|
1136
1145
|
linkType: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
1137
|
-
link: "link";
|
|
1138
1146
|
text: "text";
|
|
1147
|
+
link: "link";
|
|
1139
1148
|
}>>>;
|
|
1140
1149
|
url: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
1141
1150
|
openInNewTab: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -1870,6 +1879,10 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
1870
1879
|
}, z.core.$strip>>>;
|
|
1871
1880
|
canvasColor: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodString, z.ZodString, z.ZodLiteral<"transparent">]>>>>;
|
|
1872
1881
|
textColor: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodString, z.ZodString, z.ZodLiteral<"transparent">]>>>;
|
|
1882
|
+
hostTheme: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
1883
|
+
light: "light";
|
|
1884
|
+
follow: "follow";
|
|
1885
|
+
}>>>;
|
|
1873
1886
|
fontFamily: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
1874
1887
|
MODERN_SANS: "MODERN_SANS";
|
|
1875
1888
|
BOOK_SANS: "BOOK_SANS";
|
|
@@ -2164,8 +2177,8 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
2164
2177
|
"upper-roman": "upper-roman";
|
|
2165
2178
|
}>>>;
|
|
2166
2179
|
numberSuffix: z.ZodPreprocess<z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
2167
|
-
".": ".";
|
|
2168
2180
|
")": ")";
|
|
2181
|
+
".": ".";
|
|
2169
2182
|
}>>>>;
|
|
2170
2183
|
startNumber: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
2171
2184
|
markerColor: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodString, z.ZodLiteral<"transparent">]>>>;
|
|
@@ -2239,6 +2252,10 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
2239
2252
|
MenuPicker: z.ZodObject<{
|
|
2240
2253
|
menuId: z.ZodDefault<z.ZodString>;
|
|
2241
2254
|
useCustomMenu: z.ZodDefault<z.ZodBoolean>;
|
|
2255
|
+
navRole: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
2256
|
+
footer: "footer";
|
|
2257
|
+
header: "header";
|
|
2258
|
+
}>>>;
|
|
2242
2259
|
stickyNav: z.ZodDefault<z.ZodBoolean>;
|
|
2243
2260
|
stickyNavTablet: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
2244
2261
|
stickyNavMobile: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -2250,6 +2267,7 @@ export declare const EditorBlock: ({ type, data }: import('@usewaypoint/document
|
|
|
2250
2267
|
orientation: z.ZodDefault<z.ZodEnum<{
|
|
2251
2268
|
vertical: "vertical";
|
|
2252
2269
|
horizontal: "horizontal";
|
|
2270
|
+
columns: "columns";
|
|
2253
2271
|
}>>;
|
|
2254
2272
|
menuItems: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>>>;
|
|
2255
2273
|
startChildrenIds: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
@@ -26,6 +26,12 @@ export type TemplateItemFieldDef = {
|
|
|
26
26
|
/** `time` sub-fields only — 24h / AM/PM. Timezone reuses `dateTz`. */
|
|
27
27
|
timeFormat?: TimeFormatPreset;
|
|
28
28
|
dateTz?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Items-array fields only: the block item key this sub-field writes to
|
|
31
|
+
* (e.g. MenuPicker `name` / `href`), so the variable id can be anything the
|
|
32
|
+
* author likes (`navLabel`). Falls back to `id` when absent.
|
|
33
|
+
*/
|
|
34
|
+
mapsTo?: string;
|
|
29
35
|
};
|
|
30
36
|
export type TemplateArrayRow = Record<string, string>;
|
|
31
37
|
export type TemplateFormField = {
|
|
@@ -159,6 +165,21 @@ export declare function stripTokenWrapper(html: string, { prefix, suffix }: {
|
|
|
159
165
|
prefix: string;
|
|
160
166
|
suffix: string;
|
|
161
167
|
}): string;
|
|
168
|
+
/**
|
|
169
|
+
* Like stripTokenWrapper, but also returns the EDITED wrapper (outermost
|
|
170
|
+
* layer) so toolbar changes made on it — e.g. clearing tablet/mobile
|
|
171
|
+
* `data-fs-*` on the wrapper span — can be written back to the block instead
|
|
172
|
+
* of being discarded with the strip. `prefix`/`suffix` are null when the
|
|
173
|
+
* wrapper couldn't be matched structurally.
|
|
174
|
+
*/
|
|
175
|
+
export declare function splitEditedTokenHtml(html: string, wrapper: {
|
|
176
|
+
prefix: string;
|
|
177
|
+
suffix: string;
|
|
178
|
+
}): {
|
|
179
|
+
value: string;
|
|
180
|
+
prefix: string | null;
|
|
181
|
+
suffix: string | null;
|
|
182
|
+
};
|
|
162
183
|
/**
|
|
163
184
|
* When a Text/Heading/Button block's text is a SINGLE template token
|
|
164
185
|
* (`{{description}}` for a scalar field, or `{{this.sub}}` for a row sub-field
|
|
@@ -179,23 +200,18 @@ export declare function resolveEditableTokenField(rawText: string, blockId: stri
|
|
|
179
200
|
value: string;
|
|
180
201
|
apply: (next: string, forms: TemplateFormField[]) => TemplateFormField[];
|
|
181
202
|
} | null;
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
* so the Variables tab stays in sync in real time.
|
|
185
|
-
*
|
|
186
|
-
* - Scalar fields (text / textarea / number / image) and plain array fields
|
|
187
|
-
* (no sourceBlockId): removed when their {{id}} token no longer appears in
|
|
188
|
-
* any remaining block's text props.
|
|
189
|
-
* - Container-repeat array fields (sourceBlockId set):
|
|
190
|
-
* • sourceBlockId gone → whole field removed.
|
|
191
|
-
* • individual rowIds gone → those rows pruned.
|
|
192
|
-
*
|
|
193
|
-
* Returns the SAME reference when nothing changed so callers can skip a write.
|
|
194
|
-
*/
|
|
203
|
+
/** Drop stale MenuPicker container-repeat fields. Same reference when none. */
|
|
204
|
+
export declare function dropStaleMenuRepeatFields(document: TEditorConfiguration | null | undefined, fields: TemplateFormField[]): TemplateFormField[];
|
|
195
205
|
export declare function pruneOrphanFormFields(document: TEditorConfiguration | null | undefined, fields: TemplateFormField[] | null | undefined): TemplateFormField[];
|
|
196
206
|
export declare function getTextFieldsForType(type: string | undefined): string[] | undefined;
|
|
197
207
|
export declare function getTemplateForms(document: TEditorConfiguration | null | undefined): TemplateFormField[];
|
|
198
208
|
export declare function applyVariables(input: string | null | undefined, fields: TemplateFormField[] | null | undefined, rowContext?: TemplateArrayRow | null): string;
|
|
209
|
+
/**
|
|
210
|
+
* Resolve {{tokens}} in MenuPicker `menuItems[]` (name/label/href, recursing
|
|
211
|
+
* into `children[]`). Returns the SAME array reference when nothing changed.
|
|
212
|
+
*/
|
|
213
|
+
export declare function substituteMenuItems(items: any[] | null | undefined, fields: TemplateFormField[] | null | undefined, rowContext?: TemplateArrayRow | null): any[] | null | undefined;
|
|
214
|
+
export declare function htmlToPlainText(html: string): string;
|
|
199
215
|
export declare function substituteBlockText(block: any, fields: TemplateFormField[] | null | undefined, rowContext?: TemplateArrayRow | null, rowIndex?: Map<string, TemplateArrayRow> | null): any;
|
|
200
216
|
/**
|
|
201
217
|
* Permanently substitute every token into the document and drop `formFields`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ContainerProps } from './ContainerPropsSchema';
|
|
2
|
-
export default function ContainerReader({ style, props, blockId }: ContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export default function ContainerReader({ style, props, responsive, blockId }: ContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -11,6 +11,10 @@ export declare const EmailLayoutPropsSchema: z.ZodObject<{
|
|
|
11
11
|
borderRadius: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
12
12
|
canvasColor: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodString, z.ZodString, z.ZodLiteral<"transparent">]>>>>;
|
|
13
13
|
textColor: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodString, z.ZodString, z.ZodLiteral<"transparent">]>>>;
|
|
14
|
+
hostTheme: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
15
|
+
light: "light";
|
|
16
|
+
follow: "follow";
|
|
17
|
+
}>>>;
|
|
14
18
|
fontFamily: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
15
19
|
MODERN_SANS: "MODERN_SANS";
|
|
16
20
|
BOOK_SANS: "BOOK_SANS";
|
|
@@ -49,6 +49,9 @@ declare const FlexColumnsPropsSchema: z.ZodObject<{
|
|
|
49
49
|
columnShrink: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
50
50
|
columnShrinkTablet: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
51
51
|
columnShrinkMobile: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodBoolean>>>;
|
|
52
|
+
columnSpan: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
53
|
+
columnSpanTablet: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
54
|
+
columnSpanMobile: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNullable<z.ZodNumber>>>>;
|
|
52
55
|
equalColumns: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
53
56
|
columns: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
54
57
|
childrenIds: z.ZodArray<z.ZodString>;
|
|
@@ -40,6 +40,8 @@ export type DeviceLayout = {
|
|
|
40
40
|
layout: FlexRowLayout;
|
|
41
41
|
/** Per-column shrink-to-content flags, one entry per column. */
|
|
42
42
|
shrink: boolean[];
|
|
43
|
+
/** Per-column 12-grid span, one entry per column; null = no span. */
|
|
44
|
+
span: (number | null)[];
|
|
43
45
|
/** All non-shrink columns share the row width equally. */
|
|
44
46
|
equalColumns: boolean;
|
|
45
47
|
reverseColumns: boolean;
|
|
@@ -58,7 +60,7 @@ export declare function resolveDeviceLayout(props: FlexProps, device: FlexDevice
|
|
|
58
60
|
* equal — take an identical share of the row, whatever the content
|
|
59
61
|
* plain — grow from natural width
|
|
60
62
|
*/
|
|
61
|
-
export type ColumnKind = 'plain' | 'equal' | 'shrink';
|
|
63
|
+
export type ColumnKind = 'plain' | 'equal' | 'shrink' | 'span';
|
|
62
64
|
/**
|
|
63
65
|
* The block's complete stylesheet: structure, then one fully-restated sizing block
|
|
64
66
|
* per device in ascending-specificity-free source order (desktop → tablet → mobile).
|
|
@@ -75,7 +77,7 @@ export declare function buildResponsiveRowCss(instanceClass: string, opts: {
|
|
|
75
77
|
* owns that at every breakpoint. Kept for the editor canvas, which renders without
|
|
76
78
|
* the stylesheet and needs the active device's sizing directly.
|
|
77
79
|
*/
|
|
78
|
-
export declare function buildColumnStyle(kind: ColumnKind, stacked: boolean): CSSProperties;
|
|
80
|
+
export declare function buildColumnStyle(kind: ColumnKind, stacked: boolean, span?: number | null, gap?: number): CSSProperties;
|
|
79
81
|
/** The kind of a column on a given device — shared by the editor and the reader. */
|
|
80
82
|
export declare function columnKindFor(index: number, device: DeviceLayout): ColumnKind;
|
|
81
83
|
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
p: any;
|
|
4
|
+
menuItems: any[];
|
|
5
|
+
menuKey: string;
|
|
6
|
+
textColor: string;
|
|
7
|
+
backgroundColor: string;
|
|
8
|
+
fontFamily?: string;
|
|
9
|
+
start?: React.ReactNode;
|
|
10
|
+
end?: React.ReactNode;
|
|
11
|
+
};
|
|
12
|
+
declare const MenuColumns: ({ p, menuItems, menuKey, textColor, backgroundColor, fontFamily, start, end }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export default MenuColumns;
|
|
@@ -2,6 +2,10 @@ import { z } from 'zod';
|
|
|
2
2
|
declare const MenuPropsInnerSchema: z.ZodObject<{
|
|
3
3
|
menuId: z.ZodDefault<z.ZodString>;
|
|
4
4
|
useCustomMenu: z.ZodDefault<z.ZodBoolean>;
|
|
5
|
+
navRole: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
6
|
+
footer: "footer";
|
|
7
|
+
header: "header";
|
|
8
|
+
}>>>;
|
|
5
9
|
stickyNav: z.ZodDefault<z.ZodBoolean>;
|
|
6
10
|
stickyNavTablet: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
7
11
|
stickyNavMobile: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -13,6 +17,7 @@ declare const MenuPropsInnerSchema: z.ZodObject<{
|
|
|
13
17
|
orientation: z.ZodDefault<z.ZodEnum<{
|
|
14
18
|
vertical: "vertical";
|
|
15
19
|
horizontal: "horizontal";
|
|
20
|
+
columns: "columns";
|
|
16
21
|
}>>;
|
|
17
22
|
menuItems: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>>>;
|
|
18
23
|
startChildrenIds: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
@@ -71,6 +76,10 @@ export declare const MenuPropsSchema: z.ZodObject<{
|
|
|
71
76
|
props: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
72
77
|
menuId: z.ZodDefault<z.ZodString>;
|
|
73
78
|
useCustomMenu: z.ZodDefault<z.ZodBoolean>;
|
|
79
|
+
navRole: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
80
|
+
footer: "footer";
|
|
81
|
+
header: "header";
|
|
82
|
+
}>>>;
|
|
74
83
|
stickyNav: z.ZodDefault<z.ZodBoolean>;
|
|
75
84
|
stickyNavTablet: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
76
85
|
stickyNavMobile: z.ZodNullable<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -82,6 +91,7 @@ export declare const MenuPropsSchema: z.ZodObject<{
|
|
|
82
91
|
orientation: z.ZodDefault<z.ZodEnum<{
|
|
83
92
|
vertical: "vertical";
|
|
84
93
|
horizontal: "horizontal";
|
|
94
|
+
columns: "columns";
|
|
85
95
|
}>>;
|
|
86
96
|
menuItems: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>>>;
|
|
87
97
|
startChildrenIds: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
@@ -1,9 +1,105 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Host-application theme support.
|
|
3
|
+
*
|
|
4
|
+
* Published output follows the host's light/dark theme through CSS custom
|
|
5
|
+
* properties (`--pp-*`) defined by `HOST_THEME_CSS`. A color adapts only when it
|
|
6
|
+
* is rendered in a theme-role slot AND its value is null or that slot's own
|
|
7
|
+
* seed default; every other value stays literal. Light = variables undefined,
|
|
8
|
+
* so each `var(--pp-x, <literal>)` resolves to the original literal.
|
|
5
9
|
*/
|
|
10
|
+
export type ThemeRole = 'text' | 'text-strong' | 'text-muted' | 'link' | 'surface' | 'surface-alt' | 'track' | 'border' | 'border-subtle';
|
|
11
|
+
export type ThemeSlotDef = {
|
|
12
|
+
role: ThemeRole;
|
|
13
|
+
/** Values (normalized) that count as the editor-seeded default for this slot. */
|
|
14
|
+
seeds: string[];
|
|
15
|
+
/** Applied when raw is null. Without it a null raw stays undefined (inherits). */
|
|
16
|
+
nullFallback?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function normalizeColor(raw: string | null | undefined): string;
|
|
19
|
+
/** Central registry of theme-aware slots (see host-theme-plan.md, matrix C). */
|
|
20
|
+
export declare const THEME_SLOTS: {
|
|
21
|
+
readonly pageText: ThemeSlotDef;
|
|
22
|
+
readonly containerFill: ThemeSlotDef;
|
|
23
|
+
readonly layoutText: ThemeSlotDef;
|
|
24
|
+
readonly canvas: ThemeSlotDef;
|
|
25
|
+
readonly closeIcon: ThemeSlotDef;
|
|
26
|
+
readonly brandingText: ThemeSlotDef;
|
|
27
|
+
readonly blockText: ThemeSlotDef;
|
|
28
|
+
readonly listText: ThemeSlotDef;
|
|
29
|
+
readonly link: ThemeSlotDef;
|
|
30
|
+
readonly codeBg: ThemeSlotDef;
|
|
31
|
+
readonly quoteBorder: ThemeSlotDef;
|
|
32
|
+
readonly divider: ThemeSlotDef;
|
|
33
|
+
readonly tableText: ThemeSlotDef;
|
|
34
|
+
readonly tableBorder: ThemeSlotDef;
|
|
35
|
+
readonly tableHeaderBg: ThemeSlotDef;
|
|
36
|
+
readonly tableHeaderText: ThemeSlotDef;
|
|
37
|
+
readonly tableStripe: ThemeSlotDef;
|
|
38
|
+
readonly track: ThemeSlotDef;
|
|
39
|
+
readonly trackText: ThemeSlotDef;
|
|
40
|
+
readonly timerText: ThemeSlotDef;
|
|
41
|
+
readonly timerLabel: ThemeSlotDef;
|
|
42
|
+
readonly timerTrack: ThemeSlotDef;
|
|
43
|
+
readonly breadcrumbText: ThemeSlotDef;
|
|
44
|
+
readonly menuText: ThemeSlotDef;
|
|
45
|
+
readonly menuSurface: ThemeSlotDef;
|
|
46
|
+
readonly carouselArrow: ThemeSlotDef;
|
|
47
|
+
readonly carouselArrowBg: ThemeSlotDef;
|
|
48
|
+
readonly carouselArrowBorder: ThemeSlotDef;
|
|
49
|
+
readonly carouselDot: ThemeSlotDef;
|
|
50
|
+
readonly carouselDotActive: ThemeSlotDef;
|
|
51
|
+
readonly paginationBg: ThemeSlotDef;
|
|
52
|
+
readonly paginationText: ThemeSlotDef;
|
|
53
|
+
readonly paginationBorder: ThemeSlotDef;
|
|
54
|
+
readonly surface: ThemeSlotDef;
|
|
55
|
+
readonly surfaceLiteral: ThemeSlotDef;
|
|
56
|
+
readonly bgAdaptive: ThemeSlotDef;
|
|
57
|
+
readonly buttonText: ThemeSlotDef;
|
|
58
|
+
readonly borderAdaptive: ThemeSlotDef;
|
|
59
|
+
readonly borderSubtle: ThemeSlotDef;
|
|
60
|
+
readonly surfaceAlt: ThemeSlotDef;
|
|
61
|
+
readonly tabsRing: ThemeSlotDef;
|
|
62
|
+
};
|
|
63
|
+
export type ThemeSlotName = keyof typeof THEME_SLOTS;
|
|
64
|
+
/** Dark-mode counterpart of an authored color, or null when it should stay as authored. */
|
|
65
|
+
export declare function darkCounterpart(raw: string, kind: 'text' | 'bg'): string | null;
|
|
66
|
+
/** True when this light solid background gets a dark counterpart (so no light lock is needed). */
|
|
67
|
+
/** True when a background is effectively see-through (empty, transparent or alpha 0). */
|
|
68
|
+
export declare function isClearBg(raw: string | null | undefined): boolean;
|
|
69
|
+
export declare function isAdaptableBg(raw: string | null | undefined): boolean;
|
|
70
|
+
type GradientKind = 'text' | 'bg' | 'border';
|
|
71
|
+
export declare const gradientKindForRole: (role: ThemeRole) => GradientKind;
|
|
72
|
+
/** Theme the seed colors of every gradient in `raw`; everything else is preserved verbatim. */
|
|
73
|
+
export declare function themeGradient(raw: string, kind?: GradientKind): string;
|
|
74
|
+
/** True when every opaque stop of the gradient adapts (so no light surface lock is needed). */
|
|
75
|
+
export declare function isFullyAdaptiveGradient(raw: string, kind?: GradientKind): boolean;
|
|
76
|
+
/** Resolve a raw color for a slot: var(--pp-role, literal) when adaptable, else literal. */
|
|
77
|
+
export declare function themeSlot(raw: string | null | undefined, name: ThemeSlotName | ThemeSlotDef): string | undefined;
|
|
78
|
+
export declare function useThemeSlot(raw: string | null | undefined, name: ThemeSlotName | ThemeSlotDef): string | undefined;
|
|
79
|
+
/** Plain-function form for colors in lists/maps (no hook rules). */
|
|
80
|
+
export declare function useThemeSlotter(): typeof themeSlot;
|
|
81
|
+
/**
|
|
82
|
+
* Spread on the element that paints an author background. Locks the subtree to
|
|
83
|
+
* light so default text stays readable on author-painted surfaces.
|
|
84
|
+
*/
|
|
85
|
+
export declare function surfaceAttrs(bgRaw?: string | null, bgImage?: string | null, adaptiveSlot?: ThemeSlotName): {
|
|
86
|
+
'data-pp-surface'?: 'fixed';
|
|
87
|
+
};
|
|
6
88
|
export declare function useColorToken(raw: string | null | undefined): string | undefined;
|
|
7
|
-
/** Plain-function form for colors that live in a list (no hook rules). */
|
|
8
89
|
export declare function useColorTokenizer(): (raw: string | null | undefined) => string | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Theme colors the rich-text toolbar baked into the markup (`<font color>` and
|
|
92
|
+
* inline `color:` declarations). Neutral dark text gets a light-dark() pair so it
|
|
93
|
+
* stays readable on a dark host; tinted/light colors stay as authored.
|
|
94
|
+
*/
|
|
95
|
+
export declare function themeHtmlColors(html: string): string;
|
|
96
|
+
/** Inverse of themeHtmlColors: restores the authored color so edited HTML is saved untouched. */
|
|
97
|
+
export declare function unthemeHtmlColors(html: string): string;
|
|
9
98
|
export declare function useThemedHtml(html: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* Nearest marked element wins: marker rules DEFINE the variables on the element
|
|
101
|
+
* carrying the marker, descendants inherit. :where() keeps specificity at 0, so
|
|
102
|
+
* same-element conflicts are decided by source order (weakest first).
|
|
103
|
+
*/
|
|
104
|
+
export declare const HOST_THEME_CSS: string;
|
|
105
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { noopListActions as default } from '../_hostListShim';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { noopListSelectors as default } from '../_hostListShim';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const StyledCellContainer: import('@emotion/styled').StyledComponent<import('@mui/system').BoxOwnProps<import('@mui/material').Theme> & Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof import('@mui/system').BoxOwnProps<import('@mui/material').Theme>> & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme>, {}, {}>;
|
|
2
|
-
export declare const StyledCellValue: import('@emotion/styled').StyledComponent<import('@mui/material').TypographyOwnProps & import('@mui/material/OverridableComponent').CommonProps & Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "top" | "bottom" | "right" | "left" | "padding" | "margin" | "style" | "lineHeight" | "children" | "className" | "fontSize" | "fontFamily" | "fontWeight" | "fontStyle" | "textAlign" | "marginBottom" | "width" | "height" | "borderRadius" | "borderColor" | "gap" | "p" | "color" | "flex" | "display" | "position" | "
|
|
2
|
+
export declare const StyledCellValue: import('@emotion/styled').StyledComponent<import('@mui/material').TypographyOwnProps & import('@mui/material/OverridableComponent').CommonProps & Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "border" | "top" | "bottom" | "right" | "left" | "padding" | "margin" | "style" | "lineHeight" | "children" | "className" | "fontSize" | "fontFamily" | "fontWeight" | "fontStyle" | "textAlign" | "marginBottom" | "width" | "height" | "borderRadius" | "borderColor" | "gap" | "p" | "color" | "flex" | "display" | "position" | "paddingBottom" | "align" | "bgcolor" | "borderTop" | "px" | "boxShadow" | "overflow" | "variant" | "paddingX" | "paddingY" | "marginX" | "marginY" | "maxWidth" | "maxHeight" | "classes" | "sx" | "letterSpacing" | "order" | "visibility" | "zIndex" | "alignContent" | "alignItems" | "alignSelf" | "boxSizing" | "columnGap" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "justifyContent" | "justifyItems" | "justifySelf" | "marginBlockEnd" | "marginBlockStart" | "marginInlineEnd" | "marginInlineStart" | "marginLeft" | "marginRight" | "marginTop" | "minHeight" | "minWidth" | "paddingBlockEnd" | "paddingBlockStart" | "paddingInlineEnd" | "paddingInlineStart" | "paddingLeft" | "paddingRight" | "paddingTop" | "rowGap" | "textOverflow" | "textTransform" | "whiteSpace" | "borderBottom" | "borderLeft" | "borderRight" | "gridArea" | "gridColumn" | "gridRow" | "marginBlock" | "marginInline" | "paddingBlock" | "paddingInline" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "my" | "pt" | "pr" | "pb" | "pl" | "py" | "typography" | "displayPrint" | "gutterBottom" | "noWrap" | "paragraph" | "variantMapping"> & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme>, {}, {}>;
|
|
3
3
|
export declare const StyledCopyIconContainer: import('@emotion/styled').StyledComponent<import('@mui/system').BoxOwnProps<import('@mui/material').Theme> & Omit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof import('@mui/system').BoxOwnProps<import('@mui/material').Theme>> & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme>, {}, {}>;
|