@shopbb/helium 0.7.7 → 0.9.0

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.
Files changed (76) hide show
  1. package/dist/analytics/index.d.ts +18 -0
  2. package/dist/analytics/index.d.ts.map +1 -0
  3. package/dist/analytics/index.js +16 -0
  4. package/dist/analytics/index.js.map +1 -0
  5. package/dist/analytics/queue.d.ts +31 -0
  6. package/dist/analytics/queue.d.ts.map +1 -0
  7. package/dist/analytics/queue.js +203 -0
  8. package/dist/analytics/queue.js.map +1 -0
  9. package/dist/analytics/react.d.ts +44 -0
  10. package/dist/analytics/react.d.ts.map +1 -0
  11. package/dist/analytics/react.js +114 -0
  12. package/dist/analytics/react.js.map +1 -0
  13. package/dist/analytics/types.d.ts +68 -0
  14. package/dist/analytics/types.d.ts.map +1 -0
  15. package/dist/analytics/types.js +7 -0
  16. package/dist/analytics/types.js.map +1 -0
  17. package/dist/components/AddToCartButton.d.ts +7 -0
  18. package/dist/components/AddToCartButton.d.ts.map +1 -1
  19. package/dist/components/AddToCartButton.js +13 -2
  20. package/dist/components/AddToCartButton.js.map +1 -1
  21. package/dist/page-schema/PageRenderer.d.ts +29 -0
  22. package/dist/page-schema/PageRenderer.d.ts.map +1 -0
  23. package/dist/page-schema/PageRenderer.js +73 -0
  24. package/dist/page-schema/PageRenderer.js.map +1 -0
  25. package/dist/page-schema/index.d.ts +20 -0
  26. package/dist/page-schema/index.d.ts.map +1 -0
  27. package/dist/page-schema/index.js +18 -0
  28. package/dist/page-schema/index.js.map +1 -0
  29. package/dist/page-schema/sections/Banner.d.ts +10 -0
  30. package/dist/page-schema/sections/Banner.d.ts.map +1 -0
  31. package/dist/page-schema/sections/Banner.js +35 -0
  32. package/dist/page-schema/sections/Banner.js.map +1 -0
  33. package/dist/page-schema/sections/Hero.d.ts +15 -0
  34. package/dist/page-schema/sections/Hero.d.ts.map +1 -0
  35. package/dist/page-schema/sections/Hero.js +44 -0
  36. package/dist/page-schema/sections/Hero.js.map +1 -0
  37. package/dist/page-schema/sections/Image.d.ts +10 -0
  38. package/dist/page-schema/sections/Image.d.ts.map +1 -0
  39. package/dist/page-schema/sections/Image.js +12 -0
  40. package/dist/page-schema/sections/Image.js.map +1 -0
  41. package/dist/page-schema/sections/ProductGrid.d.ts +29 -0
  42. package/dist/page-schema/sections/ProductGrid.d.ts.map +1 -0
  43. package/dist/page-schema/sections/ProductGrid.js +28 -0
  44. package/dist/page-schema/sections/ProductGrid.js.map +1 -0
  45. package/dist/page-schema/sections/RichText.d.ts +13 -0
  46. package/dist/page-schema/sections/RichText.d.ts.map +1 -0
  47. package/dist/page-schema/sections/RichText.js +16 -0
  48. package/dist/page-schema/sections/RichText.js.map +1 -0
  49. package/dist/page-schema/sections/Spacer.d.ts +10 -0
  50. package/dist/page-schema/sections/Spacer.d.ts.map +1 -0
  51. package/dist/page-schema/sections/Spacer.js +6 -0
  52. package/dist/page-schema/sections/Spacer.js.map +1 -0
  53. package/dist/page-schema/types.d.ts +138 -0
  54. package/dist/page-schema/types.d.ts.map +1 -0
  55. package/dist/page-schema/types.js +129 -0
  56. package/dist/page-schema/types.js.map +1 -0
  57. package/dist/react.d.ts +7 -0
  58. package/dist/react.d.ts.map +1 -1
  59. package/dist/react.js +15 -0
  60. package/dist/react.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/analytics/index.ts +27 -0
  63. package/src/analytics/queue.ts +224 -0
  64. package/src/analytics/react.tsx +146 -0
  65. package/src/analytics/types.ts +81 -0
  66. package/src/components/AddToCartButton.tsx +18 -0
  67. package/src/page-schema/PageRenderer.tsx +147 -0
  68. package/src/page-schema/index.ts +48 -0
  69. package/src/page-schema/sections/Banner.tsx +63 -0
  70. package/src/page-schema/sections/Hero.tsx +92 -0
  71. package/src/page-schema/sections/Image.tsx +42 -0
  72. package/src/page-schema/sections/ProductGrid.tsx +96 -0
  73. package/src/page-schema/sections/RichText.tsx +49 -0
  74. package/src/page-schema/sections/Spacer.tsx +15 -0
  75. package/src/page-schema/types.ts +286 -0
  76. package/src/react.tsx +59 -0
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { HeroSection } from './sections/Hero';
3
+ import { ProductGridSection } from './sections/ProductGrid';
4
+ import { BannerSection } from './sections/Banner';
5
+ import { RichTextSection } from './sections/RichText';
6
+ import { ImageSection } from './sections/Image';
7
+ import { SpacerSection } from './sections/Spacer';
8
+ export function PageRenderer({ page, productsBySection, editorMode, }) {
9
+ const globalStyle = {
10
+ backgroundColor: page.global_style?.background_color,
11
+ color: '#0f172a',
12
+ fontFamily: page.global_style?.font_family === 'serif'
13
+ ? 'Georgia, "Times New Roman", serif'
14
+ : page.global_style?.font_family === 'sans-serif'
15
+ ? '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
16
+ : 'inherit',
17
+ };
18
+ return (_jsx("div", { style: globalStyle, "data-page-slug": page.slug, children: page.sections
19
+ .filter((s) => s.visible !== false)
20
+ .map((section) => (_jsx(SectionFrame, { section: section, productsBySection: productsBySection, editorMode: editorMode }, section.id))) }));
21
+ }
22
+ function SectionFrame({ section, productsBySection, editorMode }) {
23
+ const isSelected = editorMode?.selectedSectionId === section.id;
24
+ const isEditor = !!editorMode;
25
+ const handleClick = (e) => {
26
+ if (!isEditor)
27
+ return;
28
+ // 阻止内部 a 链接跳转,让商家专注于选中
29
+ e.preventDefault();
30
+ e.stopPropagation();
31
+ editorMode?.onSectionClick?.(section.id);
32
+ };
33
+ const editorStyle = isEditor
34
+ ? {
35
+ position: 'relative',
36
+ cursor: 'pointer',
37
+ outline: isSelected ? '2px solid #f97316' : '2px solid transparent',
38
+ outlineOffset: '-2px',
39
+ transition: 'outline-color 120ms ease',
40
+ }
41
+ : {};
42
+ const onMouseEnter = (e) => {
43
+ if (!isEditor || isSelected)
44
+ return;
45
+ e.currentTarget.style.outlineColor = '#fed7aa';
46
+ };
47
+ const onMouseLeave = (e) => {
48
+ if (!isEditor || isSelected)
49
+ return;
50
+ e.currentTarget.style.outlineColor = 'transparent';
51
+ };
52
+ return (_jsx("div", { "data-section-id": section.id, "data-section-type": section.type, style: editorStyle, onClick: handleClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: renderSection(section, productsBySection) }));
53
+ }
54
+ function renderSection(section, productsBySection) {
55
+ switch (section.type) {
56
+ case 'hero':
57
+ return _jsx(HeroSection, { data: section.data });
58
+ case 'product-grid':
59
+ return (_jsx(ProductGridSection, { data: section.data, products: productsBySection?.[section.id] }));
60
+ case 'banner':
61
+ return _jsx(BannerSection, { data: section.data });
62
+ case 'rich-text':
63
+ return _jsx(RichTextSection, { data: section.data });
64
+ case 'image':
65
+ return _jsx(ImageSection, { data: section.data });
66
+ case 'spacer':
67
+ return _jsx(SpacerSection, { data: section.data });
68
+ default:
69
+ // exhaustive check
70
+ return (_jsxs("div", { style: { padding: 16, background: '#fef2f2', color: '#b91c1c' }, children: ["\u672A\u77E5 section \u7C7B\u578B\uFF1A", section.type] }));
71
+ }
72
+ }
73
+ //# sourceMappingURL=PageRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageRenderer.js","sourceRoot":"","sources":["../../src/page-schema/PageRenderer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @shopbb/helium 的 Page Schema 模块
3
+ *
4
+ * 公开 API:
5
+ * - types:Page / Section / 各 section 的 data 类型
6
+ * - <PageRenderer>:按 schema 渲染一整页
7
+ * - 6 个 section 组件(也可以单独引用)
8
+ * - 工具:createSection / createEmptyPage / validatePage / DEFAULT_DATA
9
+ */
10
+ export type { Page, PageGlobalStyle, Section, AnySection, SectionType, HeroData, HeroSection as HeroSectionType, ProductGridData, ProductGridSection as ProductGridSectionType, BannerData, BannerSection as BannerSectionType, RichTextData, RichTextSection as RichTextSectionType, ImageData, ImageSection as ImageSectionType, SpacerData, SpacerSection as SpacerSectionType, } from './types';
11
+ export { newSectionId, createSection, createEmptyPage, validateSection, validatePage, DEFAULT_DATA, } from './types';
12
+ export { PageRenderer } from './PageRenderer';
13
+ export type { PageRendererProps } from './PageRenderer';
14
+ export { HeroSection } from './sections/Hero';
15
+ export { ProductGridSection } from './sections/ProductGrid';
16
+ export { BannerSection } from './sections/Banner';
17
+ export { RichTextSection } from './sections/RichText';
18
+ export { ImageSection } from './sections/Image';
19
+ export { SpacerSection } from './sections/Spacer';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/page-schema/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,IAAI,EACJ,eAAe,EACf,OAAO,EACP,UAAU,EACV,WAAW,EACX,QAAQ,EACR,WAAW,IAAI,eAAe,EAC9B,eAAe,EACf,kBAAkB,IAAI,sBAAsB,EAC5C,UAAU,EACV,aAAa,IAAI,iBAAiB,EAClC,YAAY,EACZ,eAAe,IAAI,mBAAmB,EACtC,SAAS,EACT,YAAY,IAAI,gBAAgB,EAChC,UAAU,EACV,aAAa,IAAI,iBAAiB,GACnC,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @shopbb/helium 的 Page Schema 模块
3
+ *
4
+ * 公开 API:
5
+ * - types:Page / Section / 各 section 的 data 类型
6
+ * - <PageRenderer>:按 schema 渲染一整页
7
+ * - 6 个 section 组件(也可以单独引用)
8
+ * - 工具:createSection / createEmptyPage / validatePage / DEFAULT_DATA
9
+ */
10
+ export { newSectionId, createSection, createEmptyPage, validateSection, validatePage, DEFAULT_DATA, } from './types';
11
+ export { PageRenderer } from './PageRenderer';
12
+ export { HeroSection } from './sections/Hero';
13
+ export { ProductGridSection } from './sections/ProductGrid';
14
+ export { BannerSection } from './sections/Banner';
15
+ export { RichTextSection } from './sections/RichText';
16
+ export { ImageSection } from './sections/Image';
17
+ export { SpacerSection } from './sections/Spacer';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/page-schema/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * <BannerSection> — 顶部细条状横幅
3
+ */
4
+ import * as React from 'react';
5
+ import type { BannerData } from '../types';
6
+ export interface BannerSectionProps {
7
+ data: BannerData;
8
+ }
9
+ export declare function BannerSection({ data }: BannerSectionProps): React.ReactElement | null;
10
+ //# sourceMappingURL=Banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/Banner.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAmDrF"}
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * <BannerSection> — 顶部细条状横幅
4
+ */
5
+ import * as React from 'react';
6
+ export function BannerSection({ data }) {
7
+ const [dismissed, setDismissed] = React.useState(false);
8
+ if (dismissed)
9
+ return null;
10
+ const style = {
11
+ padding: '12px 32px',
12
+ background: data.background_color ?? '#f97316',
13
+ color: data.text_color ?? '#ffffff',
14
+ display: 'flex',
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
+ gap: 14,
18
+ fontSize: 14,
19
+ fontWeight: 500,
20
+ };
21
+ return (_jsxs("div", { style: style, children: [_jsx("span", { children: data.text }), data.link && (_jsx("a", { href: data.link, style: {
22
+ color: 'inherit',
23
+ textDecoration: 'underline',
24
+ fontWeight: 600,
25
+ }, children: data.link_label ?? '查看详情' })), data.dismissible && (_jsx("button", { type: "button", "aria-label": "\u5173\u95ED", onClick: () => setDismissed(true), style: {
26
+ marginLeft: 'auto',
27
+ background: 'transparent',
28
+ border: 'none',
29
+ color: 'inherit',
30
+ cursor: 'pointer',
31
+ fontSize: 18,
32
+ opacity: 0.8,
33
+ }, children: "\u00D7" }))] }));
34
+ }
35
+ //# sourceMappingURL=Banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../src/page-schema/sections/Banner.tsx"],"names":[],"mappings":";AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAAsB;IACxD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,KAAK,GAAwB;QACjC,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,IAAI,CAAC,gBAAgB,IAAI,SAAS;QAC9C,KAAK,EAAE,IAAI,CAAC,UAAU,IAAI,SAAS;QACnC,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;QACxB,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,GAAG;KAChB,CAAC;IAEF,OAAO,CACL,eAAK,KAAK,EAAE,KAAK,aACf,yBAAO,IAAI,CAAC,IAAI,GAAQ,EACvB,IAAI,CAAC,IAAI,IAAI,CACZ,YACE,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,KAAK,EAAE;oBACL,KAAK,EAAE,SAAS;oBAChB,cAAc,EAAE,WAAW;oBAC3B,UAAU,EAAE,GAAG;iBAChB,YAEA,IAAI,CAAC,UAAU,IAAI,MAAM,GACxB,CACL,EACA,IAAI,CAAC,WAAW,IAAI,CACnB,iBACE,IAAI,EAAC,QAAQ,gBACF,cAAI,EACf,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EACjC,KAAK,EAAE;oBACL,UAAU,EAAE,MAAM;oBAClB,UAAU,EAAE,aAAa;oBACzB,MAAM,EAAE,MAAM;oBACd,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,EAAE;oBACZ,OAAO,EAAE,GAAG;iBACb,uBAGM,CACV,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * <HeroSection> — 渲染 hero 区块
3
+ *
4
+ * 这是按 Page Schema 设计的纯渲染组件:
5
+ * - props 直接接收 HeroData
6
+ * - 不读取 schema,不操作 schema,只渲染
7
+ * - 编辑器与 production storefront 共用同一份组件
8
+ */
9
+ import * as React from 'react';
10
+ import type { HeroData } from '../types';
11
+ export interface HeroSectionProps {
12
+ data: HeroData;
13
+ }
14
+ export declare function HeroSection({ data }: HeroSectionProps): React.ReactElement;
15
+ //# sourceMappingURL=Hero.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hero.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/Hero.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;CAChB;AASD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAoE1E"}
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const HEIGHT_MAP = {
3
+ small: '240px',
4
+ medium: '380px',
5
+ large: '540px',
6
+ full: '85vh',
7
+ };
8
+ export function HeroSection({ data }) {
9
+ const height = HEIGHT_MAP[data.height ?? 'medium'];
10
+ const align = data.text_align ?? 'center';
11
+ const style = {
12
+ position: 'relative',
13
+ minHeight: height,
14
+ display: 'flex',
15
+ flexDirection: 'column',
16
+ justifyContent: 'center',
17
+ alignItems: align === 'center' ? 'center' : align === 'right' ? 'flex-end' : 'flex-start',
18
+ padding: '64px 32px',
19
+ background: data.background_image
20
+ ? `linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0.35)), url(${data.background_image}) center/cover`
21
+ : data.background_color ?? '#0f172a',
22
+ color: data.text_color ?? '#ffffff',
23
+ textAlign: align,
24
+ };
25
+ return (_jsxs("section", { style: style, children: [_jsx("h1", { style: { fontSize: 'clamp(2rem, 5vw, 3.5rem)', fontWeight: 800, margin: 0, maxWidth: '24ch' }, children: data.headline }), data.subheadline && (_jsx("p", { style: { fontSize: 'clamp(1rem, 2vw, 1.25rem)', marginTop: 16, maxWidth: '40ch', opacity: 0.9 }, children: data.subheadline })), (data.cta_label || data.secondary_cta_label) && (_jsxs("div", { style: { marginTop: 28, display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: align }, children: [data.cta_label && (_jsx("a", { href: data.cta_link ?? '#', style: {
26
+ padding: '12px 28px',
27
+ background: data.text_color === '#ffffff' ? '#fff' : '#0f172a',
28
+ color: data.text_color === '#ffffff' ? '#0f172a' : '#ffffff',
29
+ borderRadius: 8,
30
+ fontWeight: 600,
31
+ textDecoration: 'none',
32
+ fontSize: 15,
33
+ }, children: data.cta_label })), data.secondary_cta_label && (_jsx("a", { href: data.secondary_cta_link ?? '#', style: {
34
+ padding: '12px 28px',
35
+ background: 'transparent',
36
+ color: 'inherit',
37
+ border: '1px solid currentColor',
38
+ borderRadius: 8,
39
+ fontWeight: 600,
40
+ textDecoration: 'none',
41
+ fontSize: 15,
42
+ }, children: data.secondary_cta_label }))] }))] }));
43
+ }
44
+ //# sourceMappingURL=Hero.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hero.js","sourceRoot":"","sources":["../../../src/page-schema/sections/Hero.tsx"],"names":[],"mappings":";AAgBA,MAAM,UAAU,GAAoD;IAClE,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,OAAO;IACf,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,EAAoB;IACpD,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC;IAE1C,MAAM,KAAK,GAAwB;QACjC,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,cAAc,EAAE,QAAQ;QACxB,UAAU,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;QACzF,OAAO,EAAE,WAAW;QACpB,UAAU,EAAE,IAAI,CAAC,gBAAgB;YAC/B,CAAC,CAAC,4DAA4D,IAAI,CAAC,gBAAgB,gBAAgB;YACnG,CAAC,CAAC,IAAI,CAAC,gBAAgB,IAAI,SAAS;QACtC,KAAK,EAAE,IAAI,CAAC,UAAU,IAAI,SAAS;QACnC,SAAS,EAAE,KAAK;KACjB,CAAC;IAEF,OAAO,CACL,mBAAS,KAAK,EAAE,KAAK,aACnB,aAAI,KAAK,EAAE,EAAE,QAAQ,EAAE,0BAA0B,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,YAC9F,IAAI,CAAC,QAAQ,GACX,EACJ,IAAI,CAAC,WAAW,IAAI,CACnB,YAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,2BAA2B,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,YAC/F,IAAI,CAAC,WAAW,GACf,CACL,EACA,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAC/C,eAAK,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,aAC7F,IAAI,CAAC,SAAS,IAAI,CACjB,YACE,IAAI,EAAE,IAAI,CAAC,QAAQ,IAAI,GAAG,EAC1B,KAAK,EAAE;4BACL,OAAO,EAAE,WAAW;4BACpB,UAAU,EAAE,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;4BAC9D,KAAK,EAAE,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;4BAC5D,YAAY,EAAE,CAAC;4BACf,UAAU,EAAE,GAAG;4BACf,cAAc,EAAE,MAAM;4BACtB,QAAQ,EAAE,EAAE;yBACb,YAEA,IAAI,CAAC,SAAS,GACb,CACL,EACA,IAAI,CAAC,mBAAmB,IAAI,CAC3B,YACE,IAAI,EAAE,IAAI,CAAC,kBAAkB,IAAI,GAAG,EACpC,KAAK,EAAE;4BACL,OAAO,EAAE,WAAW;4BACpB,UAAU,EAAE,aAAa;4BACzB,KAAK,EAAE,SAAS;4BAChB,MAAM,EAAE,wBAAwB;4BAChC,YAAY,EAAE,CAAC;4BACf,UAAU,EAAE,GAAG;4BACf,cAAc,EAAE,MAAM;4BACtB,QAAQ,EAAE,EAAE;yBACb,YAEA,IAAI,CAAC,mBAAmB,GACvB,CACL,IACG,CACP,IACO,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * <ImageSection> — 单张图片,可加链接
3
+ */
4
+ import * as React from 'react';
5
+ import type { ImageData } from '../types';
6
+ export interface ImageSectionProps {
7
+ data: ImageData;
8
+ }
9
+ export declare function ImageSection({ data }: ImageSectionProps): React.ReactElement;
10
+ //# sourceMappingURL=Image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/Image.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,CAAC;CACjB;AAQD,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAwB5E"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const WIDTH_MAP = {
3
+ full: '100%',
4
+ normal: '1200px',
5
+ narrow: '760px',
6
+ };
7
+ export function ImageSection({ data }) {
8
+ const maxWidth = WIDTH_MAP[data.width ?? 'normal'];
9
+ const img = (_jsx("img", { src: data.url, alt: data.alt ?? '', style: { display: 'block', width: '100%', height: 'auto' } }));
10
+ return (_jsx("section", { style: { padding: data.width === 'full' ? 0 : '32px', textAlign: 'center' }, children: _jsx("div", { style: { maxWidth, margin: '0 auto' }, children: data.link ? (_jsx("a", { href: data.link, style: { display: 'block' }, children: img })) : (img) }) }));
11
+ }
12
+ //# sourceMappingURL=Image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Image.js","sourceRoot":"","sources":["../../../src/page-schema/sections/Image.tsx"],"names":[],"mappings":";AAWA,MAAM,SAAS,GAAoD;IACjE,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,OAAO;CAChB,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,EAAqB;IACtD,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;IAEnD,MAAM,GAAG,GAAG,CACV,cACE,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE,EACnB,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAC1D,CACH,CAAC;IAEF,OAAO,CACL,kBAAS,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,YAClF,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YACvC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CACX,YAAG,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,YAC5C,GAAG,GACF,CACL,CAAC,CAAC,CAAC,CACF,GAAG,CACJ,GACG,GACE,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * <ProductGridSection> — 商品网格
3
+ *
4
+ * 拉取商品数据需要 storefront client,由父组件通过 props 注入避免组件耦合。
5
+ *
6
+ * P0 简化:组件本身不拉数据,仅按传入的 products 数组渲染。Page renderer 负责
7
+ * 在渲染前根据 selection_mode 拉好商品。
8
+ */
9
+ import * as React from 'react';
10
+ import type { ProductGridData } from '../types';
11
+ export interface ProductGridSectionProps {
12
+ data: ProductGridData;
13
+ /** 父组件预先拉好的商品数据 */
14
+ products?: Array<{
15
+ id: string;
16
+ handle: string;
17
+ title: string;
18
+ price?: {
19
+ amount: string;
20
+ currencyCode: string;
21
+ };
22
+ image?: {
23
+ url: string;
24
+ alt?: string;
25
+ };
26
+ }>;
27
+ }
28
+ export declare function ProductGridSection({ data, products }: ProductGridSectionProps): React.ReactElement;
29
+ //# sourceMappingURL=ProductGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductGrid.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/ProductGrid.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,eAAe,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAA;SAAE,CAAC;QACjD,KAAK,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACvC,CAAC,CAAC;CACJ;AAED,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,uBAAuB,GAAG,KAAK,CAAC,YAAY,CAuElG"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function ProductGridSection({ data, products }) {
3
+ const columns = data.columns ?? 3;
4
+ const list = products ?? [];
5
+ return (_jsxs("section", { style: { padding: '64px 32px', maxWidth: 1280, margin: '0 auto' }, children: [data.title && (_jsx("h2", { style: { fontSize: 'clamp(1.5rem, 3vw, 2rem)', margin: 0, fontWeight: 800 }, children: data.title })), data.subtitle && (_jsx("p", { style: { marginTop: 8, color: '#64748b', fontSize: 15 }, children: data.subtitle })), _jsx("div", { style: {
6
+ marginTop: 24,
7
+ display: 'grid',
8
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
9
+ gap: 24,
10
+ }, children: list.length === 0 ? (_jsx("div", { style: {
11
+ gridColumn: '1 / -1',
12
+ padding: '40px 0',
13
+ textAlign: 'center',
14
+ color: '#94a3b8',
15
+ fontSize: 14,
16
+ }, children: data.selection_mode === 'manual'
17
+ ? '(暂未选定商品)'
18
+ : '(暂无商品数据,编辑器预览模式不拉取真实数据)' })) : (list.map((p) => (_jsxs("a", { href: `/products/${p.handle}`, style: {
19
+ background: '#fff',
20
+ border: '1px solid #e2e8f0',
21
+ borderRadius: 10,
22
+ overflow: 'hidden',
23
+ textDecoration: 'none',
24
+ color: 'inherit',
25
+ display: 'block',
26
+ }, children: [p.image && (_jsx("img", { src: p.image.url, alt: p.image.alt || p.title, style: { width: '100%', aspectRatio: '1 / 1', objectFit: 'cover', display: 'block' } })), _jsxs("div", { style: { padding: 14 }, children: [_jsx("div", { style: { fontSize: 14, fontWeight: 600, color: '#0f172a' }, children: p.title }), p.price && (_jsxs("div", { style: { marginTop: 6, fontSize: 15, color: '#ea580c', fontWeight: 700 }, children: [p.price.currencyCode === 'CNY' ? '¥' : p.price.currencyCode + ' ', p.price.amount] }))] })] }, p.id)))) })] }));
27
+ }
28
+ //# sourceMappingURL=ProductGrid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductGrid.js","sourceRoot":"","sources":["../../../src/page-schema/sections/ProductGrid.tsx"],"names":[],"mappings":";AAwBA,MAAM,UAAU,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAA2B;IAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,QAAQ,IAAI,EAAE,CAAC;IAE5B,OAAO,CACL,mBAAS,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aACvE,IAAI,CAAC,KAAK,IAAI,CACb,aAAI,KAAK,EAAE,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,YAAG,IAAI,CAAC,KAAK,GAAM,CACnG,EACA,IAAI,CAAC,QAAQ,IAAI,CAChB,YAAG,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAG,IAAI,CAAC,QAAQ,GAAK,CAChF,EACD,cACE,KAAK,EAAE;oBACL,SAAS,EAAE,EAAE;oBACb,OAAO,EAAE,MAAM;oBACf,mBAAmB,EAAE,UAAU,OAAO,mBAAmB;oBACzD,GAAG,EAAE,EAAE;iBACR,YAEA,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACnB,cACE,KAAK,EAAE;wBACL,UAAU,EAAE,QAAQ;wBACpB,OAAO,EAAE,QAAQ;wBACjB,SAAS,EAAE,QAAQ;wBACnB,KAAK,EAAE,SAAS;wBAChB,QAAQ,EAAE,EAAE;qBACb,YAEA,IAAI,CAAC,cAAc,KAAK,QAAQ;wBAC/B,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,yBAAyB,GACzB,CACP,CAAC,CAAC,CAAC,CACF,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACd,aAEE,IAAI,EAAE,aAAa,CAAC,CAAC,MAAM,EAAE,EAC7B,KAAK,EAAE;wBACL,UAAU,EAAE,MAAM;wBAClB,MAAM,EAAE,mBAAmB;wBAC3B,YAAY,EAAE,EAAE;wBAChB,QAAQ,EAAE,QAAQ;wBAClB,cAAc,EAAE,MAAM;wBACtB,KAAK,EAAE,SAAS;wBAChB,OAAO,EAAE,OAAO;qBACjB,aAEA,CAAC,CAAC,KAAK,IAAI,CACV,cACE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,EAC3B,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GACpF,CACH,EACD,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,aACzB,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,YAAG,CAAC,CAAC,KAAK,GAAO,EAC/E,CAAC,CAAC,KAAK,IAAI,CACV,eAAK,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,aAC1E,CAAC,CAAC,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,EACjE,CAAC,CAAC,KAAK,CAAC,MAAM,IACX,CACP,IACG,KA3BD,CAAC,CAAC,EAAE,CA4BP,CACL,CAAC,CACH,GACG,IACE,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * <RichTextSection> — 富文本
3
+ *
4
+ * P0:只支持 plain text + 简单换行;markdown 渲染留给商家自己用 marked 库或写成 html
5
+ * mode。等编辑器成熟后再上 markdown 渲染。
6
+ */
7
+ import * as React from 'react';
8
+ import type { RichTextData } from '../types';
9
+ export interface RichTextSectionProps {
10
+ data: RichTextData;
11
+ }
12
+ export declare function RichTextSection({ data }: RichTextSectionProps): React.ReactElement;
13
+ //# sourceMappingURL=RichText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichText.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/RichText.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,CAAC;CACpB;AAQD,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CA4BlF"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ const WIDTH_MAP = {
3
+ narrow: '640px',
4
+ normal: '880px',
5
+ wide: '1200px',
6
+ };
7
+ export function RichTextSection({ data }) {
8
+ const maxWidth = WIDTH_MAP[data.max_width ?? 'normal'];
9
+ if (data.format === 'html') {
10
+ return (_jsx("section", { style: { padding: '48px 32px' }, children: _jsx("div", { style: { maxWidth, margin: '0 auto', lineHeight: 1.7, fontSize: 15.5, color: '#0f172a' }, dangerouslySetInnerHTML: { __html: data.body } }) }));
11
+ }
12
+ // markdown / plain:按段落分割(双换行 = 新段落)
13
+ const paragraphs = data.body.split(/\n{2,}/);
14
+ return (_jsx("section", { style: { padding: '48px 32px' }, children: _jsx("div", { style: { maxWidth, margin: '0 auto', lineHeight: 1.7, fontSize: 15.5, color: '#0f172a' }, children: paragraphs.map((p, i) => (_jsx("p", { style: { margin: i === 0 ? '0' : '1em 0 0', whiteSpace: 'pre-line' }, children: p }, i))) }) }));
15
+ }
16
+ //# sourceMappingURL=RichText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichText.js","sourceRoot":"","sources":["../../../src/page-schema/sections/RichText.tsx"],"names":[],"mappings":";AAcA,MAAM,SAAS,GAA2D;IACxE,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;IACf,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,EAAE,IAAI,EAAwB;IAC5D,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC;IAEvD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,CACL,kBAAS,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YACtC,cACE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EACxF,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,GAC9C,GACM,CACX,CAAC;IACJ,CAAC;IAED,oCAAoC;IACpC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO,CACL,kBAAS,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,YACtC,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,YAC1F,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACxB,YAAW,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAC5E,CAAC,IADI,CAAC,CAEL,CACL,CAAC,GACE,GACE,CACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * <SpacerSection> — 垂直留白
3
+ */
4
+ import * as React from 'react';
5
+ import type { SpacerData } from '../types';
6
+ export interface SpacerSectionProps {
7
+ data: SpacerData;
8
+ }
9
+ export declare function SpacerSection({ data }: SpacerSectionProps): React.ReactElement;
10
+ //# sourceMappingURL=Spacer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spacer.d.ts","sourceRoot":"","sources":["../../../src/page-schema/sections/Spacer.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAG9E"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export function SpacerSection({ data }) {
3
+ const height = typeof data.height === 'number' ? `${data.height}px` : data.height;
4
+ return _jsx("div", { style: { height }, "aria-hidden": true });
5
+ }
6
+ //# sourceMappingURL=Spacer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spacer.js","sourceRoot":"","sources":["../../../src/page-schema/sections/Spacer.tsx"],"names":[],"mappings":";AAWA,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAAsB;IACxD,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAClF,OAAO,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,wBAAgB,CAAC;AAChD,CAAC"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Page Schema — 装修页面的结构化数据模型
3
+ *
4
+ * 一个 Page 是若干 Section 的有序数组。每个 Section 是 (type, data) 的结构化值,
5
+ * 不是任意 React 代码。这样 agent / 编辑器 / 渲染器都能精准操作。
6
+ *
7
+ * 设计原则:
8
+ * 1. 强 schema:每个 type 的 data 字段固定,agent 不能"乱发挥"
9
+ * 2. stable id:每个 section 有唯一 id,编辑器选中、agent 引用都靠它
10
+ * 3. 可演进:新加 section type 只需扩 SectionType 联合 + 实现对应 React 组件
11
+ * 4. 反规范化:data 是平铺字段而不是嵌套结构,方便 agent 修改单个属性
12
+ */
13
+ export type SectionType = 'hero' | 'product-grid' | 'banner' | 'rich-text' | 'image' | 'spacer';
14
+ /** 通用 section wrapper */
15
+ export interface Section<T extends SectionType = SectionType, D = unknown> {
16
+ /** 唯一 ID,stable,编辑器与 agent 都引用它 */
17
+ id: string;
18
+ /** Section 类型 */
19
+ type: T;
20
+ /** 类型对应的数据字段 */
21
+ data: D;
22
+ /** 是否可见。隐藏的 section 不渲染但保留在 schema 里(方便商家临时下线某块) */
23
+ visible: boolean;
24
+ }
25
+ export interface HeroData {
26
+ /** 大标题 */
27
+ headline: string;
28
+ /** 副标题 */
29
+ subheadline?: string;
30
+ /** 背景图 URL */
31
+ background_image?: string;
32
+ /** 背景色,hex 或 css 颜色 */
33
+ background_color?: string;
34
+ /** 文字颜色 */
35
+ text_color?: string;
36
+ /** 主 CTA 按钮文案 */
37
+ cta_label?: string;
38
+ /** 主 CTA 链接 */
39
+ cta_link?: string;
40
+ /** 副 CTA 按钮文案 */
41
+ secondary_cta_label?: string;
42
+ /** 副 CTA 链接 */
43
+ secondary_cta_link?: string;
44
+ /** 高度 */
45
+ height?: 'small' | 'medium' | 'large' | 'full';
46
+ /** 文字对齐 */
47
+ text_align?: 'left' | 'center' | 'right';
48
+ }
49
+ export interface ProductGridData {
50
+ /** 标题(可选) */
51
+ title?: string;
52
+ /** 副标题 */
53
+ subtitle?: string;
54
+ /** 选商品的方式 */
55
+ selection_mode: 'manual' | 'collection' | 'newest' | 'top-selling';
56
+ /** manual 模式下,指定的 product handle 列表 */
57
+ product_handles?: string[];
58
+ /** collection 模式下,指定的 collection handle */
59
+ collection_handle?: string;
60
+ /** 自动模式下取多少个 */
61
+ limit?: number;
62
+ /** 一行几列 */
63
+ columns?: 2 | 3 | 4;
64
+ }
65
+ export interface BannerData {
66
+ /** 主文案 */
67
+ text: string;
68
+ /** 链接(可选) */
69
+ link?: string;
70
+ /** 链接打开文案,例如"立即查看" */
71
+ link_label?: string;
72
+ /** 背景色 */
73
+ background_color?: string;
74
+ /** 文字色 */
75
+ text_color?: string;
76
+ /** 关闭按钮(用户能 dismiss) */
77
+ dismissible?: boolean;
78
+ }
79
+ export interface RichTextData {
80
+ /** Markdown / HTML 文本 */
81
+ body: string;
82
+ /** 渲染模式 */
83
+ format?: 'markdown' | 'html';
84
+ /** 最大宽度(约束阅读体验) */
85
+ max_width?: 'narrow' | 'normal' | 'wide';
86
+ }
87
+ export interface ImageData {
88
+ /** 图片 URL */
89
+ url: string;
90
+ /** alt 文本(无障碍) */
91
+ alt?: string;
92
+ /** 点击跳转链接 */
93
+ link?: string;
94
+ /** 宽度模式 */
95
+ width?: 'full' | 'normal' | 'narrow';
96
+ }
97
+ export interface SpacerData {
98
+ /** 高度(像素或者 css 单位字符串) */
99
+ height: number | string;
100
+ }
101
+ export type HeroSection = Section<'hero', HeroData>;
102
+ export type ProductGridSection = Section<'product-grid', ProductGridData>;
103
+ export type BannerSection = Section<'banner', BannerData>;
104
+ export type RichTextSection = Section<'rich-text', RichTextData>;
105
+ export type ImageSection = Section<'image', ImageData>;
106
+ export type SpacerSection = Section<'spacer', SpacerData>;
107
+ export type AnySection = HeroSection | ProductGridSection | BannerSection | RichTextSection | ImageSection | SpacerSection;
108
+ /** 全局样式(应用到整个 page 的层级) */
109
+ export interface PageGlobalStyle {
110
+ primary_color?: string;
111
+ background_color?: string;
112
+ font_family?: 'system' | 'serif' | 'sans-serif' | string;
113
+ }
114
+ export interface Page {
115
+ /** 页面标识,例如 'home' / 'about' / 'collections/featured' */
116
+ slug: string;
117
+ /** 浏览器标题(可选,缺省用 store name) */
118
+ title?: string;
119
+ /** Section 数组,按顺序渲染 */
120
+ sections: AnySection[];
121
+ /** 全局样式 */
122
+ global_style?: PageGlobalStyle;
123
+ /** Schema 版本,用于将来升级时迁移 */
124
+ schema_version: 1;
125
+ }
126
+ export declare function newSectionId(type: SectionType): string;
127
+ export declare const DEFAULT_DATA: {
128
+ [K in SectionType]: AnySection['data'];
129
+ };
130
+ /** 创建一个新 section(带默认 data) */
131
+ export declare function createSection<T extends SectionType>(type: T): AnySection;
132
+ /** 创建一个空白 page */
133
+ export declare function createEmptyPage(slug: string): Page;
134
+ /** 校验一个 section 数据完整性。返回错误列表,空数组表示合法 */
135
+ export declare function validateSection(section: AnySection): string[];
136
+ /** 校验整个 page */
137
+ export declare function validatePage(page: Page): string[];
138
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/page-schema/types.ts"],"names":[],"mappings":"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"}