fontdue-js 3.6.0 → 3.7.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.
- package/CHANGELOG.md +8 -0
- package/dist/__generated__/FontFamiliesQuery.graphql.d.ts +4 -1
- package/dist/__generated__/FontFamiliesQuery.graphql.js +46 -39
- package/dist/__generated__/PriceBar_node.graphql.d.ts +4 -1
- package/dist/__generated__/PriceBar_node.graphql.js +23 -16
- package/dist/__generated__/StoreModalFamily_collection.graphql.d.ts +3 -2
- package/dist/__generated__/StoreModalFamily_collection.graphql.js +3 -3
- package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.d.ts +23 -0
- package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.js +303 -0
- package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +4 -9
- package/dist/__generated__/StoreModalIndexQuery.graphql.js +90 -53
- package/dist/__generated__/StoreModalIndex_viewer.graphql.d.ts +24 -0
- package/dist/__generated__/StoreModalIndex_viewer.graphql.js +134 -0
- package/dist/__generated__/StoreModalProductContent_collection.graphql.d.ts +4 -1
- package/dist/__generated__/StoreModalProductContent_collection.graphql.js +12 -5
- package/dist/__generated__/StoreModalProductLicenseSelection_collection.graphql.d.ts +2 -1
- package/dist/__generated__/StoreModalProductLicenseSelection_collection.graphql.js +27 -24
- package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalProductQuery.graphql.js +78 -77
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +54 -53
- package/dist/__generated__/StoreModalProductSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalProductSlugQuery.graphql.js +78 -77
- package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersIDQuery.graphql.js +17 -10
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +17 -10
- package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersSlugQuery.graphql.js +17 -10
- package/dist/__generated__/storefrontEventsTrackStorefrontEventMutation.graphql.d.ts +41 -0
- package/dist/__generated__/storefrontEventsTrackStorefrontEventMutation.graphql.js +65 -0
- package/dist/__tests__/bundleSelectionOrder.test.js +92 -0
- package/dist/__tests__/collectionBundleSelection.test.js +441 -1446
- package/dist/__tests__/infiniteScroll.test.js +180 -0
- package/dist/__tests__/licenseExclusions.test.js +2 -1
- package/dist/__tests__/storefrontEvents.test.js +167 -0
- package/dist/__tests__/typeTesterAutofitFeatures.test.js +138 -0
- package/dist/components/Cart/Checkout.js +11 -1
- package/dist/components/Cart/storefrontEvents.d.ts +34 -0
- package/dist/components/Cart/storefrontEvents.js +138 -0
- package/dist/components/FontFamilies/index.js +4 -3
- package/dist/components/Precart/index.js +6 -0
- package/dist/components/PriceBar/index.js +5 -3
- package/dist/components/Root/productState.d.ts +2 -8
- package/dist/components/Root/productState.js +46 -57
- package/dist/components/SKUPrice/index.js +7 -8
- package/dist/components/StoreModal/StoreModalFamily.js +4 -2
- package/dist/components/StoreModal/StoreModalIndex.js +48 -7
- package/dist/components/StoreModal/StoreModalProduct.js +16 -9
- package/dist/components/StoreModalProductLicenseSelection/StoreModalProductLicense.d.ts +2 -1
- package/dist/components/StoreModalProductLicenseSelection/StoreModalProductLicense.js +8 -3
- package/dist/components/StoreModalProductLicenseSelection/index.js +3 -2
- package/dist/components/TypeTester/useTypeTesterStyler.js +1 -0
- package/dist/components/elements/StoreModalContainer/StoreModalContainerContext.d.ts +1 -0
- package/dist/components/elements/StoreModalContainer/index.js +9 -4
- package/dist/components/elements/StoreModalIndexLoadMore/index.d.ts +8 -0
- package/dist/components/elements/StoreModalIndexLoadMore/index.js +21 -0
- package/dist/components/elements/StoreModalUnifiedCheckout.js +12 -0
- package/dist/components/useInfiniteScroll.d.ts +28 -0
- package/dist/components/useInfiniteScroll.js +50 -0
- package/dist/fontdue.css +33 -0
- package/dist/hooks/useAutofit.d.ts +2 -1
- package/dist/hooks/useAutofit.js +10 -4
- package/dist/reducer.d.ts +5 -5
- package/dist/reducer.js +9 -87
- package/dist/selection.d.ts +40 -0
- package/dist/selection.js +494 -0
- package/dist/utils.d.ts +1 -12
- package/dist/utils.js +1 -36
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import _storefrontEventsTrackStorefrontEventMutation from "../../__generated__/storefrontEventsTrackStorefrontEventMutation.graphql.js";
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { commitMutation, graphql, useRelayEnvironment } from 'react-relay';
|
|
4
|
+
import { useStore } from 'react-redux';
|
|
5
|
+
import { orderTrackingInput } from './orderTracking.js';
|
|
6
|
+
/**
|
|
7
|
+
* The storefront moments that happen entirely in the browser – a collection
|
|
8
|
+
* opened in the store modal, its licences changed, the payment details
|
|
9
|
+
* completed. Nothing reaches the server at those moments on its own, so they
|
|
10
|
+
* are reported through `trackStorefrontEvent`, which records them as "Product
|
|
11
|
+
* Viewed", "Product Customized" and "Payment Info Entered" with the same
|
|
12
|
+
* consent and identifiers as the order events around them (Meta reads them as
|
|
13
|
+
* ViewContent, CustomizeProduct and AddPaymentInfo).
|
|
14
|
+
*
|
|
15
|
+
* Every call is fire-and-forget: tracking must never break the store.
|
|
16
|
+
*/
|
|
17
|
+
function track(environment, input) {
|
|
18
|
+
const tracking = orderTrackingInput();
|
|
19
|
+
// Outside a browser there is no moment to report.
|
|
20
|
+
if (!tracking) return;
|
|
21
|
+
try {
|
|
22
|
+
commitMutation(environment, {
|
|
23
|
+
mutation: (_storefrontEventsTrackStorefrontEventMutation.hash && _storefrontEventsTrackStorefrontEventMutation.hash !== "340cc13477a15b926e2307d36c644053" && console.error("The definition of 'storefrontEventsTrackStorefrontEventMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _storefrontEventsTrackStorefrontEventMutation),
|
|
24
|
+
variables: {
|
|
25
|
+
input: {
|
|
26
|
+
...input,
|
|
27
|
+
tracking
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
onCompleted: () => undefined,
|
|
31
|
+
onError: () => undefined
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
// Ignore — see above.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// React can run an effect twice for one mount – StrictMode in development, a
|
|
39
|
+
// Suspense retry – and each run would count as a second look.
|
|
40
|
+
const VIEW_REPEAT_MS = 2000;
|
|
41
|
+
let lastView = null;
|
|
42
|
+
|
|
43
|
+
/** Reports the store modal opening on a collection. */
|
|
44
|
+
export function trackProductViewed(environment, collectionId) {
|
|
45
|
+
var _lastView;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
if (((_lastView = lastView) === null || _lastView === void 0 ? void 0 : _lastView.collectionId) === collectionId && now - lastView.at < VIEW_REPEAT_MS) return;
|
|
48
|
+
lastView = {
|
|
49
|
+
collectionId,
|
|
50
|
+
at: now
|
|
51
|
+
};
|
|
52
|
+
track(environment, {
|
|
53
|
+
event: 'PRODUCT_VIEWED',
|
|
54
|
+
collectionId
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The licence choices in the store's state, in the shape `createOrderItems`
|
|
59
|
+
* takes them – one selection per licence variable, or one bare selection for a
|
|
60
|
+
* licence without variables. Sorted, so the same configuration reached in a
|
|
61
|
+
* different order reads the same.
|
|
62
|
+
*/
|
|
63
|
+
export function licenseSelectionsFromOptions(licenseOptions) {
|
|
64
|
+
const selections = licenseOptions.flatMap(_ref => {
|
|
65
|
+
let {
|
|
66
|
+
licenseId,
|
|
67
|
+
licenseOptions: options
|
|
68
|
+
} = _ref;
|
|
69
|
+
const variableIds = Object.keys(options ?? {});
|
|
70
|
+
if (variableIds.length === 0) return [{
|
|
71
|
+
licenseId
|
|
72
|
+
}];
|
|
73
|
+
return variableIds.map(licenseVariableId => ({
|
|
74
|
+
licenseId,
|
|
75
|
+
licenseVariableId,
|
|
76
|
+
licenseOptionId: options[licenseVariableId]
|
|
77
|
+
}));
|
|
78
|
+
});
|
|
79
|
+
const key = s => `${s.licenseId}:${s.licenseVariableId ?? ''}`;
|
|
80
|
+
return selections.sort((a, b) => key(a).localeCompare(key(b)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// A buyer clicks through a few licences and sizes before settling. Report the
|
|
84
|
+
// configuration they settle on rather than every step on the way, and only
|
|
85
|
+
// when it differs from the last one reported for that collection.
|
|
86
|
+
const CUSTOMIZE_SETTLE_MS = 1500;
|
|
87
|
+
const pendingCustomizations = new Map();
|
|
88
|
+
const reportedConfigurations = new Map();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Reports the buyer changing their licence choices for a collection, once the
|
|
92
|
+
* choices settle. Call it from the handler of the buyer's own click, never from
|
|
93
|
+
* an effect: licences a foundry marks as selected by default are applied on
|
|
94
|
+
* mount, and that isn't the buyer customizing anything.
|
|
95
|
+
*
|
|
96
|
+
* `currentLicenseOptions` is read when the report fires, so it sees the
|
|
97
|
+
* configuration the buyer settled on.
|
|
98
|
+
*/
|
|
99
|
+
export function trackProductCustomized(environment, collectionId, currentLicenseOptions) {
|
|
100
|
+
clearTimeout(pendingCustomizations.get(collectionId));
|
|
101
|
+
pendingCustomizations.set(collectionId, setTimeout(() => {
|
|
102
|
+
pendingCustomizations.delete(collectionId);
|
|
103
|
+
const licenseSelections = licenseSelectionsFromOptions(currentLicenseOptions());
|
|
104
|
+
// Unticking everything configures nothing.
|
|
105
|
+
if (licenseSelections.length === 0) return;
|
|
106
|
+
const configuration = JSON.stringify(licenseSelections);
|
|
107
|
+
if (reportedConfigurations.get(collectionId) === configuration) return;
|
|
108
|
+
reportedConfigurations.set(collectionId, configuration);
|
|
109
|
+
track(environment, {
|
|
110
|
+
event: 'PRODUCT_CUSTOMIZED',
|
|
111
|
+
collectionId,
|
|
112
|
+
licenseSelections
|
|
113
|
+
});
|
|
114
|
+
}, CUSTOMIZE_SETTLE_MS));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* `trackProductCustomized` bound to the store and Relay environment in
|
|
119
|
+
* context, for a licence control's click handlers.
|
|
120
|
+
*/
|
|
121
|
+
export function useTrackProductCustomized(collectionId) {
|
|
122
|
+
const environment = useRelayEnvironment();
|
|
123
|
+
const store = useStore();
|
|
124
|
+
return useCallback(() => {
|
|
125
|
+
if (!collectionId) return;
|
|
126
|
+
trackProductCustomized(environment, collectionId, () => store.getState().licenseOptions);
|
|
127
|
+
}, [environment, store, collectionId]);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Reports the checkout's payment details as complete. The server records it
|
|
132
|
+
* once per order, however often this is called.
|
|
133
|
+
*/
|
|
134
|
+
export function trackPaymentInfoEntered(environment) {
|
|
135
|
+
track(environment, {
|
|
136
|
+
event: 'PAYMENT_INFO_ENTERED'
|
|
137
|
+
});
|
|
138
|
+
}
|
|
@@ -24,20 +24,21 @@ function FontFamilies(_ref) {
|
|
|
24
24
|
} = useLicenseAndOrderVariables();
|
|
25
25
|
const {
|
|
26
26
|
node
|
|
27
|
-
} = useLazyLoadQuery((_FontFamiliesQuery.hash && _FontFamiliesQuery.hash !== "
|
|
27
|
+
} = useLazyLoadQuery((_FontFamiliesQuery.hash && _FontFamiliesQuery.hash !== "1ccff8f69fae99e65e6007bf25e4f8a3" && console.error("The definition of 'FontFamiliesQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _FontFamiliesQuery), {
|
|
28
28
|
collectionId,
|
|
29
29
|
licenseOptions: licenseOptionsSpecs,
|
|
30
30
|
orderVariables: orderVariableSelections
|
|
31
31
|
});
|
|
32
32
|
if (!node) return null;
|
|
33
|
+
// Unlisted collections are only sold through an upgrade – see StoreModalProduct.
|
|
33
34
|
return /*#__PURE__*/React.createElement("div", {
|
|
34
35
|
className: "font-families"
|
|
35
36
|
}, /*#__PURE__*/React.createElement("div", {
|
|
36
37
|
className: "font-families__items"
|
|
37
|
-
}, /*#__PURE__*/React.createElement(Family, {
|
|
38
|
+
}, node.visibility !== 'UNLISTED' && /*#__PURE__*/React.createElement(Family, {
|
|
38
39
|
node: node,
|
|
39
40
|
size: "wide"
|
|
40
|
-
}), (_node$families = node.families) === null || _node$families === void 0 ? void 0 : _node$families.map((family, index) => /*#__PURE__*/React.createElement(Family, {
|
|
41
|
+
}), (_node$families = node.families) === null || _node$families === void 0 ? void 0 : _node$families.filter(family => family.visibility !== 'UNLISTED').map((family, index) => /*#__PURE__*/React.createElement(Family, {
|
|
41
42
|
key: index,
|
|
42
43
|
node: family
|
|
43
44
|
}))));
|
|
@@ -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 !== "
|
|
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
|
|
6
|
-
|
|
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;
|
|
@@ -53,58 +53,50 @@ const allSkus = function (collection) {
|
|
|
53
53
|
}
|
|
54
54
|
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
55
|
};
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
collectionBundles = collection.collectionBundles.reduce((res, collBundle) => ({
|
|
67
|
-
...res,
|
|
68
|
-
...flattenSkuData(collBundle)
|
|
69
|
-
}), {});
|
|
70
|
-
}
|
|
71
|
-
let children = {};
|
|
72
|
-
if ('children' in collection && collection.children) {
|
|
73
|
-
children = collection.children.reduce((res, child) => ({
|
|
74
|
-
...res,
|
|
75
|
-
...flattenSkuData(child)
|
|
76
|
-
}), {});
|
|
77
|
-
}
|
|
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
|
-
};
|
|
56
|
+
|
|
57
|
+
// The styles each SKU grants, by SKU id: a style's SKU grants that style, a
|
|
58
|
+
// bundle its styles, a family its styles, a superfamily its families' styles
|
|
59
|
+
// and a collection bundle its member collections' styles. This is all the
|
|
60
|
+
// selection needs to price any combination of them (see selection.ts).
|
|
61
|
+
|
|
62
|
+
const styleIdsOf = collection => {
|
|
63
|
+
var _collection$fontStyle2, _collection$children2;
|
|
64
|
+
if ('memberCollections' in collection && collection.memberCollections) {
|
|
65
|
+
return collection.memberCollections.flatMap(member => member.fontStyles.map(s => s.id));
|
|
101
66
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
67
|
+
const own = 'fontStyles' in collection ? ((_collection$fontStyle2 = collection.fontStyles) === null || _collection$fontStyle2 === void 0 ? void 0 : _collection$fontStyle2.map(s => s.id)) ?? [] : [];
|
|
68
|
+
const children = 'children' in collection ? ((_collection$children2 = collection.children) === null || _collection$children2 === void 0 ? void 0 : _collection$children2.flatMap(child => {
|
|
69
|
+
var _child$fontStyles;
|
|
70
|
+
return ((_child$fontStyles = child.fontStyles) === null || _child$fontStyles === void 0 ? void 0 : _child$fontStyles.map(s => s.id)) ?? [];
|
|
71
|
+
})) ?? [] : [];
|
|
72
|
+
return [...new Set([...own, ...children])];
|
|
73
|
+
};
|
|
74
|
+
const flattenSkuStyleIds = collection => {
|
|
75
|
+
var _collection$sku;
|
|
76
|
+
const result = {};
|
|
77
|
+
const add = (skuId, styleIds) => {
|
|
78
|
+
// A collection that returns no styles of its own (a superfamily listed as
|
|
79
|
+
// a collection bundle member) says nothing about what it grants.
|
|
80
|
+
if (skuId && styleIds.length > 0) result[skuId] = styleIds;
|
|
107
81
|
};
|
|
82
|
+
const addStyles = fontStyles => {
|
|
83
|
+
for (const style of fontStyles ?? []) {
|
|
84
|
+
var _style$sku;
|
|
85
|
+
add((_style$sku = style.sku) === null || _style$sku === void 0 ? void 0 : _style$sku.id, [style.id]);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
add((_collection$sku = collection.sku) === null || _collection$sku === void 0 ? void 0 : _collection$sku.id, styleIdsOf(collection));
|
|
89
|
+
if ('fontStyles' in collection) addStyles(collection.fontStyles);
|
|
90
|
+
if ('memberCollections' in collection) {
|
|
91
|
+
for (const member of collection.memberCollections ?? []) {
|
|
92
|
+
var _member$sku;
|
|
93
|
+
add((_member$sku = member.sku) === null || _member$sku === void 0 ? void 0 : _member$sku.id, member.fontStyles.map(s => s.id));
|
|
94
|
+
addStyles(member.fontStyles);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const nested = [...('bundles' in collection ? collection.bundles ?? [] : []), ...('collectionBundles' in collection ? collection.collectionBundles ?? [] : []), ...('children' in collection ? collection.children ?? [] : [])];
|
|
98
|
+
for (const child of nested) Object.assign(result, flattenSkuStyleIds(child));
|
|
99
|
+
return result;
|
|
108
100
|
};
|
|
109
101
|
const flattenSkuPrices = collection => {
|
|
110
102
|
return allSkus(collection).reduce((acc, sku) => {
|
|
@@ -122,14 +114,11 @@ export const populateProductStateReducer = (state, action) => {
|
|
|
122
114
|
return {
|
|
123
115
|
...state,
|
|
124
116
|
// {
|
|
125
|
-
// [
|
|
126
|
-
// childrenSkuIds: [skuId...],
|
|
127
|
-
// fontStyleSkuIds: [skuId...],
|
|
128
|
-
// }
|
|
117
|
+
// [skuId]: [styleId...]
|
|
129
118
|
// }
|
|
130
|
-
|
|
131
|
-
...state.
|
|
132
|
-
...
|
|
119
|
+
skuStyleIds: {
|
|
120
|
+
...state.skuStyleIds,
|
|
121
|
+
...flattenSkuStyleIds(data.node)
|
|
133
122
|
},
|
|
134
123
|
// {
|
|
135
124
|
// [skuId]: amount,
|
|
@@ -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 {
|
|
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
|
|
13
|
+
const cost = additionalCost(state, options.sku.id);
|
|
13
14
|
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
if (
|
|
17
|
-
|
|
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 {
|
|
@@ -38,7 +38,7 @@ export default function StoreModalFamily(_ref) {
|
|
|
38
38
|
onSelect,
|
|
39
39
|
title
|
|
40
40
|
} = _ref;
|
|
41
|
-
const collection = useFragment((_StoreModalFamily_collection.hash && _StoreModalFamily_collection.hash !== "
|
|
41
|
+
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);
|
|
42
42
|
const fontStyles = useMemo(() => stylesGrouped(collection), [collection]);
|
|
43
43
|
if ((fontStyles === null || fontStyles === void 0 ? void 0 : fontStyles.length) === 0 && collection.collectionType === 'superfamily' && !collection.sku) return null;
|
|
44
44
|
return /*#__PURE__*/React.createElement(FamilyElement, null, {
|
|
@@ -47,7 +47,9 @@ export default function StoreModalFamily(_ref) {
|
|
|
47
47
|
collection: collection,
|
|
48
48
|
onSelectSku: onSelect
|
|
49
49
|
}),
|
|
50
|
-
|
|
50
|
+
// An unlisted bundle gets no button, but its price still applies as an
|
|
51
|
+
// upgrade: the product state reads every bundle.
|
|
52
|
+
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
53
|
key: bundle.id,
|
|
52
54
|
bundle: bundle,
|
|
53
55
|
onSelectSku: onSelect
|
|
@@ -1,20 +1,61 @@
|
|
|
1
|
+
import _StoreModalIndex_viewer from "../../__generated__/StoreModalIndex_viewer.graphql.js";
|
|
1
2
|
import _StoreModalIndexQuery from "../../__generated__/StoreModalIndexQuery.graphql.js";
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { graphql, usePreloadedQuery } from 'react-relay';
|
|
3
|
+
import React, { useCallback, useContext } from 'react';
|
|
4
|
+
import { graphql, usePaginationFragment, usePreloadedQuery } from 'react-relay';
|
|
4
5
|
import StoreModalPageContainer from '../elements/StoreModalPageContainer/index.js';
|
|
6
|
+
import StoreModalIndexLoadMore from '../elements/StoreModalIndexLoadMore/index.js';
|
|
7
|
+
import StoreModalContainerContext from '../elements/StoreModalContainer/StoreModalContainerContext.js';
|
|
5
8
|
import StoreModalIndexItem from './StoreModalIndexItem.js';
|
|
9
|
+
import useInfiniteScroll from '../useInfiniteScroll.js';
|
|
10
|
+
|
|
11
|
+
// How many collections arrive at a time. Enough that a typical catalogue is one
|
|
12
|
+
// request, few enough that a large one doesn't make the visitor wait for every
|
|
13
|
+
// collection's feature style before anything renders. The GraphQL below can't
|
|
14
|
+
// interpolate, so the same number is written into the query's `$count` default
|
|
15
|
+
// and the fragment's argument definitions — keep the three in step.
|
|
16
|
+
const PAGE_SIZE = 25;
|
|
17
|
+
|
|
18
|
+
// Start the next page while the sentinel is still this far below the modal's
|
|
19
|
+
// visible area, so the pages join up without the visitor reaching a dead end.
|
|
20
|
+
const LOAD_MORE_MARGIN = '0px 0px 600px 0px';
|
|
6
21
|
const StoreModalIndex = _ref => {
|
|
7
|
-
var
|
|
22
|
+
var _data$rootCollections;
|
|
8
23
|
let {
|
|
9
24
|
prepared
|
|
10
25
|
} = _ref;
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
26
|
+
const queryData = usePreloadedQuery((_StoreModalIndexQuery.hash && _StoreModalIndexQuery.hash !== "125a10155b690929f0eae6e9e6c7188c" && console.error("The definition of 'StoreModalIndexQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalIndexQuery), prepared.indexQuery);
|
|
27
|
+
|
|
28
|
+
// The query type only carries the fragment spread, not its data type, so
|
|
29
|
+
// both sides are named explicitly for `data` to be typed.
|
|
30
|
+
const {
|
|
31
|
+
data,
|
|
32
|
+
loadNext,
|
|
33
|
+
hasNext,
|
|
34
|
+
isLoadingNext
|
|
35
|
+
} = usePaginationFragment((_StoreModalIndex_viewer.hash && _StoreModalIndex_viewer.hash !== "f4bd120deb8eea66de4257529cbb022e" && console.error("The definition of 'StoreModalIndex_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalIndex_viewer), queryData.viewer);
|
|
36
|
+
const {
|
|
37
|
+
scrollContainer
|
|
38
|
+
} = useContext(StoreModalContainerContext);
|
|
39
|
+
const handleLoadMore = useCallback(() => {
|
|
40
|
+
// Relay ignores this while a page is already in flight, so the observer
|
|
41
|
+
// firing repeatedly on the way down costs nothing.
|
|
42
|
+
loadNext(PAGE_SIZE);
|
|
43
|
+
}, [loadNext]);
|
|
44
|
+
const sentinelRef = useInfiniteScroll({
|
|
45
|
+
enabled: hasNext && !isLoadingNext,
|
|
46
|
+
onLoadMore: handleLoadMore,
|
|
47
|
+
rootRef: scrollContainer,
|
|
48
|
+
rootMargin: LOAD_MORE_MARGIN
|
|
49
|
+
});
|
|
50
|
+
const edges = (data === null || data === void 0 ? void 0 : (_data$rootCollections = data.rootCollections) === null || _data$rootCollections === void 0 ? void 0 : _data$rootCollections.edges) ?? [];
|
|
14
51
|
return /*#__PURE__*/React.createElement(StoreModalPageContainer, null, {
|
|
15
|
-
body: edges.map(edge => /*#__PURE__*/React.createElement(StoreModalIndexItem, {
|
|
52
|
+
body: /*#__PURE__*/React.createElement(React.Fragment, null, edges.map(edge => /*#__PURE__*/React.createElement(StoreModalIndexItem, {
|
|
16
53
|
collection: edge.node,
|
|
17
54
|
key: edge.node.id
|
|
55
|
+
})), hasNext && /*#__PURE__*/React.createElement(StoreModalIndexLoadMore, {
|
|
56
|
+
sentinelRef: sentinelRef,
|
|
57
|
+
onClick: handleLoadMore,
|
|
58
|
+
loading: isLoadingNext
|
|
18
59
|
}))
|
|
19
60
|
});
|
|
20
61
|
};
|
|
@@ -16,6 +16,7 @@ import ConfigContext from '../ConfigContext.js';
|
|
|
16
16
|
import { useRefetchOnLicenseChanges } from '../../hooks/useRefetchOnLicenseChanges.js';
|
|
17
17
|
import StoreModalLicenseeIsBillingSelection from './StoreModalLicenseeIsBillingSelection.js';
|
|
18
18
|
import { useLicenseAndOrderVariables } from '../../hooks/useLicenseAndOrderVariables.js';
|
|
19
|
+
import { trackProductViewed } from '../Cart/storefrontEvents.js';
|
|
19
20
|
|
|
20
21
|
// A product is addressed by collection id or by slug — the same two
|
|
21
22
|
// identifiers `BuyButton` takes. Two queries rather than one with `@skip`,
|
|
@@ -29,7 +30,7 @@ export const productIdQuery = (_StoreModalProductQuery.hash && _StoreModalProduc
|
|
|
29
30
|
export const productSlugQuery = (_StoreModalProductSlugQuery.hash && _StoreModalProductSlugQuery.hash !== "f0bb35ed9f88ad214b40fd1f3b92fed0" && console.error("The definition of 'StoreModalProductSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalProductSlugQuery);
|
|
30
31
|
const productViewerFragment = (_StoreModalProductViewer.hash && _StoreModalProductViewer.hash !== "3d2fc7da461822a44bb26e9b3f1715fb" && console.error("The definition of 'StoreModalProductViewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalProductViewer);
|
|
31
32
|
const StoreModalProductContent = _ref => {
|
|
32
|
-
var _config$storeModal, _viewer$orderVariable, _viewer$settings, _viewer$settings2, _viewer$settings3, _viewer$settings4, _viewer$settings5, _viewer$settings6, _viewer$settings7, _viewer$settings8
|
|
33
|
+
var _config$storeModal, _viewer$orderVariable, _viewer$settings, _viewer$settings2, _viewer$settings3, _viewer$settings4, _viewer$settings5, _viewer$settings6, _viewer$settings7, _viewer$settings8;
|
|
33
34
|
let {
|
|
34
35
|
collection: collectionRef,
|
|
35
36
|
viewer: viewerRef
|
|
@@ -37,7 +38,7 @@ const StoreModalProductContent = _ref => {
|
|
|
37
38
|
const config = useContext(ConfigContext);
|
|
38
39
|
const environment = useRelayEnvironment();
|
|
39
40
|
const viewer = useFragment(productViewerFragment, viewerRef);
|
|
40
|
-
const [data, refetch] = useRefetchableFragment((_StoreModalProductContent_collection.hash && _StoreModalProductContent_collection.hash !== "
|
|
41
|
+
const [data, refetch] = useRefetchableFragment((_StoreModalProductContent_collection.hash && _StoreModalProductContent_collection.hash !== "f7a9e591b5e1596f4d518fc5d9d46e91" && console.error("The definition of 'StoreModalProductContent_collection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalProductContent_collection), collectionRef ?? null);
|
|
41
42
|
const collection = data;
|
|
42
43
|
const refetchVariables = useMemo(() => collection !== null && collection !== void 0 && collection.id ? {
|
|
43
44
|
id: collection.id
|
|
@@ -60,6 +61,9 @@ const StoreModalProductContent = _ref => {
|
|
|
60
61
|
useEffect(() => {
|
|
61
62
|
if (collection !== null && collection !== void 0 && collection.id) populateProductState(store, environment, collection.id);
|
|
62
63
|
}, [collection === null || collection === void 0 ? void 0 : collection.id]);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (collection !== null && collection !== void 0 && collection.id) trackProductViewed(environment, collection.id);
|
|
66
|
+
}, [collection === null || collection === void 0 ? void 0 : collection.id]);
|
|
63
67
|
useEffect(() => {
|
|
64
68
|
return () => {
|
|
65
69
|
// unselect the skus when this component unmounts,
|
|
@@ -126,6 +130,12 @@ const StoreModalProductContent = _ref => {
|
|
|
126
130
|
__html: ((_viewer$settings8 = viewer.settings) === null || _viewer$settings8 === void 0 ? void 0 : _viewer$settings8.storeModalSelectFontsLabel) ?? ''
|
|
127
131
|
}
|
|
128
132
|
});
|
|
133
|
+
|
|
134
|
+
// An unlisted collection gets no block – no family button, bundles or
|
|
135
|
+
// styles – but stays in the product state, so selecting its siblings can
|
|
136
|
+
// still upgrade to it (an unlisted superfamily) or to a collection bundle
|
|
137
|
+
// containing it (an unlisted variable family).
|
|
138
|
+
const selectableFamilies = [collection, ...(collection.children ?? [])].filter(family => family.visibility !== 'UNLISTED');
|
|
129
139
|
return /*#__PURE__*/React.createElement(StoreModalPageContainer, null, {
|
|
130
140
|
body: /*#__PURE__*/React.createElement(Fragment, null, licensesPosition === 'top' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StoreModalLicenseeIsBillingSelection, {
|
|
131
141
|
disabled: false
|
|
@@ -148,13 +158,10 @@ const StoreModalProductContent = _ref => {
|
|
|
148
158
|
})), /*#__PURE__*/React.createElement("div", {
|
|
149
159
|
className: "store-modal__families",
|
|
150
160
|
"data-disabled": licensesPosition === 'top' ? !anyLicenseOptionsSelected || !hasSelectionForLicenseeIsBillingIdentity || !!requiredOrderVariablesNotYetSelected : false
|
|
151
|
-
}, /*#__PURE__*/React.createElement(StoreModalFamily, {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}), (_collection$children = collection.children) === null || _collection$children === void 0 ? void 0 : _collection$children.map(child => /*#__PURE__*/React.createElement(StoreModalFamily, {
|
|
156
|
-
key: child.id,
|
|
157
|
-
collection: child,
|
|
161
|
+
}, selectableFamilies.map((family, index) => /*#__PURE__*/React.createElement(StoreModalFamily, {
|
|
162
|
+
key: family.id,
|
|
163
|
+
title: index === 0 ? selectFontsLabel : undefined,
|
|
164
|
+
collection: family,
|
|
158
165
|
onSelect: handleSelectProduct
|
|
159
166
|
}))), licensesPosition === 'bottom' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StoreModalLicenseeIsBillingSelection, {
|
|
160
167
|
disabled: !anySkusSelected
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { StoreModalProductLicense_license$key } from '../../__generated__/StoreModalProductLicense_license.graphql.js';
|
|
3
3
|
interface StoreModalProductLicenseProps {
|
|
4
4
|
license: StoreModalProductLicense_license$key;
|
|
5
|
+
collectionId?: string;
|
|
5
6
|
}
|
|
6
|
-
export default function StoreModalProduceLicense({ license: licenseKey, }: StoreModalProductLicenseProps): React.JSX.Element;
|
|
7
|
+
export default function StoreModalProduceLicense({ license: licenseKey, collectionId, }: StoreModalProductLicenseProps): React.JSX.Element;
|
|
7
8
|
export {};
|
|
@@ -6,6 +6,7 @@ import LicenseElement from './LicenseElement.js';
|
|
|
6
6
|
import LicenseVariableElement from './LicenseVariableElement.js';
|
|
7
7
|
import VariableTableAmounts from '../VariableTableAmounts/index.js';
|
|
8
8
|
import LicenseVariableRadioElement from './LicenseVariableRadioElement.js';
|
|
9
|
+
import { useTrackProductCustomized } from '../Cart/storefrontEvents.js';
|
|
9
10
|
const specFromLicense = license => {
|
|
10
11
|
let licenseOptionSpec = {
|
|
11
12
|
licenseId: license.id
|
|
@@ -31,7 +32,8 @@ const specFromLicense = license => {
|
|
|
31
32
|
export default function StoreModalProduceLicense(_ref) {
|
|
32
33
|
var _license$variables;
|
|
33
34
|
let {
|
|
34
|
-
license: licenseKey
|
|
35
|
+
license: licenseKey,
|
|
36
|
+
collectionId
|
|
35
37
|
} = _ref;
|
|
36
38
|
const license = useFragment((_StoreModalProductLicense_license.hash && _StoreModalProductLicense_license.hash !== "87cd41e76dcd8952d7096940a383b9f3" && console.error("The definition of 'StoreModalProductLicense_license' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalProductLicense_license), licenseKey);
|
|
37
39
|
const licenseOptions = useSelector(state => state.licenseOptions);
|
|
@@ -43,6 +45,7 @@ export default function StoreModalProduceLicense(_ref) {
|
|
|
43
45
|
});
|
|
44
46
|
const isSelected = Boolean(selectedOptions);
|
|
45
47
|
const dispatch = useDispatch();
|
|
48
|
+
const trackCustomized = useTrackProductCustomized(collectionId);
|
|
46
49
|
const handleSelectLicense = useCallback(() => {
|
|
47
50
|
var _license$excludedLice;
|
|
48
51
|
dispatch({
|
|
@@ -52,7 +55,8 @@ export default function StoreModalProduceLicense(_ref) {
|
|
|
52
55
|
licenseOptionSpec: specFromLicense(license),
|
|
53
56
|
excludedLicenseIds: (_license$excludedLice = license.excludedLicenses) === null || _license$excludedLice === void 0 ? void 0 : _license$excludedLice.map(l => l.id)
|
|
54
57
|
});
|
|
55
|
-
|
|
58
|
+
trackCustomized();
|
|
59
|
+
}, [dispatch, license, isSelected, trackCustomized]);
|
|
56
60
|
const handleLicenseOptionChange = useCallback(_ref3 => {
|
|
57
61
|
let {
|
|
58
62
|
variableId,
|
|
@@ -72,7 +76,8 @@ export default function StoreModalProduceLicense(_ref) {
|
|
|
72
76
|
variableId,
|
|
73
77
|
optionId
|
|
74
78
|
});
|
|
75
|
-
|
|
79
|
+
trackCustomized();
|
|
80
|
+
}, [dispatch, license, isSelected, trackCustomized]);
|
|
76
81
|
useEffect(() => {
|
|
77
82
|
if (license.defaultSelected) {
|
|
78
83
|
var _license$excludedLice3;
|
|
@@ -11,7 +11,7 @@ export default function StoreModalProductLicenseSelection(_ref) {
|
|
|
11
11
|
label
|
|
12
12
|
}
|
|
13
13
|
} = _ref;
|
|
14
|
-
const collection = useFragment((_StoreModalProductLicenseSelection_collection.hash && _StoreModalProductLicenseSelection_collection.hash !== "
|
|
14
|
+
const collection = useFragment((_StoreModalProductLicenseSelection_collection.hash && _StoreModalProductLicenseSelection_collection.hash !== "c3609e849ae8057e71542d32716f3ddc" && console.error("The definition of 'StoreModalProductLicenseSelection_collection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalProductLicenseSelection_collection), collectionKey);
|
|
15
15
|
return /*#__PURE__*/React.createElement("div", {
|
|
16
16
|
className: "store-modal__license-selection__container",
|
|
17
17
|
"data-disabled": disabled
|
|
@@ -21,6 +21,7 @@ export default function StoreModalProductLicenseSelection(_ref) {
|
|
|
21
21
|
className: "store-modal__license-selection__licenses"
|
|
22
22
|
}, collection === null || collection === void 0 ? void 0 : (_collection$licenses = collection.licenses) === null || _collection$licenses === void 0 ? void 0 : _collection$licenses.map(license => license && /*#__PURE__*/React.createElement(StoreModalProductLicense, {
|
|
23
23
|
key: license.id,
|
|
24
|
-
license: license
|
|
24
|
+
license: license,
|
|
25
|
+
collectionId: collection.id
|
|
25
26
|
}))));
|
|
26
27
|
}
|