fontdue-js 3.8.0 → 3.9.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 +5 -0
- package/README.md +3 -1
- package/dist/__generated__/TestFontsForm_Query.graphql.d.ts +14 -2
- package/dist/__generated__/TestFontsForm_Query.graphql.js +76 -18
- package/dist/__tests__/testFontsFamilyChoice.test.js +150 -0
- package/dist/components/ConfigContext.d.ts +11 -0
- package/dist/components/ConfigContext.js +7 -1
- package/dist/components/TestFontsForm/TestFontsFormElement.d.ts +4 -1
- package/dist/components/TestFontsForm/TestFontsFormElement.js +11 -3
- package/dist/components/TestFontsForm/index.d.ts +6 -3
- package/dist/components/TestFontsForm/index.js +82 -13
- package/dist/components/TestFontsForm/index.server.js +2 -1
- package/dist/components/TestFontsForm/variables.d.ts +8 -0
- package/dist/components/TestFontsForm/variables.js +22 -0
- package/dist/fontdue.css +7 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## 3.9.0
|
|
2
|
+
|
|
3
|
+
- `TestFontsForm` can let the visitor choose which families to download. With *Customer’s choice* set under *Settings → Test fonts* – or `testFonts: { familySelection: "choice" }` in the config, or the `familySelection` prop (`family-selection` on `<fontdue-test-fonts-form>`) – the form lists the families with a checkbox each plus *Select all*, and the download holds only the ticked ones. Ships new stylesheet rules, so take `dist/fontdue.css` from this version alongside the JS.
|
|
4
|
+
- `TestFontsForm` takes `collectionSlug` or `collectionId` (`collection-slug` / `collection-id`, comma-separated for several) to offer just those families, with no checkboxes – for a form on a family’s own page. When preloading, pass the same value to `loadTestFontsFormQuery({ collectionSlug })`; the old options-only call still works.
|
|
5
|
+
|
|
1
6
|
## 3.8.0
|
|
2
7
|
|
|
3
8
|
- Font packs. `StoreModal` lists a store’s packs at the top of its browse page and opens one as a product page, with the same price bar, license picker, cart line and checkout a collection gets. `BuyButton` takes `fontPackId` or `fontPackSlug` in place of `collectionId`/`collectionSlug` – `font-pack-id` or `font-pack-slug` on `<fontdue-buy-button>` – and `?store=product/<pack-slug>` opens a pack directly. Packs honour `indexExcludeTags` the way collections do.
|
package/README.md
CHANGED
|
@@ -842,10 +842,12 @@ import TestFontsForm, { loadTestFontsFormQuery } from "fontdue-js/TestFontsForm"
|
|
|
842
842
|
|
|
843
843
|
| Prop | Description |
|
|
844
844
|
| --- | --- |
|
|
845
|
-
| `preloadedQuery` | (Optional, SSR) Result of `loadTestFontsFormQuery()
|
|
845
|
+
| `preloadedQuery` | (Optional, SSR) Result of `loadTestFontsFormQuery({ collectionSlug, collectionId })` – pass the same collection props as the form. Lazy if omitted. |
|
|
846
846
|
| `agreementLabel` | (Optional) `string` Label for the required agreement checkbox. Defaults to the "EULA agreement text" field in your Fontdue Labels settings. |
|
|
847
847
|
| `downloadLabel` | (Optional) `string` Submit button label. Defaults to `"Download test fonts"`. |
|
|
848
848
|
| `newsletterCheckboxChecked` | (Optional) `boolean` Pre-check the newsletter opt-in. |
|
|
849
|
+
| `collectionSlug` / `collectionId` | (Optional) `string \| string[]` Limit the download to these font collections (a superfamily stands for its families). No family checkboxes are shown. |
|
|
850
|
+
| `familySelection` | (Optional) `'all' \| 'choice'` Overrides `config.testFonts.familySelection` and the dashboard's *Families in each download* setting. `'choice'` lists the families as checkboxes. |
|
|
849
851
|
|
|
850
852
|
## `NewsletterSignup`
|
|
851
853
|
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @generated SignedSource<<
|
|
2
|
+
* @generated SignedSource<<47f718aeae16846330759690c693dce6>>
|
|
3
3
|
* @lightSyntaxTransform
|
|
4
4
|
* @nogrep
|
|
5
5
|
*/
|
|
6
6
|
import { ConcreteRequest } from 'relay-runtime';
|
|
7
|
-
export type TestFontsForm_Query$variables =
|
|
7
|
+
export type TestFontsForm_Query$variables = {
|
|
8
|
+
collectionIds?: ReadonlyArray<string> | null;
|
|
9
|
+
collectionSlugs?: ReadonlyArray<string> | null;
|
|
10
|
+
};
|
|
8
11
|
export type TestFontsForm_Query$data = {
|
|
9
12
|
readonly viewer: {
|
|
13
|
+
readonly fontdueConfig: {
|
|
14
|
+
readonly testFonts: {
|
|
15
|
+
readonly familySelection: string;
|
|
16
|
+
};
|
|
17
|
+
} | null;
|
|
10
18
|
readonly settings: {
|
|
11
19
|
readonly eulaAgreementLabel: string | null;
|
|
12
20
|
readonly newsletterOptInLabel: string | null;
|
|
@@ -15,6 +23,10 @@ export type TestFontsForm_Query$data = {
|
|
|
15
23
|
} | null;
|
|
16
24
|
readonly testFonts: {
|
|
17
25
|
readonly archiveUrl: string | null;
|
|
26
|
+
readonly families: ReadonlyArray<{
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
}>;
|
|
18
30
|
} | null;
|
|
19
31
|
};
|
|
20
32
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @generated SignedSource<<
|
|
2
|
+
* @generated SignedSource<<47f718aeae16846330759690c693dce6>>
|
|
3
3
|
* @lightSyntaxTransform
|
|
4
4
|
* @nogrep
|
|
5
5
|
*/
|
|
@@ -10,11 +10,20 @@
|
|
|
10
10
|
|
|
11
11
|
const node = function () {
|
|
12
12
|
var v0 = [{
|
|
13
|
+
"defaultValue": null,
|
|
14
|
+
"kind": "LocalArgument",
|
|
15
|
+
"name": "collectionIds"
|
|
16
|
+
}, {
|
|
17
|
+
"defaultValue": null,
|
|
18
|
+
"kind": "LocalArgument",
|
|
19
|
+
"name": "collectionSlugs"
|
|
20
|
+
}],
|
|
21
|
+
v1 = [{
|
|
13
22
|
"kind": "Literal",
|
|
14
23
|
"name": "format",
|
|
15
24
|
"value": "HTML"
|
|
16
25
|
}],
|
|
17
|
-
|
|
26
|
+
v2 = {
|
|
18
27
|
"alias": null,
|
|
19
28
|
"args": null,
|
|
20
29
|
"concreteType": "Settings",
|
|
@@ -23,13 +32,13 @@ const node = function () {
|
|
|
23
32
|
"plural": false,
|
|
24
33
|
"selections": [{
|
|
25
34
|
"alias": null,
|
|
26
|
-
"args":
|
|
35
|
+
"args": v1 /*: any*/,
|
|
27
36
|
"kind": "ScalarField",
|
|
28
37
|
"name": "eulaAgreementLabel",
|
|
29
38
|
"storageKey": "eulaAgreementLabel(format:\"HTML\")"
|
|
30
39
|
}, {
|
|
31
40
|
"alias": null,
|
|
32
|
-
"args":
|
|
41
|
+
"args": v1 /*: any*/,
|
|
33
42
|
"kind": "ScalarField",
|
|
34
43
|
"name": "newsletterOptInLabel",
|
|
35
44
|
"storageKey": "newsletterOptInLabel(format:\"HTML\")"
|
|
@@ -48,9 +57,49 @@ const node = function () {
|
|
|
48
57
|
}],
|
|
49
58
|
"storageKey": null
|
|
50
59
|
},
|
|
51
|
-
|
|
60
|
+
v3 = {
|
|
61
|
+
"alias": null,
|
|
62
|
+
"args": null,
|
|
63
|
+
"concreteType": "FontdueConfig",
|
|
64
|
+
"kind": "LinkedField",
|
|
65
|
+
"name": "fontdueConfig",
|
|
66
|
+
"plural": false,
|
|
67
|
+
"selections": [{
|
|
68
|
+
"alias": null,
|
|
69
|
+
"args": null,
|
|
70
|
+
"concreteType": "FontdueTestFontsConfig",
|
|
71
|
+
"kind": "LinkedField",
|
|
72
|
+
"name": "testFonts",
|
|
73
|
+
"plural": false,
|
|
74
|
+
"selections": [{
|
|
75
|
+
"alias": null,
|
|
76
|
+
"args": null,
|
|
77
|
+
"kind": "ScalarField",
|
|
78
|
+
"name": "familySelection",
|
|
79
|
+
"storageKey": null
|
|
80
|
+
}],
|
|
81
|
+
"storageKey": null
|
|
82
|
+
}],
|
|
83
|
+
"storageKey": null
|
|
84
|
+
},
|
|
85
|
+
v4 = {
|
|
52
86
|
"alias": null,
|
|
53
87
|
"args": null,
|
|
88
|
+
"kind": "ScalarField",
|
|
89
|
+
"name": "id",
|
|
90
|
+
"storageKey": null
|
|
91
|
+
},
|
|
92
|
+
v5 = {
|
|
93
|
+
"alias": null,
|
|
94
|
+
"args": [{
|
|
95
|
+
"kind": "Variable",
|
|
96
|
+
"name": "collectionIds",
|
|
97
|
+
"variableName": "collectionIds"
|
|
98
|
+
}, {
|
|
99
|
+
"kind": "Variable",
|
|
100
|
+
"name": "collectionSlugs",
|
|
101
|
+
"variableName": "collectionSlugs"
|
|
102
|
+
}],
|
|
54
103
|
"concreteType": "TestFonts",
|
|
55
104
|
"kind": "LinkedField",
|
|
56
105
|
"name": "testFonts",
|
|
@@ -61,12 +110,27 @@ const node = function () {
|
|
|
61
110
|
"kind": "ScalarField",
|
|
62
111
|
"name": "archiveUrl",
|
|
63
112
|
"storageKey": null
|
|
113
|
+
}, {
|
|
114
|
+
"alias": null,
|
|
115
|
+
"args": null,
|
|
116
|
+
"concreteType": "FontCollection",
|
|
117
|
+
"kind": "LinkedField",
|
|
118
|
+
"name": "families",
|
|
119
|
+
"plural": true,
|
|
120
|
+
"selections": [v4 /*: any*/, {
|
|
121
|
+
"alias": null,
|
|
122
|
+
"args": null,
|
|
123
|
+
"kind": "ScalarField",
|
|
124
|
+
"name": "name",
|
|
125
|
+
"storageKey": null
|
|
126
|
+
}],
|
|
127
|
+
"storageKey": null
|
|
64
128
|
}],
|
|
65
129
|
"storageKey": null
|
|
66
130
|
};
|
|
67
131
|
return {
|
|
68
132
|
"fragment": {
|
|
69
|
-
"argumentDefinitions":
|
|
133
|
+
"argumentDefinitions": v0 /*: any*/,
|
|
70
134
|
"kind": "Fragment",
|
|
71
135
|
"metadata": null,
|
|
72
136
|
"name": "TestFontsForm_Query",
|
|
@@ -77,7 +141,7 @@ const node = function () {
|
|
|
77
141
|
"kind": "LinkedField",
|
|
78
142
|
"name": "viewer",
|
|
79
143
|
"plural": false,
|
|
80
|
-
"selections": [
|
|
144
|
+
"selections": [v2 /*: any*/, v3 /*: any*/, v5 /*: any*/],
|
|
81
145
|
"storageKey": null
|
|
82
146
|
}],
|
|
83
147
|
"type": "RootQueryType",
|
|
@@ -85,7 +149,7 @@ const node = function () {
|
|
|
85
149
|
},
|
|
86
150
|
"kind": "Request",
|
|
87
151
|
"operation": {
|
|
88
|
-
"argumentDefinitions":
|
|
152
|
+
"argumentDefinitions": v0 /*: any*/,
|
|
89
153
|
"kind": "Operation",
|
|
90
154
|
"name": "TestFontsForm_Query",
|
|
91
155
|
"selections": [{
|
|
@@ -95,25 +159,19 @@ const node = function () {
|
|
|
95
159
|
"kind": "LinkedField",
|
|
96
160
|
"name": "viewer",
|
|
97
161
|
"plural": false,
|
|
98
|
-
"selections": [
|
|
99
|
-
"alias": null,
|
|
100
|
-
"args": null,
|
|
101
|
-
"kind": "ScalarField",
|
|
102
|
-
"name": "id",
|
|
103
|
-
"storageKey": null
|
|
104
|
-
}],
|
|
162
|
+
"selections": [v2 /*: any*/, v3 /*: any*/, v5 /*: any*/, v4 /*: any*/],
|
|
105
163
|
"storageKey": null
|
|
106
164
|
}]
|
|
107
165
|
},
|
|
108
166
|
"params": {
|
|
109
|
-
"cacheID": "
|
|
167
|
+
"cacheID": "42a58842afe113b89a0bc969738246a8",
|
|
110
168
|
"id": null,
|
|
111
169
|
"metadata": {},
|
|
112
170
|
"name": "TestFontsForm_Query",
|
|
113
171
|
"operationKind": "query",
|
|
114
|
-
"text": "query TestFontsForm_Query {\n viewer {\n settings {\n eulaAgreementLabel(format: HTML)\n newsletterOptInLabel(format: HTML)\n recaptchaEnabled\n recaptchaSiteKey\n }\n testFonts {\n archiveUrl\n }\n id\n }\n}\n"
|
|
172
|
+
"text": "query TestFontsForm_Query(\n $collectionIds: [ID!]\n $collectionSlugs: [String!]\n) {\n viewer {\n settings {\n eulaAgreementLabel(format: HTML)\n newsletterOptInLabel(format: HTML)\n recaptchaEnabled\n recaptchaSiteKey\n }\n fontdueConfig {\n testFonts {\n familySelection\n }\n }\n testFonts(collectionIds: $collectionIds, collectionSlugs: $collectionSlugs) {\n archiveUrl\n families {\n id\n name\n }\n }\n id\n }\n}\n"
|
|
115
173
|
}
|
|
116
174
|
};
|
|
117
175
|
}();
|
|
118
|
-
node.hash = "
|
|
176
|
+
node.hash = "da75e312a602ac0ee2dfb79271299c77";
|
|
119
177
|
export default node;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
// The test fonts form's family choice (FD-28): the archive endpoint takes
|
|
4
|
+
// `collection_ids[]` to narrow the ZIP, and the form fills it from checkboxes
|
|
5
|
+
// (`familySelection: 'choice'`) or from its own `collectionId`/`collectionSlug`.
|
|
6
|
+
|
|
7
|
+
import React, { act } from 'react';
|
|
8
|
+
import { createRoot } from 'react-dom/client';
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
10
|
+
const {
|
|
11
|
+
queryRef
|
|
12
|
+
} = vi.hoisted(() => ({
|
|
13
|
+
queryRef: {
|
|
14
|
+
data: null,
|
|
15
|
+
variables: null
|
|
16
|
+
}
|
|
17
|
+
}));
|
|
18
|
+
vi.mock('react-relay', () => ({
|
|
19
|
+
graphql: () => null,
|
|
20
|
+
commitMutation: vi.fn(),
|
|
21
|
+
useRelayEnvironment: () => ({}),
|
|
22
|
+
usePreloadedQuery: () => queryRef.data,
|
|
23
|
+
useLazyLoadQuery: (_query, variables) => {
|
|
24
|
+
queryRef.variables = variables;
|
|
25
|
+
return queryRef.data;
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
vi.mock('../components/FontdueContextProvider/index.js', () => ({
|
|
29
|
+
EnsureFontdueContext: _ref => {
|
|
30
|
+
let {
|
|
31
|
+
children
|
|
32
|
+
} = _ref;
|
|
33
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
34
|
+
},
|
|
35
|
+
LazyQueryBoundary: _ref2 => {
|
|
36
|
+
let {
|
|
37
|
+
children
|
|
38
|
+
} = _ref2;
|
|
39
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
import TestFontsForm from '../components/TestFontsForm/index.js';
|
|
43
|
+
import ConfigContext, { makeConfig } from '../components/ConfigContext.js';
|
|
44
|
+
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
45
|
+
const families = [{
|
|
46
|
+
id: 'RmFtaWx5OjE=',
|
|
47
|
+
name: 'Alpha'
|
|
48
|
+
}, {
|
|
49
|
+
id: 'RmFtaWx5OjI=',
|
|
50
|
+
name: 'Beta'
|
|
51
|
+
}];
|
|
52
|
+
const viewer = function (familySelection) {
|
|
53
|
+
let list = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : families;
|
|
54
|
+
return {
|
|
55
|
+
viewer: {
|
|
56
|
+
settings: {
|
|
57
|
+
eulaAgreementLabel: 'I agree',
|
|
58
|
+
newsletterOptInLabel: null,
|
|
59
|
+
recaptchaEnabled: false,
|
|
60
|
+
recaptchaSiteKey: null
|
|
61
|
+
},
|
|
62
|
+
fontdueConfig: {
|
|
63
|
+
testFonts: {
|
|
64
|
+
familySelection
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
testFonts: {
|
|
68
|
+
archiveUrl: 'https://example.test/test-fonts/archive',
|
|
69
|
+
families: list
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
let container;
|
|
75
|
+
let root;
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
container = document.createElement('div');
|
|
78
|
+
document.body.append(container);
|
|
79
|
+
root = createRoot(container);
|
|
80
|
+
});
|
|
81
|
+
afterEach(() => {
|
|
82
|
+
act(() => root.unmount());
|
|
83
|
+
container.remove();
|
|
84
|
+
});
|
|
85
|
+
const render = function () {
|
|
86
|
+
let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
87
|
+
let config = arguments.length > 1 ? arguments[1] : undefined;
|
|
88
|
+
return act(() => root.render( /*#__PURE__*/React.createElement(ConfigContext.Provider, {
|
|
89
|
+
value: makeConfig(config)
|
|
90
|
+
}, /*#__PURE__*/React.createElement(TestFontsForm, props))));
|
|
91
|
+
};
|
|
92
|
+
const familyCheckboxes = () => [...container.querySelectorAll('.test-fonts__family input')];
|
|
93
|
+
const hiddenIds = () => [...container.querySelectorAll('input[type="hidden"]')].filter(input => input.name === 'collection_ids[]').map(input => input.value);
|
|
94
|
+
describe('TestFontsForm family choice', () => {
|
|
95
|
+
it('downloads everything without checkboxes by default', () => {
|
|
96
|
+
queryRef.data = viewer('all');
|
|
97
|
+
render();
|
|
98
|
+
expect(familyCheckboxes()).toHaveLength(0);
|
|
99
|
+
expect(hiddenIds()).toEqual([]);
|
|
100
|
+
expect(queryRef.variables).toEqual({
|
|
101
|
+
collectionIds: null,
|
|
102
|
+
collectionSlugs: null
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
it('lists the families when the dashboard says choice, and sends the ticked ones', () => {
|
|
106
|
+
queryRef.data = viewer('choice');
|
|
107
|
+
render();
|
|
108
|
+
expect(familyCheckboxes().map(box => box.value)).toEqual(families.map(f => f.id));
|
|
109
|
+
expect(container.textContent).toContain('Beta');
|
|
110
|
+
expect(hiddenIds()).toEqual([]);
|
|
111
|
+
act(() => familyCheckboxes()[1].click());
|
|
112
|
+
expect(hiddenIds()).toEqual(['RmFtaWx5OjI=']);
|
|
113
|
+
act(() => container.querySelector('.test-fonts__families__all input').click());
|
|
114
|
+
expect(hiddenIds()).toEqual(families.map(f => f.id));
|
|
115
|
+
});
|
|
116
|
+
it('lets code config and the prop override the dashboard setting', () => {
|
|
117
|
+
queryRef.data = viewer('choice');
|
|
118
|
+
render({}, {
|
|
119
|
+
testFonts: {
|
|
120
|
+
familySelection: 'all'
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
expect(familyCheckboxes()).toHaveLength(0);
|
|
124
|
+
queryRef.data = viewer('all');
|
|
125
|
+
render({
|
|
126
|
+
familySelection: 'choice'
|
|
127
|
+
});
|
|
128
|
+
expect(familyCheckboxes()).toHaveLength(2);
|
|
129
|
+
});
|
|
130
|
+
it('downloads exactly the named collections without checkboxes', () => {
|
|
131
|
+
queryRef.data = viewer('choice', [families[0]]);
|
|
132
|
+
render({
|
|
133
|
+
collectionSlug: 'alpha, gamma'
|
|
134
|
+
});
|
|
135
|
+
expect(queryRef.variables).toEqual({
|
|
136
|
+
collectionIds: null,
|
|
137
|
+
collectionSlugs: ['alpha', 'gamma']
|
|
138
|
+
});
|
|
139
|
+
expect(familyCheckboxes()).toHaveLength(0);
|
|
140
|
+
expect(hiddenIds()).toEqual(['RmFtaWx5OjE=']);
|
|
141
|
+
});
|
|
142
|
+
it('says so when the named collections have no test fonts', () => {
|
|
143
|
+
queryRef.data = viewer('all', []);
|
|
144
|
+
render({
|
|
145
|
+
collectionId: 'RmFtaWx5Ojk='
|
|
146
|
+
});
|
|
147
|
+
expect(container.querySelector('form')).toBeNull();
|
|
148
|
+
expect(container.textContent).toContain('Test fonts aren’t available for this family.');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -28,8 +28,13 @@ interface PreviewConfig {
|
|
|
28
28
|
revalidateEndpoint?: string;
|
|
29
29
|
clientSide?: boolean;
|
|
30
30
|
}
|
|
31
|
+
export type TestFontsFamilySelection = 'all' | 'choice';
|
|
32
|
+
interface TestFontsConfig {
|
|
33
|
+
familySelection?: TestFontsFamilySelection;
|
|
34
|
+
}
|
|
31
35
|
export interface Config {
|
|
32
36
|
form?: FormConfig;
|
|
37
|
+
testFonts?: TestFontsConfig;
|
|
33
38
|
storeModal?: StoreModalConfig;
|
|
34
39
|
typeTester?: TypeTesterConfig;
|
|
35
40
|
stripe?: StripeConfig;
|
|
@@ -94,6 +99,9 @@ export declare const makeConfig: (config?: Config) => {
|
|
|
94
99
|
form: {
|
|
95
100
|
checkboxStyle: "check" | "cross";
|
|
96
101
|
};
|
|
102
|
+
testFonts: {
|
|
103
|
+
familySelection: TestFontsFamilySelection | undefined;
|
|
104
|
+
};
|
|
97
105
|
storeModal: {
|
|
98
106
|
indexLayout: "styled-aa" | "styled-font-names";
|
|
99
107
|
indexExcludeTags: string[] | undefined;
|
|
@@ -172,6 +180,9 @@ declare const _default: React.Context<{
|
|
|
172
180
|
form: {
|
|
173
181
|
checkboxStyle: "check" | "cross";
|
|
174
182
|
};
|
|
183
|
+
testFonts: {
|
|
184
|
+
familySelection: TestFontsFamilySelection | undefined;
|
|
185
|
+
};
|
|
175
186
|
storeModal: {
|
|
176
187
|
indexLayout: "styled-aa" | "styled-font-names";
|
|
177
188
|
indexExcludeTags: string[] | undefined;
|
|
@@ -88,12 +88,18 @@ export const mergeConfig = (base, override) => {
|
|
|
88
88
|
return deepMerge(base, override);
|
|
89
89
|
};
|
|
90
90
|
export const makeConfig = config => {
|
|
91
|
-
var _config$form, _config$storeModal, _config$storeModal2, _config$storeModal3, _config$storeModal4, _config$stripe, _config$tracking, _config$tracking2, _config$tracking3, _config$tracking4, _config$preview, _config$preview2, _config$preview3;
|
|
91
|
+
var _config$form, _config$testFonts, _config$storeModal, _config$storeModal2, _config$storeModal3, _config$storeModal4, _config$stripe, _config$tracking, _config$tracking2, _config$tracking3, _config$tracking4, _config$preview, _config$preview2, _config$preview3;
|
|
92
92
|
return {
|
|
93
93
|
typeTester: makeTypeTesterConfig(config === null || config === void 0 ? void 0 : config.typeTester),
|
|
94
94
|
form: {
|
|
95
95
|
checkboxStyle: (config === null || config === void 0 ? void 0 : (_config$form = config.form) === null || _config$form === void 0 ? void 0 : _config$form.checkboxStyle) ?? 'check'
|
|
96
96
|
},
|
|
97
|
+
testFonts: {
|
|
98
|
+
// Deliberately no default: the form falls back to the dashboard setting
|
|
99
|
+
// it reads in its own query (the npm path never merges server config
|
|
100
|
+
// into `children`'s context – see ServerConfigProvider).
|
|
101
|
+
familySelection: config === null || config === void 0 ? void 0 : (_config$testFonts = config.testFonts) === null || _config$testFonts === void 0 ? void 0 : _config$testFonts.familySelection
|
|
102
|
+
},
|
|
97
103
|
storeModal: {
|
|
98
104
|
indexLayout: (config === null || config === void 0 ? void 0 : (_config$storeModal = config.storeModal) === null || _config$storeModal === void 0 ? void 0 : _config$storeModal.indexLayout) ?? 'styled-aa',
|
|
99
105
|
indexExcludeTags: config === null || config === void 0 ? void 0 : (_config$storeModal2 = config.storeModal) === null || _config$storeModal2 === void 0 ? void 0 : _config$storeModal2.indexExcludeTags,
|
|
@@ -3,6 +3,9 @@ interface TestFontsFormElement_props {
|
|
|
3
3
|
agreementLabel?: string;
|
|
4
4
|
downloadLabel?: string;
|
|
5
5
|
newsletterCheckboxChecked?: string;
|
|
6
|
+
collectionId?: string;
|
|
7
|
+
collectionSlug?: string;
|
|
8
|
+
familySelection?: string;
|
|
6
9
|
}
|
|
7
|
-
declare const TestFontsFormElement: (props: TestFontsFormElement_props) => React.JSX.Element;
|
|
10
|
+
declare const TestFontsFormElement: ({ familySelection, ...props }: TestFontsFormElement_props) => React.JSX.Element;
|
|
8
11
|
export default TestFontsFormElement;
|
|
@@ -1,7 +1,15 @@
|
|
|
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 TestFontsFormFetcher from './index.js';
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const FAMILY_SELECTIONS = ['all', 'choice'];
|
|
5
|
+
const TestFontsFormElement = _ref => {
|
|
6
|
+
let {
|
|
7
|
+
familySelection,
|
|
8
|
+
...props
|
|
9
|
+
} = _ref;
|
|
10
|
+
return /*#__PURE__*/React.createElement(TestFontsFormFetcher, _extends({}, props, {
|
|
11
|
+
familySelection: familySelection && FAMILY_SELECTIONS.includes(familySelection) ? familySelection : undefined,
|
|
12
|
+
newsletterCheckboxChecked: props.newsletterCheckboxChecked === 'true' ? true : false
|
|
13
|
+
}));
|
|
14
|
+
};
|
|
7
15
|
export default TestFontsFormElement;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TestFontsForm_Query } from '../../__generated__/TestFontsForm_Query.graphql.js';
|
|
3
3
|
import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
|
|
4
|
-
import { Config } from '../ConfigContext.js';
|
|
5
|
-
|
|
4
|
+
import { Config, TestFontsFamilySelection } from '../ConfigContext.js';
|
|
5
|
+
import { TestFontsFormCollectionProps } from './variables.js';
|
|
6
|
+
export interface TestFontsForm_props extends TestFontsFormCollectionProps {
|
|
6
7
|
agreementLabel?: string;
|
|
7
8
|
downloadLabel?: string;
|
|
8
9
|
newsletterCheckboxChecked?: boolean;
|
|
10
|
+
familySelection?: TestFontsFamilySelection;
|
|
9
11
|
}
|
|
10
12
|
export type TestFontsFormPreloadedQuery = SerializablePreloadedQuery<TestFontsForm_Query>;
|
|
11
|
-
export
|
|
13
|
+
export type LoadTestFontsFormQueryVariables = TestFontsFormCollectionProps;
|
|
14
|
+
export declare function loadTestFontsFormQuery(variables?: LoadTestFontsFormQueryVariables | LoadQueryOptions, options?: LoadQueryOptions): Promise<TestFontsFormPreloadedQuery>;
|
|
12
15
|
export declare function TestFontsFormPreloadedQueryRenderer({ preloadedQuery, ...rest }: TestFontsForm_props & {
|
|
13
16
|
preloadedQuery: TestFontsFormPreloadedQuery;
|
|
14
17
|
}): React.JSX.Element;
|
|
@@ -3,7 +3,7 @@
|
|
|
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
4
|
import _TestFontsForm_Query from "../../__generated__/TestFontsForm_Query.graphql.js";
|
|
5
5
|
import _TestFontsFormUpdateCustomerMutation from "../../__generated__/TestFontsFormUpdateCustomerMutation.graphql.js";
|
|
6
|
-
import React, { useState, useRef, useCallback } from 'react';
|
|
6
|
+
import React, { useState, useRef, useCallback, useContext, useId } from 'react';
|
|
7
7
|
import { commitMutation, graphql, useRelayEnvironment, useLazyLoadQuery, usePreloadedQuery } from 'react-relay';
|
|
8
8
|
// The script-injecting reCAPTCHA wrapper (loads Google's api.js). Importing the
|
|
9
9
|
// package's barebone named export instead was the FD-917 root cause; see
|
|
@@ -16,8 +16,18 @@ import Checkbox from '../Checkbox/index.js';
|
|
|
16
16
|
import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
|
|
17
17
|
import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQuery.js';
|
|
18
18
|
import { EnsureFontdueContext, LazyQueryBoundary } from '../FontdueContextProvider/index.js';
|
|
19
|
+
import ConfigContext from '../ConfigContext.js';
|
|
20
|
+
import { testFontsFormQueryVariables } from './variables.js';
|
|
19
21
|
import { useRecaptchaTimeout, isRecaptchaScriptLoaded, RECAPTCHA_UNAVAILABLE_MESSAGE } from '../../hooks/useRecaptchaTimeout.js';
|
|
20
22
|
const updateCustomerMutation = (_TestFontsFormUpdateCustomerMutation.hash && _TestFontsFormUpdateCustomerMutation.hash !== "ba56958399f0893bd667ff02c33a6975" && console.error("The definition of 'TestFontsFormUpdateCustomerMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _TestFontsFormUpdateCustomerMutation);
|
|
23
|
+
// The archive endpoint's family filter: `collection_ids[]` narrows the ZIP to
|
|
24
|
+
// those families; none means every family.
|
|
25
|
+
const COLLECTION_IDS_PARAM = 'collection_ids[]';
|
|
26
|
+
const withCollectionIds = (archiveUrl, collectionIds) => {
|
|
27
|
+
if (collectionIds.length === 0) return archiveUrl;
|
|
28
|
+
const query = new URLSearchParams(collectionIds.map(id => [COLLECTION_IDS_PARAM, id]));
|
|
29
|
+
return `${archiveUrl}${archiveUrl.includes('?') ? '&' : '?'}${query}`;
|
|
30
|
+
};
|
|
21
31
|
const TestFontsDownloading = _ref => {
|
|
22
32
|
let {
|
|
23
33
|
archiveUrl
|
|
@@ -31,12 +41,15 @@ const TestFontsDownloading = _ref => {
|
|
|
31
41
|
}, "here"), ".")));
|
|
32
42
|
};
|
|
33
43
|
const TestFontsFormComponent = _ref2 => {
|
|
34
|
-
var _data$viewer$settings, _data$viewer$settings2, _data$viewer$
|
|
44
|
+
var _data$viewer$testFont, _data$viewer$fontdueC, _data$viewer$settings, _data$viewer$settings2, _data$viewer$testFont2;
|
|
35
45
|
let {
|
|
36
46
|
data,
|
|
37
47
|
agreementLabel,
|
|
38
48
|
downloadLabel = 'Download test fonts',
|
|
39
|
-
newsletterCheckboxChecked = false
|
|
49
|
+
newsletterCheckboxChecked = false,
|
|
50
|
+
collectionId,
|
|
51
|
+
collectionSlug,
|
|
52
|
+
familySelection: familySelectionProp
|
|
40
53
|
} = _ref2;
|
|
41
54
|
const [email, setEmail] = useState('');
|
|
42
55
|
const [name, setName] = useState('');
|
|
@@ -52,7 +65,28 @@ const TestFontsFormComponent = _ref2 => {
|
|
|
52
65
|
const recaptchaRef = useRef(null);
|
|
53
66
|
const recaptchaTimeout = useRecaptchaTimeout();
|
|
54
67
|
const environment = useRelayEnvironment();
|
|
68
|
+
const config = useContext(ConfigContext);
|
|
69
|
+
const idPrefix = useId();
|
|
70
|
+
const [chosenIds, setChosenIds] = useState([]);
|
|
55
71
|
if (!data.viewer) return null;
|
|
72
|
+
const families = ((_data$viewer$testFont = data.viewer.testFonts) === null || _data$viewer$testFont === void 0 ? void 0 : _data$viewer$testFont.families) ?? [];
|
|
73
|
+
const {
|
|
74
|
+
collectionIds,
|
|
75
|
+
collectionSlugs
|
|
76
|
+
} = testFontsFormQueryVariables({
|
|
77
|
+
collectionId,
|
|
78
|
+
collectionSlug
|
|
79
|
+
});
|
|
80
|
+
// A form for particular collections downloads exactly those families.
|
|
81
|
+
const limited = collectionIds != null || collectionSlugs != null;
|
|
82
|
+
// This form's prop, then code config (which, on the script-tag path, already
|
|
83
|
+
// has the dashboard setting merged beneath it), then the dashboard setting.
|
|
84
|
+
const familySelection = familySelectionProp ?? config.testFonts.familySelection ?? ((_data$viewer$fontdueC = data.viewer.fontdueConfig) === null || _data$viewer$fontdueC === void 0 ? void 0 : _data$viewer$fontdueC.testFonts.familySelection) ?? 'all';
|
|
85
|
+
// One family leaves nothing to choose.
|
|
86
|
+
const choosing = !limited && familySelection === 'choice' && families.length > 1;
|
|
87
|
+
const downloadIds = limited ? families.map(family => family.id) : choosing ? families.map(family => family.id).filter(id => chosenIds.includes(id)) : [];
|
|
88
|
+
const toggleFamily = (id, checked) => setChosenIds(ids => checked ? [...ids, id] : ids.filter(other => other !== id));
|
|
89
|
+
const allChosen = families.every(family => chosenIds.includes(family.id));
|
|
56
90
|
const recaptchaEnabled = ((_data$viewer$settings = data.viewer.settings) === null || _data$viewer$settings === void 0 ? void 0 : _data$viewer$settings.recaptchaEnabled) ?? false;
|
|
57
91
|
const recaptchaSiteKey = (_data$viewer$settings2 = data.viewer.settings) === null || _data$viewer$settings2 === void 0 ? void 0 : _data$viewer$settings2.recaptchaSiteKey;
|
|
58
92
|
const submitForm = useCallback(token => {
|
|
@@ -151,23 +185,48 @@ const TestFontsFormComponent = _ref2 => {
|
|
|
151
185
|
}
|
|
152
186
|
submitForm(recaptchaToken);
|
|
153
187
|
};
|
|
154
|
-
|
|
155
|
-
// Button is disabled only while actively submitting or waiting for reCAPTCHA
|
|
156
|
-
const disabled = !eulaAgreed || !email || !name;
|
|
188
|
+
const disabled = !eulaAgreed || !email || !name || choosing && downloadIds.length === 0;
|
|
157
189
|
const settings = data.viewer.settings;
|
|
158
190
|
const newsletterOptInLabel = settings === null || settings === void 0 ? void 0 : settings.newsletterOptInLabel;
|
|
159
191
|
const eulaAgreementLabel = settings === null || settings === void 0 ? void 0 : settings.eulaAgreementLabel;
|
|
160
|
-
const archiveUrl = (_data$viewer$
|
|
192
|
+
const archiveUrl = (_data$viewer$testFont2 = data.viewer.testFonts) === null || _data$viewer$testFont2 === void 0 ? void 0 : _data$viewer$testFont2.archiveUrl;
|
|
193
|
+
if (limited && families.length === 0) {
|
|
194
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
195
|
+
className: "test-fonts test-fonts--unavailable"
|
|
196
|
+
}, /*#__PURE__*/React.createElement("p", null, "Test fonts aren\u2019t available for this family."));
|
|
197
|
+
}
|
|
161
198
|
return /*#__PURE__*/React.createElement("div", {
|
|
162
199
|
className: "test-fonts"
|
|
163
200
|
}, error && /*#__PURE__*/React.createElement("div", {
|
|
164
201
|
className: "test-fonts__errors"
|
|
165
202
|
}, error), submitted ? /*#__PURE__*/React.createElement(TestFontsDownloading, {
|
|
166
|
-
archiveUrl: archiveUrl
|
|
203
|
+
archiveUrl: withCollectionIds(archiveUrl, downloadIds)
|
|
167
204
|
}) : /*#__PURE__*/React.createElement("form", {
|
|
168
205
|
className: "test-fonts__form",
|
|
169
206
|
onSubmit: handleSubmit
|
|
207
|
+
}, choosing && /*#__PURE__*/React.createElement("div", {
|
|
208
|
+
className: "test-fonts__section test-fonts__families",
|
|
209
|
+
role: "group",
|
|
210
|
+
"aria-label": "Families"
|
|
170
211
|
}, /*#__PURE__*/React.createElement("div", {
|
|
212
|
+
className: "test-fonts__checkbox-field test-fonts__families__all"
|
|
213
|
+
}, /*#__PURE__*/React.createElement(Checkbox, {
|
|
214
|
+
id: `${idPrefix}-families-all`,
|
|
215
|
+
checked: allChosen,
|
|
216
|
+
onChange: event => setChosenIds(event.target.checked ? families.map(family => family.id) : [])
|
|
217
|
+
}), /*#__PURE__*/React.createElement("label", {
|
|
218
|
+
htmlFor: `${idPrefix}-families-all`
|
|
219
|
+
}, "Select all")), families.map((family, index) => /*#__PURE__*/React.createElement("div", {
|
|
220
|
+
className: "test-fonts__checkbox-field test-fonts__family",
|
|
221
|
+
key: family.id
|
|
222
|
+
}, /*#__PURE__*/React.createElement(Checkbox, {
|
|
223
|
+
id: `${idPrefix}-family-${index}`,
|
|
224
|
+
value: family.id,
|
|
225
|
+
checked: chosenIds.includes(family.id),
|
|
226
|
+
onChange: event => toggleFamily(family.id, event.target.checked)
|
|
227
|
+
}), /*#__PURE__*/React.createElement("label", {
|
|
228
|
+
htmlFor: `${idPrefix}-family-${index}`
|
|
229
|
+
}, family.name)))), /*#__PURE__*/React.createElement("div", {
|
|
171
230
|
className: "test-fonts__section"
|
|
172
231
|
}, /*#__PURE__*/React.createElement(TextField, {
|
|
173
232
|
label: "Name *",
|
|
@@ -223,11 +282,21 @@ const TestFontsFormComponent = _ref2 => {
|
|
|
223
282
|
}, " \u2192")))), /*#__PURE__*/React.createElement("form", {
|
|
224
283
|
action: archiveUrl ?? undefined,
|
|
225
284
|
ref: downloadForm
|
|
226
|
-
}
|
|
285
|
+
}, downloadIds.map(id => /*#__PURE__*/React.createElement("input", {
|
|
286
|
+
key: id,
|
|
287
|
+
type: "hidden",
|
|
288
|
+
name: COLLECTION_IDS_PARAM,
|
|
289
|
+
value: id
|
|
290
|
+
}))));
|
|
227
291
|
};
|
|
228
|
-
const query = (_TestFontsForm_Query.hash && _TestFontsForm_Query.hash !== "
|
|
229
|
-
|
|
230
|
-
|
|
292
|
+
const query = (_TestFontsForm_Query.hash && _TestFontsForm_Query.hash !== "da75e312a602ac0ee2dfb79271299c77" && console.error("The definition of 'TestFontsForm_Query' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _TestFontsForm_Query);
|
|
293
|
+
// Pass the same `collectionId` / `collectionSlug` as the form's props.
|
|
294
|
+
export async function loadTestFontsFormQuery(variables, options) {
|
|
295
|
+
// Before the collection variables existed this took `options` alone.
|
|
296
|
+
if (variables && ('url' in variables || 'headers' in variables)) {
|
|
297
|
+
return loadTestFontsFormQuery({}, variables);
|
|
298
|
+
}
|
|
299
|
+
return loadSerializableQuery(TestFontsFormQueryNode, testFontsFormQueryVariables(variables ?? {}), options);
|
|
231
300
|
}
|
|
232
301
|
export function TestFontsFormPreloadedQueryRenderer(_ref4) {
|
|
233
302
|
let {
|
|
@@ -244,7 +313,7 @@ export function TestFontsFormPreloadedQueryRenderer(_ref4) {
|
|
|
244
313
|
}, rest));
|
|
245
314
|
}
|
|
246
315
|
function TestFontsFormLazyQueryRenderer(props) {
|
|
247
|
-
const data = useLazyLoadQuery(query,
|
|
316
|
+
const data = useLazyLoadQuery(query, testFontsFormQueryVariables(props));
|
|
248
317
|
return /*#__PURE__*/React.createElement(TestFontsFormComponent, _extends({
|
|
249
318
|
data: data
|
|
250
319
|
}, props));
|
|
@@ -2,6 +2,7 @@ function _extends() { return _extends = Object.assign ? Object.assign.bind() : f
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
|
|
4
4
|
import { TestFontsFormPreloadedQueryRenderer } from './index.js';
|
|
5
|
+
import { testFontsFormQueryVariables } from './variables.js';
|
|
5
6
|
import TestFontsFormQueryNode from '../../__generated__/TestFontsForm_Query.graphql.js';
|
|
6
7
|
// Stub for the RSC export condition. See FontdueProvider/index.server.tsx
|
|
7
8
|
// for the rationale.
|
|
@@ -14,7 +15,7 @@ export function loadTestFontsFormQuery() {
|
|
|
14
15
|
// `<TestFontsForm />` in an RSC without manually invoking
|
|
15
16
|
// `loadTestFontsFormQuery` + threading `preloadedQuery` through props.
|
|
16
17
|
export default async function TestFontsForm(props) {
|
|
17
|
-
const preloadedQuery = await loadSerializableQuery(TestFontsFormQueryNode,
|
|
18
|
+
const preloadedQuery = await loadSerializableQuery(TestFontsFormQueryNode, testFontsFormQueryVariables(props));
|
|
18
19
|
return /*#__PURE__*/React.createElement(TestFontsFormPreloadedQueryRenderer, _extends({
|
|
19
20
|
preloadedQuery: preloadedQuery
|
|
20
21
|
}, props));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TestFontsFormCollectionProps {
|
|
2
|
+
collectionId?: string | readonly string[];
|
|
3
|
+
collectionSlug?: string | readonly string[];
|
|
4
|
+
}
|
|
5
|
+
export declare const testFontsFormQueryVariables: ({ collectionId, collectionSlug, }: TestFontsFormCollectionProps) => {
|
|
6
|
+
collectionIds: string[] | null;
|
|
7
|
+
collectionSlugs: string[] | null;
|
|
8
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Shared by the client component and the RSC entry (index.server.tsx), so it
|
|
2
|
+
// lives outside the 'use client' module: a server component can't call a
|
|
3
|
+
// function imported from one.
|
|
4
|
+
|
|
5
|
+
const toList = value => {
|
|
6
|
+
if (value == null) return null;
|
|
7
|
+
const list = (typeof value === 'string' ? value.split(',') : [...value]).map(item => item.trim()).filter(Boolean);
|
|
8
|
+
return list.length > 0 ? list : null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// The query's variables for a form's collection props: null (no narrowing)
|
|
12
|
+
// unless the form is limited to particular collections.
|
|
13
|
+
export const testFontsFormQueryVariables = _ref => {
|
|
14
|
+
let {
|
|
15
|
+
collectionId,
|
|
16
|
+
collectionSlug
|
|
17
|
+
} = _ref;
|
|
18
|
+
return {
|
|
19
|
+
collectionIds: toList(collectionId),
|
|
20
|
+
collectionSlugs: toList(collectionSlug)
|
|
21
|
+
};
|
|
22
|
+
};
|
package/dist/fontdue.css
CHANGED
|
@@ -182,6 +182,13 @@
|
|
|
182
182
|
.test-fonts__checkbox-field label p {
|
|
183
183
|
margin: 0;
|
|
184
184
|
}
|
|
185
|
+
.test-fonts__families {
|
|
186
|
+
--checkbox-size: 20px;
|
|
187
|
+
--checkbox-margin: 10px;
|
|
188
|
+
}
|
|
189
|
+
.test-fonts__families .test-fonts__checkbox-field {
|
|
190
|
+
margin-bottom: 10px;
|
|
191
|
+
}
|
|
185
192
|
.test-fonts__agreement[data-highlighted=true] {
|
|
186
193
|
color: red;
|
|
187
194
|
}
|
package/dist/version.js
CHANGED