@shopbb/helium 0.8.0 → 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 (51) hide show
  1. package/dist/page-schema/PageRenderer.d.ts +29 -0
  2. package/dist/page-schema/PageRenderer.d.ts.map +1 -0
  3. package/dist/page-schema/PageRenderer.js +73 -0
  4. package/dist/page-schema/PageRenderer.js.map +1 -0
  5. package/dist/page-schema/index.d.ts +20 -0
  6. package/dist/page-schema/index.d.ts.map +1 -0
  7. package/dist/page-schema/index.js +18 -0
  8. package/dist/page-schema/index.js.map +1 -0
  9. package/dist/page-schema/sections/Banner.d.ts +10 -0
  10. package/dist/page-schema/sections/Banner.d.ts.map +1 -0
  11. package/dist/page-schema/sections/Banner.js +35 -0
  12. package/dist/page-schema/sections/Banner.js.map +1 -0
  13. package/dist/page-schema/sections/Hero.d.ts +15 -0
  14. package/dist/page-schema/sections/Hero.d.ts.map +1 -0
  15. package/dist/page-schema/sections/Hero.js +44 -0
  16. package/dist/page-schema/sections/Hero.js.map +1 -0
  17. package/dist/page-schema/sections/Image.d.ts +10 -0
  18. package/dist/page-schema/sections/Image.d.ts.map +1 -0
  19. package/dist/page-schema/sections/Image.js +12 -0
  20. package/dist/page-schema/sections/Image.js.map +1 -0
  21. package/dist/page-schema/sections/ProductGrid.d.ts +29 -0
  22. package/dist/page-schema/sections/ProductGrid.d.ts.map +1 -0
  23. package/dist/page-schema/sections/ProductGrid.js +28 -0
  24. package/dist/page-schema/sections/ProductGrid.js.map +1 -0
  25. package/dist/page-schema/sections/RichText.d.ts +13 -0
  26. package/dist/page-schema/sections/RichText.d.ts.map +1 -0
  27. package/dist/page-schema/sections/RichText.js +16 -0
  28. package/dist/page-schema/sections/RichText.js.map +1 -0
  29. package/dist/page-schema/sections/Spacer.d.ts +10 -0
  30. package/dist/page-schema/sections/Spacer.d.ts.map +1 -0
  31. package/dist/page-schema/sections/Spacer.js +6 -0
  32. package/dist/page-schema/sections/Spacer.js.map +1 -0
  33. package/dist/page-schema/types.d.ts +138 -0
  34. package/dist/page-schema/types.d.ts.map +1 -0
  35. package/dist/page-schema/types.js +129 -0
  36. package/dist/page-schema/types.js.map +1 -0
  37. package/dist/react.d.ts +2 -0
  38. package/dist/react.d.ts.map +1 -1
  39. package/dist/react.js +5 -0
  40. package/dist/react.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/page-schema/PageRenderer.tsx +147 -0
  43. package/src/page-schema/index.ts +48 -0
  44. package/src/page-schema/sections/Banner.tsx +63 -0
  45. package/src/page-schema/sections/Hero.tsx +92 -0
  46. package/src/page-schema/sections/Image.tsx +42 -0
  47. package/src/page-schema/sections/ProductGrid.tsx +96 -0
  48. package/src/page-schema/sections/RichText.tsx +49 -0
  49. package/src/page-schema/sections/Spacer.tsx +15 -0
  50. package/src/page-schema/types.ts +286 -0
  51. package/src/react.tsx +33 -0
@@ -0,0 +1,29 @@
1
+ /**
2
+ * <PageRenderer> — 按 Page Schema 渲染一整页
3
+ *
4
+ * 同一份组件在 production storefront 与 admin 编辑器画布共用。
5
+ *
6
+ * 商品网格的 selection_mode 自动模式(newest / top-selling / collection)
7
+ * 由父组件预先拉数据通过 productsBySection prop 注入,组件本身不发请求。
8
+ * 这让 renderer 保持纯组件、可在 SSR / CSR / 编辑器画布任何环境用。
9
+ */
10
+ import * as React from 'react';
11
+ import type { Page } from './types';
12
+ export interface PageRendererProps {
13
+ page: Page;
14
+ /**
15
+ * 按 section.id 提供该 section 用到的商品数据(仅 product-grid 用到)。
16
+ * Page renderer 不发请求,请父组件按 schema 计算后传入。
17
+ */
18
+ productsBySection?: Record<string, any[]>;
19
+ /**
20
+ * 编辑器模式下传入 onSectionClick / selectedSectionId,渲染时会给每个 section
21
+ * 加 hover / 选中外框,便于点选定位。
22
+ */
23
+ editorMode?: {
24
+ selectedSectionId?: string | null;
25
+ onSectionClick?: (sectionId: string) => void;
26
+ };
27
+ }
28
+ export declare function PageRenderer({ page, productsBySection, editorMode, }: PageRendererProps): React.ReactElement;
29
+ //# sourceMappingURL=PageRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageRenderer.d.ts","sourceRoot":"","sources":["../../src/page-schema/PageRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAc,IAAI,EAAE,MAAM,SAAS,CAAC;AAQhD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,IAAI,CAAC;IACX;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C;;;OAGG;IACH,UAAU,CAAC,EAAE;QACX,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,iBAAiB,EACjB,UAAU,GACX,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CA0BxC"}
@@ -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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"}