fontdue-js 3.8.0 → 3.10.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 +11 -0
- package/README.md +3 -1
- package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.d.ts +10 -1
- package/dist/__generated__/StoreModalIndexItem_fontCollection.graphql.js +45 -35
- package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalIndexPaginationQuery.graphql.js +101 -93
- package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +3 -1
- package/dist/__generated__/StoreModalIndexQuery.graphql.js +24 -17
- package/dist/__generated__/TestFontsForm_Query.graphql.d.ts +14 -2
- package/dist/__generated__/TestFontsForm_Query.graphql.js +76 -18
- package/dist/__tests__/storeModalIndexUnlisted.test.js +71 -0
- package/dist/__tests__/testFontsFamilyChoice.test.js +150 -0
- package/dist/__tests__/typeTesterTruncate.test.js +71 -1
- package/dist/components/ConfigContext.d.ts +11 -0
- package/dist/components/ConfigContext.js +7 -1
- package/dist/components/StoreModal/StoreModalIndex.js +8 -2
- package/dist/components/StoreModal/StoreModalIndexItem.d.ts +1 -1
- package/dist/components/StoreModal/StoreModalIndexItem.js +26 -8
- 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/components/TypeTester/truncate.d.ts +10 -0
- package/dist/components/TypeTester/truncate.js +31 -0
- package/dist/components/TypeTester/useTypeTesterStyler.d.ts +1 -6
- package/dist/components/TypeTester/useTypeTesterStyler.js +22 -15
- package/dist/fontdue.css +22 -10
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -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,71 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
// The index lists root collections. An unlisted one isn't offered on its own
|
|
4
|
+
// (FD-1239): an unlisted family drops out, and an unlisted superfamily is
|
|
5
|
+
// replaced by its listed families, each opening the superfamily's page so a
|
|
6
|
+
// selection there still upgrades to it.
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
10
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
11
|
+
|
|
12
|
+
// The fragment reader hands back the data it was given.
|
|
13
|
+
vi.mock('react-relay', () => ({
|
|
14
|
+
graphql: () => null,
|
|
15
|
+
useFragment: (_fragment, key) => key
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// Each entry renders what it links to, so the markup shows the navigation.
|
|
19
|
+
vi.mock('../components/StoreModal/StoreModalIndexEntry.js', () => ({
|
|
20
|
+
default: _ref => {
|
|
21
|
+
let {
|
|
22
|
+
productId,
|
|
23
|
+
name,
|
|
24
|
+
label
|
|
25
|
+
} = _ref;
|
|
26
|
+
return /*#__PURE__*/React.createElement("li", {
|
|
27
|
+
"data-product": productId
|
|
28
|
+
}, name, " (", label, ")");
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
import StoreModalIndexItem from '../components/StoreModal/StoreModalIndexItem.js';
|
|
32
|
+
const family = function (name, visibility) {
|
|
33
|
+
let totalStyles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 4;
|
|
34
|
+
let isVariableFont = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
35
|
+
return {
|
|
36
|
+
id: `collection:${name}`,
|
|
37
|
+
name,
|
|
38
|
+
visibility,
|
|
39
|
+
collectionType: 'FAMILY',
|
|
40
|
+
isVariableFont,
|
|
41
|
+
totalStyles,
|
|
42
|
+
featureStyle: null,
|
|
43
|
+
children: []
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const superfamily = (visibility, children) => ({
|
|
47
|
+
id: 'collection:Super',
|
|
48
|
+
name: 'Super',
|
|
49
|
+
visibility,
|
|
50
|
+
collectionType: 'SUPERFAMILY',
|
|
51
|
+
isVariableFont: false,
|
|
52
|
+
totalStyles: 10,
|
|
53
|
+
featureStyle: null,
|
|
54
|
+
children
|
|
55
|
+
});
|
|
56
|
+
const markup = collection => renderToStaticMarkup( /*#__PURE__*/React.createElement(StoreModalIndexItem, {
|
|
57
|
+
collection: collection
|
|
58
|
+
}));
|
|
59
|
+
describe('StoreModalIndexItem visibility', () => {
|
|
60
|
+
it('lists a visible superfamily as one entry', () => {
|
|
61
|
+
const html = markup(superfamily('VISIBLE', [family('Sans', 'VISIBLE')]));
|
|
62
|
+
expect(html).toBe('<li data-product="collection:Super">Super (10 styles)</li>');
|
|
63
|
+
});
|
|
64
|
+
it('leaves out an unlisted root family', () => {
|
|
65
|
+
expect(markup(family('Sans', 'UNLISTED'))).toBe('');
|
|
66
|
+
});
|
|
67
|
+
it('replaces an unlisted superfamily with its listed families, each opening the superfamily', () => {
|
|
68
|
+
const html = markup(superfamily('UNLISTED', [family('Sans', 'VISIBLE'), family('Serif', 'VISIBLE', 6), family('Sans Variable', 'UNLISTED', 2, true), family('Mono Variable', 'VISIBLE', 1, true)]));
|
|
69
|
+
expect(html).toBe('<li data-product="collection:Super">Sans (4 styles)</li>' + '<li data-product="collection:Super">Serif (6 styles)</li>' + '<li data-product="collection:Super">Mono Variable (1 variable font)</li>');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -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
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
|
-
import { normalizeTruncate, parseTruncateAttribute, shouldTruncate } from "../components/TypeTester/truncate.js";
|
|
2
|
+
import { normalizeTruncate, parseTruncateAttribute, shouldTruncate, truncateColumnStyle } from "../components/TypeTester/truncate.js";
|
|
3
3
|
import { mergeConfig } from "../components/ConfigContext.js";
|
|
4
4
|
describe('normalizeTruncate', () => {
|
|
5
5
|
it('is off when unset or false', () => {
|
|
@@ -215,4 +215,74 @@ describe('mergeConfig with the object truncate form', () => {
|
|
|
215
215
|
});
|
|
216
216
|
expect((_merged$typeTester2 = merged.typeTester) === null || _merged$typeTester2 === void 0 ? void 0 : _merged$typeTester2.truncate).toBe(20);
|
|
217
217
|
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// The stylesheet carries the column-width that WebKit before Safari 26.1 needs
|
|
221
|
+
// to build a single column (FD-191); these pin what the inline style leaves
|
|
222
|
+
// for it to reach, and what it must never touch.
|
|
223
|
+
describe('truncateColumnStyle', () => {
|
|
224
|
+
it('is the bare single column with columns off', () => {
|
|
225
|
+
expect(truncateColumnStyle(false)).toEqual({
|
|
226
|
+
columnCount: 1
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
it('writes configured columns as they are', () => {
|
|
230
|
+
expect(truncateColumnStyle({
|
|
231
|
+
count: 3,
|
|
232
|
+
width: '20ch',
|
|
233
|
+
gap: '1em'
|
|
234
|
+
})).toEqual({
|
|
235
|
+
columnCount: 3,
|
|
236
|
+
columnWidth: '20ch',
|
|
237
|
+
columnGap: '1em'
|
|
238
|
+
});
|
|
239
|
+
expect(truncateColumnStyle({
|
|
240
|
+
count: 'auto',
|
|
241
|
+
width: '40ch',
|
|
242
|
+
gap: '1em'
|
|
243
|
+
})).toEqual({
|
|
244
|
+
columnCount: 'auto',
|
|
245
|
+
columnWidth: '40ch',
|
|
246
|
+
columnGap: '1em'
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
it('leaves the width off a configured single column with an auto width', () => {
|
|
250
|
+
expect(truncateColumnStyle({
|
|
251
|
+
count: 1,
|
|
252
|
+
width: 'auto',
|
|
253
|
+
gap: '1em'
|
|
254
|
+
})).toEqual({
|
|
255
|
+
columnCount: 1,
|
|
256
|
+
columnGap: '1em'
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// A script-tag config is untyped JSON, so the count can arrive as a string
|
|
261
|
+
// and the width as an empty string.
|
|
262
|
+
it('reads a loosely typed single column the same way', () => {
|
|
263
|
+
const loose = {
|
|
264
|
+
count: '1',
|
|
265
|
+
width: '',
|
|
266
|
+
gap: '1em'
|
|
267
|
+
};
|
|
268
|
+
expect(truncateColumnStyle(loose)).toEqual({
|
|
269
|
+
columnCount: 1,
|
|
270
|
+
columnGap: '1em'
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// With `column-count: auto` a 1px column-width would mean one column per
|
|
275
|
+
// pixel, so an auto count keeps its inline auto width, which the stylesheet
|
|
276
|
+
// cannot override.
|
|
277
|
+
it('keeps the auto width of an auto column count', () => {
|
|
278
|
+
expect(truncateColumnStyle({
|
|
279
|
+
count: 'auto',
|
|
280
|
+
width: 'auto',
|
|
281
|
+
gap: '1em'
|
|
282
|
+
})).toEqual({
|
|
283
|
+
columnCount: 'auto',
|
|
284
|
+
columnWidth: 'auto',
|
|
285
|
+
columnGap: '1em'
|
|
286
|
+
});
|
|
287
|
+
});
|
|
218
288
|
});
|
|
@@ -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,
|
|
@@ -29,7 +29,7 @@ const StoreModalIndex = _ref => {
|
|
|
29
29
|
let {
|
|
30
30
|
prepared
|
|
31
31
|
} = _ref;
|
|
32
|
-
const queryData = usePreloadedQuery((_StoreModalIndexQuery.hash && _StoreModalIndexQuery.hash !== "
|
|
32
|
+
const queryData = usePreloadedQuery((_StoreModalIndexQuery.hash && _StoreModalIndexQuery.hash !== "13fce0376ef1b098e7f1f34dfdc7dad4" && 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);
|
|
33
33
|
|
|
34
34
|
// The query type only carries the fragment spread, not its data type, so
|
|
35
35
|
// both sides are named explicitly for `data` to be typed.
|
|
@@ -53,7 +53,13 @@ const StoreModalIndex = _ref => {
|
|
|
53
53
|
rootRef: scrollContainer,
|
|
54
54
|
rootMargin: LOAD_MORE_MARGIN
|
|
55
55
|
});
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
// An unlisted pack is sold through its own Buy Button or page, not offered
|
|
58
|
+
// in the index; the API returns it so a site can build that page.
|
|
59
|
+
const packEdges = (((_queryData$viewer = queryData.viewer) === null || _queryData$viewer === void 0 ? void 0 : (_queryData$viewer$fon = _queryData$viewer.fontPacks) === null || _queryData$viewer$fon === void 0 ? void 0 : _queryData$viewer$fon.edges) ?? []).filter(edge => {
|
|
60
|
+
var _edge$node;
|
|
61
|
+
return (edge === null || edge === void 0 ? void 0 : (_edge$node = edge.node) === null || _edge$node === void 0 ? void 0 : _edge$node.visibility) !== 'UNLISTED';
|
|
62
|
+
});
|
|
57
63
|
const edges = (data === null || data === void 0 ? void 0 : (_data$rootCollections = data.rootCollections) === null || _data$rootCollections === void 0 ? void 0 : _data$rootCollections.edges) ?? [];
|
|
58
64
|
return /*#__PURE__*/React.createElement(StoreModalPageContainer, null, {
|
|
59
65
|
body: /*#__PURE__*/React.createElement(React.Fragment, null, packEdges.map(edge => /*#__PURE__*/React.createElement(StoreModalIndexPackItem, {
|
|
@@ -3,5 +3,5 @@ import { StoreModalIndexItem_fontCollection$key } from '__generated__/StoreModal
|
|
|
3
3
|
interface StoreModalIndexItem_props {
|
|
4
4
|
collection: StoreModalIndexItem_fontCollection$key;
|
|
5
5
|
}
|
|
6
|
-
declare const StoreModalIndexItem: ({ collection }: StoreModalIndexItem_props) => React.JSX.Element;
|
|
6
|
+
declare const StoreModalIndexItem: ({ collection }: StoreModalIndexItem_props) => React.JSX.Element | null;
|
|
7
7
|
export default StoreModalIndexItem;
|
|
@@ -4,29 +4,47 @@ import { graphql, useFragment } from 'react-relay';
|
|
|
4
4
|
import StoreModalIndexEntry from './StoreModalIndexEntry.js';
|
|
5
5
|
import useTotalStyles from '../useTotalStyles.js';
|
|
6
6
|
import { pluralize } from '../../utils.js';
|
|
7
|
+
const styleLabel = (totalStyles, variableFonts) => {
|
|
8
|
+
const label = [];
|
|
9
|
+
if (totalStyles > 0) label.push(pluralize(totalStyles, 'style'));
|
|
10
|
+
if (variableFonts > 0) label.push(pluralize(variableFonts, 'variable font'));
|
|
11
|
+
return label.join(', ');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// One root collection on the index page. An unlisted collection isn't offered
|
|
15
|
+
// on its own (FD-1239), so it has no entry of its own here either: an unlisted
|
|
16
|
+
// family drops out, and an unlisted superfamily is replaced by its listed
|
|
17
|
+
// families. Those still open the superfamily's page, where selecting them
|
|
18
|
+
// upgrades to the superfamily.
|
|
7
19
|
const StoreModalIndexItem = _ref => {
|
|
8
20
|
let {
|
|
9
21
|
collection
|
|
10
22
|
} = _ref;
|
|
11
|
-
const data = useFragment((_StoreModalIndexItem_fontCollection.hash && _StoreModalIndexItem_fontCollection.hash !== "
|
|
23
|
+
const data = useFragment((_StoreModalIndexItem_fontCollection.hash && _StoreModalIndexItem_fontCollection.hash !== "46573dcfb540ddfba2e28144704bd554" && console.error("The definition of 'StoreModalIndexItem_fontCollection' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _StoreModalIndexItem_fontCollection), collection);
|
|
12
24
|
const {
|
|
13
25
|
totalStyles,
|
|
14
26
|
variableFonts
|
|
15
27
|
} = useTotalStyles({
|
|
16
28
|
fontCollection: data
|
|
17
29
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
if (data.visibility === 'UNLISTED') {
|
|
31
|
+
if (data.collectionType === 'FAMILY') return null;
|
|
32
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, (data.children ?? []).filter(family => family.visibility !== 'UNLISTED').map(family => {
|
|
33
|
+
const styles = family.totalStyles ?? 0;
|
|
34
|
+
return /*#__PURE__*/React.createElement(StoreModalIndexEntry, {
|
|
35
|
+
key: family.id,
|
|
36
|
+
productId: data.id,
|
|
37
|
+
name: family.name,
|
|
38
|
+
featureStyle: family.featureStyle,
|
|
39
|
+
label: family.isVariableFont ? styleLabel(0, styles) : styleLabel(styles, 0)
|
|
40
|
+
});
|
|
41
|
+
}));
|
|
24
42
|
}
|
|
25
43
|
return /*#__PURE__*/React.createElement(StoreModalIndexEntry, {
|
|
26
44
|
productId: data.id,
|
|
27
45
|
name: data.name,
|
|
28
46
|
featureStyle: data.featureStyle,
|
|
29
|
-
label:
|
|
47
|
+
label: styleLabel(totalStyles, variableFonts)
|
|
30
48
|
});
|
|
31
49
|
};
|
|
32
50
|
export default StoreModalIndexItem;
|
|
@@ -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;
|