fontdue-js 3.7.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 (123) hide show
  1. package/CHANGELOG.md +6 -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__/NodePasswordFormElementIDQuery.graphql.d.ts +3 -3
  40. package/dist/__generated__/NodePasswordFormElementIDQuery.graphql.js +9 -9
  41. package/dist/__generated__/NodePasswordFormElementPackSlugQuery.graphql.d.ts +25 -0
  42. package/dist/__generated__/NodePasswordFormElementPackSlugQuery.graphql.js +108 -0
  43. package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +1 -1
  44. package/dist/__generated__/PrecartAddToCartMutation.graphql.js +32 -26
  45. package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +1 -1
  46. package/dist/__generated__/StoreModalCartQuery.graphql.js +37 -31
  47. package/dist/__generated__/StoreModalIndexPackItem_fontPack.graphql.d.ts +23 -0
  48. package/dist/__generated__/StoreModalIndexPackItem_fontPack.graphql.js +58 -0
  49. package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +9 -1
  50. package/dist/__generated__/StoreModalIndexQuery.graphql.js +174 -110
  51. package/dist/__generated__/StoreModalPackButton_fontPack.graphql.d.ts +33 -0
  52. package/dist/__generated__/StoreModalPackButton_fontPack.graphql.js +119 -0
  53. package/dist/__generated__/StoreModalPack_fontPack.graphql.d.ts +45 -0
  54. package/dist/__generated__/StoreModalPack_fontPack.graphql.js +150 -0
  55. package/dist/__generated__/StoreModalProductContent_collection.graphql.d.ts +3 -2
  56. package/dist/__generated__/StoreModalProductContent_collection.graphql.js +36 -19
  57. package/dist/__generated__/{StoreModalProductLicenseSelection_collection.graphql.d.ts → StoreModalProductLicenseSelection_licenseable.graphql.d.ts} +6 -6
  58. package/dist/__generated__/{StoreModalProductLicenseSelection_collection.graphql.js → StoreModalProductLicenseSelection_licenseable.graphql.js} +5 -5
  59. package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +1 -1
  60. package/dist/__generated__/StoreModalProductQuery.graphql.js +159 -103
  61. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +1 -1
  62. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +184 -128
  63. package/dist/__generated__/StoreModalProductSlugQuery.graphql.d.ts +5 -1
  64. package/dist/__generated__/StoreModalProductSlugQuery.graphql.js +248 -171
  65. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.d.ts +1 -1
  66. package/dist/__generated__/StoreModalProductSummaryRefetchQuery.graphql.js +9 -4
  67. package/dist/__generated__/StoreModalProductSummary_viewer.graphql.d.ts +7 -1
  68. package/dist/__generated__/StoreModalProductSummary_viewer.graphql.js +7 -2
  69. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
  70. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +26 -20
  71. package/dist/__generated__/productState_Query.graphql.d.ts +99 -1
  72. package/dist/__generated__/productState_Query.graphql.js +43 -4
  73. package/dist/__generated__/productState_fontPack.graphql.d.ts +111 -0
  74. package/dist/__generated__/productState_fontPack.graphql.js +117 -0
  75. package/dist/__tests__/bundleSelectionOrder.test.js +2 -0
  76. package/dist/__tests__/collectionBundleSelection.test.js +2 -0
  77. package/dist/__tests__/fontPackSelection.test.js +435 -0
  78. package/dist/__tests__/licenseExclusions.test.js +2 -0
  79. package/dist/__tests__/storeModalPackButton.test.js +102 -0
  80. package/dist/__tests__/storeModalPackUnlisted.test.js +112 -0
  81. package/dist/__tests__/storeModalRoutes.test.js +9 -0
  82. package/dist/components/AddToCartBanner/index.js +1 -1
  83. package/dist/components/BuyButton/index.d.ts +29 -9
  84. package/dist/components/BuyButton/index.js +123 -26
  85. package/dist/components/BuyButton/index.server.d.ts +4 -2
  86. package/dist/components/BuyButton/index.server.js +24 -3
  87. package/dist/components/Cart/CartItem/CartItemProduct.js +3 -3
  88. package/dist/components/CollectionAa/index.js +2 -2
  89. package/dist/components/NodePasswordForm/NodePasswordFormElement.d.ts +1 -1
  90. package/dist/components/NodePasswordForm/NodePasswordFormElement.js +45 -21
  91. package/dist/components/NodePasswordForm/index.d.ts +7 -4
  92. package/dist/components/NodePasswordForm/index.js +6 -6
  93. package/dist/components/Root/productState.js +57 -7
  94. package/dist/components/StoreModal/StoreModalFamily.d.ts +7 -0
  95. package/dist/components/StoreModal/StoreModalFamily.js +7 -5
  96. package/dist/components/StoreModal/StoreModalIndex.js +13 -3
  97. package/dist/components/StoreModal/StoreModalIndexEntry.d.ts +13 -0
  98. package/dist/components/StoreModal/StoreModalIndexEntry.js +43 -0
  99. package/dist/components/StoreModal/StoreModalIndexItem.js +7 -30
  100. package/dist/components/StoreModal/StoreModalIndexPackItem.d.ts +7 -0
  101. package/dist/components/StoreModal/StoreModalIndexPackItem.js +21 -0
  102. package/dist/components/StoreModal/StoreModalPack.d.ts +9 -0
  103. package/dist/components/StoreModal/StoreModalPack.js +79 -0
  104. package/dist/components/StoreModal/StoreModalPackButton.d.ts +8 -0
  105. package/dist/components/StoreModal/StoreModalPackButton.js +53 -0
  106. package/dist/components/StoreModal/StoreModalProduct.js +38 -15
  107. package/dist/components/StoreModalProductLicenseSelection/index.d.ts +3 -3
  108. package/dist/components/StoreModalProductLicenseSelection/index.js +6 -6
  109. package/dist/components/StoreModalProductSummary/index.js +1 -1
  110. package/dist/components/elements/StoreModalFamily/index.d.ts +1 -1
  111. package/dist/components/elements/StoreModalFamily/index.js +1 -1
  112. package/dist/fontdue.css +6 -0
  113. package/dist/reducer.d.ts +7 -0
  114. package/dist/reducer.js +9 -0
  115. package/dist/selection.d.ts +5 -1
  116. package/dist/selection.js +61 -16
  117. package/dist/storeModalRoutes.js +5 -4
  118. package/dist/version.js +1 -1
  119. package/package.json +1 -1
  120. package/dist/__generated__/BuyButton_collection.graphql.d.ts +0 -25
  121. package/dist/__generated__/BuyButton_collection.graphql.js +0 -49
  122. package/fontdue.css +0 -2733
  123. package/fontdue.css.map +0 -1
@@ -0,0 +1,112 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ // A pack page renders a block per member. An unlisted collection has no block
4
+ // anywhere in the Store Modal (FD-1239), so the pack page leaves it out too –
5
+ // the pack still grants it, and the pack button still sells it.
6
+
7
+ import React from 'react';
8
+ import { renderToStaticMarkup } from 'react-dom/server';
9
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
10
+ const {
11
+ stateRef
12
+ } = vi.hoisted(() => ({
13
+ stateRef: {
14
+ current: null
15
+ }
16
+ }));
17
+
18
+ // The fragment reader hands back the data it was given; the redux selector
19
+ // runs against a default store's state.
20
+ vi.mock('react-relay', () => ({
21
+ graphql: () => null,
22
+ fetchQuery: vi.fn(),
23
+ useFragment: (_fragment, key) => key
24
+ }));
25
+ vi.mock('react-redux', async importOriginal => ({
26
+ ...(await importOriginal()),
27
+ useSelector: selector => selector(stateRef.current)
28
+ }));
29
+ import StoreModalPack from '../components/StoreModal/StoreModalPack.js';
30
+ import { createDefaultStore } from '../reducer.js';
31
+ const money = amount => ({
32
+ amount,
33
+ currency: 'USD'
34
+ });
35
+ const style = name => ({
36
+ id: `style:${name}`,
37
+ name: 'Regular',
38
+ supportedLanguages: ['en'],
39
+ variableInstances: [],
40
+ sku: {
41
+ id: `sku:style:${name}`,
42
+ price: money(4000)
43
+ },
44
+ cssFamily: name,
45
+ cssWeight: '400',
46
+ cssStretch: 'normal',
47
+ cssStyle: 'normal'
48
+ });
49
+ const family = function (name, visibility) {
50
+ let children = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
51
+ return {
52
+ __typename: 'FontCollection',
53
+ id: `collection:${name}`,
54
+ name,
55
+ visibility,
56
+ collectionType: 'family',
57
+ isVariableFont: false,
58
+ sku: {
59
+ id: `sku:${name}`,
60
+ price: money(20000)
61
+ },
62
+ totalStyles: 1,
63
+ totalStylesPrice: money(4000),
64
+ featureStyle: null,
65
+ bundles: [],
66
+ fontStyles: [style(name)],
67
+ children
68
+ };
69
+ };
70
+ const styleMember = (familyName, visibility) => ({
71
+ __typename: 'FontStyle',
72
+ ...style(familyName),
73
+ family: {
74
+ id: `collection:${familyName}`,
75
+ name: familyName,
76
+ isVariableFont: false,
77
+ visibility
78
+ }
79
+ });
80
+ const pack = {
81
+ name: 'Anniversary pack',
82
+ sku: {
83
+ id: 'sku:pack',
84
+ price: money(30000)
85
+ },
86
+ featureStyle: null,
87
+ totalStyles: 6,
88
+ totalStylesPrice: money(60000),
89
+ members: [family('Alpha', 'VISIBLE', [family('Bravo', 'VISIBLE'), family('Charlie', 'UNLISTED')]), family('Delta', 'UNLISTED'), styleMember('Echo', 'VISIBLE'), styleMember('Foxtrot', 'UNLISTED')]
90
+ };
91
+ describe('StoreModalPack member blocks', () => {
92
+ beforeEach(() => {
93
+ stateRef.current = createDefaultStore(undefined).getState();
94
+ });
95
+ const markup = () => renderToStaticMarkup( /*#__PURE__*/React.createElement(StoreModalPack, {
96
+ pack: pack,
97
+ onSelect: () => {}
98
+ }));
99
+ it('renders a block for each visible member and child family', () => {
100
+ expect(markup()).toContain('Alpha');
101
+ expect(markup()).toContain('Bravo');
102
+ expect(markup()).toContain('Echo');
103
+ });
104
+ it('leaves out an unlisted member, an unlisted child and an unlisted style member', () => {
105
+ expect(markup()).not.toContain('Charlie');
106
+ expect(markup()).not.toContain('Delta');
107
+ expect(markup()).not.toContain('Foxtrot');
108
+ });
109
+ it('still sells the pack as a whole', () => {
110
+ expect(markup()).toContain('Anniversary pack');
111
+ });
112
+ });
@@ -69,6 +69,15 @@ describe('storeModalUrlActions', () => {
69
69
  it('opens the modal on its default route for ?store=open', () => {
70
70
  expect(storeModalUrlActions('?store=open', config(['unlisted']))).toEqual([OPEN]);
71
71
  });
72
+ it('opens the modal on the browse page for ?store=index', () => {
73
+ expect(storeModalUrlActions('?store=index', config(['unlisted']))).toEqual([{
74
+ type: 'STORE_MODAL_REPLACE',
75
+ route: 'index',
76
+ variables: {
77
+ excludeTags: ['unlisted']
78
+ }
79
+ }, OPEN]);
80
+ });
72
81
  it('opens the modal on a product for ?store=product/<id>', () => {
73
82
  expect(storeModalUrlActions(`?store=product/${PRODUCT_ID}`, config())).toEqual([{
74
83
  type: 'STORE_MODAL_REPLACE',
@@ -21,7 +21,7 @@ const getOrderItemName = item => {
21
21
  if ('name' in product) return product.name;
22
22
  return null;
23
23
  };
24
- _AddToCartBanner_item.hash && _AddToCartBanner_item.hash !== "93905c08206c30255368dbb06f59ccec" && console.error("The definition of 'AddToCartBanner_item' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _AddToCartBanner_item;
24
+ _AddToCartBanner_item.hash && _AddToCartBanner_item.hash !== "5b6c677fd518073e74b1651f3b872e8a" && console.error("The definition of 'AddToCartBanner_item' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _AddToCartBanner_item;
25
25
  function AddToCartBanner(_ref) {
26
26
  var _order$orderItems, _order$orderItems2;
27
27
  let {
@@ -1,19 +1,35 @@
1
1
  import React from 'react';
2
2
  import { BuyButtonIDQuery } from '../../__generated__/BuyButtonIDQuery.graphql.js';
3
3
  import { BuyButtonSlugQuery } from '../../__generated__/BuyButtonSlugQuery.graphql.js';
4
+ import { BuyButtonPackIDQuery } from '../../__generated__/BuyButtonPackIDQuery.graphql.js';
5
+ import { BuyButtonPackSlugQuery } from '../../__generated__/BuyButtonPackSlugQuery.graphql.js';
4
6
  import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
5
7
  import { Config } from '../ConfigContext.js';
6
8
  export interface BuyButton_props {
7
9
  collectionName?: string;
8
10
  label?: string;
9
11
  }
10
- export type BuyButtonPreloadedQuery = SerializablePreloadedQuery<BuyButtonIDQuery> | SerializablePreloadedQuery<BuyButtonSlugQuery>;
12
+ export type BuyButtonPreloadedQuery = SerializablePreloadedQuery<BuyButtonIDQuery> | SerializablePreloadedQuery<BuyButtonSlugQuery> | SerializablePreloadedQuery<BuyButtonPackIDQuery> | SerializablePreloadedQuery<BuyButtonPackSlugQuery>;
11
13
  export type LoadBuyButtonQueryVariables = {
12
14
  collectionId: string;
13
15
  collectionSlug?: never;
16
+ fontPackId?: never;
17
+ fontPackSlug?: never;
14
18
  } | {
15
19
  collectionId?: never;
16
20
  collectionSlug: string;
21
+ fontPackId?: never;
22
+ fontPackSlug?: never;
23
+ } | {
24
+ collectionId?: never;
25
+ collectionSlug?: never;
26
+ fontPackId: string;
27
+ fontPackSlug?: never;
28
+ } | {
29
+ collectionId?: never;
30
+ collectionSlug?: never;
31
+ fontPackId?: never;
32
+ fontPackSlug: string;
17
33
  };
18
34
  export declare function loadBuyButtonQuery(variables: LoadBuyButtonQueryVariables, options?: LoadQueryOptions): Promise<BuyButtonPreloadedQuery>;
19
35
  export declare function BuyButtonPreloadedIDQueryRenderer({ preloadedQuery, ...rest }: BuyButton_props & {
@@ -22,19 +38,23 @@ export declare function BuyButtonPreloadedIDQueryRenderer({ preloadedQuery, ...r
22
38
  export declare function BuyButtonPreloadedSlugQueryRenderer({ preloadedQuery, ...rest }: BuyButton_props & {
23
39
  preloadedQuery: SerializablePreloadedQuery<BuyButtonSlugQuery>;
24
40
  }): React.JSX.Element;
41
+ export declare function BuyButtonPreloadedPackIDQueryRenderer({ preloadedQuery, ...rest }: BuyButton_props & {
42
+ preloadedQuery: SerializablePreloadedQuery<BuyButtonPackIDQuery>;
43
+ }): React.JSX.Element;
44
+ export declare function BuyButtonPreloadedPackSlugQueryRenderer({ preloadedQuery, ...rest }: BuyButton_props & {
45
+ preloadedQuery: SerializablePreloadedQuery<BuyButtonPackSlugQuery>;
46
+ }): React.JSX.Element;
47
+ type BuyButton_lazyProps = LoadBuyButtonQueryVariables;
25
48
  export type BuyButton_unifiedProps = BuyButton_props & {
26
49
  config?: Config;
27
50
  } & ({
28
51
  preloadedQuery: BuyButtonPreloadedQuery;
29
52
  collectionId?: never;
30
53
  collectionSlug?: never;
31
- } | {
54
+ fontPackId?: never;
55
+ fontPackSlug?: never;
56
+ } | ({
32
57
  preloadedQuery?: never;
33
- collectionId: string;
34
- collectionSlug?: never;
35
- } | {
36
- preloadedQuery?: never;
37
- collectionId?: never;
38
- collectionSlug: string;
39
- });
58
+ } & BuyButton_lazyProps));
40
59
  export default function BuyButton(props: BuyButton_unifiedProps): React.JSX.Element;
60
+ export {};
@@ -1,9 +1,11 @@
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 _BuyButtonPackSlugQuery from "../../__generated__/BuyButtonPackSlugQuery.graphql.js";
5
+ import _BuyButtonPackIDQuery from "../../__generated__/BuyButtonPackIDQuery.graphql.js";
4
6
  import _BuyButtonSlugQuery from "../../__generated__/BuyButtonSlugQuery.graphql.js";
5
7
  import _BuyButtonIDQuery from "../../__generated__/BuyButtonIDQuery.graphql.js";
6
- import _BuyButton_collection from "../../__generated__/BuyButton_collection.graphql.js";
8
+ import _BuyButton_product from "../../__generated__/BuyButton_product.graphql.js";
7
9
  import React, { useCallback, useContext, useEffect } from 'react';
8
10
  import { graphql, useRelayEnvironment, useLazyLoadQuery, useFragment, usePreloadedQuery } from 'react-relay';
9
11
  import { useDispatch, useStore } from 'react-redux';
@@ -11,37 +13,41 @@ import ComponentsContext from '../ComponentsContext.js';
11
13
  import { populateProductState } from '../Root/productState.js';
12
14
  import BuyButtonIDQueryNode from '../../__generated__/BuyButtonIDQuery.graphql.js';
13
15
  import BuyButtonSlugQueryNode from '../../__generated__/BuyButtonSlugQuery.graphql.js';
16
+ import BuyButtonPackIDQueryNode from '../../__generated__/BuyButtonPackIDQuery.graphql.js';
17
+ import BuyButtonPackSlugQueryNode from '../../__generated__/BuyButtonPackSlugQuery.graphql.js';
14
18
  import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
15
19
  import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQuery.js';
16
20
  import { EnsureFontdueContext, LazyQueryBoundary } from '../FontdueContextProvider/index.js';
17
21
  function BuyButtonComponent(_ref) {
18
22
  let {
19
- collection: collectionKey,
23
+ product: productKey,
20
24
  label,
21
25
  collectionName
22
26
  } = _ref;
23
- const collection = useFragment((_BuyButton_collection.hash && _BuyButton_collection.hash !== "9c47030d7450494449d4aa5bda16e27e" && console.error("The definition of 'BuyButton_collection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButton_collection), collectionKey);
27
+ // A collection or a font pack — both open the store modal's product page,
28
+ // which renders whichever it is given.
29
+ const product = useFragment((_BuyButton_product.hash && _BuyButton_product.hash !== "007b16f72407229f0f743958a541c39a" && console.error("The definition of 'BuyButton_product' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButton_product), productKey);
24
30
  const store = useStore();
25
31
  const components = useContext(ComponentsContext);
26
32
  const dispatch = useDispatch();
27
33
  const environment = useRelayEnvironment();
28
34
  const handleClick = useCallback(() => {
29
- if (!collection) return;
35
+ if (!product) return;
30
36
  dispatch({
31
37
  type: 'STORE_MODAL_NAVIGATE',
32
38
  route: 'product',
33
39
  variables: {
34
- productId: collection.id
40
+ productId: product.id
35
41
  }
36
42
  });
37
43
  dispatch({
38
44
  type: 'OPEN_CART'
39
45
  });
40
- }, [dispatch, collection]);
46
+ }, [dispatch, product]);
41
47
  useEffect(() => {
42
- if (!collection) return;
43
- populateProductState(store, environment, collection.id);
44
- }, [collection === null || collection === void 0 ? void 0 : collection.id]);
48
+ if (!product) return;
49
+ populateProductState(store, environment, product.id);
50
+ }, [product === null || product === void 0 ? void 0 : product.id]);
45
51
  if (components.BuyButton) {
46
52
  return /*#__PURE__*/React.createElement(components.BuyButton, {
47
53
  innerProps: {
@@ -49,14 +55,21 @@ function BuyButtonComponent(_ref) {
49
55
  }
50
56
  });
51
57
  }
58
+
59
+ // Collections keep their historical label (the fragment never fetched the
60
+ // collection's name, so `collectionName` fills it in); a pack's name comes
61
+ // from the query.
62
+ const productName = collectionName ?? ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontPack' ? product.name : '');
52
63
  return /*#__PURE__*/React.createElement("button", {
53
64
  className: "buy-button",
54
65
  onClick: handleClick,
55
66
  type: "button"
56
- }, label ? label : `Buy ${collectionName ?? ''}`);
67
+ }, label ? label : `Buy ${productName}`);
57
68
  }
58
- const idQuery = (_BuyButtonIDQuery.hash && _BuyButtonIDQuery.hash !== "4fbf1dbf9e6c530a5d38c697b174d8b0" && console.error("The definition of 'BuyButtonIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonIDQuery);
59
- const slugQuery = (_BuyButtonSlugQuery.hash && _BuyButtonSlugQuery.hash !== "6e750adea09698f7cb61f435cd88fd26" && console.error("The definition of 'BuyButtonSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonSlugQuery);
69
+ const idQuery = (_BuyButtonIDQuery.hash && _BuyButtonIDQuery.hash !== "602547ee927b734b5fa2d6d1f2c93765" && console.error("The definition of 'BuyButtonIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonIDQuery);
70
+ const slugQuery = (_BuyButtonSlugQuery.hash && _BuyButtonSlugQuery.hash !== "14c9d7a1ef98d03b73b22374983b5fb4" && console.error("The definition of 'BuyButtonSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonSlugQuery);
71
+ const packIdQuery = (_BuyButtonPackIDQuery.hash && _BuyButtonPackIDQuery.hash !== "7c9a7e75de7c428c5a3aec1235d0516e" && console.error("The definition of 'BuyButtonPackIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonPackIDQuery);
72
+ const packSlugQuery = (_BuyButtonPackSlugQuery.hash && _BuyButtonPackSlugQuery.hash !== "7d9d7c6c7343fe13ccb1e79b6696e416" && console.error("The definition of 'BuyButtonPackSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _BuyButtonPackSlugQuery);
60
73
  export async function loadBuyButtonQuery(variables, options) {
61
74
  if (variables.collectionId) {
62
75
  return loadSerializableQuery(BuyButtonIDQueryNode, {
@@ -68,7 +81,17 @@ export async function loadBuyButtonQuery(variables, options) {
68
81
  collectionSlug: variables.collectionSlug
69
82
  }, options);
70
83
  }
71
- throw new Error('loadBuyButtonQuery expected either a collectionId or collectionSlug');
84
+ if (variables.fontPackId) {
85
+ return loadSerializableQuery(BuyButtonPackIDQueryNode, {
86
+ fontPackId: variables.fontPackId
87
+ }, options);
88
+ }
89
+ if (variables.fontPackSlug) {
90
+ return loadSerializableQuery(BuyButtonPackSlugQueryNode, {
91
+ fontPackSlug: variables.fontPackSlug
92
+ }, options);
93
+ }
94
+ throw new Error('loadBuyButtonQuery expected one of collectionId, collectionSlug, fontPackId or fontPackSlug');
72
95
  }
73
96
  function BuyButtonIDQueryRenderer(_ref2) {
74
97
  let {
@@ -102,7 +125,7 @@ function BuyButtonSlugQueryRenderer(_ref4) {
102
125
  collectionSlug
103
126
  });
104
127
  return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, {
105
- collection: ((_data$viewer = data.viewer) === null || _data$viewer === void 0 ? void 0 : (_data$viewer$slug = _data$viewer.slug) === null || _data$viewer$slug === void 0 ? void 0 : _data$viewer$slug.collection) ?? null
128
+ product: ((_data$viewer = data.viewer) === null || _data$viewer === void 0 ? void 0 : (_data$viewer$slug = _data$viewer.slug) === null || _data$viewer$slug === void 0 ? void 0 : _data$viewer$slug.product) ?? null
106
129
  }));
107
130
  }
108
131
  export function BuyButtonPreloadedSlugQueryRenderer(_ref5) {
@@ -117,25 +140,83 @@ export function BuyButtonPreloadedSlugQueryRenderer(_ref5) {
117
140
  const queryRef = useSerializablePreloadedQuery(preloadedQuery, 'store-or-network', slugQuery);
118
141
  const data = usePreloadedQuery(slugQuery, queryRef);
119
142
  return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, {
120
- collection: ((_data$viewer2 = data.viewer) === null || _data$viewer2 === void 0 ? void 0 : (_data$viewer2$slug = _data$viewer2.slug) === null || _data$viewer2$slug === void 0 ? void 0 : _data$viewer2$slug.collection) ?? null
143
+ product: ((_data$viewer2 = data.viewer) === null || _data$viewer2 === void 0 ? void 0 : (_data$viewer2$slug = _data$viewer2.slug) === null || _data$viewer2$slug === void 0 ? void 0 : _data$viewer2$slug.product) ?? null
121
144
  }));
122
145
  }
123
- function BuyButtonPreloadedRenderer(_ref6) {
146
+ function BuyButtonPackIDQueryRenderer(_ref6) {
124
147
  let {
125
- preloadedQuery,
148
+ fontPackId,
126
149
  ...rest
127
150
  } = _ref6;
128
- if (preloadedQuery.params.name === 'BuyButtonIDQuery') {
129
- return /*#__PURE__*/React.createElement(BuyButtonPreloadedIDQueryRenderer, _extends({
130
- preloadedQuery: preloadedQuery
131
- }, rest));
151
+ const data = useLazyLoadQuery(packIdQuery, {
152
+ fontPackId
153
+ });
154
+ return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, data));
155
+ }
156
+ export function BuyButtonPreloadedPackIDQueryRenderer(_ref7) {
157
+ let {
158
+ preloadedQuery,
159
+ ...rest
160
+ } = _ref7;
161
+ const queryRef = useSerializablePreloadedQuery(preloadedQuery, 'store-or-network', packIdQuery);
162
+ const data = usePreloadedQuery(packIdQuery, queryRef);
163
+ return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, data));
164
+ }
165
+ function BuyButtonPackSlugQueryRenderer(_ref8) {
166
+ var _data$viewer3, _data$viewer3$slug;
167
+ let {
168
+ fontPackSlug,
169
+ ...rest
170
+ } = _ref8;
171
+ const data = useLazyLoadQuery(packSlugQuery, {
172
+ fontPackSlug
173
+ });
174
+ return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, {
175
+ product: ((_data$viewer3 = data.viewer) === null || _data$viewer3 === void 0 ? void 0 : (_data$viewer3$slug = _data$viewer3.slug) === null || _data$viewer3$slug === void 0 ? void 0 : _data$viewer3$slug.product) ?? null
176
+ }));
177
+ }
178
+ export function BuyButtonPreloadedPackSlugQueryRenderer(_ref9) {
179
+ var _data$viewer4, _data$viewer4$slug;
180
+ let {
181
+ preloadedQuery,
182
+ ...rest
183
+ } = _ref9;
184
+ const queryRef = useSerializablePreloadedQuery(preloadedQuery, 'store-or-network', packSlugQuery);
185
+ const data = usePreloadedQuery(packSlugQuery, queryRef);
186
+ return /*#__PURE__*/React.createElement(BuyButtonComponent, _extends({}, rest, {
187
+ product: ((_data$viewer4 = data.viewer) === null || _data$viewer4 === void 0 ? void 0 : (_data$viewer4$slug = _data$viewer4.slug) === null || _data$viewer4$slug === void 0 ? void 0 : _data$viewer4$slug.product) ?? null
188
+ }));
189
+ }
190
+ function BuyButtonPreloadedRenderer(_ref10) {
191
+ let {
192
+ preloadedQuery,
193
+ ...rest
194
+ } = _ref10;
195
+ switch (preloadedQuery.params.name) {
196
+ case 'BuyButtonIDQuery':
197
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedIDQueryRenderer, _extends({
198
+ preloadedQuery: preloadedQuery
199
+ }, rest));
200
+ case 'BuyButtonPackIDQuery':
201
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedPackIDQueryRenderer, _extends({
202
+ preloadedQuery: preloadedQuery
203
+ }, rest));
204
+ case 'BuyButtonPackSlugQuery':
205
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedPackSlugQueryRenderer, _extends({
206
+ preloadedQuery: preloadedQuery
207
+ }, rest));
208
+ default:
209
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedSlugQueryRenderer, _extends({
210
+ preloadedQuery: preloadedQuery
211
+ }, rest));
132
212
  }
133
- return /*#__PURE__*/React.createElement(BuyButtonPreloadedSlugQueryRenderer, _extends({
134
- preloadedQuery: preloadedQuery
135
- }, rest));
136
213
  }
214
+
215
+ // A lazy button identifies its product the same way `loadBuyButtonQuery` does.
216
+
137
217
  // Unified BuyButton entry. Accepts a preloaded query (server-side preload
138
- // path) or `{collectionId}`/`{collectionSlug}` for lazy fetch.
218
+ // path) or one of `{collectionId}`/`{collectionSlug}`/`{fontPackId}`/
219
+ // `{fontPackSlug}` for lazy fetch.
139
220
  // `EnsureFontdueContext` only self-wraps with `FontdueContextProvider` when
140
221
  // no parent Fontdue context is present, seeding it with `config`.
141
222
  export default function BuyButton(props) {
@@ -164,8 +245,24 @@ export default function BuyButton(props) {
164
245
  inner = /*#__PURE__*/React.createElement(LazyQueryBoundary, null, /*#__PURE__*/React.createElement(BuyButtonSlugQueryRenderer, _extends({
165
246
  collectionSlug: collectionSlug
166
247
  }, rest)));
248
+ } else if ('fontPackId' in props && props.fontPackId) {
249
+ const {
250
+ fontPackId,
251
+ ...rest
252
+ } = props;
253
+ inner = /*#__PURE__*/React.createElement(LazyQueryBoundary, null, /*#__PURE__*/React.createElement(BuyButtonPackIDQueryRenderer, _extends({
254
+ fontPackId: fontPackId
255
+ }, rest)));
256
+ } else if ('fontPackSlug' in props && props.fontPackSlug) {
257
+ const {
258
+ fontPackSlug,
259
+ ...rest
260
+ } = props;
261
+ inner = /*#__PURE__*/React.createElement(LazyQueryBoundary, null, /*#__PURE__*/React.createElement(BuyButtonPackSlugQueryRenderer, _extends({
262
+ fontPackSlug: fontPackSlug
263
+ }, rest)));
167
264
  } else {
168
- throw new Error('BuyButton expected one of preloadedQuery, collectionId, or collectionSlug');
265
+ throw new Error('BuyButton expected one of preloadedQuery, collectionId, collectionSlug, fontPackId, or fontPackSlug');
169
266
  }
170
267
  return /*#__PURE__*/React.createElement(EnsureFontdueContext, {
171
268
  config: props.config
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
  import { BuyButton_props } from './index.js';
3
3
  import { Config } from '../ConfigContext.js';
4
- export type { BuyButtonPreloadedQuery } from './index.js';
4
+ export type { BuyButtonPreloadedQuery, LoadBuyButtonQueryVariables } from './index.js';
5
5
  export declare function loadBuyButtonQuery(): never;
6
- export default function BuyButton({ collectionId, collectionSlug, ...rest }: BuyButton_props & {
6
+ export default function BuyButton({ collectionId, collectionSlug, fontPackId, fontPackSlug, ...rest }: BuyButton_props & {
7
7
  collectionId?: string | null;
8
8
  collectionSlug?: string | null;
9
+ fontPackId?: string | null;
10
+ fontPackSlug?: string | null;
9
11
  config?: Config;
10
12
  }): Promise<React.JSX.Element | null>;
@@ -1,9 +1,11 @@
1
1
  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); }
2
2
  import React from 'react';
3
3
  import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
4
- import { BuyButtonPreloadedIDQueryRenderer, BuyButtonPreloadedSlugQueryRenderer } from './index.js';
4
+ import { BuyButtonPreloadedIDQueryRenderer, BuyButtonPreloadedSlugQueryRenderer, BuyButtonPreloadedPackIDQueryRenderer, BuyButtonPreloadedPackSlugQueryRenderer } from './index.js';
5
5
  import BuyButtonIDQueryNode from '../../__generated__/BuyButtonIDQuery.graphql.js';
6
6
  import BuyButtonSlugQueryNode from '../../__generated__/BuyButtonSlugQuery.graphql.js';
7
+ import BuyButtonPackIDQueryNode from '../../__generated__/BuyButtonPackIDQuery.graphql.js';
8
+ import BuyButtonPackSlugQueryNode from '../../__generated__/BuyButtonPackSlugQuery.graphql.js';
7
9
  // Stub for the RSC export condition. See FontdueProvider/index.server.tsx
8
10
  // for the rationale.
9
11
  export function loadBuyButtonQuery() {
@@ -12,12 +14,15 @@ export function loadBuyButtonQuery() {
12
14
 
13
15
  // Next RSC variant: awaits the query on the server and hands the response to
14
16
  // the client `*PreloadedQueryRenderer`. Lets pages just write
15
- // `<BuyButton collectionId={id} />` in an RSC without manually invoking
16
- // `loadBuyButtonQuery` + threading `preloadedQuery` through props.
17
+ // `<BuyButton collectionId={id} />` (or `fontPackId`) in an RSC without
18
+ // manually invoking `loadBuyButtonQuery` + threading `preloadedQuery` through
19
+ // props.
17
20
  export default async function BuyButton(_ref) {
18
21
  let {
19
22
  collectionId,
20
23
  collectionSlug,
24
+ fontPackId,
25
+ fontPackSlug,
21
26
  ...rest
22
27
  } = _ref;
23
28
  if (collectionId) {
@@ -36,5 +41,21 @@ export default async function BuyButton(_ref) {
36
41
  preloadedQuery: preloadedQuery
37
42
  }, rest));
38
43
  }
44
+ if (fontPackId) {
45
+ const preloadedQuery = await loadSerializableQuery(BuyButtonPackIDQueryNode, {
46
+ fontPackId
47
+ });
48
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedPackIDQueryRenderer, _extends({
49
+ preloadedQuery: preloadedQuery
50
+ }, rest));
51
+ }
52
+ if (fontPackSlug) {
53
+ const preloadedQuery = await loadSerializableQuery(BuyButtonPackSlugQueryNode, {
54
+ fontPackSlug
55
+ });
56
+ return /*#__PURE__*/React.createElement(BuyButtonPreloadedPackSlugQueryRenderer, _extends({
57
+ preloadedQuery: preloadedQuery
58
+ }, rest));
59
+ }
39
60
  return null;
40
61
  }
@@ -9,13 +9,13 @@ export default function CartItemProduct(_ref) {
9
9
  let {
10
10
  product: productKey
11
11
  } = _ref;
12
- const product = useFragment((_CartItemProduct_product.hash && _CartItemProduct_product.hash !== "a3931102e3ec08c57abd262038b5d74a" && console.error("The definition of 'CartItemProduct_product' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CartItemProduct_product), productKey);
12
+ const product = useFragment((_CartItemProduct_product.hash && _CartItemProduct_product.hash !== "15b269b9bb33a3bfa7b10486e99da183" && console.error("The definition of 'CartItemProduct_product' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CartItemProduct_product), productKey);
13
13
  let productName = (product === null || product === void 0 ? void 0 : product.name) ?? '??';
14
14
  if ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontStyle' && product.family) productName = `${product.family.name} ${product.name}`;
15
15
  if (((product === null || product === void 0 ? void 0 : product.__typename) === 'Bundle' || (product === null || product === void 0 ? void 0 : product.__typename) === 'CollectionBundle') && product.fontCollection && !((_product$name = product.name) !== null && _product$name !== void 0 && _product$name.startsWith(product.fontCollection.name))) productName = `${product.fontCollection.name} ${product.name}`;
16
16
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
17
17
  className: "cart-item__aa"
18
- }, product ? /*#__PURE__*/React.createElement(React.Fragment, null, ['FontCollection', 'Bundle', 'CollectionBundle'].indexOf(product.__typename) >= 0 ? /*#__PURE__*/React.createElement(CollectionAa, {
18
+ }, product ? /*#__PURE__*/React.createElement(React.Fragment, null, ['FontCollection', 'Bundle', 'CollectionBundle', 'FontPack'].indexOf(product.__typename) >= 0 ? /*#__PURE__*/React.createElement(CollectionAa, {
19
19
  product: product
20
20
  }) : /*#__PURE__*/React.createElement(FontStyle, {
21
21
  fontStyle: product
@@ -25,7 +25,7 @@ export default function CartItemProduct(_ref) {
25
25
  className: "cart-item__name"
26
26
  }, productName), product !== null && product !== void 0 && product.isVariableFont || product !== null && product !== void 0 && (_product$variableInst = product.variableInstances) !== null && _product$variableInst !== void 0 && _product$variableInst.length ? /*#__PURE__*/React.createElement("div", {
27
27
  className: "cart-item__label"
28
- }, "Variable font") : ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontCollection' || (product === null || product === void 0 ? void 0 : product.__typename) === 'CollectionBundle') && /*#__PURE__*/React.createElement("div", {
28
+ }, "Variable font") : ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontCollection' || (product === null || product === void 0 ? void 0 : product.__typename) === 'CollectionBundle' || (product === null || product === void 0 ? void 0 : product.__typename) === 'FontPack') && /*#__PURE__*/React.createElement("div", {
29
29
  className: "cart-item__label"
30
30
  }, "(", pluralize(product.totalStyles ?? 0, 'style'), ")")));
31
31
  }
@@ -7,12 +7,12 @@ export const CollectionAa = _ref => {
7
7
  let {
8
8
  product: productKey
9
9
  } = _ref;
10
- const product = useFragment((_CollectionAa_product.hash && _CollectionAa_product.hash !== "c6b0113fe8474166dab3649c41880d84" && console.error("The definition of 'CollectionAa_product' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CollectionAa_product), productKey);
10
+ const product = useFragment((_CollectionAa_product.hash && _CollectionAa_product.hash !== "a3ee4dc4f6eb38b9c24a21cdc2cb6bc0" && console.error("The definition of 'CollectionAa_product' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CollectionAa_product), productKey);
11
11
  let fontStyle;
12
12
  if ((product === null || product === void 0 ? void 0 : product.__typename) === 'Bundle') {
13
13
  var _product$fontStyles;
14
14
  fontStyle = (_product$fontStyles = product.fontStyles) === null || _product$fontStyles === void 0 ? void 0 : _product$fontStyles[0];
15
- } else if ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontCollection') {
15
+ } else if ((product === null || product === void 0 ? void 0 : product.__typename) === 'FontCollection' || (product === null || product === void 0 ? void 0 : product.__typename) === 'FontPack') {
16
16
  fontStyle = product.featureStyle;
17
17
  }
18
18
  if (!fontStyle) return null;
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import { NodePasswordForm_props } from './index.js';
3
- export default function NodePasswordFormElement({ collectionId, collectionSlug, ...rest }: NodePasswordForm_props): React.JSX.Element;
3
+ export default function NodePasswordFormElement(props: NodePasswordForm_props): React.JSX.Element;