@shoppexio/builder-runtime 0.1.1 → 0.1.3
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/YouTubeEmbed.d.ts +13 -0
- package/dist/YouTubeEmbed.d.ts.map +1 -0
- package/dist/YouTubeEmbed.js +49 -0
- package/dist/YouTubeEmbedBuilderBlock.d.ts +7 -0
- package/dist/YouTubeEmbedBuilderBlock.d.ts.map +1 -0
- package/dist/YouTubeEmbedBuilderBlock.js +16 -0
- package/dist/block-style-settings.d.ts +5 -0
- package/dist/block-style-settings.d.ts.map +1 -0
- package/dist/block-style-settings.js +16 -0
- package/dist/builder-runtime.test.d.ts +2 -0
- package/dist/builder-runtime.test.d.ts.map +1 -0
- package/dist/builder-runtime.test.js +115 -0
- package/dist/content.d.ts +6 -0
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +31 -7
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/layout.d.ts +3 -8
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +2 -10
- package/dist/manifest-setting-paths.d.ts +5 -0
- package/dist/manifest-setting-paths.d.ts.map +1 -0
- package/dist/manifest-setting-paths.js +40 -0
- package/dist/merchant-custom-page.d.ts +57 -0
- package/dist/merchant-custom-page.d.ts.map +1 -0
- package/dist/merchant-custom-page.js +63 -0
- package/dist/preview-fixtures.d.ts +16 -0
- package/dist/preview-fixtures.d.ts.map +1 -0
- package/dist/preview-fixtures.js +40 -0
- package/dist/preview-mode.d.ts +2 -0
- package/dist/preview-mode.d.ts.map +1 -0
- package/dist/preview-mode.js +7 -0
- package/dist/product-page.d.ts +13 -0
- package/dist/product-page.d.ts.map +1 -0
- package/dist/product-page.js +18 -0
- package/dist/react-runtime.test.d.ts +2 -0
- package/dist/react-runtime.test.d.ts.map +1 -0
- package/dist/react-runtime.test.js +332 -0
- package/dist/react.d.ts +37 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +138 -46
- package/dist/search-bar-settings.d.ts +33 -0
- package/dist/search-bar-settings.d.ts.map +1 -0
- package/dist/search-bar-settings.js +99 -0
- package/dist/standard-product-blocks.d.ts +48 -0
- package/dist/standard-product-blocks.d.ts.map +1 -0
- package/dist/standard-product-blocks.js +45 -0
- package/dist/standard-product-page.d.ts +69 -0
- package/dist/standard-product-page.d.ts.map +1 -0
- package/dist/standard-product-page.js +89 -0
- package/dist/storefront-google-fonts.d.ts +2 -0
- package/dist/storefront-google-fonts.d.ts.map +1 -0
- package/dist/storefront-google-fonts.js +28 -0
- package/dist/youtube-embed-block.d.ts +10 -0
- package/dist/youtube-embed-block.d.ts.map +1 -0
- package/dist/youtube-embed-block.js +19 -0
- package/dist/youtube.d.ts +5 -0
- package/dist/youtube.d.ts.map +1 -0
- package/dist/youtube.js +52 -0
- package/package.json +3 -3
- package/src/YouTubeEmbed.tsx +105 -0
- package/src/YouTubeEmbedBuilderBlock.tsx +49 -0
- package/src/block-style-settings.ts +24 -0
- package/src/builder-runtime.test.ts +69 -0
- package/src/content.ts +44 -9
- package/src/index.ts +8 -0
- package/src/layout.ts +11 -21
- package/src/manifest-setting-paths.test.ts +23 -0
- package/src/manifest-setting-paths.ts +55 -0
- package/src/merchant-custom-page.tsx +161 -0
- package/src/preview-fixtures.ts +56 -0
- package/src/preview-mode.ts +8 -0
- package/src/product-page.test.ts +37 -0
- package/src/product-page.ts +32 -0
- package/src/react-runtime.test.tsx +42 -0
- package/src/react.tsx +243 -49
- package/src/search-bar-settings.test.ts +72 -0
- package/src/search-bar-settings.ts +176 -0
- package/src/standard-product-blocks.test.tsx +93 -0
- package/src/standard-product-blocks.tsx +121 -0
- package/src/standard-product-page.test.ts +171 -0
- package/src/standard-product-page.ts +169 -0
- package/src/storefront-google-fonts.test.ts +31 -0
- package/src/storefront-google-fonts.ts +43 -0
- package/src/youtube-embed-block.test.ts +76 -0
- package/src/youtube-embed-block.ts +28 -0
- package/src/youtube-embed-builder-block.test.tsx +166 -0
- package/src/youtube.test.ts +48 -0
- package/src/youtube.ts +66 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface YouTubeEmbedProps {
|
|
2
|
+
videoUrl?: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
height?: number;
|
|
5
|
+
privacyEnhanced?: boolean;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function YouTubeEmbed({ videoUrl, title, height, privacyEnhanced, className, }: YouTubeEmbedProps): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export declare function YouTubeEmbedPreviewPlaceholder({ className, height, }: {
|
|
10
|
+
className?: string;
|
|
11
|
+
height?: number;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=YouTubeEmbed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"YouTubeEmbed.d.ts","sourceRoot":"","sources":["../src/YouTubeEmbed.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,YAAY,CAAC,EAC3B,QAAa,EACb,KAAuB,EACvB,MAAM,EACN,eAAuB,EACvB,SAAc,GACf,EAAE,iBAAiB,kDAoCnB;AAED,wBAAgB,8BAA8B,CAAC,EAC7C,SAAc,EACd,MAAM,GACP,EAAE;IACD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,2CAsCA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { buildYouTubeEmbedSrc, parseYouTubeVideoId } from './youtube.js';
|
|
5
|
+
const DEFAULT_HEIGHT = 400;
|
|
6
|
+
const EMBED_MAX_WIDTH = 640;
|
|
7
|
+
export function YouTubeEmbed({ videoUrl = '', title = 'YouTube video', height, privacyEnhanced = false, className = '', }) {
|
|
8
|
+
const videoId = useMemo(() => parseYouTubeVideoId(videoUrl), [videoUrl]);
|
|
9
|
+
const resolvedHeight = typeof height === 'number' && height > 0 ? height : DEFAULT_HEIGHT;
|
|
10
|
+
if (!videoId) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return (_jsx("section", { className: `my-8 ${className}`, style: { display: 'flex', justifyContent: 'center' }, children: _jsx("div", { style: {
|
|
14
|
+
position: 'relative',
|
|
15
|
+
width: '100%',
|
|
16
|
+
maxWidth: `${EMBED_MAX_WIDTH}px`,
|
|
17
|
+
height: `${resolvedHeight}px`,
|
|
18
|
+
borderRadius: 'inherit',
|
|
19
|
+
}, children: _jsx("iframe", { src: buildYouTubeEmbedSrc(videoId, { privacyEnhanced }), title: title, allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true, loading: "lazy", style: {
|
|
20
|
+
display: 'block',
|
|
21
|
+
width: '100%',
|
|
22
|
+
height: '100%',
|
|
23
|
+
border: 0,
|
|
24
|
+
} }) }) }));
|
|
25
|
+
}
|
|
26
|
+
export function YouTubeEmbedPreviewPlaceholder({ className = '', height, }) {
|
|
27
|
+
const resolvedHeight = typeof height === 'number' && height > 0 ? height : DEFAULT_HEIGHT;
|
|
28
|
+
return (_jsx("section", { className: `my-8 ${className}`, style: { display: 'flex', justifyContent: 'center' }, children: _jsx("div", { style: {
|
|
29
|
+
position: 'relative',
|
|
30
|
+
width: '100%',
|
|
31
|
+
maxWidth: `${EMBED_MAX_WIDTH}px`,
|
|
32
|
+
height: `${resolvedHeight}px`,
|
|
33
|
+
borderRadius: 'inherit',
|
|
34
|
+
}, children: _jsx("div", { style: {
|
|
35
|
+
display: 'flex',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
width: '100%',
|
|
39
|
+
height: '100%',
|
|
40
|
+
padding: '0 24px',
|
|
41
|
+
border: '1px dashed rgba(127, 127, 127, 0.35)',
|
|
42
|
+
borderRadius: 'inherit',
|
|
43
|
+
background: 'rgba(127, 127, 127, 0.06)',
|
|
44
|
+
color: '#5f6470',
|
|
45
|
+
fontFamily: 'Inter, system-ui, sans-serif',
|
|
46
|
+
fontSize: '13px',
|
|
47
|
+
textAlign: 'center',
|
|
48
|
+
}, "aria-hidden": "true", children: "Paste a YouTube link or video ID in the Inspector to preview the player here." }) }) }));
|
|
49
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BlockInstance } from '@shoppex/builder-contracts';
|
|
2
|
+
export type YouTubeEmbedBuilderBlockProps = {
|
|
3
|
+
block: Pick<BlockInstance, 'id' | 'type' | 'settings'>;
|
|
4
|
+
pageId?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function YouTubeEmbedBuilderBlock({ block, pageId, }: YouTubeEmbedBuilderBlockProps): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
//# sourceMappingURL=YouTubeEmbedBuilderBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"YouTubeEmbedBuilderBlock.d.ts","sourceRoot":"","sources":["../src/YouTubeEmbedBuilderBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUhE,MAAM,MAAM,6BAA6B,GAAG;IAC1C,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,MAAe,GAChB,EAAE,6BAA6B,kDA8B/B"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { builderBlock } from './attributes.js';
|
|
3
|
+
import { isBuilderPreviewMode } from './preview-mode.js';
|
|
4
|
+
import { YouTubeEmbed, YouTubeEmbedPreviewPlaceholder } from './YouTubeEmbed.js';
|
|
5
|
+
import { getYouTubeEmbedBlockStyleProps, readYouTubeEmbedBlockSettings, } from './youtube-embed-block.js';
|
|
6
|
+
import { parseYouTubeVideoId } from './youtube.js';
|
|
7
|
+
export function YouTubeEmbedBuilderBlock({ block, pageId = 'home', }) {
|
|
8
|
+
const settings = readYouTubeEmbedBlockSettings(block);
|
|
9
|
+
const videoId = parseYouTubeVideoId(settings.videoUrl);
|
|
10
|
+
const showPreviewPlaceholder = !videoId && isBuilderPreviewMode();
|
|
11
|
+
if (!videoId && !showPreviewPlaceholder) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const styleProps = getYouTubeEmbedBlockStyleProps(block);
|
|
15
|
+
return (_jsx("div", { "data-page-id": pageId, ...builderBlock(block.id, block.type), style: Object.keys(styleProps).length > 0 ? styleProps : undefined, children: videoId ? (_jsx(YouTubeEmbed, { videoUrl: settings.videoUrl, title: settings.title, height: settings.height, privacyEnhanced: settings.privacyEnhanced })) : (_jsx(YouTubeEmbedPreviewPlaceholder, { height: settings.height })) }, block.id));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-style-settings.d.ts","sourceRoot":"","sources":["../src/block-style-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,kBAAkB,GAC3B,aAAa,CAiBf"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function readManifestStyleBlockProps(settings) {
|
|
2
|
+
const bg = settings['style.background'];
|
|
3
|
+
const radius = settings['style.borderRadius'];
|
|
4
|
+
const padding = settings['style.padding'];
|
|
5
|
+
const style = {};
|
|
6
|
+
if (typeof bg === 'string' && bg.length > 0) {
|
|
7
|
+
style.backgroundColor = bg;
|
|
8
|
+
}
|
|
9
|
+
if (typeof radius === 'number') {
|
|
10
|
+
style.borderRadius = `${radius}px`;
|
|
11
|
+
}
|
|
12
|
+
if (typeof padding === 'number') {
|
|
13
|
+
style.padding = `${padding}px`;
|
|
14
|
+
}
|
|
15
|
+
return style;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-runtime.test.d.ts","sourceRoot":"","sources":["../src/builder-runtime.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { createBlockInstance, createEmptyBuilderSettings } from '@shoppex/builder-contracts';
|
|
3
|
+
import { builderBlock, builderContent, builderSlot, canAddBlock, createBuilderCss, getBuilderContentList, getBuilderContentString, getPageBlocks, resolveBlockSettings, resolveStyleSlotValue, } from './index.js';
|
|
4
|
+
function createSettings() {
|
|
5
|
+
return {
|
|
6
|
+
...createEmptyBuilderSettings(1),
|
|
7
|
+
theme: {
|
|
8
|
+
content: {
|
|
9
|
+
'hero.title': 'Launch sale',
|
|
10
|
+
faq: {
|
|
11
|
+
items: [{ question: 'Can I edit sections?', answer: 'Yes' }],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
layout: {
|
|
15
|
+
home: {
|
|
16
|
+
blocks: [
|
|
17
|
+
createBlockInstance({
|
|
18
|
+
id: 'hero-1',
|
|
19
|
+
type: 'hero',
|
|
20
|
+
settings: { title: 'Hero block' },
|
|
21
|
+
style_overrides: {
|
|
22
|
+
'button.radius': { base: 14 },
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
style_slots: {
|
|
29
|
+
'button.radius': { base: 8, md: 12 },
|
|
30
|
+
'color.primary': '#ff5500',
|
|
31
|
+
},
|
|
32
|
+
pages: [],
|
|
33
|
+
terms: {},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const manifest = {
|
|
38
|
+
id: 'default',
|
|
39
|
+
name: 'Default',
|
|
40
|
+
version: '2.0.0',
|
|
41
|
+
pages: {
|
|
42
|
+
home: {
|
|
43
|
+
label: 'Home',
|
|
44
|
+
allowedBlocks: ['hero'],
|
|
45
|
+
defaultBlocks: [],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
blocks: {
|
|
49
|
+
hero: {
|
|
50
|
+
label: 'Hero',
|
|
51
|
+
variants: [],
|
|
52
|
+
settings: {
|
|
53
|
+
title: { type: 'text', label: 'Headline', defaultValue: 'Default hero' },
|
|
54
|
+
},
|
|
55
|
+
exposedStyleSlots: ['button.radius'],
|
|
56
|
+
presets: [],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
styleSlots: {},
|
|
60
|
+
presets: {},
|
|
61
|
+
};
|
|
62
|
+
describe('@shoppex/builder-runtime', () => {
|
|
63
|
+
test('reads direct and nested content values', () => {
|
|
64
|
+
const settings = createSettings();
|
|
65
|
+
expect(getBuilderContentString(settings, 'hero.title')).toBe('Launch sale');
|
|
66
|
+
expect(getBuilderContentList(settings, 'faq.items')).toEqual([{ question: 'Can I edit sections?', answer: 'Yes' }]);
|
|
67
|
+
});
|
|
68
|
+
test('preserves intentionally empty content strings', () => {
|
|
69
|
+
const settings = createSettings();
|
|
70
|
+
settings.theme.content['hero.subtitle'] = '';
|
|
71
|
+
expect(getBuilderContentString(settings, 'hero.subtitle', 'Default subtitle')).toBe('');
|
|
72
|
+
});
|
|
73
|
+
test('resolves page blocks', () => {
|
|
74
|
+
const settings = createSettings();
|
|
75
|
+
expect(getPageBlocks(settings, 'home')).toHaveLength(1);
|
|
76
|
+
expect(getPageBlocks(settings, 'missing')).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
test('resolves style slots with breakpoint fallback and block override', () => {
|
|
79
|
+
const settings = createSettings();
|
|
80
|
+
const block = settings.theme.layout.home.blocks[0];
|
|
81
|
+
expect(resolveStyleSlotValue(settings, 'button.radius', { breakpoint: 'lg' })).toBe(12);
|
|
82
|
+
expect(resolveStyleSlotValue(settings, 'button.radius', { block, breakpoint: 'md' })).toBe(14);
|
|
83
|
+
});
|
|
84
|
+
test('emits CSS variables with responsive media blocks', () => {
|
|
85
|
+
const css = createBuilderCss(createSettings());
|
|
86
|
+
expect(css).toContain('--builder-button-radius: 8px;');
|
|
87
|
+
expect(css).toContain('--builder-color-primary: #ff5500;');
|
|
88
|
+
expect(css).toContain('@media (min-width: 768px)');
|
|
89
|
+
expect(css).toContain('--builder-button-radius: 12px;');
|
|
90
|
+
});
|
|
91
|
+
test('checks block limits against the manifest', () => {
|
|
92
|
+
const settings = createSettings();
|
|
93
|
+
expect(canAddBlock(settings, manifest, 'home', 'hero')).toBe(true);
|
|
94
|
+
expect(canAddBlock(settings, manifest, 'home', 'faq')).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
test('merges block defaults from the manifest', () => {
|
|
97
|
+
const block = createBlockInstance({
|
|
98
|
+
id: 'hero-2',
|
|
99
|
+
type: 'hero',
|
|
100
|
+
settings: {},
|
|
101
|
+
});
|
|
102
|
+
expect(resolveBlockSettings(block, manifest)).toEqual({ title: 'Default hero' });
|
|
103
|
+
});
|
|
104
|
+
test('creates the three supported builder attributes', () => {
|
|
105
|
+
expect(builderContent('hero.title')).toEqual({ 'data-builder-content': 'hero.title' });
|
|
106
|
+
expect(builderSlot('button.radius', { blockId: 'hero-1' })).toEqual({
|
|
107
|
+
'data-builder-slot': 'button.radius',
|
|
108
|
+
'data-builder-block': 'hero-1',
|
|
109
|
+
});
|
|
110
|
+
expect(builderBlock('hero-1', 'hero')).toEqual({
|
|
111
|
+
'data-builder-block': 'hero-1',
|
|
112
|
+
'data-builder-block-type': 'hero',
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
package/dist/content.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export type JsonRecord = Record<string, unknown>;
|
|
|
3
3
|
export declare function getBuilderContentValue(settings: BuilderSettings, path: string): unknown;
|
|
4
4
|
export declare function getBuilderContentString(settings: BuilderSettings, path: string, fallback?: string): string | undefined;
|
|
5
5
|
export declare function getBuilderContentList<T = unknown>(settings: BuilderSettings, path: string, fallback?: T[]): T[];
|
|
6
|
+
export type NormalizedGalleryItem = {
|
|
7
|
+
url: string;
|
|
8
|
+
alt?: string;
|
|
9
|
+
caption?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function normalizeGalleryItems(raw: unknown): NormalizedGalleryItem[];
|
|
6
12
|
export declare function getBuilderContentRecord(settings: BuilderSettings): JsonRecord;
|
|
7
13
|
export declare function getBlockSettingValue<T = unknown>(settings: BuilderSettings, input: {
|
|
8
14
|
pageId: string;
|
package/dist/content.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGlE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGtH;AAED,wBAAgB,qBAAqB,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,CAAC,EAAO,GAAG,CAAC,EAAE,CAGnH;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,qBAAqB,EAAE,CA+B3E;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,CAE7E;AAED,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,OAAO,EAC9C,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,GACpE,CAAC,CAaH"}
|
package/dist/content.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
+
import { resolveManifestSettingRecordValue } from './manifest-setting-paths.js';
|
|
1
2
|
export function getBuilderContentValue(settings, path) {
|
|
2
|
-
|
|
3
|
-
if (Object.prototype.hasOwnProperty.call(content, path)) {
|
|
4
|
-
return content[path];
|
|
5
|
-
}
|
|
6
|
-
return getByDottedPath(content, path);
|
|
3
|
+
return resolveManifestSettingRecordValue(settings.theme.content, path);
|
|
7
4
|
}
|
|
8
5
|
export function getBuilderContentString(settings, path, fallback) {
|
|
9
6
|
const value = getBuilderContentValue(settings, path);
|
|
@@ -13,6 +10,32 @@ export function getBuilderContentList(settings, path, fallback = []) {
|
|
|
13
10
|
const value = getBuilderContentValue(settings, path);
|
|
14
11
|
return Array.isArray(value) ? value : fallback;
|
|
15
12
|
}
|
|
13
|
+
export function normalizeGalleryItems(raw) {
|
|
14
|
+
if (!Array.isArray(raw)) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const items = [];
|
|
18
|
+
for (const entry of raw) {
|
|
19
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const record = entry;
|
|
23
|
+
const url = typeof record.url === 'string' && record.url.length > 0
|
|
24
|
+
? record.url
|
|
25
|
+
: typeof record.image === 'string' && record.image.length > 0
|
|
26
|
+
? record.image
|
|
27
|
+
: null;
|
|
28
|
+
if (!url) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
items.push({
|
|
32
|
+
url,
|
|
33
|
+
alt: typeof record.alt === 'string' ? record.alt : undefined,
|
|
34
|
+
caption: typeof record.caption === 'string' ? record.caption : undefined,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return items;
|
|
38
|
+
}
|
|
16
39
|
export function getBuilderContentRecord(settings) {
|
|
17
40
|
return settings.theme.content;
|
|
18
41
|
}
|
|
@@ -21,8 +44,9 @@ export function getBlockSettingValue(settings, input) {
|
|
|
21
44
|
if (!block) {
|
|
22
45
|
return input.fallback;
|
|
23
46
|
}
|
|
24
|
-
|
|
25
|
-
|
|
47
|
+
const resolved = resolveManifestSettingRecordValue(block.settings, input.path);
|
|
48
|
+
if (resolved !== undefined) {
|
|
49
|
+
return resolved;
|
|
26
50
|
}
|
|
27
51
|
const nested = getByDottedPath(block.settings, input.path);
|
|
28
52
|
return nested === undefined ? input.fallback : nested;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
export * from './manifest-setting-paths.js';
|
|
2
|
+
export * from './preview-fixtures.js';
|
|
3
|
+
export * from './product-page.js';
|
|
4
|
+
export * from './standard-product-page.js';
|
|
1
5
|
export * from './attributes.js';
|
|
2
6
|
export * from './content.js';
|
|
3
7
|
export * from './css-vars.js';
|
|
4
8
|
export * from './layout.js';
|
|
5
9
|
export * from './react.js';
|
|
10
|
+
export * from './storefront-google-fonts.js';
|
|
6
11
|
export * from './style-slots.js';
|
|
12
|
+
export * from './block-style-settings.js';
|
|
13
|
+
export * from './preview-mode.js';
|
|
14
|
+
export * from './youtube.js';
|
|
7
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
export * from './manifest-setting-paths.js';
|
|
2
|
+
export * from './preview-fixtures.js';
|
|
3
|
+
export * from './product-page.js';
|
|
4
|
+
export * from './standard-product-page.js';
|
|
1
5
|
export * from './attributes.js';
|
|
2
6
|
export * from './content.js';
|
|
3
7
|
export * from './css-vars.js';
|
|
4
8
|
export * from './layout.js';
|
|
5
9
|
export * from './react.js';
|
|
10
|
+
export * from './storefront-google-fonts.js';
|
|
6
11
|
export * from './style-slots.js';
|
|
12
|
+
export * from './block-style-settings.js';
|
|
13
|
+
export * from './preview-mode.js';
|
|
14
|
+
export * from './youtube.js';
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { getThemePageBlockOrderFromManifest as resolveThemePageBlockOrder, type BlockInstance, type BuilderSettings, type PageLayout, type ThemeManifest, type ThemePageBlockOrderPage } from '@shoppex/builder-contracts';
|
|
2
2
|
export type ThemePageBlockOrderManifest = {
|
|
3
|
-
pages?: Record<string,
|
|
4
|
-
allowedBlocks?: string[];
|
|
5
|
-
defaultBlocks?: Array<{
|
|
6
|
-
type?: string;
|
|
7
|
-
}>;
|
|
8
|
-
}>;
|
|
3
|
+
pages?: Record<string, ThemePageBlockOrderPage>;
|
|
9
4
|
};
|
|
5
|
+
export { resolveThemePageBlockOrder as getThemePageBlockOrderFromManifest };
|
|
10
6
|
export declare function getPageLayout(settings: BuilderSettings, pageId: string): PageLayout;
|
|
11
7
|
export declare function getPageBlocks(settings: BuilderSettings, pageId: string): BlockInstance[];
|
|
12
8
|
export declare function getVisiblePageBlocks(settings: BuilderSettings, pageId: string): BlockInstance[];
|
|
13
9
|
export declare function getBlockById(settings: BuilderSettings, pageId: string, blockId: string): BlockInstance | null;
|
|
14
10
|
export declare function getAllowedBlockTypes(manifest: ThemeManifest, pageId: string): string[];
|
|
15
|
-
export declare function getThemePageBlockOrderFromManifest(manifest: ThemePageBlockOrderManifest, pageId: string): string[];
|
|
16
11
|
export declare function canAddBlock(settings: BuilderSettings, manifest: ThemeManifest, pageId: string, blockType: string): boolean;
|
|
17
12
|
export declare function resolveBlockSettings(block: BlockInstance, manifest: ThemeManifest): Record<string, unknown>;
|
|
18
13
|
//# sourceMappingURL=layout.d.ts.map
|
package/dist/layout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,IAAI,0BAA0B,EAChE,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAC7B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,2BAA2B,GAAG;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACjD,CAAC;AAEF,OAAO,EAAE,0BAA0B,IAAI,kCAAkC,EAAE,CAAC;AAE5E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAEnF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAExF;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAE/F;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAE7G;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAc1H;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB3G"}
|
package/dist/layout.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getThemePageBlockOrderFromManifest as resolveThemePageBlockOrder, } from '@shoppex/builder-contracts';
|
|
2
|
+
export { resolveThemePageBlockOrder as getThemePageBlockOrderFromManifest };
|
|
1
3
|
export function getPageLayout(settings, pageId) {
|
|
2
4
|
return settings.theme.layout[pageId] ?? { blocks: [] };
|
|
3
5
|
}
|
|
@@ -13,16 +15,6 @@ export function getBlockById(settings, pageId, blockId) {
|
|
|
13
15
|
export function getAllowedBlockTypes(manifest, pageId) {
|
|
14
16
|
return manifest.pages[pageId]?.allowedBlocks ?? [];
|
|
15
17
|
}
|
|
16
|
-
export function getThemePageBlockOrderFromManifest(manifest, pageId) {
|
|
17
|
-
const page = manifest.pages?.[pageId];
|
|
18
|
-
if (!page) {
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
const defaultBlockTypes = (page.defaultBlocks ?? [])
|
|
22
|
-
.map((block) => block.type)
|
|
23
|
-
.filter((blockType) => typeof blockType === 'string' && blockType.length > 0);
|
|
24
|
-
return defaultBlockTypes.length > 0 ? defaultBlockTypes : page.allowedBlocks ?? [];
|
|
25
|
-
}
|
|
26
18
|
export function canAddBlock(settings, manifest, pageId, blockType) {
|
|
27
19
|
const page = manifest.pages[pageId];
|
|
28
20
|
const blockDefinition = manifest.blocks[blockType];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { JsonRecord } from './content.js';
|
|
2
|
+
export declare function toSnakeCaseManifestSegment(value: string): string;
|
|
3
|
+
export declare function toSnakeCaseManifestPath(path: string): string;
|
|
4
|
+
export declare function resolveManifestSettingRecordValue(record: JsonRecord, path: string): unknown;
|
|
5
|
+
//# sourceMappingURL=manifest-setting-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-setting-paths.d.ts","sourceRoot":"","sources":["../src/manifest-setting-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAgBD,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAoBT"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function toSnakeCaseManifestSegment(value) {
|
|
2
|
+
return value
|
|
3
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
4
|
+
.replace(/[\s-]+/g, '_')
|
|
5
|
+
.toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
export function toSnakeCaseManifestPath(path) {
|
|
8
|
+
return path
|
|
9
|
+
.split('.')
|
|
10
|
+
.filter(Boolean)
|
|
11
|
+
.map(toSnakeCaseManifestSegment)
|
|
12
|
+
.join('.');
|
|
13
|
+
}
|
|
14
|
+
function getByDottedPath(record, path) {
|
|
15
|
+
let current = record;
|
|
16
|
+
for (const segment of path.split('.')) {
|
|
17
|
+
if (!current || typeof current !== 'object') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
current = current[segment];
|
|
21
|
+
}
|
|
22
|
+
return current;
|
|
23
|
+
}
|
|
24
|
+
export function resolveManifestSettingRecordValue(record, path) {
|
|
25
|
+
if (Object.prototype.hasOwnProperty.call(record, path)) {
|
|
26
|
+
return record[path];
|
|
27
|
+
}
|
|
28
|
+
const snakePath = toSnakeCaseManifestPath(path);
|
|
29
|
+
if (snakePath !== path && Object.prototype.hasOwnProperty.call(record, snakePath)) {
|
|
30
|
+
return record[snakePath];
|
|
31
|
+
}
|
|
32
|
+
const nested = getByDottedPath(record, path);
|
|
33
|
+
if (nested !== undefined) {
|
|
34
|
+
return nested;
|
|
35
|
+
}
|
|
36
|
+
if (snakePath !== path) {
|
|
37
|
+
return getByDottedPath(record, snakePath);
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import { type BuilderBlockRegistry } from './react.js';
|
|
3
|
+
type CustomEmbedProps = {
|
|
4
|
+
embedHtml?: string;
|
|
5
|
+
height?: number;
|
|
6
|
+
autoResize?: boolean;
|
|
7
|
+
width?: 'full' | 'boxed' | 'embed';
|
|
8
|
+
};
|
|
9
|
+
type TextBlockProps = {
|
|
10
|
+
eyebrow?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
body?: string;
|
|
13
|
+
alignment?: 'left' | 'center' | 'right';
|
|
14
|
+
ctaLabel?: string;
|
|
15
|
+
ctaHref?: string;
|
|
16
|
+
styleBackground?: string;
|
|
17
|
+
styleAccentColor?: string;
|
|
18
|
+
};
|
|
19
|
+
export type MerchantCustomPageRegistryOptions = {
|
|
20
|
+
pageId: string;
|
|
21
|
+
CustomEmbed: ComponentType<CustomEmbedProps>;
|
|
22
|
+
TextBlock?: ComponentType<TextBlockProps>;
|
|
23
|
+
};
|
|
24
|
+
export declare function createMerchantCustomPageRegistry(options: MerchantCustomPageRegistryOptions): BuilderBlockRegistry;
|
|
25
|
+
export declare function MerchantCustomPageBuilderView({ pageId, registry, className, children, }: {
|
|
26
|
+
pageId: string;
|
|
27
|
+
registry: BuilderBlockRegistry;
|
|
28
|
+
className?: string;
|
|
29
|
+
children?: ReactNode;
|
|
30
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
31
|
+
export declare function useMerchantCustomPageRegistry(options: MerchantCustomPageRegistryOptions | null): BuilderBlockRegistry | null;
|
|
32
|
+
export declare function useMerchantCustomPageView(slug: string | undefined, components: Pick<MerchantCustomPageRegistryOptions, 'CustomEmbed' | 'TextBlock'>): {
|
|
33
|
+
customPage: {
|
|
34
|
+
id: string;
|
|
35
|
+
title: string;
|
|
36
|
+
slug: string;
|
|
37
|
+
visible: boolean;
|
|
38
|
+
layout: {
|
|
39
|
+
blocks: {
|
|
40
|
+
id: string;
|
|
41
|
+
type: string;
|
|
42
|
+
visible: boolean;
|
|
43
|
+
settings: Record<string, unknown>;
|
|
44
|
+
variant?: string | undefined;
|
|
45
|
+
style_overrides?: Partial<Record<import("@shoppex/builder-contracts").StyleSlotId, import("@shoppex/builder-contracts").StyleSlotValue>> | undefined;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
seo?: {
|
|
49
|
+
title?: string | undefined;
|
|
50
|
+
description?: string | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
} | undefined;
|
|
53
|
+
registry: BuilderBlockRegistry | null;
|
|
54
|
+
hasBuilderContent: boolean;
|
|
55
|
+
};
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=merchant-custom-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merchant-custom-page.d.ts","sourceRoot":"","sources":["../src/merchant-custom-page.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAItD,OAAO,EAAsD,KAAK,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAG3G,KAAK,gBAAgB,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;CACpC,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAC7C,SAAS,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;CAC3C,CAAC;AAYF,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,oBAAoB,CAqDtB;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,MAAM,EACN,QAAQ,EACR,SAAS,EACT,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,kDAaA;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,iCAAiC,GAAG,IAAI,GAChD,oBAAoB,GAAG,IAAI,CAK7B;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,UAAU,EAAE,IAAI,CAAC,iCAAiC,EAAE,aAAa,GAAG,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;EAsBjF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { findCustomPageBySlug } from '@shoppex/builder-contracts';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
import { builderBlock } from './attributes.js';
|
|
6
|
+
import { readManifestStyleBlockProps } from './block-style-settings.js';
|
|
7
|
+
import { BuilderPage, useBuilderRuntime, useThemePageBlocks } from './react.js';
|
|
8
|
+
import { YouTubeEmbedBuilderBlock } from './YouTubeEmbedBuilderBlock.js';
|
|
9
|
+
function readStringSetting(block, key) {
|
|
10
|
+
const value = block.settings[key];
|
|
11
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
12
|
+
}
|
|
13
|
+
function readNumberSetting(block, key) {
|
|
14
|
+
const value = block.settings[key];
|
|
15
|
+
return typeof value === 'number' && value > 0 ? value : undefined;
|
|
16
|
+
}
|
|
17
|
+
export function createMerchantCustomPageRegistry(options) {
|
|
18
|
+
const { pageId, CustomEmbed, TextBlock } = options;
|
|
19
|
+
const registry = {
|
|
20
|
+
'youtube-embed': ({ block }) => (_jsx(YouTubeEmbedBuilderBlock, { block: block, pageId: pageId })),
|
|
21
|
+
'custom-html': ({ block }) => {
|
|
22
|
+
const styleProps = readManifestStyleBlockProps(block.settings);
|
|
23
|
+
const width = block.settings.width;
|
|
24
|
+
return (_jsx("div", { "data-page-id": pageId, ...builderBlock(block.id, block.type), style: Object.keys(styleProps).length > 0 ? styleProps : undefined, children: _jsx(CustomEmbed, { embedHtml: readStringSetting(block, 'embedHtml'), height: readNumberSetting(block, 'height'), autoResize: block.settings.autoResize === true, width: width === 'full' || width === 'boxed' || width === 'embed'
|
|
25
|
+
? width
|
|
26
|
+
: 'embed' }) }, block.id));
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
if (TextBlock) {
|
|
30
|
+
registry['text-block'] = ({ block }) => (_jsx("div", { "data-page-id": pageId, ...builderBlock(block.id, block.type), children: _jsx(TextBlock, { eyebrow: readStringSetting(block, 'eyebrow'), title: readStringSetting(block, 'title'), body: readStringSetting(block, 'body'), alignment: readStringSetting(block, 'alignment') ??
|
|
31
|
+
undefined, ctaLabel: readStringSetting(block, 'ctaLabel'), ctaHref: readStringSetting(block, 'ctaHref'), styleBackground: readStringSetting(block, 'style.background'), styleAccentColor: readStringSetting(block, 'style.accentColor') }) }, block.id));
|
|
32
|
+
}
|
|
33
|
+
return registry;
|
|
34
|
+
}
|
|
35
|
+
export function MerchantCustomPageBuilderView({ pageId, registry, className, children, }) {
|
|
36
|
+
const blocks = useThemePageBlocks(pageId, []);
|
|
37
|
+
if (blocks.length === 0) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return (_jsxs("div", { className: className, children: [children, _jsx(BuilderPage, { pageId: pageId, blocks: blocks, registry: registry, context: null })] }));
|
|
41
|
+
}
|
|
42
|
+
export function useMerchantCustomPageRegistry(options) {
|
|
43
|
+
return useMemo(() => (options ? createMerchantCustomPageRegistry(options) : null), [options?.pageId, options?.CustomEmbed, options?.TextBlock]);
|
|
44
|
+
}
|
|
45
|
+
export function useMerchantCustomPageView(slug, components) {
|
|
46
|
+
const { settings } = useBuilderRuntime();
|
|
47
|
+
const customPage = slug ? findCustomPageBySlug(settings, slug) : undefined;
|
|
48
|
+
const registry = useMerchantCustomPageRegistry(customPage
|
|
49
|
+
? {
|
|
50
|
+
pageId: customPage.id,
|
|
51
|
+
CustomEmbed: components.CustomEmbed,
|
|
52
|
+
TextBlock: components.TextBlock,
|
|
53
|
+
}
|
|
54
|
+
: null);
|
|
55
|
+
const builderBlockCount = customPage
|
|
56
|
+
? (settings.theme.layout[customPage.id]?.blocks.length ?? 0)
|
|
57
|
+
: 0;
|
|
58
|
+
return {
|
|
59
|
+
customPage,
|
|
60
|
+
registry,
|
|
61
|
+
hasBuilderContent: builderBlockCount > 0,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type BuilderPreviewReview = {
|
|
2
|
+
id: string;
|
|
3
|
+
author: string | null;
|
|
4
|
+
comment: string | null;
|
|
5
|
+
rating: number | null;
|
|
6
|
+
created_at: string;
|
|
7
|
+
is_automated?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type BuilderPreviewFaqItem = {
|
|
10
|
+
question: string;
|
|
11
|
+
answer: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const BUILDER_PREVIEW_REVIEWS: BuilderPreviewReview[];
|
|
14
|
+
export declare function getBuilderPreviewReviewFixtures<T = BuilderPreviewReview>(): T[];
|
|
15
|
+
export declare const BUILDER_PREVIEW_FAQ_ITEMS: BuilderPreviewFaqItem[];
|
|
16
|
+
//# sourceMappingURL=preview-fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-fixtures.d.ts","sourceRoot":"","sources":["../src/preview-fixtures.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,oBAAoB,EAsBzD,CAAC;AAEF,wBAAgB,+BAA+B,CAAC,CAAC,GAAG,oBAAoB,KAAK,CAAC,EAAE,CAE/E;AAED,eAAO,MAAM,yBAAyB,EAAE,qBAAqB,EAa5D,CAAC"}
|