@shopbb/helium 0.3.0-alpha.1 → 0.3.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 (34) hide show
  1. package/dist/components/AddToCartButton.d.ts.map +1 -1
  2. package/dist/components/AddToCartButton.js +17 -5
  3. package/dist/components/AddToCartButton.js.map +1 -1
  4. package/dist/components/AnalyticsProvider.d.ts +106 -0
  5. package/dist/components/AnalyticsProvider.d.ts.map +1 -0
  6. package/dist/components/AnalyticsProvider.js +135 -0
  7. package/dist/components/AnalyticsProvider.js.map +1 -0
  8. package/dist/components/CartProvider.d.ts +111 -0
  9. package/dist/components/CartProvider.d.ts.map +1 -0
  10. package/dist/components/CartProvider.js +263 -0
  11. package/dist/components/CartProvider.js.map +1 -0
  12. package/dist/components/Money.d.ts.map +1 -1
  13. package/dist/components/Money.js +6 -1
  14. package/dist/components/Money.js.map +1 -1
  15. package/dist/components/ProductOptionsProvider.d.ts +70 -0
  16. package/dist/components/ProductOptionsProvider.d.ts.map +1 -0
  17. package/dist/components/ProductOptionsProvider.js +93 -0
  18. package/dist/components/ProductOptionsProvider.js.map +1 -0
  19. package/dist/components/ShopProvider.d.ts +49 -0
  20. package/dist/components/ShopProvider.d.ts.map +1 -0
  21. package/dist/components/ShopProvider.js +62 -0
  22. package/dist/components/ShopProvider.js.map +1 -0
  23. package/dist/components/index.d.ts +18 -1
  24. package/dist/components/index.d.ts.map +1 -1
  25. package/dist/components/index.js +16 -1
  26. package/dist/components/index.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/components/AddToCartButton.tsx +16 -5
  29. package/src/components/AnalyticsProvider.tsx +175 -0
  30. package/src/components/CartProvider.tsx +378 -0
  31. package/src/components/Money.tsx +7 -1
  32. package/src/components/ProductOptionsProvider.tsx +149 -0
  33. package/src/components/ShopProvider.tsx +86 -0
  34. package/src/components/index.ts +39 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AddToCartButton.d.ts","sourceRoot":"","sources":["../../src/components/AddToCartButton.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtH,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa;IACb,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,2BAA2B;IAC3B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,wBAAwB;IACxB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CA+C1D"}
1
+ {"version":3,"file":"AddToCartButton.d.ts","sourceRoot":"","sources":["../../src/components/AddToCartButton.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtH,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa;IACb,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,2BAA2B;IAC3B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,wBAAwB;IACxB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CAwD1D"}
@@ -22,20 +22,32 @@ import { jsx as _jsx } from "react/jsx-runtime";
22
22
  * Phase 2 后:组件会自动从 <CartProvider> 拿,无需 onAdd 也能用。
23
23
  */
24
24
  import * as React from 'react';
25
+ import { useCartOptional } from './CartProvider';
26
+ import { useAnalytics } from './AnalyticsProvider';
25
27
  export function AddToCartButton(props) {
26
28
  const { variantId, quantity = 1, onAdd, onAdded, onError, loadingText = '加入中...', unavailableText = '缺货', children = '加入购物车', disabled: disabledProp, ...rest } = props;
27
29
  const [adding, setAdding] = React.useState(false);
30
+ const cart = useCartOptional();
31
+ const analytics = useAnalytics();
28
32
  const handleClick = async (e) => {
29
33
  e.preventDefault();
30
34
  if (adding || disabledProp)
31
35
  return;
32
- if (!onAdd) {
33
- console.warn('[AddToCartButton] onAdd not provided; this button does nothing in Phase 1');
34
- return;
35
- }
36
36
  setAdding(true);
37
37
  try {
38
- await onAdd(variantId, quantity);
38
+ if (onAdd) {
39
+ // 商家显式传了 onAdd 优先用(Phase 1 兼容路径)
40
+ await onAdd(variantId, quantity);
41
+ }
42
+ else if (cart) {
43
+ // 自动从 <CartProvider> 取
44
+ await cart.linesAdd([{ merchandiseId: variantId, quantity }]);
45
+ }
46
+ else {
47
+ console.warn('[AddToCartButton] no onAdd and no <CartProvider> — button does nothing');
48
+ return;
49
+ }
50
+ analytics.emit('add_to_cart', { variantId, quantity });
39
51
  onAdded?.();
40
52
  }
41
53
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"AddToCartButton.js","sourceRoot":"","sources":["../../src/components/AddToCartButton.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAmB/B,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EACJ,SAAS,EACT,QAAQ,GAAG,CAAC,EACZ,KAAK,EACL,OAAO,EACP,OAAO,EACP,WAAW,GAAG,QAAQ,EACtB,eAAe,GAAG,IAAI,EACtB,QAAQ,GAAG,OAAO,EAClB,QAAQ,EAAE,YAAY,EACtB,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,MAAM,WAAW,GAAG,KAAK,EAAE,CAAsC,EAAE,EAAE;QACnE,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,MAAM,IAAI,YAAY;YAAE,OAAO;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;YAC1F,OAAO;QACT,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACjC,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,KACT,IAAI,4CAEM,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EACrC,QAAQ,EAAE,YAAY,IAAI,MAAM,EAChC,OAAO,EAAE,WAAW,YAEnB,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,GAC1D,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"AddToCartButton.js","sourceRoot":"","sources":["../../src/components/AddToCartButton.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAmBnD,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EACJ,SAAS,EACT,QAAQ,GAAG,CAAC,EACZ,KAAK,EACL,OAAO,EACP,OAAO,EACP,WAAW,GAAG,QAAQ,EACtB,eAAe,GAAG,IAAI,EACtB,QAAQ,GAAG,OAAO,EAClB,QAAQ,EAAE,YAAY,EACtB,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IAEjC,MAAM,WAAW,GAAG,KAAK,EAAE,CAAsC,EAAE,EAAE;QACnE,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,MAAM,IAAI,YAAY;YAAE,OAAO;QAEnC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,CAAC;gBACV,iCAAiC;gBACjC,MAAM,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACnC,CAAC;iBAAM,IAAI,IAAI,EAAE,CAAC;gBAChB,uBAAuB;gBACvB,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;gBACvF,OAAO;YACT,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,KACT,IAAI,4CAEM,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EACrC,QAAQ,EAAE,YAAY,IAAI,MAAM,EAChC,OAAO,EAAE,WAAW,YAEnB,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,GAC1D,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * <AnalyticsProvider> + useAnalytics() + <Analytics.*> 事件组件
3
+ *
4
+ * 简单事件总线:
5
+ * - 商家注册 reporters(GA / Plausible / 自家 API)
6
+ * - 通过 <Analytics.PageView /> / <Analytics.ProductView /> 等组件声明式触发
7
+ * - 也可以 useAnalytics().emit(name, data)
8
+ *
9
+ * 用法:
10
+ * <AnalyticsProvider
11
+ * onEvent={(e) => {
12
+ * fetch('/api/analytics', { method: 'POST', body: JSON.stringify(e) });
13
+ * window.dataLayer?.push(e);
14
+ * }}
15
+ * >
16
+ * <App />
17
+ * </AnalyticsProvider>
18
+ *
19
+ * // 在某页:
20
+ * <Analytics.PageView path="/products" title="Products" />
21
+ * <Analytics.ProductView product={product} />
22
+ * <Analytics.AddToCart cart={cart} addedLineId={lineId} />
23
+ *
24
+ * // 命令式:
25
+ * const { emit } = useAnalytics();
26
+ * emit('search', { query: 'wireless' });
27
+ */
28
+ import * as React from 'react';
29
+ export interface AnalyticsEvent {
30
+ /** 事件名,例如 'page_view' / 'product_view' / 'add_to_cart' */
31
+ name: string;
32
+ /** 时间戳 (ms) */
33
+ timestamp: number;
34
+ /** 当前 shop(如果在 ShopProvider 内) */
35
+ shop?: {
36
+ storeId: string;
37
+ shopName: string;
38
+ } | null;
39
+ /** 自定义 payload */
40
+ payload: Record<string, any>;
41
+ }
42
+ export interface AnalyticsContextValue {
43
+ emit: (name: string, payload?: Record<string, any>) => void;
44
+ }
45
+ export interface AnalyticsProviderProps {
46
+ children: React.ReactNode;
47
+ /** 接收所有事件的回调 */
48
+ onEvent?: (event: AnalyticsEvent) => void;
49
+ /** 是否自动监听 cart 变化触发 cart_updated 事件 */
50
+ trackCart?: boolean;
51
+ }
52
+ export declare function AnalyticsProvider(props: AnalyticsProviderProps): import("react/jsx-runtime").JSX.Element;
53
+ export declare function useAnalytics(): AnalyticsContextValue;
54
+ declare function PageView(props: {
55
+ path?: string;
56
+ title?: string;
57
+ [key: string]: any;
58
+ }): null;
59
+ declare function ProductView(props: {
60
+ product: {
61
+ id: string;
62
+ handle?: string;
63
+ title?: string;
64
+ };
65
+ [key: string]: any;
66
+ }): null;
67
+ declare function CollectionView(props: {
68
+ collection: {
69
+ id: string;
70
+ handle?: string;
71
+ };
72
+ [key: string]: any;
73
+ }): null;
74
+ declare function SearchView(props: {
75
+ query: string;
76
+ results?: number;
77
+ }): null;
78
+ declare function AddToCart(props: {
79
+ variantId: string;
80
+ quantity?: number;
81
+ [key: string]: any;
82
+ }): null;
83
+ declare function CheckoutStart(props: {
84
+ cart?: {
85
+ id: string;
86
+ totalQuantity?: number;
87
+ };
88
+ }): null;
89
+ declare function Purchase(props: {
90
+ orderId: string;
91
+ total: number;
92
+ currencyCode: string;
93
+ [key: string]: any;
94
+ }): null;
95
+ /** 命名空间导出,让用户写 <Analytics.PageView /> */
96
+ export declare const Analytics: {
97
+ PageView: typeof PageView;
98
+ ProductView: typeof ProductView;
99
+ CollectionView: typeof CollectionView;
100
+ SearchView: typeof SearchView;
101
+ AddToCart: typeof AddToCart;
102
+ CheckoutStart: typeof CheckoutStart;
103
+ Purchase: typeof Purchase;
104
+ };
105
+ export {};
106
+ //# sourceMappingURL=AnalyticsProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsProvider.d.ts","sourceRoot":"","sources":["../../src/components/AnalyticsProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAC7D;AAID,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,gBAAgB;IAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1C,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,2CAkC9D;AAED,wBAAgB,YAAY,IAAI,qBAAqB,CAOpD;AAkBD,iBAAS,QAAQ,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QAE7E;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QAQ3G;AAED,iBAAS,cAAc,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QAOjG;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,QAE7D;AAED,iBAAS,SAAS,CAAC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QAOrF;AAED,iBAAS,aAAa,CAAC,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,QAK9E;AAED,iBAAS,QAAQ,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,QAEpG;AAED,yCAAyC;AACzC,eAAO,MAAM,SAAS;;;;;;;;CAQrB,CAAC"}
@@ -0,0 +1,135 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * <AnalyticsProvider> + useAnalytics() + <Analytics.*> 事件组件
4
+ *
5
+ * 简单事件总线:
6
+ * - 商家注册 reporters(GA / Plausible / 自家 API)
7
+ * - 通过 <Analytics.PageView /> / <Analytics.ProductView /> 等组件声明式触发
8
+ * - 也可以 useAnalytics().emit(name, data)
9
+ *
10
+ * 用法:
11
+ * <AnalyticsProvider
12
+ * onEvent={(e) => {
13
+ * fetch('/api/analytics', { method: 'POST', body: JSON.stringify(e) });
14
+ * window.dataLayer?.push(e);
15
+ * }}
16
+ * >
17
+ * <App />
18
+ * </AnalyticsProvider>
19
+ *
20
+ * // 在某页:
21
+ * <Analytics.PageView path="/products" title="Products" />
22
+ * <Analytics.ProductView product={product} />
23
+ * <Analytics.AddToCart cart={cart} addedLineId={lineId} />
24
+ *
25
+ * // 命令式:
26
+ * const { emit } = useAnalytics();
27
+ * emit('search', { query: 'wireless' });
28
+ */
29
+ import * as React from 'react';
30
+ import { useCartOptional } from './CartProvider';
31
+ import { useShopOptional } from './ShopProvider';
32
+ const Ctx = React.createContext(null);
33
+ export function AnalyticsProvider(props) {
34
+ const { children, onEvent, trackCart = true } = props;
35
+ const shop = useShopOptional();
36
+ const cartCtx = useCartOptional();
37
+ const onEventRef = React.useRef(onEvent);
38
+ React.useEffect(() => {
39
+ onEventRef.current = onEvent;
40
+ }, [onEvent]);
41
+ const emit = React.useCallback((name, payload = {}) => {
42
+ onEventRef.current?.({
43
+ name,
44
+ timestamp: Date.now(),
45
+ shop: shop ? { storeId: shop.storeId, shopName: shop.shopName } : null,
46
+ payload,
47
+ });
48
+ }, [shop]);
49
+ // cart 自动追踪
50
+ React.useEffect(() => {
51
+ if (!trackCart || !cartCtx)
52
+ return;
53
+ return cartCtx.subscribe((c) => {
54
+ emit('cart_updated', {
55
+ cartId: c?.id,
56
+ totalQuantity: c?.totalQuantity,
57
+ totalAmount: c?.cost.totalAmount,
58
+ });
59
+ });
60
+ }, [trackCart, cartCtx, emit]);
61
+ return _jsx(Ctx.Provider, { value: { emit }, children: children });
62
+ }
63
+ export function useAnalytics() {
64
+ const v = React.useContext(Ctx);
65
+ if (!v) {
66
+ // 没 Provider 时返回 noop(不 throw,便于组件可选嵌入)
67
+ return { emit: () => { } };
68
+ }
69
+ return v;
70
+ }
71
+ // ============================================================
72
+ // 声明式事件组件
73
+ // ============================================================
74
+ function useEmitOnMount(name, payload) {
75
+ const { emit } = useAnalytics();
76
+ const payloadRef = React.useRef(payload);
77
+ payloadRef.current = payload;
78
+ React.useEffect(() => {
79
+ emit(name, payloadRef.current);
80
+ // 只 mount 时触发一次(路由切换会重新 mount)
81
+ // eslint-disable-next-line react-hooks/exhaustive-deps
82
+ }, []);
83
+ return null;
84
+ }
85
+ function PageView(props) {
86
+ return useEmitOnMount('page_view', props);
87
+ }
88
+ function ProductView(props) {
89
+ const { product, ...rest } = props;
90
+ return useEmitOnMount('product_view', {
91
+ ...rest,
92
+ productId: product.id,
93
+ productHandle: product.handle,
94
+ productTitle: product.title,
95
+ });
96
+ }
97
+ function CollectionView(props) {
98
+ const { collection, ...rest } = props;
99
+ return useEmitOnMount('collection_view', {
100
+ ...rest,
101
+ collectionId: collection.id,
102
+ collectionHandle: collection.handle,
103
+ });
104
+ }
105
+ function SearchView(props) {
106
+ return useEmitOnMount('search', { query: props.query, results: props.results });
107
+ }
108
+ function AddToCart(props) {
109
+ const { variantId, quantity, ...rest } = props;
110
+ return useEmitOnMount('add_to_cart', {
111
+ ...rest,
112
+ variantId,
113
+ quantity: quantity ?? 1,
114
+ });
115
+ }
116
+ function CheckoutStart(props) {
117
+ return useEmitOnMount('checkout_start', {
118
+ cartId: props.cart?.id,
119
+ totalQuantity: props.cart?.totalQuantity,
120
+ });
121
+ }
122
+ function Purchase(props) {
123
+ return useEmitOnMount('purchase', props);
124
+ }
125
+ /** 命名空间导出,让用户写 <Analytics.PageView /> */
126
+ export const Analytics = {
127
+ PageView,
128
+ ProductView,
129
+ CollectionView,
130
+ SearchView,
131
+ AddToCart,
132
+ CheckoutStart,
133
+ Purchase,
134
+ };
135
+ //# sourceMappingURL=AnalyticsProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsProvider.js","sourceRoot":"","sources":["../../src/components/AnalyticsProvider.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAiBjD,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAA+B,IAAI,CAAC,CAAC;AAUpE,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACtD,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC/B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAC5B,CAAC,IAAY,EAAE,UAA+B,EAAE,EAAE,EAAE;QAClD,UAAU,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI;YACtE,OAAO;SACR,CAAC,CAAC;IACL,CAAC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,YAAY;IACZ,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO;YAAE,OAAO;QACnC,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,cAAc,EAAE;gBACnB,MAAM,EAAE,CAAC,EAAE,EAAE;gBACb,aAAa,EAAE,CAAC,EAAE,aAAa;gBAC/B,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,WAAW;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAE/B,OAAO,KAAC,GAAG,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,IAAI,EAAE,YAAG,QAAQ,GAAgB,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,wCAAwC;QACxC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,+DAA+D;AAC/D,UAAU;AACV,+DAA+D;AAE/D,SAAS,cAAc,CAAC,IAAY,EAAE,OAA4B;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QAC/B,+BAA+B;QAC/B,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,KAA4D;IAC5E,OAAO,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,WAAW,CAAC,KAAuF;IAC1G,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACnC,OAAO,cAAc,CAAC,cAAc,EAAE;QACpC,GAAG,IAAI;QACP,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,YAAY,EAAE,OAAO,CAAC,KAAK;KAC5B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,KAA0E;IAChG,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACtC,OAAO,cAAc,CAAC,iBAAiB,EAAE;QACvC,GAAG,IAAI;QACP,YAAY,EAAE,UAAU,CAAC,EAAE;QAC3B,gBAAgB,EAAE,UAAU,CAAC,MAAM;KACpC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,KAA0C;IAC5D,OAAO,cAAc,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,SAAS,CAAC,KAAmE;IACpF,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAC/C,OAAO,cAAc,CAAC,aAAa,EAAE;QACnC,GAAG,IAAI;QACP,SAAS;QACT,QAAQ,EAAE,QAAQ,IAAI,CAAC;KACxB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,KAAwD;IAC7E,OAAO,cAAc,CAAC,gBAAgB,EAAE;QACtC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE;QACtB,aAAa,EAAE,KAAK,CAAC,IAAI,EAAE,aAAa;KACzC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,KAAmF;IACnG,OAAO,cAAc,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ;IACR,WAAW;IACX,cAAc;IACd,UAAU;IACV,SAAS;IACT,aAAa;IACb,QAAQ;CACT,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * <CartProvider> + useCart()
3
+ *
4
+ * 接管 cart 全生命周期:
5
+ * - 自动从 cookie 读取 cart_id 并 fetch
6
+ * - 不存在则懒创建
7
+ * - linesAdd / linesUpdate / linesRemove 全部带 optimistic update + 失败回滚
8
+ * - subscribe(callback) 给外部(如 Analytics)订阅 cart 变化
9
+ *
10
+ * 用法:
11
+ * <ShopProvider {...}>
12
+ * <CartProvider>
13
+ * <App />
14
+ * </CartProvider>
15
+ * </ShopProvider>
16
+ *
17
+ * const { cart, status, linesAdd, linesUpdate, linesRemove } = useCart();
18
+ *
19
+ * 注意:必须套在 <ShopProvider> 内(依赖它的 storefrontAccessToken + apiUrl)。
20
+ */
21
+ import * as React from 'react';
22
+ export interface CartLineMerchandise {
23
+ id: string;
24
+ title?: string;
25
+ image?: {
26
+ url: string;
27
+ altText?: string | null;
28
+ width?: number | null;
29
+ height?: number | null;
30
+ };
31
+ price?: {
32
+ amount: string;
33
+ currencyCode: string;
34
+ };
35
+ product?: {
36
+ title: string;
37
+ handle: string;
38
+ };
39
+ }
40
+ export interface CartLine {
41
+ id: string;
42
+ quantity: number;
43
+ merchandise: CartLineMerchandise;
44
+ cost: {
45
+ totalAmount: {
46
+ amount: string;
47
+ currencyCode: string;
48
+ };
49
+ };
50
+ }
51
+ export interface Cart {
52
+ id: string;
53
+ totalQuantity: number;
54
+ checkoutUrl: string;
55
+ lines: {
56
+ nodes: CartLine[];
57
+ };
58
+ cost: {
59
+ subtotalAmount: {
60
+ amount: string;
61
+ currencyCode: string;
62
+ };
63
+ totalAmount: {
64
+ amount: string;
65
+ currencyCode: string;
66
+ };
67
+ };
68
+ }
69
+ export type CartStatus = 'uninitialized' | 'loading' | 'idle' | 'updating' | 'error';
70
+ export interface CartUserError {
71
+ field?: string[] | null;
72
+ message: string;
73
+ code?: string;
74
+ }
75
+ export interface CartContextValue {
76
+ cart: Cart | null;
77
+ status: CartStatus;
78
+ error: string | null;
79
+ /** 加 line */
80
+ linesAdd: (lines: Array<{
81
+ merchandiseId: string;
82
+ quantity?: number;
83
+ }>) => Promise<void>;
84
+ /** 更新数量(lineId, quantity);quantity<=0 等价 remove */
85
+ linesUpdate: (lines: Array<{
86
+ id: string;
87
+ quantity: number;
88
+ }>) => Promise<void>;
89
+ /** 删 line */
90
+ linesRemove: (lineIds: string[]) => Promise<void>;
91
+ /** 重新从服务端拉 cart */
92
+ refetch: () => Promise<void>;
93
+ /** 订阅 cart 变化(Analytics 用) */
94
+ subscribe: (listener: (cart: Cart | null) => void) => () => void;
95
+ }
96
+ export interface CartProviderProps {
97
+ children: React.ReactNode;
98
+ /** 加载完成后是否自动拉 cart。默认 true */
99
+ fetchOnMount?: boolean;
100
+ }
101
+ export declare function CartProvider({ children, fetchOnMount }: CartProviderProps): import("react/jsx-runtime").JSX.Element;
102
+ /**
103
+ * 拿 cart context。Provider 外 throw。
104
+ */
105
+ export declare function useCart(): CartContextValue;
106
+ /**
107
+ * 非 throw 版本:Provider 外返回 null。
108
+ * 给可选 fallback 用,比如 <AddToCartButton> 在没 Provider 时退化到 props.onAdd。
109
+ */
110
+ export declare function useCartOptional(): CartContextValue | null;
111
+ //# sourceMappingURL=CartProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartProvider.d.ts","sourceRoot":"","sources":["../../src/components/CartProvider.tsx"],"names":[],"mappings":"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"}