@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
@@ -18,18 +18,15 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
18
18
  */
19
19
  import * as React from 'react';
20
20
  import { useDiscounts } from './DiscountProvider';
21
- import { useAnalytics } from './AnalyticsProvider';
22
21
  import { Money } from './Money';
23
22
  import { useMounted } from './hooks/useMounted';
23
+ import { CartForm } from './CartForm';
24
24
  export function DiscountSelector(props) {
25
25
  const { className, unauthenticatedFallback, renderApplied } = props;
26
26
  const mounted = useMounted();
27
- const { myDiscounts, myDiscountsStatus, cartAllocations, appliedClaim, selectCartDiscount, } = useDiscounts();
28
- const analytics = useAnalytics();
27
+ const { myDiscounts, myDiscountsStatus, cartAllocations, appliedClaim, } = useDiscounts();
29
28
  const [open, setOpen] = React.useState(false);
30
- const [pending, setPending] = React.useState(false);
31
29
  // SSR + client 首次 render:返回固定占位,保证 hydration 不 mismatch。
32
- // mounted 后才进入真正的渲染分支。
33
30
  if (!mounted) {
34
31
  return _jsx("div", { "data-discount-selector": true, "data-ssr-placeholder": true, className: className });
35
32
  }
@@ -38,17 +35,6 @@ export function DiscountSelector(props) {
38
35
  const appliedClaimId = appliedClaim?.claimId ?? null;
39
36
  const appliedTitle = appliedClaim?.title ?? appliedAlloc?.title;
40
37
  const appliedCode = appliedClaim?.code ?? appliedAlloc?.code;
41
- const handleSelect = async (claimId) => {
42
- setPending(true);
43
- try {
44
- await selectCartDiscount(claimId);
45
- analytics.emit('discount_select', { claimId });
46
- }
47
- finally {
48
- setPending(false);
49
- setOpen(false);
50
- }
51
- };
52
38
  // 未登录
53
39
  if (myDiscountsStatus === 'unauthenticated') {
54
40
  return unauthenticatedFallback !== undefined ? _jsx(_Fragment, { children: unauthenticatedFallback }) : (_jsxs("div", { "data-discount-selector": true, "data-unauth": true, className: className, children: [_jsx("span", { children: "\u767B\u5F55\u540E\u53EF\u4F7F\u7528\u4F18\u60E0\u5238" }), _jsx("a", { href: "/login?next=/cart", children: "\u53BB\u767B\u5F55" })] }));
@@ -65,17 +51,20 @@ export function DiscountSelector(props) {
65
51
  title: appliedTitle ?? '',
66
52
  amount: appliedAlloc?.discountedAmount ?? { amount: '0', currencyCode: 'CNY' },
67
53
  onChange: () => setOpen(true),
68
- }) : (_jsxs("div", { "data-applied": true, children: [_jsxs("div", { "data-info": true, children: [_jsx("span", { "data-label": true, children: "\u5DF2\u4F7F\u7528" }), _jsx("strong", { "data-title": true, children: appliedTitle }), appliedAlloc && (_jsxs("span", { "data-amount": true, children: ["\u2212 ", _jsx(Money, { data: { amount: appliedAlloc.discountedAmount.amount, currencyCode: appliedAlloc.discountedAmount.currencyCode } })] }))] }), _jsx("div", { "data-actions": true, children: _jsx("button", { type: "button", onClick: () => setOpen(true), disabled: pending, children: "\u5207\u6362" }) })] }))) : (_jsxs("div", { "data-empty-applied": true, children: [_jsx("div", { "data-info": true, children: _jsxs("span", { "data-label": true, children: ["\u6709 ", availableClaims.length, " \u5F20\u53EF\u7528\u4F18\u60E0\u5238"] }) }), _jsx("button", { type: "button", onClick: () => setOpen(true), disabled: pending, children: "\u9009\u62E9" })] })) }), open && (_jsx(DiscountPickerSheet, { claims: availableClaims, currentClaimId: appliedClaimId, onSelect: handleSelect, onClose: () => setOpen(false), pending: pending }))] }));
54
+ }) : (_jsxs("div", { "data-applied": true, children: [_jsxs("div", { "data-info": true, children: [_jsx("span", { "data-label": true, children: "\u5DF2\u4F7F\u7528" }), _jsx("strong", { "data-title": true, children: appliedTitle }), appliedAlloc && (_jsxs("span", { "data-amount": true, children: ["\u2212 ", _jsx(Money, { data: { amount: appliedAlloc.discountedAmount.amount, currencyCode: appliedAlloc.discountedAmount.currencyCode } })] }))] }), _jsx("div", { "data-actions": true, children: _jsx("button", { type: "button", onClick: () => setOpen(true), children: "\u5207\u6362" }) })] }))) : (_jsxs("div", { "data-empty-applied": true, children: [_jsx("div", { "data-info": true, children: _jsxs("span", { "data-label": true, children: ["\u6709 ", availableClaims.length, " \u5F20\u53EF\u7528\u4F18\u60E0\u5238"] }) }), _jsx("button", { type: "button", onClick: () => setOpen(true), children: "\u9009\u62E9" })] })) }), open && (_jsx(DiscountPickerSheet, { claims: availableClaims, currentClaimId: appliedClaimId, onClose: () => setOpen(false) }))] }));
69
55
  }
70
56
  /**
71
57
  * 抽屉式选券面板。
72
58
  * Demo 实现为屏底固定面板;商家可以替换为 modal / 抽屉等。
73
59
  */
74
- function DiscountPickerSheet({ claims, currentClaimId, onSelect, onClose, pending, }) {
60
+ function DiscountPickerSheet({ claims, currentClaimId, onClose, }) {
75
61
  return (_jsx("div", { "data-discount-picker-overlay": true, onClick: onClose, children: _jsxs("div", { "data-discount-picker-sheet": true, onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { "data-sheet-header": true, children: [_jsx("h3", { children: "\u9009\u62E9\u4F18\u60E0\u5238" }), _jsx("button", { type: "button", onClick: onClose, "data-sheet-close": true, children: "\u00D7" })] }), _jsx("div", { "data-sheet-list": true, children: claims.map((c) => {
62
+ // claim_id 既可能是 gid 也可能是 raw —— oxygen mutation 接受两种
76
63
  const id = c.id.replace(/^gid:\/\/shopbb\/DiscountClaim\//, '');
77
64
  const isCurrent = currentClaimId === id;
78
- return (_jsxs("button", { type: "button", "data-claim-card": true, "data-current": isCurrent ? '' : undefined, onClick: () => onSelect(id), disabled: pending, children: [_jsxs("div", { "data-claim-left": true, children: [_jsx("div", { "data-claim-value": true, children: formatValue(c) }), c.discount.minSubtotal && (_jsxs("div", { "data-claim-min": true, children: ["\u6EE1 ", _jsx(Money, { data: { amount: c.discount.minSubtotal.amount, currencyCode: c.discount.minSubtotal.currencyCode } }), " \u53EF\u7528"] }))] }), _jsxs("div", { "data-claim-right": true, children: [_jsx("div", { "data-claim-title": true, children: c.discount.title }), c.discount.code && _jsx("div", { "data-claim-code": true, children: c.discount.code }), c.expiresAt && (_jsxs("div", { "data-claim-expiry": true, children: [new Date(c.expiresAt).toLocaleDateString('zh-CN'), " \u8FC7\u671F"] }))] }), isCurrent && _jsx("span", { "data-claim-current-tag": true, children: "\u5F53\u524D\u4F7F\u7528" })] }, c.id));
65
+ return (
66
+ // 每张券一个 <CartForm>,submit 走 /cart action → cart.selectDiscount
67
+ _jsx(CartForm, { action: "CustomDiscountSelect", inputs: { claimId: id }, children: (fetcher) => (_jsxs("button", { type: "submit", "data-claim-card": true, "data-current": isCurrent ? '' : undefined, disabled: fetcher.state !== 'idle', children: [_jsxs("div", { "data-claim-left": true, children: [_jsx("div", { "data-claim-value": true, children: formatValue(c) }), c.discount.minSubtotal && (_jsxs("div", { "data-claim-min": true, children: ["\u6EE1 ", _jsx(Money, { data: { amount: c.discount.minSubtotal.amount, currencyCode: c.discount.minSubtotal.currencyCode } }), " \u53EF\u7528"] }))] }), _jsxs("div", { "data-claim-right": true, children: [_jsx("div", { "data-claim-title": true, children: c.discount.title }), c.discount.code && _jsx("div", { "data-claim-code": true, children: c.discount.code }), c.expiresAt && (_jsxs("div", { "data-claim-expiry": true, children: [new Date(c.expiresAt).toLocaleDateString('zh-CN'), " \u8FC7\u671F"] }))] }), isCurrent && _jsx("span", { "data-claim-current-tag": true, children: "\u5F53\u524D\u4F7F\u7528" })] })) }, c.id));
79
68
  }) })] }) }));
80
69
  }
81
70
  function formatValue(c) {
@@ -1 +1 @@
1
- {"version":3,"file":"DiscountSelector.js","sourceRoot":"","sources":["../../src/components/DiscountSelector.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DiscountSelector.js","sourceRoot":"","sources":["../../src/components/DiscountSelector.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,21 @@
1
+ /**
2
+ * IMAGE_FRAGMENT — 对齐 Hydrogen React 同名常量
3
+ *
4
+ * 商家在 GraphQL 查询里直接用:
5
+ *
6
+ * import { IMAGE_FRAGMENT } from '@shopbb/helium';
7
+ *
8
+ * const Q = `
9
+ * ${IMAGE_FRAGMENT}
10
+ * query {
11
+ * product(handle: "x") {
12
+ * featuredImage { ...Image }
13
+ * images(first: 5) { nodes { ...Image } }
14
+ * }
15
+ * }
16
+ * `;
17
+ */
18
+ export declare const IMAGE_FRAGMENT = "\n fragment Image on Image {\n id\n url\n altText\n width\n height\n }\n";
1
19
  /**
2
20
  * <Image> — 响应式商品图片
3
21
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC/G,cAAc;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAkBD,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CAmCtC"}
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,8FAQ1B,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC/G,cAAc;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAkBD,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CAmCtC"}
@@ -1,4 +1,30 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * IMAGE_FRAGMENT — 对齐 Hydrogen React 同名常量
4
+ *
5
+ * 商家在 GraphQL 查询里直接用:
6
+ *
7
+ * import { IMAGE_FRAGMENT } from '@shopbb/helium';
8
+ *
9
+ * const Q = `
10
+ * ${IMAGE_FRAGMENT}
11
+ * query {
12
+ * product(handle: "x") {
13
+ * featuredImage { ...Image }
14
+ * images(first: 5) { nodes { ...Image } }
15
+ * }
16
+ * }
17
+ * `;
18
+ */
19
+ export const IMAGE_FRAGMENT = /* GraphQL */ `
20
+ fragment Image on Image {
21
+ id
22
+ url
23
+ altText
24
+ width
25
+ height
26
+ }
27
+ `;
2
28
  // 默认 srcset 档位
3
29
  const DEFAULT_WIDTHS = [375, 750, 1024, 1536, 1920];
4
30
  /** 给 url 加 ?width=N query */
@@ -1 +1 @@
1
- {"version":3,"file":"Image.js","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":";AAyCA,eAAe;AACf,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEpD,6BAA6B;AAC7B,SAAS,SAAS,CAAC,GAAW,EAAE,KAAa;IAC3C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;QACnB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1C,OAAO,GAAG,GAAG,GAAG,GAAG,SAAS,KAAK,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAiB;IACrC,MAAM,EACJ,IAAI,EACJ,KAAK,EACL,WAAW,EACX,OAAO,GAAG,MAAM,EAChB,MAAM,GAAG,cAAc,EACvB,KAAK,EACL,GAAG,EAAE,OAAO,EACZ,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,YAAY;IACZ,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAwB;QACtC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACtE,GAAG,KAAK;KACT,CAAC;IAEF,OAAO,CACL,iBACM,IAAI,EACR,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAC,OAAO,EAChB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,EAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS,EAChC,KAAK,EAAE,UAAU,GACjB,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Image.js","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;;;;;;;;CAQ3C,CAAC;AA2CF,eAAe;AACf,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEpD,6BAA6B;AAC7B,SAAS,SAAS,CAAC,GAAW,EAAE,KAAa;IAC3C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,mBAAmB;QACnB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1C,OAAO,GAAG,GAAG,GAAG,GAAG,SAAS,KAAK,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAiB;IACrC,MAAM,EACJ,IAAI,EACJ,KAAK,EACL,WAAW,EACX,OAAO,GAAG,MAAM,EAChB,MAAM,GAAG,cAAc,EACvB,KAAK,EACL,GAAG,EAAE,OAAO,EACZ,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,YAAY;IACZ,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAwB;QACtC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACtE,GAAG,KAAK;KACT,CAAC;IAEF,OAAO,CACL,iBACM,IAAI,EACR,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAC,OAAO,EAChB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS,EAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS,EAChC,KAAK,EAAE,UAAU,GACjB,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * <Pagination> + getPaginationVariables() — 对齐 Hydrogen Pagination
3
+ *
4
+ * GraphQL cursor-based 分页(forward + backward)。SSR 友好:URL ?cursor= / ?direction= 控制。
5
+ *
6
+ * 用法(服务端 loader):
7
+ *
8
+ * const variables = getPaginationVariables(request, { pageBy: 20 });
9
+ * // → { first: 20, last: undefined, startCursor: undefined, endCursor: undefined }
10
+ * const data = await storefront.query(PRODUCTS_QUERY, { variables });
11
+ *
12
+ * 用法(组件):
13
+ *
14
+ * <Pagination connection={data.products}>
15
+ * {({ nodes, hasNextPage, NextLink, hasPreviousPage, PreviousLink, state }) => (
16
+ * <>
17
+ * {hasPreviousPage && <PreviousLink>上一页</PreviousLink>}
18
+ * <ul>{nodes.map((n) => <li key={n.id}>{n.title}</li>)}</ul>
19
+ * {hasNextPage && <NextLink>下一页</NextLink>}
20
+ * </>
21
+ * )}
22
+ * </Pagination>
23
+ */
24
+ import * as React from 'react';
25
+ export interface PaginationConnection<T = any> {
26
+ pageInfo: {
27
+ hasNextPage: boolean;
28
+ hasPreviousPage: boolean;
29
+ startCursor?: string | null;
30
+ endCursor?: string | null;
31
+ };
32
+ nodes?: T[];
33
+ edges?: Array<{
34
+ node: T;
35
+ cursor?: string;
36
+ }>;
37
+ }
38
+ export interface PaginationVariables {
39
+ first?: number;
40
+ last?: number;
41
+ startCursor?: string | null;
42
+ endCursor?: string | null;
43
+ }
44
+ /**
45
+ * 从 request URL 解析分页 query params。
46
+ *
47
+ * ?direction=next&cursor=xxx → { first: 20, endCursor: 'xxx' }
48
+ * ?direction=previous&cursor=xxx → { last: 20, startCursor: 'xxx' }
49
+ * (没 param) → { first: 20 }
50
+ */
51
+ export declare function getPaginationVariables(request: Request, options?: {
52
+ pageBy?: number;
53
+ }): PaginationVariables;
54
+ export interface PaginationRenderProps<T> {
55
+ /** 拍平后的当前页 nodes */
56
+ nodes: T[];
57
+ /** Raw pageInfo(hasNextPage / hasPreviousPage 等) */
58
+ pageInfo: PaginationConnection['pageInfo'];
59
+ /** 当前 URL state */
60
+ state: {
61
+ direction: 'next' | 'previous' | null;
62
+ cursor: string | null;
63
+ };
64
+ hasNextPage: boolean;
65
+ hasPreviousPage: boolean;
66
+ /** "下一页" 链接组件(自动加 ?direction=next&cursor=...) */
67
+ NextLink: React.FC<{
68
+ children: React.ReactNode;
69
+ className?: string;
70
+ }>;
71
+ /** "上一页" 链接组件 */
72
+ PreviousLink: React.FC<{
73
+ children: React.ReactNode;
74
+ className?: string;
75
+ }>;
76
+ }
77
+ export interface PaginationProps<T> {
78
+ connection: PaginationConnection<T>;
79
+ children: (props: PaginationRenderProps<T>) => React.ReactNode;
80
+ }
81
+ export declare function Pagination<T>(props: PaginationProps<T>): import("react/jsx-runtime").JSX.Element;
82
+ //# sourceMappingURL=Pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../src/components/Pagination.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,GAAG;IAC3C,QAAQ,EAAE;QACR,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,mBAAmB,CAYrB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,oBAAoB;IACpB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,oDAAoD;IACpD,QAAQ,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC3C,mBAAmB;IACnB,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAExE,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,iBAAiB;IACjB,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CAChE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,2CA8CtD"}
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * <Pagination> + getPaginationVariables() — 对齐 Hydrogen Pagination
4
+ *
5
+ * GraphQL cursor-based 分页(forward + backward)。SSR 友好:URL ?cursor= / ?direction= 控制。
6
+ *
7
+ * 用法(服务端 loader):
8
+ *
9
+ * const variables = getPaginationVariables(request, { pageBy: 20 });
10
+ * // → { first: 20, last: undefined, startCursor: undefined, endCursor: undefined }
11
+ * const data = await storefront.query(PRODUCTS_QUERY, { variables });
12
+ *
13
+ * 用法(组件):
14
+ *
15
+ * <Pagination connection={data.products}>
16
+ * {({ nodes, hasNextPage, NextLink, hasPreviousPage, PreviousLink, state }) => (
17
+ * <>
18
+ * {hasPreviousPage && <PreviousLink>上一页</PreviousLink>}
19
+ * <ul>{nodes.map((n) => <li key={n.id}>{n.title}</li>)}</ul>
20
+ * {hasNextPage && <NextLink>下一页</NextLink>}
21
+ * </>
22
+ * )}
23
+ * </Pagination>
24
+ */
25
+ import * as React from 'react';
26
+ import { flattenConnection } from '../utils/flattenConnection';
27
+ const DEFAULT_PAGE_BY = 20;
28
+ /**
29
+ * 从 request URL 解析分页 query params。
30
+ *
31
+ * ?direction=next&cursor=xxx → { first: 20, endCursor: 'xxx' }
32
+ * ?direction=previous&cursor=xxx → { last: 20, startCursor: 'xxx' }
33
+ * (没 param) → { first: 20 }
34
+ */
35
+ export function getPaginationVariables(request, options = {}) {
36
+ const { pageBy = DEFAULT_PAGE_BY } = options;
37
+ const url = new URL(request.url);
38
+ const direction = url.searchParams.get('direction');
39
+ const cursor = url.searchParams.get('cursor');
40
+ if (direction === 'previous' && cursor) {
41
+ return { last: pageBy, startCursor: cursor };
42
+ }
43
+ if (direction === 'next' && cursor) {
44
+ return { first: pageBy, endCursor: cursor };
45
+ }
46
+ return { first: pageBy };
47
+ }
48
+ export function Pagination(props) {
49
+ const { connection, children } = props;
50
+ const pageInfo = connection.pageInfo;
51
+ const nodes = flattenConnection(connection);
52
+ // 当前 URL state(hydrate 后才能访问 window.location)
53
+ const [urlState, setUrlState] = React.useState({
54
+ direction: null, cursor: null,
55
+ });
56
+ React.useEffect(() => {
57
+ if (typeof window === 'undefined')
58
+ return;
59
+ const params = new URLSearchParams(window.location.search);
60
+ const d = params.get('direction');
61
+ setUrlState({
62
+ direction: d === 'next' || d === 'previous' ? d : null,
63
+ cursor: params.get('cursor'),
64
+ });
65
+ }, []);
66
+ const nextHref = pageInfo.endCursor
67
+ ? `?direction=next&cursor=${encodeURIComponent(pageInfo.endCursor)}`
68
+ : '#';
69
+ const prevHref = pageInfo.startCursor
70
+ ? `?direction=previous&cursor=${encodeURIComponent(pageInfo.startCursor)}`
71
+ : '#';
72
+ const NextLink = ({ children, className }) => (_jsx("a", { href: nextHref, className: className, "data-pagination-next": true, children: children }));
73
+ const PreviousLink = ({ children, className }) => (_jsx("a", { href: prevHref, className: className, "data-pagination-prev": true, children: children }));
74
+ return (_jsx(_Fragment, { children: children({
75
+ nodes,
76
+ pageInfo,
77
+ state: urlState,
78
+ hasNextPage: pageInfo.hasNextPage,
79
+ hasPreviousPage: pageInfo.hasPreviousPage,
80
+ NextLink,
81
+ PreviousLink,
82
+ }) }));
83
+ }
84
+ //# sourceMappingURL=Pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/components/Pagination.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAmB,MAAM,4BAA4B,CAAC;AAEhF,MAAM,eAAe,GAAG,EAAE,CAAC;AAoB3B;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAgB,EAChB,UAA+B,EAAE;IAEjC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,SAAS,KAAK,UAAU,IAAI,MAAM,EAAE,CAAC;QACvC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,SAAS,KAAK,MAAM,IAAI,MAAM,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAuBD,MAAM,UAAU,UAAU,CAAI,KAAyB;IACrD,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;IACrC,MAAM,KAAK,GAAG,iBAAiB,CAAC,UAA2B,CAAC,CAAC;IAE7D,8CAA8C;IAC9C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAmE;QAC/G,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;KAC9B,CAAC,CAAC;IACH,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClC,WAAW,CAAC;YACV,SAAS,EAAE,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;YACtD,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;SAC7B,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS;QACjC,CAAC,CAAC,0BAA0B,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QACpE,CAAC,CAAC,GAAG,CAAC;IACR,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW;QACnC,CAAC,CAAC,8BAA8B,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QAC1E,CAAC,CAAC,GAAG,CAAC;IAER,MAAM,QAAQ,GAAgE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CACzG,YAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,0CAAwB,QAAQ,GAAK,CAC7E,CAAC;IACF,MAAM,YAAY,GAAgE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAC7G,YAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,0CAAwB,QAAQ,GAAK,CAC7E,CAAC;IAEF,OAAO,CACL,4BACG,QAAQ,CAAC;YACR,KAAK;YACL,QAAQ;YACR,KAAK,EAAE,QAAQ;YACf,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,QAAQ;YACR,YAAY;SACb,CAAC,GACD,CACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * <RichText> — 对齐 Hydrogen React
3
+ *
4
+ * 渲染 Shopify rich-text metafield 的 JSON 结构。Shopify rich-text 标准格式:
5
+ *
6
+ * {
7
+ * type: "root",
8
+ * children: [
9
+ * { type: "heading", level: 1, children: [{type: "text", value: "Hello"}] },
10
+ * { type: "paragraph", children: [
11
+ * {type: "text", value: "Hello "},
12
+ * {type: "text", value: "world", bold: true},
13
+ * {type: "link", url: "...", children: [{type: "text", value: "click"}]},
14
+ * ]},
15
+ * ],
16
+ * }
17
+ *
18
+ * 用法:
19
+ * const rich = JSON.parse(product.descriptionRichText);
20
+ * <RichText data={rich} />
21
+ *
22
+ * // 自定义节点渲染(覆盖默认)
23
+ * <RichText data={rich} components={{ heading: ({level, children}) =>
24
+ * React.createElement(`h${level}`, {className: 'my-h'}, children) }} />
25
+ */
26
+ import * as React from 'react';
27
+ export interface RichTextNode {
28
+ type: string;
29
+ value?: string;
30
+ level?: number;
31
+ url?: string;
32
+ title?: string;
33
+ target?: string;
34
+ bold?: boolean;
35
+ italic?: boolean;
36
+ listType?: 'ordered' | 'unordered';
37
+ children?: RichTextNode[];
38
+ }
39
+ export interface RichTextComponents {
40
+ root?: (props: {
41
+ children: React.ReactNode;
42
+ }) => React.ReactElement;
43
+ paragraph?: (props: {
44
+ children: React.ReactNode;
45
+ }) => React.ReactElement;
46
+ heading?: (props: {
47
+ level: number;
48
+ children: React.ReactNode;
49
+ }) => React.ReactElement;
50
+ list?: (props: {
51
+ listType: 'ordered' | 'unordered';
52
+ children: React.ReactNode;
53
+ }) => React.ReactElement;
54
+ listItem?: (props: {
55
+ children: React.ReactNode;
56
+ }) => React.ReactElement;
57
+ link?: (props: {
58
+ url: string;
59
+ title?: string;
60
+ target?: string;
61
+ children: React.ReactNode;
62
+ }) => React.ReactElement;
63
+ text?: (props: {
64
+ value: string;
65
+ bold?: boolean;
66
+ italic?: boolean;
67
+ }) => React.ReactElement;
68
+ }
69
+ export interface RichTextProps {
70
+ /** Rich-text JSON object(已 parse 过的)或者 JSON string */
71
+ data: RichTextNode | string | null | undefined;
72
+ /** 自定义渲染器 */
73
+ components?: RichTextComponents;
74
+ /** 包裹容器 className */
75
+ className?: string;
76
+ }
77
+ export declare function RichText({ data, components, className }: RichTextProps): import("react/jsx-runtime").JSX.Element | null;
78
+ //# sourceMappingURL=RichText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichText.d.ts","sourceRoot":"","sources":["../../src/components/RichText.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACnC,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IACpE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IACzE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IACtF,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,SAAS,GAAG,WAAW,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IACvG,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IACxE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;IAClH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,CAAC;CAC3F;AAED,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,aAAa;IACb,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,aAAa,kDAkBtE"}
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * <RichText> — 对齐 Hydrogen React
4
+ *
5
+ * 渲染 Shopify rich-text metafield 的 JSON 结构。Shopify rich-text 标准格式:
6
+ *
7
+ * {
8
+ * type: "root",
9
+ * children: [
10
+ * { type: "heading", level: 1, children: [{type: "text", value: "Hello"}] },
11
+ * { type: "paragraph", children: [
12
+ * {type: "text", value: "Hello "},
13
+ * {type: "text", value: "world", bold: true},
14
+ * {type: "link", url: "...", children: [{type: "text", value: "click"}]},
15
+ * ]},
16
+ * ],
17
+ * }
18
+ *
19
+ * 用法:
20
+ * const rich = JSON.parse(product.descriptionRichText);
21
+ * <RichText data={rich} />
22
+ *
23
+ * // 自定义节点渲染(覆盖默认)
24
+ * <RichText data={rich} components={{ heading: ({level, children}) =>
25
+ * React.createElement(`h${level}`, {className: 'my-h'}, children) }} />
26
+ */
27
+ import * as React from 'react';
28
+ const DEFAULTS = {
29
+ root: ({ children }) => _jsx("div", { "data-rich-text": true, children: children }),
30
+ paragraph: ({ children }) => _jsx("p", { children: children }),
31
+ heading: ({ level, children }) => React.createElement(`h${Math.min(Math.max(level, 1), 6)}`, null, children),
32
+ list: ({ listType, children }) => (listType === 'ordered' ? _jsx("ol", { children: children }) : _jsx("ul", { children: children })),
33
+ listItem: ({ children }) => _jsx("li", { children: children }),
34
+ link: ({ url, title, target, children }) => (_jsx("a", { href: url, title: title, target: target, rel: target === '_blank' ? 'noopener noreferrer' : undefined, children: children })),
35
+ text: ({ value, bold, italic }) => {
36
+ let out = value;
37
+ if (italic)
38
+ out = _jsx("em", { children: out });
39
+ if (bold)
40
+ out = _jsx("strong", { children: out });
41
+ return _jsx(_Fragment, { children: out });
42
+ },
43
+ };
44
+ function renderNode(node, comps, key) {
45
+ if (!node)
46
+ return null;
47
+ const childrenNodes = (node.children || []).map((c, i) => renderNode(c, comps, i));
48
+ switch (node.type) {
49
+ case 'root':
50
+ return _jsx(React.Fragment, { children: comps.root({ children: childrenNodes }) }, key);
51
+ case 'paragraph':
52
+ return _jsx(React.Fragment, { children: comps.paragraph({ children: childrenNodes }) }, key);
53
+ case 'heading':
54
+ return _jsx(React.Fragment, { children: comps.heading({ level: node.level || 2, children: childrenNodes }) }, key);
55
+ case 'list':
56
+ return _jsx(React.Fragment, { children: comps.list({ listType: node.listType || 'unordered', children: childrenNodes }) }, key);
57
+ case 'list-item':
58
+ return _jsx(React.Fragment, { children: comps.listItem({ children: childrenNodes }) }, key);
59
+ case 'link':
60
+ return _jsx(React.Fragment, { children: comps.link({ url: node.url || '#', title: node.title, target: node.target, children: childrenNodes }) }, key);
61
+ case 'text':
62
+ return _jsx(React.Fragment, { children: comps.text({ value: node.value || '', bold: node.bold, italic: node.italic }) }, key);
63
+ default:
64
+ // unknown type — 递归 children 不出错
65
+ return _jsx(React.Fragment, { children: childrenNodes }, key);
66
+ }
67
+ }
68
+ export function RichText({ data, components, className }) {
69
+ let parsed = null;
70
+ if (!data)
71
+ return null;
72
+ if (typeof data === 'string') {
73
+ try {
74
+ parsed = JSON.parse(data);
75
+ }
76
+ catch {
77
+ return _jsx("div", { className: className, children: data });
78
+ }
79
+ }
80
+ else {
81
+ parsed = data;
82
+ }
83
+ if (!parsed)
84
+ return null;
85
+ const comps = { ...DEFAULTS, ...(components || {}) };
86
+ const rendered = renderNode(parsed, comps, 0);
87
+ if (className && parsed.type === 'root') {
88
+ // 简单包一层,给 root 加 className
89
+ return _jsx("div", { className: className, "data-rich-text": true, children: rendered });
90
+ }
91
+ return _jsx(_Fragment, { children: rendered });
92
+ }
93
+ //# sourceMappingURL=RichText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichText.js","sourceRoot":"","sources":["../../src/components/RichText.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * <Seo data={SeoConfig} /> — 对齐 Hydrogen React
3
+ *
4
+ * Hydrogen 在 Remix 里用 `meta` export 注入 head;我们在客户端用 `<Seo>`
5
+ * 做 SPA 路由切换时的 document.title / meta 动态更新。
6
+ *
7
+ * SSR 阶段 Seo 组件渲染为 null(不输出 DOM);服务端商家应该用 getSeoMeta
8
+ * 生成 head HTML 直接拼到 <head>。
9
+ *
10
+ * 用法(客户端 SPA navigate 时):
11
+ *
12
+ * <Seo data={{
13
+ * title: product.title,
14
+ * description: product.description,
15
+ * image: product.featuredImage?.url,
16
+ * url: location.href,
17
+ * type: 'product',
18
+ * }} />
19
+ */
20
+ import { type SeoConfig } from '../seo/getSeoMeta';
21
+ export interface SeoProps {
22
+ data: SeoConfig;
23
+ }
24
+ export declare function Seo({ data }: SeoProps): null;
25
+ //# sourceMappingURL=Seo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Seo.d.ts","sourceRoot":"","sources":["../../src/components/Seo.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,QAiCrC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * <Seo data={SeoConfig} /> — 对齐 Hydrogen React
3
+ *
4
+ * Hydrogen 在 Remix 里用 `meta` export 注入 head;我们在客户端用 `<Seo>`
5
+ * 做 SPA 路由切换时的 document.title / meta 动态更新。
6
+ *
7
+ * SSR 阶段 Seo 组件渲染为 null(不输出 DOM);服务端商家应该用 getSeoMeta
8
+ * 生成 head HTML 直接拼到 <head>。
9
+ *
10
+ * 用法(客户端 SPA navigate 时):
11
+ *
12
+ * <Seo data={{
13
+ * title: product.title,
14
+ * description: product.description,
15
+ * image: product.featuredImage?.url,
16
+ * url: location.href,
17
+ * type: 'product',
18
+ * }} />
19
+ */
20
+ import * as React from 'react';
21
+ import { getSeoMeta } from '../seo/getSeoMeta';
22
+ export function Seo({ data }) {
23
+ React.useEffect(() => {
24
+ if (typeof document === 'undefined')
25
+ return;
26
+ const seo = getSeoMeta(data);
27
+ if (seo.fullTitle)
28
+ document.title = seo.fullTitle;
29
+ // 同步关键 meta:description / og:* / twitter:*
30
+ for (const m of seo.meta) {
31
+ const attr = m.name ? 'name' : 'property';
32
+ const key = m.name || m.property;
33
+ let el = document.querySelector(`meta[${attr}="${key}"]`);
34
+ if (!el) {
35
+ el = document.createElement('meta');
36
+ el.setAttribute(attr, key);
37
+ document.head.appendChild(el);
38
+ }
39
+ el.setAttribute('content', m.content);
40
+ }
41
+ // canonical
42
+ if (data.url) {
43
+ let canon = document.querySelector('link[rel="canonical"]');
44
+ if (!canon) {
45
+ canon = document.createElement('link');
46
+ canon.setAttribute('rel', 'canonical');
47
+ document.head.appendChild(canon);
48
+ }
49
+ canon.setAttribute('href', data.url);
50
+ }
51
+ }, [data]);
52
+ return null;
53
+ }
54
+ //# sourceMappingURL=Seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Seo.js","sourceRoot":"","sources":["../../src/components/Seo.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAkB,MAAM,mBAAmB,CAAC;AAM/D,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,EAAY;IACpC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO,QAAQ,KAAK,WAAW;YAAE,OAAO;QAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAE7B,IAAI,GAAG,CAAC,SAAS;YAAE,QAAQ,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC;QAElD,2CAA2C;QAC3C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;YAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAS,CAAC;YAClC,IAAI,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAA2B,CAAC;YACpF,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACpC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QAED,YAAY;QACZ,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,uBAAuB,CAA2B,CAAC;YACtF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACvC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;gBACvC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC;YACD,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,IAAI,CAAC;AACd,CAAC"}