@shopbb/helium 0.5.10 → 0.6.1

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 (132) hide show
  1. package/dist/cache/withCache.d.ts +49 -0
  2. package/dist/cache/withCache.d.ts.map +1 -0
  3. package/dist/cache/withCache.js +117 -0
  4. package/dist/cache/withCache.js.map +1 -0
  5. package/dist/components/AddToCartButton.d.ts +28 -22
  6. package/dist/components/AddToCartButton.d.ts.map +1 -1
  7. package/dist/components/AddToCartButton.js +36 -47
  8. package/dist/components/AddToCartButton.js.map +1 -1
  9. package/dist/components/BuyNowButton.d.ts +45 -0
  10. package/dist/components/BuyNowButton.d.ts.map +1 -0
  11. package/dist/components/BuyNowButton.js +49 -0
  12. package/dist/components/BuyNowButton.js.map +1 -0
  13. package/dist/components/CartCheckoutButton.d.ts +39 -0
  14. package/dist/components/CartCheckoutButton.d.ts.map +1 -0
  15. package/dist/components/CartCheckoutButton.js +32 -0
  16. package/dist/components/CartCheckoutButton.js.map +1 -0
  17. package/dist/components/CartCost.d.ts +43 -0
  18. package/dist/components/CartCost.d.ts.map +1 -0
  19. package/dist/components/CartCost.js +34 -0
  20. package/dist/components/CartCost.js.map +1 -0
  21. package/dist/components/CartForm.d.ts +201 -0
  22. package/dist/components/CartForm.d.ts.map +1 -0
  23. package/dist/components/CartForm.js +213 -0
  24. package/dist/components/CartForm.js.map +1 -0
  25. package/dist/components/CartLineProvider.d.ts +78 -0
  26. package/dist/components/CartLineProvider.d.ts.map +1 -0
  27. package/dist/components/CartLineProvider.js +46 -0
  28. package/dist/components/CartLineProvider.js.map +1 -0
  29. package/dist/components/CartLineQuantity.d.ts +24 -0
  30. package/dist/components/CartLineQuantity.d.ts.map +1 -0
  31. package/dist/components/CartLineQuantity.js +9 -0
  32. package/dist/components/CartLineQuantity.js.map +1 -0
  33. package/dist/components/DiscountSelector.d.ts.map +1 -1
  34. package/dist/components/DiscountSelector.js +8 -19
  35. package/dist/components/DiscountSelector.js.map +1 -1
  36. package/dist/components/Image.d.ts +18 -0
  37. package/dist/components/Image.d.ts.map +1 -1
  38. package/dist/components/Image.js +26 -0
  39. package/dist/components/Image.js.map +1 -1
  40. package/dist/components/Pagination.d.ts +82 -0
  41. package/dist/components/Pagination.d.ts.map +1 -0
  42. package/dist/components/Pagination.js +84 -0
  43. package/dist/components/Pagination.js.map +1 -0
  44. package/dist/components/RichText.d.ts +78 -0
  45. package/dist/components/RichText.d.ts.map +1 -0
  46. package/dist/components/RichText.js +93 -0
  47. package/dist/components/RichText.js.map +1 -0
  48. package/dist/components/Seo.d.ts +25 -0
  49. package/dist/components/Seo.d.ts.map +1 -0
  50. package/dist/components/Seo.js +54 -0
  51. package/dist/components/Seo.js.map +1 -0
  52. package/dist/components/hooks/useMoney.d.ts +40 -0
  53. package/dist/components/hooks/useMoney.d.ts.map +1 -0
  54. package/dist/components/hooks/useMoney.js +60 -0
  55. package/dist/components/hooks/useMoney.js.map +1 -0
  56. package/dist/components/hooks/useOptimisticCart.d.ts +50 -0
  57. package/dist/components/hooks/useOptimisticCart.d.ts.map +1 -0
  58. package/dist/components/hooks/useOptimisticCart.js +146 -0
  59. package/dist/components/hooks/useOptimisticCart.js.map +1 -0
  60. package/dist/components/index.d.ts +28 -0
  61. package/dist/components/index.d.ts.map +1 -1
  62. package/dist/components/index.js +21 -0
  63. package/dist/components/index.js.map +1 -1
  64. package/dist/createCartHandler.d.ts.map +1 -1
  65. package/dist/createCartHandler.js +57 -0
  66. package/dist/createCartHandler.js.map +1 -1
  67. package/dist/csp/csp.d.ts +57 -0
  68. package/dist/csp/csp.d.ts.map +1 -0
  69. package/dist/csp/csp.js +73 -0
  70. package/dist/csp/csp.js.map +1 -0
  71. package/dist/customer/createCustomerAccountClient.d.ts +43 -0
  72. package/dist/customer/createCustomerAccountClient.d.ts.map +1 -0
  73. package/dist/customer/createCustomerAccountClient.js +68 -0
  74. package/dist/customer/createCustomerAccountClient.js.map +1 -0
  75. package/dist/handleCartFormAction.d.ts +39 -0
  76. package/dist/handleCartFormAction.d.ts.map +1 -0
  77. package/dist/handleCartFormAction.js +103 -0
  78. package/dist/handleCartFormAction.js.map +1 -0
  79. package/dist/index.d.ts +18 -0
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +11 -0
  82. package/dist/index.js.map +1 -1
  83. package/dist/routing/storefrontRedirect.d.ts +37 -0
  84. package/dist/routing/storefrontRedirect.d.ts.map +1 -0
  85. package/dist/routing/storefrontRedirect.js +64 -0
  86. package/dist/routing/storefrontRedirect.js.map +1 -0
  87. package/dist/seo/getSeoMeta.d.ts +68 -0
  88. package/dist/seo/getSeoMeta.d.ts.map +1 -0
  89. package/dist/seo/getSeoMeta.js +89 -0
  90. package/dist/seo/getSeoMeta.js.map +1 -0
  91. package/dist/sitemap/sitemap.d.ts +55 -0
  92. package/dist/sitemap/sitemap.d.ts.map +1 -0
  93. package/dist/sitemap/sitemap.js +93 -0
  94. package/dist/sitemap/sitemap.js.map +1 -0
  95. package/dist/types.d.ts +12 -0
  96. package/dist/types.d.ts.map +1 -1
  97. package/dist/utils/flattenConnection.d.ts +25 -0
  98. package/dist/utils/flattenConnection.d.ts.map +1 -0
  99. package/dist/utils/flattenConnection.js +25 -0
  100. package/dist/utils/flattenConnection.js.map +1 -0
  101. package/dist/utils/parseGid.d.ts +17 -0
  102. package/dist/utils/parseGid.d.ts.map +1 -0
  103. package/dist/utils/parseGid.js +19 -0
  104. package/dist/utils/parseGid.js.map +1 -0
  105. package/package.json +1 -1
  106. package/src/cache/withCache.ts +144 -0
  107. package/src/components/AddToCartButton.tsx +94 -56
  108. package/src/components/BuyNowButton.tsx +135 -0
  109. package/src/components/CartCheckoutButton.tsx +97 -0
  110. package/src/components/CartCost.tsx +65 -0
  111. package/src/components/CartForm.tsx +311 -0
  112. package/src/components/CartLineProvider.tsx +77 -0
  113. package/src/components/CartLineQuantity.tsx +37 -0
  114. package/src/components/DiscountSelector.tsx +34 -45
  115. package/src/components/Image.tsx +27 -0
  116. package/src/components/Pagination.tsx +139 -0
  117. package/src/components/RichText.tsx +122 -0
  118. package/src/components/Seo.tsx +61 -0
  119. package/src/components/hooks/useMoney.ts +87 -0
  120. package/src/components/hooks/useOptimisticCart.ts +183 -0
  121. package/src/components/index.ts +44 -0
  122. package/src/createCartHandler.ts +71 -0
  123. package/src/csp/csp.tsx +119 -0
  124. package/src/customer/createCustomerAccountClient.ts +89 -0
  125. package/src/handleCartFormAction.ts +129 -0
  126. package/src/index.ts +24 -0
  127. package/src/routing/storefrontRedirect.ts +86 -0
  128. package/src/seo/getSeoMeta.ts +125 -0
  129. package/src/sitemap/sitemap.ts +121 -0
  130. package/src/types.ts +12 -1
  131. package/src/utils/flattenConnection.ts +33 -0
  132. package/src/utils/parseGid.ts +25 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * useMoney — 对齐 Hydrogen React 同名 hook
3
+ *
4
+ * 把 GraphQL MoneyV2 拆成多个易用字段,便于自定义渲染。
5
+ *
6
+ * const { amount, currencyCode, currencySymbol, withoutTrailingZerosAndCurrency }
7
+ * = useMoney({amount: '99.00', currencyCode: 'CNY'});
8
+ *
9
+ * <div>
10
+ * <span>{currencySymbol}</span>
11
+ * <strong>{withoutTrailingZerosAndCurrency}</strong>
12
+ * </div>
13
+ *
14
+ * 与 <Money> 组件的关系:<Money> 是默认渲染;useMoney() 是低层 API,给商家
15
+ * 自定义结构用。两者背后用同一份 currency symbol 表 + 格式化逻辑。
16
+ */
17
+ export interface MoneyV2 {
18
+ amount: string;
19
+ currencyCode: string;
20
+ }
21
+ export interface MoneyParts {
22
+ /** 标准化后的金额字符串:"99.00" → "99.00"(保留两位) */
23
+ amount: string;
24
+ /** 货币代码:"CNY" */
25
+ currencyCode: string;
26
+ /** 货币符号:"¥" */
27
+ currencySymbol: string;
28
+ /** 带符号 + 千分位:"¥99.00" */
29
+ localizedString: string;
30
+ /** 去掉尾零:"99.00" → "99";"99.50" 不变 */
31
+ withoutTrailingZeros: string;
32
+ /** 去掉尾零 + 货币符号:"99" / "1,250" */
33
+ withoutTrailingZerosAndCurrency: string;
34
+ /** 仅货币符号 + 金额,不带千分位(用于排版极简场景):"¥99" */
35
+ symbolWithoutTrailingZeros: string;
36
+ /** 千分位金额:"1,234.56" */
37
+ amountWithComma: string;
38
+ }
39
+ export declare function useMoney(money: MoneyV2 | null | undefined): MoneyParts;
40
+ //# sourceMappingURL=useMoney.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMoney.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useMoney.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iCAAiC;IACjC,+BAA+B,EAAE,MAAM,CAAC;IACxC,uCAAuC;IACvC,0BAA0B,EAAE,MAAM,CAAC;IACnC,uBAAuB;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAsBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,CAuBtE"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * useMoney — 对齐 Hydrogen React 同名 hook
3
+ *
4
+ * 把 GraphQL MoneyV2 拆成多个易用字段,便于自定义渲染。
5
+ *
6
+ * const { amount, currencyCode, currencySymbol, withoutTrailingZerosAndCurrency }
7
+ * = useMoney({amount: '99.00', currencyCode: 'CNY'});
8
+ *
9
+ * <div>
10
+ * <span>{currencySymbol}</span>
11
+ * <strong>{withoutTrailingZerosAndCurrency}</strong>
12
+ * </div>
13
+ *
14
+ * 与 <Money> 组件的关系:<Money> 是默认渲染;useMoney() 是低层 API,给商家
15
+ * 自定义结构用。两者背后用同一份 currency symbol 表 + 格式化逻辑。
16
+ */
17
+ import * as React from 'react';
18
+ const CURRENCY_SYMBOL = {
19
+ CNY: '¥', USD: '$', EUR: '€', GBP: '£', JPY: '¥', HKD: 'HK$', KRW: '₩',
20
+ AUD: 'A$', CAD: 'CA$', SGD: 'S$', TWD: 'NT$', INR: '₹', BRL: 'R$',
21
+ };
22
+ function formatAmount(num, minDec, maxDec) {
23
+ if (!Number.isFinite(num))
24
+ return '0';
25
+ const neg = num < 0;
26
+ const abs = Math.abs(num);
27
+ const fixed = abs.toFixed(maxDec);
28
+ const [intPart, decPart = ''] = fixed.split('.');
29
+ const intWithSep = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
30
+ let trimDec = decPart;
31
+ while (trimDec.length > minDec && trimDec.endsWith('0')) {
32
+ trimDec = trimDec.slice(0, -1);
33
+ }
34
+ const out = trimDec ? `${intWithSep}.${trimDec}` : intWithSep;
35
+ return neg ? `-${out}` : out;
36
+ }
37
+ export function useMoney(money) {
38
+ return React.useMemo(() => {
39
+ const amount = money?.amount ?? '0';
40
+ const currencyCode = money?.currencyCode ?? 'USD';
41
+ const num = Number(amount);
42
+ const symbol = CURRENCY_SYMBOL[currencyCode] ?? currencyCode + ' ';
43
+ const amountWithComma = formatAmount(num, 2, 2);
44
+ const withoutTrailingZeros = formatAmount(num, 0, 2);
45
+ const localizedString = `${symbol}${amountWithComma}`;
46
+ const withoutTrailingZerosAndCurrency = withoutTrailingZeros;
47
+ const symbolWithoutTrailingZeros = `${symbol}${withoutTrailingZeros}`;
48
+ return {
49
+ amount: num.toFixed(2),
50
+ currencyCode,
51
+ currencySymbol: symbol,
52
+ localizedString,
53
+ withoutTrailingZeros,
54
+ withoutTrailingZerosAndCurrency,
55
+ symbolWithoutTrailingZeros,
56
+ amountWithComma,
57
+ };
58
+ }, [money?.amount, money?.currencyCode]);
59
+ }
60
+ //# sourceMappingURL=useMoney.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMoney.js","sourceRoot":"","sources":["../../../src/components/hooks/useMoney.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA0B/B,MAAM,eAAe,GAA2B;IAC9C,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG;IACtE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI;CAClE,CAAC;AAEF,SAAS,YAAY,CAAC,GAAW,EAAE,MAAc,EAAE,MAAc;IAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACtC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IACjE,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,OAAO,OAAO,CAAC,MAAM,GAAG,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;IAC9D,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAiC;IACxD,OAAO,KAAK,CAAC,OAAO,CAAa,GAAG,EAAE;QACpC,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC;QACpC,MAAM,YAAY,GAAG,KAAK,EAAE,YAAY,IAAI,KAAK,CAAC;QAClD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,eAAe,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,GAAG,CAAC;QAEnE,MAAM,eAAe,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,oBAAoB,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,eAAe,GAAG,GAAG,MAAM,GAAG,eAAe,EAAE,CAAC;QACtD,MAAM,+BAA+B,GAAG,oBAAoB,CAAC;QAC7D,MAAM,0BAA0B,GAAG,GAAG,MAAM,GAAG,oBAAoB,EAAE,CAAC;QACtE,OAAO;YACL,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YACtB,YAAY;YACZ,cAAc,EAAE,MAAM;YACtB,eAAe;YACf,oBAAoB;YACpB,+BAA+B;YAC/B,0BAA0B;YAC1B,eAAe;SAChB,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * useOptimisticCart — 对齐 Hydrogen React 同名 hook
3
+ *
4
+ * 接受 actualCart(来自 CartProvider),返回一个"叠加了所有 pending mutation"
5
+ * 的 cart 视图。让 UI 在网络回来之前立刻反应用户操作(数量+1 / 删除等)。
6
+ *
7
+ * const { cart: actualCart } = useCart();
8
+ * const cart = useOptimisticCart(actualCart);
9
+ * // cart 看起来已经"立刻应用了",但 fetcher 还在跑后端
10
+ *
11
+ * 实现:
12
+ * - <CartForm> submit 时把 pending action 注册到模块内 store
13
+ * - 完成后从 store 摘掉
14
+ * - useOptimisticCart 订阅 store,把 actualCart 复制一份 + 应用所有 pending
15
+ *
16
+ * 简化点(vs Hydrogen 完整实现):
17
+ * - 只支持 LinesAdd / LinesUpdate / LinesRemove(足够 cart 主流操作)
18
+ * - DiscountCodesUpdate / NoteUpdate 等不做 optimistic(这些在网络层用 applyCart 兜底)
19
+ * - 不持久化(页面刷新清空)
20
+ */
21
+ export interface PendingMutation {
22
+ id: string;
23
+ action: 'LinesAdd' | 'LinesUpdate' | 'LinesRemove';
24
+ inputs: any;
25
+ }
26
+ /**
27
+ * Internal: CartForm 提交时调用,注册一个 pending mutation。返回 unregister。
28
+ */
29
+ export declare function __registerPendingMutation(m: PendingMutation): () => void;
30
+ export interface OptimisticCartLine {
31
+ id: string;
32
+ quantity: number;
33
+ isOptimistic?: boolean;
34
+ merchandise?: any;
35
+ cost?: any;
36
+ attributes?: any;
37
+ [key: string]: any;
38
+ }
39
+ export interface OptimisticCart<TCart = any> {
40
+ isOptimistic?: boolean;
41
+ totalQuantity?: number;
42
+ lines?: {
43
+ nodes: OptimisticCartLine[];
44
+ edges?: any;
45
+ };
46
+ cost?: any;
47
+ [key: string]: any;
48
+ }
49
+ export declare function useOptimisticCart<TCart extends OptimisticCart = OptimisticCart>(actualCart: TCart | null): TCart | null;
50
+ //# sourceMappingURL=useOptimisticCart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOptimisticCart.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useOptimisticCart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;IACnD,MAAM,EAAE,GAAG,CAAC;CACb;AAmCD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,eAAe,GAAG,MAAM,IAAI,CAGxE;AAMD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,cAAc,CAAC,KAAK,GAAG,GAAG;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACrD,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,cAAc,GAAG,cAAc,EAC7E,UAAU,EAAE,KAAK,GAAG,IAAI,GACvB,KAAK,GAAG,IAAI,CAmFd"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * useOptimisticCart — 对齐 Hydrogen React 同名 hook
3
+ *
4
+ * 接受 actualCart(来自 CartProvider),返回一个"叠加了所有 pending mutation"
5
+ * 的 cart 视图。让 UI 在网络回来之前立刻反应用户操作(数量+1 / 删除等)。
6
+ *
7
+ * const { cart: actualCart } = useCart();
8
+ * const cart = useOptimisticCart(actualCart);
9
+ * // cart 看起来已经"立刻应用了",但 fetcher 还在跑后端
10
+ *
11
+ * 实现:
12
+ * - <CartForm> submit 时把 pending action 注册到模块内 store
13
+ * - 完成后从 store 摘掉
14
+ * - useOptimisticCart 订阅 store,把 actualCart 复制一份 + 应用所有 pending
15
+ *
16
+ * 简化点(vs Hydrogen 完整实现):
17
+ * - 只支持 LinesAdd / LinesUpdate / LinesRemove(足够 cart 主流操作)
18
+ * - DiscountCodesUpdate / NoteUpdate 等不做 optimistic(这些在网络层用 applyCart 兜底)
19
+ * - 不持久化(页面刷新清空)
20
+ */
21
+ import * as React from 'react';
22
+ import { useCartOptional } from '../CartProvider';
23
+ // 关键:snapshot 必须是稳定引用,否则 useSyncExternalStore 每次比对都觉得变了 →
24
+ // 无限 re-render(React #185)+ hydration mismatch(#418/#423)
25
+ const EMPTY_SNAPSHOT = [];
26
+ const pendingStore = {
27
+ items: new Map(),
28
+ listeners: new Set(),
29
+ cachedSnapshot: EMPTY_SNAPSHOT,
30
+ add(m) {
31
+ this.items.set(m.id, m);
32
+ this.cachedSnapshot = Array.from(this.items.values());
33
+ this.notify();
34
+ },
35
+ remove(id) {
36
+ if (this.items.delete(id)) {
37
+ this.cachedSnapshot = this.items.size === 0 ? EMPTY_SNAPSHOT : Array.from(this.items.values());
38
+ this.notify();
39
+ }
40
+ },
41
+ list() {
42
+ // 返回稳定引用(只在 add/remove 时改变)— 满足 useSyncExternalStore 契约
43
+ return this.cachedSnapshot;
44
+ },
45
+ subscribe(fn) {
46
+ this.listeners.add(fn);
47
+ return () => { this.listeners.delete(fn); };
48
+ },
49
+ notify() {
50
+ for (const fn of this.listeners)
51
+ fn();
52
+ },
53
+ };
54
+ /**
55
+ * Internal: CartForm 提交时调用,注册一个 pending mutation。返回 unregister。
56
+ */
57
+ export function __registerPendingMutation(m) {
58
+ pendingStore.add(m);
59
+ return () => pendingStore.remove(m.id);
60
+ }
61
+ export function useOptimisticCart(actualCart) {
62
+ // 订阅 pending store 重渲染
63
+ const subscribe = React.useCallback((cb) => pendingStore.subscribe(cb), []);
64
+ const getSnapshot = React.useCallback(() => pendingStore.list(), []);
65
+ const pendings = React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
66
+ // 如果没有 pending,CartProvider 内部的 cart 已经是最新(因为 applyCart 同步过)
67
+ const fallback = useCartOptional();
68
+ const baseCart = (actualCart ?? fallback?.cart);
69
+ return React.useMemo(() => {
70
+ if (!baseCart) {
71
+ // 如果没有 actual cart 但有 pending LinesAdd → 模拟一个空 cart + 即将添加的行
72
+ if (pendings.length === 0)
73
+ return null;
74
+ const optimisticLines = [];
75
+ for (const p of pendings) {
76
+ if (p.action === 'LinesAdd' && Array.isArray(p.inputs?.lines)) {
77
+ for (const ln of p.inputs.lines) {
78
+ optimisticLines.push({
79
+ id: `__optimistic_${p.id}_${ln.merchandiseId}`,
80
+ quantity: ln.quantity ?? 1,
81
+ merchandise: { id: ln.merchandiseId },
82
+ isOptimistic: true,
83
+ });
84
+ }
85
+ }
86
+ }
87
+ if (optimisticLines.length === 0)
88
+ return null;
89
+ return {
90
+ isOptimistic: true,
91
+ totalQuantity: optimisticLines.reduce((s, l) => s + l.quantity, 0),
92
+ lines: { nodes: optimisticLines },
93
+ };
94
+ }
95
+ if (pendings.length === 0)
96
+ return baseCart;
97
+ // 复制 lines(不深拷贝整个 cart — 只动 lines 节点列表)
98
+ const linesNodes = (baseCart.lines?.nodes ?? []).slice();
99
+ for (const p of pendings) {
100
+ if (p.action === 'LinesAdd' && Array.isArray(p.inputs?.lines)) {
101
+ for (const ln of p.inputs.lines) {
102
+ // 简化:若已有相同 merchandiseId 累加,否则追加
103
+ const idx = linesNodes.findIndex((l) => l.merchandise?.id === ln.merchandiseId);
104
+ if (idx >= 0) {
105
+ linesNodes[idx] = {
106
+ ...linesNodes[idx],
107
+ quantity: linesNodes[idx].quantity + (ln.quantity ?? 1),
108
+ isOptimistic: true,
109
+ };
110
+ }
111
+ else {
112
+ linesNodes.push({
113
+ id: `__optimistic_${p.id}_${ln.merchandiseId}`,
114
+ quantity: ln.quantity ?? 1,
115
+ merchandise: { id: ln.merchandiseId },
116
+ isOptimistic: true,
117
+ });
118
+ }
119
+ }
120
+ }
121
+ else if (p.action === 'LinesUpdate' && Array.isArray(p.inputs?.lines)) {
122
+ for (const ln of p.inputs.lines) {
123
+ const idx = linesNodes.findIndex((l) => l.id === ln.id);
124
+ if (idx >= 0) {
125
+ linesNodes[idx] = { ...linesNodes[idx], quantity: ln.quantity ?? linesNodes[idx].quantity, isOptimistic: true };
126
+ }
127
+ }
128
+ }
129
+ else if (p.action === 'LinesRemove' && Array.isArray(p.inputs?.lineIds)) {
130
+ for (const id of p.inputs.lineIds) {
131
+ const idx = linesNodes.findIndex((l) => l.id === id);
132
+ if (idx >= 0)
133
+ linesNodes.splice(idx, 1);
134
+ }
135
+ }
136
+ }
137
+ const totalQuantity = linesNodes.reduce((s, l) => s + l.quantity, 0);
138
+ return {
139
+ ...baseCart,
140
+ isOptimistic: true,
141
+ totalQuantity,
142
+ lines: { ...baseCart.lines, nodes: linesNodes },
143
+ };
144
+ }, [baseCart, pendings]);
145
+ }
146
+ //# sourceMappingURL=useOptimisticCart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOptimisticCart.js","sourceRoot":"","sources":["../../../src/components/hooks/useOptimisticCart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAYlD,0DAA0D;AAC1D,0DAA0D;AAC1D,MAAM,cAAc,GAAsB,EAAE,CAAC;AAE7C,MAAM,YAAY,GAAG;IACnB,KAAK,EAAE,IAAI,GAAG,EAA2B;IACzC,SAAS,EAAE,IAAI,GAAG,EAAc;IAChC,cAAc,EAAE,cAAmC;IAEnD,GAAG,CAAC,CAAkB;QACpB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IACD,MAAM,CAAC,EAAU;QACf,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/F,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,IAAI;QACF,wDAAwD;QACxD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IACD,SAAS,CAAC,EAAc;QACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM;QACJ,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS;YAAE,EAAE,EAAE,CAAC;IACxC,CAAC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,CAAkB;IAC1D,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACzC,CAAC;AAwBD,MAAM,UAAU,iBAAiB,CAC/B,UAAwB;IAExB,uBAAuB;IACvB,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,EAAc,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACxF,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAEjF,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,CAAC,UAAU,IAAK,QAAQ,EAAE,IAAY,CAAiB,CAAC;IAEzE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACxB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,6DAA6D;YAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACvC,MAAM,eAAe,GAAyB,EAAE,CAAC;YACjD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;oBAC9D,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;wBAChC,eAAe,CAAC,IAAI,CAAC;4BACnB,EAAE,EAAE,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE;4BAC9C,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC;4BAC1B,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,aAAa,EAAE;4BACrC,YAAY,EAAE,IAAI;yBACnB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC9C,OAAO;gBACL,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAClE,KAAK,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;aACzB,CAAC;QACb,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QAE3C,wCAAwC;QACxC,MAAM,UAAU,GAAG,CAAE,QAAgB,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,EAA0B,CAAC;QAE1F,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;gBAC9D,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;oBAChC,iCAAiC;oBACjC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,CAAC;oBAChF,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;wBACb,UAAU,CAAC,GAAG,CAAC,GAAG;4BAChB,GAAG,UAAU,CAAC,GAAG,CAAC;4BAClB,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC;4BACvD,YAAY,EAAE,IAAI;yBACnB,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,UAAU,CAAC,IAAI,CAAC;4BACd,EAAE,EAAE,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE;4BAC9C,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC;4BAC1B,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,aAAa,EAAE;4BACrC,YAAY,EAAE,IAAI;yBACnB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;gBACxE,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;oBAChC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;oBACxD,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;wBACb,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;oBAClH,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC1E,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAClC,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;oBACrD,IAAI,GAAG,IAAI,CAAC;wBAAE,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrE,OAAO;YACL,GAAI,QAAgB;YACpB,YAAY,EAAE,IAAI;YAClB,aAAa;YACb,KAAK,EAAE,EAAE,GAAI,QAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE;SAChD,CAAC;IACb,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC3B,CAAC"}
@@ -20,6 +20,8 @@
20
20
  */
21
21
  export { ShopProvider, useShop, useShopOptional } from './ShopProvider';
22
22
  export type { ShopContextValue, ShopProviderProps } from './ShopProvider';
23
+ export { ShopProvider as ShopifyProvider } from './ShopProvider';
24
+ export type { ShopProviderProps as ShopifyProviderProps } from './ShopProvider';
23
25
  export { CartProvider, useCart, useCartOptional } from './CartProvider';
24
26
  export type { Cart, CartLine, CartLineMerchandise, CartStatus, CartUserError, CartContextValue, CartProviderProps, } from './CartProvider';
25
27
  export { ProductOptionsProvider, useProductOptions, } from './ProductOptionsProvider';
@@ -53,4 +55,30 @@ export type { AppliedDiscountListProps, ClaimableDiscountListProps, DiscountClai
53
55
  export { DiscountSelector } from './DiscountSelector';
54
56
  export type { DiscountSelectorProps } from './DiscountSelector';
55
57
  export { useMounted } from './hooks/useMounted';
58
+ export { useOptimisticCart } from './hooks/useOptimisticCart';
59
+ export type { OptimisticCart, OptimisticCartLine, PendingMutation } from './hooks/useOptimisticCart';
60
+ export { useMoney } from './hooks/useMoney';
61
+ export type { MoneyV2, MoneyParts } from './hooks/useMoney';
62
+ export { CartForm, CART_FORM_ACTIONS, useFetcher } from './CartForm';
63
+ export type { CartFormProps, CartFormInput, CartFormFetcher, CartFormAction, CartLineInput, CartLineUpdateInput, } from './CartForm';
64
+ export { CartLineProvider, useCartLine, useCartLineOptional } from './CartLineProvider';
65
+ export type { CartLineProviderProps, CartLineLike } from './CartLineProvider';
66
+ export { CartLineQuantity } from './CartLineQuantity';
67
+ export type { CartLineQuantityProps } from './CartLineQuantity';
68
+ export { CartCost } from './CartCost';
69
+ export type { CartCostProps, MoneyValue } from './CartCost';
70
+ export { CartCheckoutButton } from './CartCheckoutButton';
71
+ export type { CartCheckoutButtonProps } from './CartCheckoutButton';
72
+ export { BuyNowButton } from './BuyNowButton';
73
+ export type { BuyNowButtonProps } from './BuyNowButton';
74
+ export { RichText } from './RichText';
75
+ export type { RichTextProps, RichTextNode, RichTextComponents } from './RichText';
76
+ export { Pagination, getPaginationVariables } from './Pagination';
77
+ export type { PaginationProps, PaginationConnection, PaginationRenderProps, PaginationVariables } from './Pagination';
78
+ export { Seo } from './Seo';
79
+ export type { SeoProps } from './Seo';
80
+ export { flattenConnection } from '../utils/flattenConnection';
81
+ export type { Connection } from '../utils/flattenConnection';
82
+ export { parseGid } from '../utils/parseGid';
83
+ export type { ParsedGid } from '../utils/parseGid';
56
84
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,8 @@
20
20
  */
21
21
  // Providers + hooks
22
22
  export { ShopProvider, useShop, useShopOptional } from './ShopProvider';
23
+ // Hydrogen-compatible alias: <ShopifyProvider> 在我们叫 <ShopProvider>,提供别名让 Hydrogen 代码无痛迁移
24
+ export { ShopProvider as ShopifyProvider } from './ShopProvider';
23
25
  export { CartProvider, useCart, useCartOptional } from './CartProvider';
24
26
  export { ProductOptionsProvider, useProductOptions, } from './ProductOptionsProvider';
25
27
  export { AnalyticsProvider, useAnalytics, Analytics } from './AnalyticsProvider';
@@ -41,4 +43,23 @@ export { AppliedDiscountList, ClaimableDiscountList, DiscountClaimButton, MyDisc
41
43
  export { DiscountSelector } from './DiscountSelector';
42
44
  // SSR / hydrate 辅助 hook
43
45
  export { useMounted } from './hooks/useMounted';
46
+ export { useOptimisticCart } from './hooks/useOptimisticCart';
47
+ export { useMoney } from './hooks/useMoney';
48
+ // CartForm — Hydrogen-compatible form-based cart mutation API
49
+ export { CartForm, CART_FORM_ACTIONS, useFetcher } from './CartForm';
50
+ // Cart line context + 子组件
51
+ export { CartLineProvider, useCartLine, useCartLineOptional } from './CartLineProvider';
52
+ export { CartLineQuantity } from './CartLineQuantity';
53
+ export { CartCost } from './CartCost';
54
+ export { CartCheckoutButton } from './CartCheckoutButton';
55
+ export { BuyNowButton } from './BuyNowButton';
56
+ // Rich text
57
+ export { RichText } from './RichText';
58
+ // Pagination
59
+ export { Pagination, getPaginationVariables } from './Pagination';
60
+ // SEO
61
+ export { Seo } from './Seo';
62
+ // 通用工具
63
+ export { flattenConnection } from '../utils/flattenConnection';
64
+ export { parseGid } from '../utils/parseGid';
44
65
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGxE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWxE,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGjF,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAG9E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOpD,WAAW;AACX,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAU/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,WAAW;AACX,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,wBAAwB;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAExE,yFAAyF;AACzF,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWxE,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGjF,QAAQ;AACR,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAG9E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOpD,WAAW;AACX,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAU/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,WAAW;AACX,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,wBAAwB;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,8DAA8D;AAC9D,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAMrE,0BAA0B;AAC1B,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAExF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,YAAY;AACZ,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAGlE,MAAM;AACN,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,OAAO;AACP,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"createCartHandler.d.ts","sourceRoot":"","sources":["../src/createCartHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAInB,MAAM,SAAS,CAAC;AAEjB,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,ktBAiCjC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAmI1E"}
1
+ {"version":3,"file":"createCartHandler.d.ts","sourceRoot":"","sources":["../src/createCartHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAInB,MAAM,SAAS,CAAC;AAEjB,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,ktBAiCjC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CA0M1E"}
@@ -93,6 +93,33 @@ export function createCartHandler(options) {
93
93
  userErrors { field message code }
94
94
  }
95
95
  }
96
+ `;
97
+ const CART_DISCOUNT_CODES_UPDATE = /* GraphQL */ `
98
+ ${DEFAULT_CART_FRAGMENT}
99
+ mutation CartDiscountCodesUpdate($cartId: ID!, $discountCodes: [String!]) {
100
+ cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {
101
+ cart { ...CartReturn }
102
+ userErrors { field message code }
103
+ }
104
+ }
105
+ `;
106
+ const CART_DISCOUNT_SELECT = /* GraphQL */ `
107
+ ${DEFAULT_CART_FRAGMENT}
108
+ mutation CartDiscountSelect($cartId: ID!, $claimId: ID!) {
109
+ cartDiscountSelect(cartId: $cartId, claimId: $claimId) {
110
+ cart { ...CartReturn }
111
+ userErrors { field message code }
112
+ }
113
+ }
114
+ `;
115
+ const CART_DISCOUNT_CLEAR = /* GraphQL */ `
116
+ ${DEFAULT_CART_FRAGMENT}
117
+ mutation CartDiscountClear($cartId: ID!) {
118
+ cartDiscountClear(cartId: $cartId) {
119
+ cart { ...CartReturn }
120
+ userErrors { field message code }
121
+ }
122
+ }
96
123
  `;
97
124
  // ----- Handler methods -----
98
125
  async function get() {
@@ -143,6 +170,33 @@ export function createCartHandler(options) {
143
170
  const data = await storefront.mutate(CART_LINES_REMOVE, { variables: { cartId, lineIds } });
144
171
  return { cart: data.cartLinesRemove.cart, userErrors: data.cartLinesRemove.userErrors };
145
172
  }
173
+ async function updateDiscountCodes(discountCodes) {
174
+ const cartId = getCartId();
175
+ if (!cartId) {
176
+ // 没 cart 就先创建一个再应用 discount
177
+ const created = await create({});
178
+ if (!created.cart)
179
+ return created;
180
+ }
181
+ const data = await storefront.mutate(CART_DISCOUNT_CODES_UPDATE, { variables: { cartId: getCartId(), discountCodes } });
182
+ return { cart: data.cartDiscountCodesUpdate.cart, userErrors: data.cartDiscountCodesUpdate.userErrors };
183
+ }
184
+ async function selectDiscount(claimId) {
185
+ const cartId = getCartId();
186
+ if (!cartId) {
187
+ return { cart: null, userErrors: [{ message: 'No cart exists', code: 'NO_CART' }] };
188
+ }
189
+ const data = await storefront.mutate(CART_DISCOUNT_SELECT, { variables: { cartId, claimId } });
190
+ return { cart: data.cartDiscountSelect.cart, userErrors: data.cartDiscountSelect.userErrors };
191
+ }
192
+ async function clearDiscount() {
193
+ const cartId = getCartId();
194
+ if (!cartId) {
195
+ return { cart: null, userErrors: [{ message: 'No cart exists', code: 'NO_CART' }] };
196
+ }
197
+ const data = await storefront.mutate(CART_DISCOUNT_CLEAR, { variables: { cartId } });
198
+ return { cart: data.cartDiscountClear.cart, userErrors: data.cartDiscountClear.userErrors };
199
+ }
146
200
  return {
147
201
  get,
148
202
  getCartId,
@@ -151,6 +205,9 @@ export function createCartHandler(options) {
151
205
  addLines,
152
206
  updateLines,
153
207
  removeLines,
208
+ updateDiscountCodes,
209
+ selectDiscount,
210
+ clearDiscount,
154
211
  };
155
212
  }
156
213
  //# sourceMappingURL=createCartHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createCartHandler.js","sourceRoot":"","sources":["../src/createCartHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createCartHandler.js","sourceRoot":"","sources":["../src/createCartHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * createContentSecurityPolicy + NonceProvider + <Script> + useNonce()
3
+ *
4
+ * 对齐 Hydrogen 的 CSP 工具集:服务端生成一次性 nonce(base64 random),通过
5
+ * Content-Security-Policy 头要求所有 inline script 带这个 nonce 才能执行;
6
+ * React 组件 <Script nonce> 自动注入 nonce 属性。
7
+ *
8
+ * 服务端:
9
+ * const { nonce, header, NonceProvider } = createContentSecurityPolicy();
10
+ * response.headers.set('Content-Security-Policy', header);
11
+ * return ReactDOMServer.renderToReadableStream(
12
+ * <NonceProvider value={nonce}><App /></NonceProvider>
13
+ * );
14
+ *
15
+ * 客户端 / 组件内:
16
+ * const nonce = useNonce();
17
+ * <script nonce={nonce} dangerouslySetInnerHTML={...} />
18
+ * // 或者用 <Script>
19
+ * <Script>{`window.foo=1`}</Script>
20
+ */
21
+ import * as React from 'react';
22
+ export interface NonceProviderProps {
23
+ value: string;
24
+ children: React.ReactNode;
25
+ }
26
+ export declare function NonceProvider({ value, children }: NonceProviderProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function useNonce(): string | undefined;
28
+ export interface ScriptProps extends React.ScriptHTMLAttributes<HTMLScriptElement> {
29
+ }
30
+ export declare function Script(props: ScriptProps): import("react/jsx-runtime").JSX.Element;
31
+ export interface CspOptions {
32
+ /** 额外的 script-src 来源(默认 'self') */
33
+ scriptSrc?: string[];
34
+ /** 额外的 style-src(默认 'self' + 'unsafe-inline') */
35
+ styleSrc?: string[];
36
+ /** 额外的 img-src(默认 'self' + data:) */
37
+ imgSrc?: string[];
38
+ /** connect-src(XHR / fetch 允许的目标) */
39
+ connectSrc?: string[];
40
+ /** font-src */
41
+ fontSrc?: string[];
42
+ /** frame-src */
43
+ frameSrc?: string[];
44
+ /** default-src */
45
+ defaultSrc?: string[];
46
+ /** Report-only 模式 */
47
+ reportOnly?: boolean;
48
+ }
49
+ export interface CspResult {
50
+ nonce: string;
51
+ /** 完整的 Content-Security-Policy header 字符串 */
52
+ header: string;
53
+ headerName: 'Content-Security-Policy' | 'Content-Security-Policy-Report-Only';
54
+ NonceProvider: typeof NonceProvider;
55
+ }
56
+ export declare function createContentSecurityPolicy(options?: CspOptions): CspResult;
57
+ //# sourceMappingURL=csp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csp.d.ts","sourceRoot":"","sources":["../../src/csp/csp.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAEpE;AAED,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAG7C;AAMD,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;CAAG;AAErF,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2CAGxC;AAMD,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qBAAqB;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,yBAAyB,GAAG,qCAAqC,CAAC;IAC9E,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AAeD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,UAAe,GAAG,SAAS,CAoB/E"}