fontdue-js 3.6.0 → 3.8.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 (167) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -4
  3. package/dist/__generated__/AddToCartBannerQuery.graphql.d.ts +1 -1
  4. package/dist/__generated__/AddToCartBannerQuery.graphql.js +16 -10
  5. package/dist/__generated__/AddToCartBanner_item.graphql.d.ts +4 -1
  6. package/dist/__generated__/AddToCartBanner_item.graphql.js +7 -2
  7. package/dist/__generated__/AddToCartBanner_order.graphql.d.ts +4 -1
  8. package/dist/__generated__/AddToCartBanner_order.graphql.js +6 -1
  9. package/dist/__generated__/BuyButtonIDQuery.graphql.d.ts +3 -3
  10. package/dist/__generated__/BuyButtonIDQuery.graphql.js +31 -16
  11. package/dist/__generated__/BuyButtonPackIDQuery.graphql.d.ts +21 -0
  12. package/dist/__generated__/BuyButtonPackIDQuery.graphql.js +129 -0
  13. package/dist/__generated__/BuyButtonPackSlugQuery.graphql.d.ts +25 -0
  14. package/dist/__generated__/BuyButtonPackSlugQuery.graphql.js +167 -0
  15. package/dist/__generated__/BuyButtonSlugQuery.graphql.d.ts +3 -3
  16. package/dist/__generated__/BuyButtonSlugQuery.graphql.js +45 -17
  17. package/dist/__generated__/BuyButton_product.graphql.d.ts +27 -0
  18. package/dist/__generated__/BuyButton_product.graphql.js +72 -0
  19. package/dist/__generated__/CartItemProduct_product.graphql.d.ts +1 -1
  20. package/dist/__generated__/CartItemProduct_product.graphql.js +7 -2
  21. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.d.ts +1 -1
  22. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.js +26 -20
  23. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.d.ts +1 -1
  24. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.js +26 -20
  25. package/dist/__generated__/CartOrderUpdateMutation.graphql.d.ts +1 -1
  26. package/dist/__generated__/CartOrderUpdateMutation.graphql.js +26 -20
  27. package/dist/__generated__/CartQuery.graphql.d.ts +1 -1
  28. package/dist/__generated__/CartQuery.graphql.js +26 -20
  29. package/dist/__generated__/CartStateUpdateMutation.graphql.d.ts +1 -1
  30. package/dist/__generated__/CartStateUpdateMutation.graphql.js +26 -20
  31. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.d.ts +1 -1
  32. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.js +26 -20
  33. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.d.ts +1 -1
  34. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.js +26 -20
  35. package/dist/__generated__/CollectionAa_Query.graphql.d.ts +1 -1
  36. package/dist/__generated__/CollectionAa_Query.graphql.js +20 -14
  37. package/dist/__generated__/CollectionAa_product.graphql.d.ts +7 -1
  38. package/dist/__generated__/CollectionAa_product.graphql.js +22 -16
  39. package/dist/__generated__/FontFamiliesQuery.graphql.d.ts +4 -1
  40. package/dist/__generated__/FontFamiliesQuery.graphql.js +46 -39
  41. package/dist/__generated__/NodePasswordFormElementIDQuery.graphql.d.ts +3 -3
  42. package/dist/__generated__/NodePasswordFormElementIDQuery.graphql.js +9 -9
  43. package/dist/__generated__/NodePasswordFormElementPackSlugQuery.graphql.d.ts +25 -0
  44. package/dist/__generated__/NodePasswordFormElementPackSlugQuery.graphql.js +108 -0
  45. package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +1 -1
  46. package/dist/__generated__/PrecartAddToCartMutation.graphql.js +32 -26
  47. package/dist/__generated__/PriceBar_node.graphql.d.ts +4 -1
  48. package/dist/__generated__/PriceBar_node.graphql.js +23 -16
  49. package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +1 -1
  50. package/dist/__generated__/StoreModalCartQuery.graphql.js +37 -31
  51. package/dist/__generated__/StoreModalFamily_collection.graphql.d.ts +3 -2
  52. package/dist/__generated__/StoreModalFamily_collection.graphql.js +3 -3
  53. package/dist/__generated__/StoreModalIndexPackItem_fontPack.graphql.d.ts +23 -0
  54. package/dist/__generated__/StoreModalIndexPackItem_fontPack.graphql.js +58 -0
  55. package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.d.ts +23 -0
  56. package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.js +303 -0
  57. package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +6 -3
  58. package/dist/__generated__/StoreModalIndexQuery.graphql.js +218 -117
  59. package/dist/__generated__/StoreModalIndex_viewer.graphql.d.ts +24 -0
  60. package/dist/__generated__/StoreModalIndex_viewer.graphql.js +134 -0
  61. package/dist/__generated__/StoreModalPackButton_fontPack.graphql.d.ts +33 -0
  62. package/dist/__generated__/StoreModalPackButton_fontPack.graphql.js +119 -0
  63. package/dist/__generated__/StoreModalPack_fontPack.graphql.d.ts +45 -0
  64. package/dist/__generated__/StoreModalPack_fontPack.graphql.js +150 -0
  65. package/dist/__generated__/StoreModalProductContent_collection.graphql.d.ts +6 -2
  66. package/dist/__generated__/StoreModalProductContent_collection.graphql.js +43 -19
  67. package/dist/__generated__/{StoreModalProductLicenseSelection_collection.graphql.d.ts → StoreModalProductLicenseSelection_licenseable.graphql.d.ts} +7 -6
  68. package/dist/__generated__/StoreModalProductLicenseSelection_licenseable.graphql.js +43 -0
  69. package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +1 -1
  70. package/dist/__generated__/StoreModalProductQuery.graphql.js +199 -142
  71. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +1 -1
  72. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +190 -133
  73. package/dist/__generated__/StoreModalProductSlugQuery.graphql.d.ts +5 -1
  74. package/dist/__generated__/StoreModalProductSlugQuery.graphql.js +254 -176
  75. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.d.ts +1 -1
  76. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.js +9 -4
  77. package/dist/__generated__/StoreModalProductSummary_viewer.graphql.d.ts +7 -1
  78. package/dist/__generated__/StoreModalProductSummary_viewer.graphql.js +7 -2
  79. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
  80. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +26 -20
  81. package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
  82. package/dist/__generated__/TypeTestersIDQuery.graphql.js +17 -10
  83. package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +1 -1
  84. package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +17 -10
  85. package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
  86. package/dist/__generated__/TypeTestersSlugQuery.graphql.js +17 -10
  87. package/dist/__generated__/productState_Query.graphql.d.ts +99 -1
  88. package/dist/__generated__/productState_Query.graphql.js +43 -4
  89. package/dist/__generated__/productState_fontPack.graphql.d.ts +111 -0
  90. package/dist/__generated__/productState_fontPack.graphql.js +117 -0
  91. package/dist/__generated__/storefrontEventsTrackStorefrontEventMutation.graphql.d.ts +41 -0
  92. package/dist/__generated__/storefrontEventsTrackStorefrontEventMutation.graphql.js +65 -0
  93. package/dist/__tests__/bundleSelectionOrder.test.js +94 -0
  94. package/dist/__tests__/collectionBundleSelection.test.js +443 -1446
  95. package/dist/__tests__/fontPackSelection.test.js +435 -0
  96. package/dist/__tests__/infiniteScroll.test.js +180 -0
  97. package/dist/__tests__/licenseExclusions.test.js +4 -1
  98. package/dist/__tests__/storeModalPackButton.test.js +102 -0
  99. package/dist/__tests__/storeModalPackUnlisted.test.js +112 -0
  100. package/dist/__tests__/storeModalRoutes.test.js +9 -0
  101. package/dist/__tests__/storefrontEvents.test.js +167 -0
  102. package/dist/__tests__/typeTesterAutofitFeatures.test.js +138 -0
  103. package/dist/components/AddToCartBanner/index.js +1 -1
  104. package/dist/components/BuyButton/index.d.ts +29 -9
  105. package/dist/components/BuyButton/index.js +123 -26
  106. package/dist/components/BuyButton/index.server.d.ts +4 -2
  107. package/dist/components/BuyButton/index.server.js +24 -3
  108. package/dist/components/Cart/CartItem/CartItemProduct.js +3 -3
  109. package/dist/components/Cart/Checkout.js +11 -1
  110. package/dist/components/Cart/storefrontEvents.d.ts +34 -0
  111. package/dist/components/Cart/storefrontEvents.js +138 -0
  112. package/dist/components/CollectionAa/index.js +2 -2
  113. package/dist/components/FontFamilies/index.js +4 -3
  114. package/dist/components/NodePasswordForm/NodePasswordFormElement.d.ts +1 -1
  115. package/dist/components/NodePasswordForm/NodePasswordFormElement.js +45 -21
  116. package/dist/components/NodePasswordForm/index.d.ts +7 -4
  117. package/dist/components/NodePasswordForm/index.js +6 -6
  118. package/dist/components/Precart/index.js +6 -0
  119. package/dist/components/PriceBar/index.js +5 -3
  120. package/dist/components/Root/productState.d.ts +2 -8
  121. package/dist/components/Root/productState.js +100 -61
  122. package/dist/components/SKUPrice/index.js +7 -8
  123. package/dist/components/StoreModal/StoreModalFamily.d.ts +7 -0
  124. package/dist/components/StoreModal/StoreModalFamily.js +11 -7
  125. package/dist/components/StoreModal/StoreModalIndex.js +58 -7
  126. package/dist/components/StoreModal/StoreModalIndexEntry.d.ts +13 -0
  127. package/dist/components/StoreModal/StoreModalIndexEntry.js +43 -0
  128. package/dist/components/StoreModal/StoreModalIndexItem.js +7 -30
  129. package/dist/components/StoreModal/StoreModalIndexPackItem.d.ts +7 -0
  130. package/dist/components/StoreModal/StoreModalIndexPackItem.js +21 -0
  131. package/dist/components/StoreModal/StoreModalPack.d.ts +9 -0
  132. package/dist/components/StoreModal/StoreModalPack.js +79 -0
  133. package/dist/components/StoreModal/StoreModalPackButton.d.ts +8 -0
  134. package/dist/components/StoreModal/StoreModalPackButton.js +53 -0
  135. package/dist/components/StoreModal/StoreModalProduct.js +49 -19
  136. package/dist/components/StoreModalProductLicenseSelection/StoreModalProductLicense.d.ts +2 -1
  137. package/dist/components/StoreModalProductLicenseSelection/StoreModalProductLicense.js +8 -3
  138. package/dist/components/StoreModalProductLicenseSelection/index.d.ts +3 -3
  139. package/dist/components/StoreModalProductLicenseSelection/index.js +7 -6
  140. package/dist/components/StoreModalProductSummary/index.js +1 -1
  141. package/dist/components/TypeTester/useTypeTesterStyler.js +1 -0
  142. package/dist/components/elements/StoreModalContainer/StoreModalContainerContext.d.ts +1 -0
  143. package/dist/components/elements/StoreModalContainer/index.js +9 -4
  144. package/dist/components/elements/StoreModalFamily/index.d.ts +1 -1
  145. package/dist/components/elements/StoreModalFamily/index.js +1 -1
  146. package/dist/components/elements/StoreModalIndexLoadMore/index.d.ts +8 -0
  147. package/dist/components/elements/StoreModalIndexLoadMore/index.js +21 -0
  148. package/dist/components/elements/StoreModalUnifiedCheckout.js +12 -0
  149. package/dist/components/useInfiniteScroll.d.ts +28 -0
  150. package/dist/components/useInfiniteScroll.js +50 -0
  151. package/dist/fontdue.css +39 -0
  152. package/dist/hooks/useAutofit.d.ts +2 -1
  153. package/dist/hooks/useAutofit.js +10 -4
  154. package/dist/reducer.d.ts +12 -5
  155. package/dist/reducer.js +18 -87
  156. package/dist/selection.d.ts +44 -0
  157. package/dist/selection.js +539 -0
  158. package/dist/storeModalRoutes.js +5 -4
  159. package/dist/utils.d.ts +1 -12
  160. package/dist/utils.js +1 -36
  161. package/dist/version.js +1 -1
  162. package/package.json +1 -1
  163. package/dist/__generated__/BuyButton_collection.graphql.d.ts +0 -25
  164. package/dist/__generated__/BuyButton_collection.graphql.js +0 -49
  165. package/dist/__generated__/StoreModalProductLicenseSelection_collection.graphql.js +0 -40
  166. package/fontdue.css +0 -2733
  167. package/fontdue.css.map +0 -1
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
4
+ import _NodePasswordFormElementPackSlugQuery from "../../__generated__/NodePasswordFormElementPackSlugQuery.graphql.js";
4
5
  import _NodePasswordFormElementSlugQuery from "../../__generated__/NodePasswordFormElementSlugQuery.graphql.js";
5
6
  import _NodePasswordFormElementIDQuery from "../../__generated__/NodePasswordFormElementIDQuery.graphql.js";
6
7
  import React from 'react';
@@ -8,25 +9,25 @@ import { graphql, useLazyLoadQuery } from 'react-relay';
8
9
  import NodePasswordForm from './index.js';
9
10
  // Auto-detecting wrapper behind the <fontdue-node-password-form> custom element.
10
11
  // Unlike the presentational React component (the default export of ./index, used
11
- // when the server has already detected the lock), this queries the collection
12
- // itself and renders the form only when access is denied — so it works dropped
13
- // onto any page, hiding itself for a visitor who already has access.
12
+ // when the server has already detected the lock), this queries the product itself
13
+ // – a collection or a font pack – and renders the form only when access is
14
+ // denied, so it works dropped onto any page, hiding itself for a visitor who
15
+ // already has access.
14
16
 
15
- const idQuery = (_NodePasswordFormElementIDQuery.hash && _NodePasswordFormElementIDQuery.hash !== "213a61ae079e4f57b7b197b0d2f5256a" && console.error("The definition of 'NodePasswordFormElementIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NodePasswordFormElementIDQuery);
17
+ // `node(id:)` resolves a collection and a pack alike, so one query serves both.
18
+ const idQuery = (_NodePasswordFormElementIDQuery.hash && _NodePasswordFormElementIDQuery.hash !== "fa35f237c6ea919a7afbe22c86ca19b5" && console.error("The definition of 'NodePasswordFormElementIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NodePasswordFormElementIDQuery);
16
19
  function NodePasswordFormIDQueryRenderer(_ref) {
17
20
  let {
18
- collectionId,
19
- ...rest
21
+ nodeId,
22
+ ...props
20
23
  } = _ref;
21
24
  const data = useLazyLoadQuery(idQuery, {
22
- collectionId
25
+ nodeId
23
26
  });
24
27
  // The @catch directive surfaces the password-protection error as ok:false; the
25
28
  // node is only locked then, so only then do we render the form (we don't want
26
29
  // to show it to a visitor who already has access).
27
- if (data.collection.ok === false) return /*#__PURE__*/React.createElement(NodePasswordForm, _extends({}, rest, {
28
- collectionId: collectionId
29
- }));
30
+ if (data.node.ok === false) return /*#__PURE__*/React.createElement(NodePasswordForm, props);
30
31
  return null;
31
32
  }
32
33
  const slugQuery = (_NodePasswordFormElementSlugQuery.hash && _NodePasswordFormElementSlugQuery.hash !== "200a33ca6a1f9e4e7e95b7100bbdd261" && console.error("The definition of 'NodePasswordFormElementSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NodePasswordFormElementSlugQuery);
@@ -34,32 +35,55 @@ function NodePasswordFormSlugQueryRenderer(_ref2) {
34
35
  var _data$viewer$slug;
35
36
  let {
36
37
  collectionSlug,
37
- ...rest
38
+ ...props
38
39
  } = _ref2;
39
40
  const data = useLazyLoadQuery(slugQuery, {
40
41
  collectionSlug
41
42
  });
42
43
  // see note in NodePasswordFormIDQueryRenderer
43
- if (((_data$viewer$slug = data.viewer.slug) === null || _data$viewer$slug === void 0 ? void 0 : _data$viewer$slug.collection.ok) === false) return /*#__PURE__*/React.createElement(NodePasswordForm, _extends({}, rest, {
44
+ if (((_data$viewer$slug = data.viewer.slug) === null || _data$viewer$slug === void 0 ? void 0 : _data$viewer$slug.collection.ok) === false) return /*#__PURE__*/React.createElement(NodePasswordForm, _extends({}, props, {
44
45
  collectionSlug: collectionSlug
45
46
  }));
46
47
  return null;
47
48
  }
48
- export default function NodePasswordFormElement(_ref3) {
49
+ const packSlugQuery = (_NodePasswordFormElementPackSlugQuery.hash && _NodePasswordFormElementPackSlugQuery.hash !== "3186720cb9ad751d233e995a102efcd1" && console.error("The definition of 'NodePasswordFormElementPackSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NodePasswordFormElementPackSlugQuery);
50
+ function NodePasswordFormPackSlugQueryRenderer(_ref3) {
51
+ var _data$viewer$slug2;
49
52
  let {
53
+ fontPackSlug,
54
+ ...props
55
+ } = _ref3;
56
+ const data = useLazyLoadQuery(packSlugQuery, {
57
+ fontPackSlug
58
+ });
59
+ // see note in NodePasswordFormIDQueryRenderer
60
+ if (((_data$viewer$slug2 = data.viewer.slug) === null || _data$viewer$slug2 === void 0 ? void 0 : _data$viewer$slug2.pack.ok) === false) return /*#__PURE__*/React.createElement(NodePasswordForm, _extends({}, props, {
61
+ fontPackSlug: fontPackSlug
62
+ }));
63
+ return null;
64
+ }
65
+ export default function NodePasswordFormElement(props) {
66
+ const {
50
67
  collectionId,
51
68
  collectionSlug,
52
- ...rest
53
- } = _ref3;
54
- if (collectionId) {
69
+ fontPackId,
70
+ fontPackSlug
71
+ } = props;
72
+ const nodeId = collectionId || fontPackId;
73
+ if (nodeId) {
55
74
  return /*#__PURE__*/React.createElement(NodePasswordFormIDQueryRenderer, _extends({
56
- collectionId: collectionId
57
- }, rest));
75
+ nodeId: nodeId
76
+ }, props));
58
77
  }
59
78
  if (collectionSlug) {
60
- return /*#__PURE__*/React.createElement(NodePasswordFormSlugQueryRenderer, _extends({
79
+ return /*#__PURE__*/React.createElement(NodePasswordFormSlugQueryRenderer, _extends({}, props, {
61
80
  collectionSlug: collectionSlug
62
- }, rest));
81
+ }));
82
+ }
83
+ if (fontPackSlug) {
84
+ return /*#__PURE__*/React.createElement(NodePasswordFormPackSlugQueryRenderer, _extends({}, props, {
85
+ fontPackSlug: fontPackSlug
86
+ }));
63
87
  }
64
- throw new Error('NodePasswordForm expected either a collectionId or collectionSlug prop');
88
+ throw new Error('NodePasswordForm expected a collectionId, collectionSlug, fontPackId or fontPackSlug prop');
65
89
  }
@@ -2,6 +2,9 @@ import React from 'react';
2
2
  export interface NodePasswordForm_props {
3
3
  collectionId?: string | null;
4
4
  collectionSlug?: string | null;
5
+ /** A font pack's identifiers, in place of the collection ones. */
6
+ fontPackId?: string | null;
7
+ fontPackSlug?: string | null;
5
8
  /**
6
9
  * Path of the storefront's unlock route (see fontdue-js/next/unlock), e.g.
7
10
  * "/api/unlock". On a successful unlock the form POSTs `{ token }` there
@@ -15,10 +18,10 @@ export interface NodePasswordForm_props {
15
18
  unlockEndpoint?: string | null;
16
19
  }
17
20
  /**
18
- * Password form for a collection you already know is locked. Render it when a
19
- * collection comes back password-protected (see the per-framework guides): it
20
- * commits the `accessNode` mutation, remembers the returned access token, and
21
- * reloads so the now-unlocked collection renders.
21
+ * Password form for a collection or font pack you already know is locked.
22
+ * Render it when the product comes back password-protected (see the
23
+ * per-framework guides): it commits the `accessNode` mutation, remembers the
24
+ * returned access token, and reloads so the now-unlocked product renders.
22
25
  *
23
26
  * Unlike the `<fontdue-node-password-form>` custom element (which detects the
24
27
  * locked state itself), this does no data fetching of its own, so it renders
@@ -8,10 +8,10 @@ import { EnsureFontdueContext } from '../FontdueContextProvider/index.js';
8
8
  import { rememberNodeAccessToken } from '../../nodeAccess.js';
9
9
  const accessNodeMutation = (_NodePasswordFormAccessNodeMutation.hash && _NodePasswordFormAccessNodeMutation.hash !== "eb0d3828d65a52c727ef60caa67709a1" && console.error("The definition of 'NodePasswordFormAccessNodeMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NodePasswordFormAccessNodeMutation);
10
10
  /**
11
- * Password form for a collection you already know is locked. Render it when a
12
- * collection comes back password-protected (see the per-framework guides): it
13
- * commits the `accessNode` mutation, remembers the returned access token, and
14
- * reloads so the now-unlocked collection renders.
11
+ * Password form for a collection or font pack you already know is locked.
12
+ * Render it when the product comes back password-protected (see the
13
+ * per-framework guides): it commits the `accessNode` mutation, remembers the
14
+ * returned access token, and reloads so the now-unlocked product renders.
15
15
  *
16
16
  * Unlike the `<fontdue-node-password-form>` custom element (which detects the
17
17
  * locked state itself), this does no data fetching of its own, so it renders
@@ -65,8 +65,8 @@ function NodePasswordFormFields(props) {
65
65
  variables: {
66
66
  input: {
67
67
  password,
68
- id: props.collectionId,
69
- slug: props.collectionSlug
68
+ id: props.collectionId || props.fontPackId || undefined,
69
+ slug: props.collectionSlug || props.fontPackSlug || undefined
70
70
  }
71
71
  },
72
72
  onCompleted: res => {
@@ -13,6 +13,7 @@ import { Price } from '../Price/index.js';
13
13
  import { pluralize } from '../../utils.js';
14
14
  import ComponentsContext from '../ComponentsContext.js';
15
15
  import { orderTrackingInput } from '../Cart/orderTracking.js';
16
+ import { useTrackProductCustomized } from '../Cart/storefrontEvents.js';
16
17
  function skuName(sku) {
17
18
  if (sku.product && 'name' in sku.product) return sku.product.name;
18
19
  return null;
@@ -79,6 +80,7 @@ function Precart(_ref3) {
79
80
  let {
80
81
  viewer: viewerKey,
81
82
  collection: collectionKey,
83
+ collectionId,
82
84
  isLoading
83
85
  } = _ref3;
84
86
  const viewer = useFragment((_Precart_viewer.hash && _Precart_viewer.hash !== "fe66a5cdbee38cae7bfb11922f945fd5" && console.error("The definition of 'Precart_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _Precart_viewer), viewerKey);
@@ -111,6 +113,7 @@ function Precart(_ref3) {
111
113
  }
112
114
  });
113
115
  }, [environment]);
116
+ const trackCustomized = useTrackProductCustomized(collectionId);
114
117
  const onSelectLicense = (id, checked) => {
115
118
  var _collection$licenses, _license$excludedLice;
116
119
  const license = collection === null || collection === void 0 ? void 0 : (_collection$licenses = collection.licenses) === null || _collection$licenses === void 0 ? void 0 : _collection$licenses.find(node => node.id === id);
@@ -123,6 +126,7 @@ function Precart(_ref3) {
123
126
  licenseOptionSpec,
124
127
  excludedLicenseIds: (_license$excludedLice = license.excludedLicenses) === null || _license$excludedLice === void 0 ? void 0 : _license$excludedLice.map(l => l.id)
125
128
  });
129
+ trackCustomized();
126
130
  };
127
131
  const onSelectLicenseOption = (licenseId, variableId, optionId) => {
128
132
  dispatch({
@@ -131,6 +135,7 @@ function Precart(_ref3) {
131
135
  variableId,
132
136
  optionId
133
137
  });
138
+ trackCustomized();
134
139
  };
135
140
  const selectedItemsArray = () => Object.keys(selectedSkuIds).filter(id => selectedSkuIds[id] === true);
136
141
  const licenseSelectionsArray = () => licenseOptions.reduce((res, _ref4) => {
@@ -340,6 +345,7 @@ function PrecartQueryRenderer(_ref6) {
340
345
  collectionId
341
346
  });
342
347
  return /*#__PURE__*/React.createElement(Precart, _extends({}, data, rest, {
348
+ collectionId: collectionId,
343
349
  isLoading: licenseOptionsSpecs !== deferredLicenseOptionsSpecs || selectedSkuIds !== deferredSelectedSkuIds
344
350
  }));
345
351
  }
@@ -6,7 +6,7 @@ function PriceBar(_ref) {
6
6
  let {
7
7
  node: nodeKey
8
8
  } = _ref;
9
- const node = useFragment((_PriceBar_node.hash && _PriceBar_node.hash !== "60c5de3c786db43860478f1b0e00f3df" && console.error("The definition of 'PriceBar_node' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _PriceBar_node), nodeKey);
9
+ const node = useFragment((_PriceBar_node.hash && _PriceBar_node.hash !== "ccde4ddfe0fb771462c7a0eccf4db454" && console.error("The definition of 'PriceBar_node' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _PriceBar_node), nodeKey);
10
10
  const [visible, setVisible] = useState(false);
11
11
  const $pricebar = useRef(null);
12
12
  useEffect(() => {
@@ -25,15 +25,17 @@ function PriceBar(_ref) {
25
25
  };
26
26
  }, [setVisible, $pricebar]);
27
27
  if (!node) return null;
28
+
29
+ // Unlisted collections are only sold through an upgrade – see StoreModalProduct.
28
30
  return /*#__PURE__*/React.createElement("div", {
29
31
  className: "price-bar",
30
32
  ref: $pricebar,
31
33
  "data-visible": visible
32
34
  }, /*#__PURE__*/React.createElement("div", {
33
35
  className: "price-bar__wrapper"
34
- }, node.parent && /*#__PURE__*/React.createElement(PriceBarSection, {
36
+ }, node.parent && node.parent.visibility !== 'UNLISTED' && /*#__PURE__*/React.createElement(PriceBarSection, {
35
37
  node: node.parent
36
- }), /*#__PURE__*/React.createElement(PriceBarSection, {
38
+ }), node.visibility !== 'UNLISTED' && /*#__PURE__*/React.createElement(PriceBarSection, {
37
39
  node: node
38
40
  })));
39
41
  }
@@ -2,13 +2,7 @@ import { Environment } from 'react-relay';
2
2
  import { Store } from 'redux';
3
3
  import { FontdueState, FontdueAction } from '../../reducer.js';
4
4
  export declare const populateProductState: (store: Store<FontdueState, FontdueAction>, environment: Environment, id: string) => import("relay-runtime").Subscription | undefined;
5
- export interface CollectionStyleSkus {
6
- fontStyleSkuIds: string[];
7
- fontStyleIds: string[];
8
- childrenSkuIds: string[];
9
- name: string;
10
- }
11
- export interface CollectionStyleSkusMap {
12
- [collectionSkuId: string]: CollectionStyleSkus | undefined;
5
+ export interface SkuStyleIds {
6
+ [skuId: string]: string[];
13
7
  }
14
8
  export declare const populateProductStateReducer: (state: FontdueState, action: FontdueAction) => FontdueState;
@@ -1,4 +1,5 @@
1
1
  import _productState_Query from "../../__generated__/productState_Query.graphql.js";
2
+ import _productState_fontPack from "../../__generated__/productState_fontPack.graphql.js";
2
3
  import _productState_node from "../../__generated__/productState_node.graphql.js";
3
4
  import _productState_collectionBundle from "../../__generated__/productState_collectionBundle.graphql.js";
4
5
  import _productState_bundle from "../../__generated__/productState_bundle.graphql.js";
@@ -11,7 +12,13 @@ _productState_collection.hash && _productState_collection.hash !== "90e56933f956
11
12
  _productState_bundle.hash && _productState_bundle.hash !== "fa38bbc9f2062a727da4f5062b362054" && console.error("The definition of 'productState_bundle' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_bundle;
12
13
  _productState_collectionBundle.hash && _productState_collectionBundle.hash !== "6744aa8f57d14b0111a0c49f488d7b03" && console.error("The definition of 'productState_collectionBundle' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_collectionBundle;
13
14
  _productState_node.hash && _productState_node.hash !== "a1e172db45ca550a254819d877497d12" && console.error("The definition of 'productState_node' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_node;
14
- const query = (_productState_Query.hash && _productState_Query.hash !== "ac3292bae9a274139d5a525fd0162711" && console.error("The definition of 'productState_Query' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_Query);
15
+
16
+ // A pack is one SKU that grants every style in `fontStyles`. Its collection
17
+ // members (a family or a superfamily with its families) are fetched in the
18
+ // same shape as a collection product so they register as ordinary
19
+ // collections, with the pack sitting above them.
20
+ _productState_fontPack.hash && _productState_fontPack.hash !== "43a236a4ddb4436a51d765a07e2b0eac" && console.error("The definition of 'productState_fontPack' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_fontPack;
21
+ const query = (_productState_Query.hash && _productState_Query.hash !== "65de750413d1564c4f3e1ec44ec7e2a2" && console.error("The definition of 'productState_Query' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _productState_Query);
15
22
  export const populateProductState = (store, environment, id) => {
16
23
  const existingState = store.getState().fetchedCollectionIds;
17
24
  if (existingState && existingState.indexOf(id) >= 0) return;
@@ -24,6 +31,7 @@ export const populateProductState = (store, environment, id) => {
24
31
  })
25
32
  });
26
33
  };
34
+ const packMemberCollections = pack => pack.members.filter(member => member.__typename === 'FontCollection');
27
35
  const allSkus = function (collection) {
28
36
  var _collection$fontStyle;
29
37
  let includeCollections = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
@@ -53,58 +61,67 @@ const allSkus = function (collection) {
53
61
  }
54
62
  return [includeCollections ? collection === null || collection === void 0 ? void 0 : collection.sku : null, ...(includeFontStyles && 'fontStyles' in collection ? (collection === null || collection === void 0 ? void 0 : (_collection$fontStyle = collection.fontStyles) === null || _collection$fontStyle === void 0 ? void 0 : _collection$fontStyle.map(style => style.sku)) ?? [] : []), ...bundleSkus, ...collectionBundleSkus, ...memberCollectionSkus, ...childrenSkus].filter(notEmpty);
55
63
  };
56
- const flattenSkuData = collection => {
57
- let bundles = {};
58
- if ('bundles' in collection && collection.bundles) {
59
- bundles = collection.bundles.reduce((res, bundle) => ({
60
- ...res,
61
- ...flattenSkuData(bundle)
62
- }), {});
64
+
65
+ // The styles each SKU grants, by SKU id: a style's SKU grants that style, a
66
+ // bundle its styles, a family its styles, a superfamily its families' styles
67
+ // and a collection bundle its member collections' styles. This is all the
68
+ // selection needs to price any combination of them (see selection.ts).
69
+
70
+ const styleIdsOf = collection => {
71
+ var _collection$fontStyle2, _collection$children2;
72
+ if ('memberCollections' in collection && collection.memberCollections) {
73
+ return collection.memberCollections.flatMap(member => member.fontStyles.map(s => s.id));
63
74
  }
64
- let collectionBundles = {};
65
- if ('collectionBundles' in collection && collection.collectionBundles) {
66
- collectionBundles = collection.collectionBundles.reduce((res, collBundle) => ({
67
- ...res,
68
- ...flattenSkuData(collBundle)
69
- }), {});
75
+ const own = 'fontStyles' in collection ? ((_collection$fontStyle2 = collection.fontStyles) === null || _collection$fontStyle2 === void 0 ? void 0 : _collection$fontStyle2.map(s => s.id)) ?? [] : [];
76
+ const children = 'children' in collection ? ((_collection$children2 = collection.children) === null || _collection$children2 === void 0 ? void 0 : _collection$children2.flatMap(child => {
77
+ var _child$fontStyles;
78
+ return ((_child$fontStyles = child.fontStyles) === null || _child$fontStyles === void 0 ? void 0 : _child$fontStyles.map(s => s.id)) ?? [];
79
+ })) ?? [] : [];
80
+ return [...new Set([...own, ...children])];
81
+ };
82
+ const flattenSkuStyleIds = collection => {
83
+ var _collection$sku;
84
+ const result = {};
85
+ const add = (skuId, styleIds) => {
86
+ // A collection that returns no styles of its own (a superfamily listed as
87
+ // a collection bundle member) says nothing about what it grants.
88
+ if (skuId && styleIds.length > 0) result[skuId] = styleIds;
89
+ };
90
+ const addStyles = fontStyles => {
91
+ for (const style of fontStyles ?? []) {
92
+ var _style$sku;
93
+ add((_style$sku = style.sku) === null || _style$sku === void 0 ? void 0 : _style$sku.id, [style.id]);
94
+ }
95
+ };
96
+ add((_collection$sku = collection.sku) === null || _collection$sku === void 0 ? void 0 : _collection$sku.id, styleIdsOf(collection));
97
+ if ('fontStyles' in collection) addStyles(collection.fontStyles);
98
+ if ('memberCollections' in collection) {
99
+ for (const member of collection.memberCollections ?? []) {
100
+ var _member$sku;
101
+ add((_member$sku = member.sku) === null || _member$sku === void 0 ? void 0 : _member$sku.id, member.fontStyles.map(s => s.id));
102
+ addStyles(member.fontStyles);
103
+ }
70
104
  }
71
- let children = {};
72
- if ('children' in collection && collection.children) {
73
- children = collection.children.reduce((res, child) => ({
74
- ...res,
75
- ...flattenSkuData(child)
76
- }), {});
105
+ const nested = [...('bundles' in collection ? collection.bundles ?? [] : []), ...('collectionBundles' in collection ? collection.collectionBundles ?? [] : []), ...('children' in collection ? collection.children ?? [] : [])];
106
+ for (const child of nested) Object.assign(result, flattenSkuStyleIds(child));
107
+ return result;
108
+ };
109
+
110
+ // The pack's SKU grants every style the pack lists, its style members' SKUs
111
+ // their one style each, and its collection members (a family, or a superfamily
112
+ // with its families) register like the collections they are – so the pack sits
113
+ // over them the way a superfamily sits over its families.
114
+ const flattenPackSkuStyleIds = pack => {
115
+ const result = {};
116
+ for (const member of packMemberCollections(pack)) {
117
+ Object.assign(result, flattenSkuStyleIds(member));
77
118
  }
78
- let collectionData = {};
79
- if (collection.sku) {
80
- var _collection$fontStyle2, _collection$children2;
81
- // For collection bundles, get font style IDs from member collections
82
- const fontStyleIds = 'memberCollections' in collection && collection.memberCollections ? collection.memberCollections.flatMap(member => {
83
- var _member$fontStyles2;
84
- return ((_member$fontStyles2 = member.fontStyles) === null || _member$fontStyles2 === void 0 ? void 0 : _member$fontStyles2.map(style => style.id)) ?? [];
85
- }) : 'fontStyles' in collection ? (((_collection$fontStyle2 = collection.fontStyles) === null || _collection$fontStyle2 === void 0 ? void 0 : _collection$fontStyle2.map(style => style.id)) ?? []).concat('children' in collection ? ((_collection$children2 = collection.children) === null || _collection$children2 === void 0 ? void 0 : _collection$children2.flatMap(child => {
86
- var _child$fontStyles;
87
- return ((_child$fontStyles = child.fontStyles) === null || _child$fontStyles === void 0 ? void 0 : _child$fontStyles.map(style => style.id)) ?? [];
88
- })) ?? [] : []) : [];
89
- collectionData = {
90
- [collection.sku.id]: {
91
- fontStyleIds,
92
- fontStyleSkuIds: allSkus(collection, false, true).map(sku => sku.id),
93
- childrenSkuIds: allSkus(collection, true, false).map(sku => sku.id).filter(skuId => {
94
- var _collection$sku;
95
- return skuId !== ((_collection$sku = collection.sku) === null || _collection$sku === void 0 ? void 0 : _collection$sku.id);
96
- }),
97
- // exclude self
98
- name: collection.name
99
- }
100
- };
119
+ for (const style of pack.fontStyles) {
120
+ if (style.sku) result[style.sku.id] = [style.id];
101
121
  }
102
- return {
103
- ...collectionData,
104
- ...children,
105
- ...bundles,
106
- ...collectionBundles
107
- };
122
+ const styleIds = pack.fontStyles.map(style => style.id);
123
+ if (pack.sku && styleIds.length > 0) result[pack.sku.id] = styleIds;
124
+ return result;
108
125
  };
109
126
  const flattenSkuPrices = collection => {
110
127
  return allSkus(collection).reduce((acc, sku) => {
@@ -112,39 +129,61 @@ const flattenSkuPrices = collection => {
112
129
  return acc;
113
130
  }, {});
114
131
  };
132
+ const flattenPackSkuPrices = pack => {
133
+ const skus = [pack.sku, ...pack.fontStyles.map(style => style.sku), ...packMemberCollections(pack).flatMap(member => allSkus(member))].filter(notEmpty);
134
+ return skus.reduce((acc, sku) => {
135
+ acc[sku.id] = sku.price.amount;
136
+ return acc;
137
+ }, {});
138
+ };
115
139
  export const populateProductStateReducer = (state, action) => {
116
- var _data$node, _data$node$sku;
140
+ var _node$sku;
117
141
  if (action.type !== 'POPULATE_PRODUCT_STATE') return state;
118
142
  const {
119
143
  data
120
144
  } = action;
121
- if (((_data$node = data.node) === null || _data$node === void 0 ? void 0 : _data$node.__typename) !== 'FontCollection') return state;
145
+ const node = data.node;
146
+ let skuStyleIds;
147
+ let skuPrices;
148
+ if ((node === null || node === void 0 ? void 0 : node.__typename) === 'FontCollection') {
149
+ skuStyleIds = flattenSkuStyleIds(node);
150
+ skuPrices = flattenSkuPrices(node);
151
+ } else if ((node === null || node === void 0 ? void 0 : node.__typename) === 'FontPack') {
152
+ skuStyleIds = flattenPackSkuStyleIds(node);
153
+ skuPrices = flattenPackSkuPrices(node);
154
+ } else {
155
+ return state;
156
+ }
122
157
  return {
123
158
  ...state,
124
159
  // {
125
- // [collectionSkuId]: {
126
- // childrenSkuIds: [skuId...],
127
- // fontStyleSkuIds: [skuId...],
128
- // }
160
+ // [skuId]: [styleId...]
129
161
  // }
130
- collectionStyleSkus: {
131
- ...state.collectionStyleSkus,
132
- ...flattenSkuData(data.node)
162
+ skuStyleIds: {
163
+ ...state.skuStyleIds,
164
+ ...skuStyleIds
133
165
  },
134
166
  // {
135
167
  // [skuId]: amount,
136
168
  // }
137
169
  skuPrices: {
138
170
  ...state.skuPrices,
139
- ...flattenSkuPrices(data.node)
171
+ ...skuPrices
140
172
  },
141
173
  // {
142
174
  // [collectionId]: [skuId]
143
175
  // }
144
176
  collectionSkus: {
145
177
  ...state.collectionSkus,
146
- [`${data.node.id}`]: ((_data$node$sku = data.node.sku) === null || _data$node$sku === void 0 ? void 0 : _data$node$sku.id) ?? null
178
+ [`${node.id}`]: ((_node$sku = node.sku) === null || _node$sku === void 0 ? void 0 : _node$sku.id) ?? null
179
+ },
180
+ // {
181
+ // [productId]: [skuId...]
182
+ // }
183
+ productSkuIds: {
184
+ ...state.productSkuIds,
185
+ [`${node.id}`]: Object.keys(skuPrices)
147
186
  },
148
- fetchedCollectionIds: state.fetchedCollectionIds.concat(data.node.id)
187
+ fetchedCollectionIds: state.fetchedCollectionIds.concat(node.id)
149
188
  };
150
189
  };
@@ -3,20 +3,19 @@ import _SKUPrice_sku from "../../__generated__/SKUPrice_sku.graphql.js";
3
3
  import React from 'react';
4
4
  import { graphql, useFragment } from 'react-relay';
5
5
  import Price from '../Price/index.js';
6
- import { collectionSkuIdWithDiscount, isSelected } from '../../reducer.js';
6
+ import { isSelected } from '../../reducer.js';
7
+ import { additionalCost } from '../../selection.js';
7
8
  import { useSelector } from 'react-redux';
8
9
  const getSavingsMultiplier = (state, options) => {
9
10
  if (options.showCollectionSavings === false) return 1;
10
11
  if (!options.sku) return 1;
11
12
  const baseSkuPrice = state.skuPrices[options.sku.id];
12
- const [collectionWithSavings, savingsAmount] = collectionSkuIdWithDiscount(state, options.sku.id);
13
+ const cost = additionalCost(state, options.sku.id);
13
14
 
14
- // we make it a multiplier since the `collectionSkuIdsDifference`
15
- // helper doesnt take license multiplication into account
16
- if (collectionWithSavings && baseSkuPrice > 0) {
17
- return savingsAmount / baseSkuPrice;
18
- }
19
- return 1;
15
+ // A multiplier, since `additionalCost` works in unlicensed prices and the
16
+ // price shown here carries the license's multipliers
17
+ if (cost === null || !(baseSkuPrice > 0)) return 1;
18
+ return cost / baseSkuPrice;
20
19
  };
21
20
  function SKUPrice(_ref) {
22
21
  let {
@@ -5,5 +5,12 @@ interface StoreModalFamilyProps {
5
5
  onSelect: (skuId: string, selected: boolean) => void;
6
6
  title?: React.ReactNode;
7
7
  }
8
+ interface GroupableStyle {
9
+ cssFamily: string | null;
10
+ cssWeight: string | null;
11
+ cssStretch: string | null;
12
+ cssStyle: string | null;
13
+ }
14
+ export declare function stylesGrouped<T extends GroupableStyle>(fontStyles: ReadonlyArray<T> | null | undefined): ReadonlyArray<ReadonlyArray<T>>;
8
15
  export default function StoreModalFamily({ collection: collectionKey, onSelect, title, }: StoreModalFamilyProps): React.JSX.Element | null;
9
16
  export {};
@@ -17,9 +17,11 @@ function chunkConsecutiveBy(collection, compare) {
17
17
  }, []);
18
18
  }
19
19
  const isSlanted = cssStyle => cssStyle === 'italic' || cssStyle === 'oblique';
20
- const stylesGrouped = collection => {
21
- if (!collection.fontStyles) return [];
22
- const chunks = chunkConsecutiveBy(collection.fontStyles, (left, right) => left.cssFamily === right.cssFamily && left.cssWeight === right.cssWeight && left.cssStretch === right.cssStretch && isSlanted(left.cssStyle) !== isSlanted(right.cssStyle));
20
+ // Pairs each upright style with its italic/oblique so the two render side by
21
+ // side. Shared with the font pack view, which groups a pack's style members.
22
+ export function stylesGrouped(fontStyles) {
23
+ if (!fontStyles) return [];
24
+ const chunks = chunkConsecutiveBy(fontStyles, (left, right) => left.cssFamily === right.cssFamily && left.cssWeight === right.cssWeight && left.cssStretch === right.cssStretch && isSlanted(left.cssStyle) !== isSlanted(right.cssStyle));
23
25
 
24
26
  // Only keep a chunk paired when it's exactly one upright + one slanted
25
27
  // (italic or oblique) style. Anything else (3+ consecutive matches, or
@@ -30,7 +32,7 @@ const stylesGrouped = collection => {
30
32
  const slantedCount = chunk.filter(s => isSlanted(s.cssStyle)).length;
31
33
  return slantedCount === 1 ? [chunk] : chunk.map(style => [style]);
32
34
  });
33
- };
35
+ }
34
36
  export default function StoreModalFamily(_ref) {
35
37
  var _collection$bundles;
36
38
  let {
@@ -38,8 +40,8 @@ export default function StoreModalFamily(_ref) {
38
40
  onSelect,
39
41
  title
40
42
  } = _ref;
41
- const collection = useFragment((_StoreModalFamily_collection.hash && _StoreModalFamily_collection.hash !== "d2d429ebada7593dd5debcce7a69317d" && console.error("The definition of 'StoreModalFamily_collection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalFamily_collection), collectionKey);
42
- const fontStyles = useMemo(() => stylesGrouped(collection), [collection]);
43
+ const collection = useFragment((_StoreModalFamily_collection.hash && _StoreModalFamily_collection.hash !== "f136cd0050f0f75f561221fac75feb85" && console.error("The definition of 'StoreModalFamily_collection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalFamily_collection), collectionKey);
44
+ const fontStyles = useMemo(() => stylesGrouped(collection.fontStyles), [collection]);
43
45
  if ((fontStyles === null || fontStyles === void 0 ? void 0 : fontStyles.length) === 0 && collection.collectionType === 'superfamily' && !collection.sku) return null;
44
46
  return /*#__PURE__*/React.createElement(FamilyElement, null, {
45
47
  title,
@@ -47,7 +49,9 @@ export default function StoreModalFamily(_ref) {
47
49
  collection: collection,
48
50
  onSelectSku: onSelect
49
51
  }),
50
- bundles: collection === null || collection === void 0 ? void 0 : (_collection$bundles = collection.bundles) === null || _collection$bundles === void 0 ? void 0 : _collection$bundles.filter(bundle => !bundle.hidden).map(bundle => /*#__PURE__*/React.createElement(StoreModalBundleButton, {
52
+ // An unlisted bundle gets no button, but its price still applies as an
53
+ // upgrade: the product state reads every bundle.
54
+ bundles: collection === null || collection === void 0 ? void 0 : (_collection$bundles = collection.bundles) === null || _collection$bundles === void 0 ? void 0 : _collection$bundles.filter(bundle => bundle.visibility !== 'UNLISTED').map(bundle => /*#__PURE__*/React.createElement(StoreModalBundleButton, {
51
55
  key: bundle.id,
52
56
  bundle: bundle,
53
57
  onSelectSku: onSelect