fontdue-js 2.0.1 → 2.1.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 CHANGED
@@ -1,3 +1,11 @@
1
+ ## 2.1.0
2
+
3
+ - Added support for variable fonts to the standalone TypeTester component
4
+
5
+ ## 2.0.1
6
+
7
+ - Fixed issue with new relay environment headers, add request name to requests
8
+
1
9
  ## 2.0.0
2
10
 
3
11
  - __Breaking change__: This is a major upgrade to support React 18 concurrent mode, including changes to how we resolve data using Suspense via Relay. Upgrading meant we require some new features only available in React 18. But this change also means that Fontdue components can now fully resolve during server-side rendering (e.g. in Next.js), making for much smoother initial page loads. Usage on the server (e.g. Next.js) now requires the NEXT_PUBLIC_FONTDUE_URL to be set instead of passing the `url` prop to the FontdueProvider.
package/README.md CHANGED
@@ -189,8 +189,13 @@ import TypeTester from 'fontdue-js/TypeTester';
189
189
  | `fontSize` | (Optional) `number` Initial font size in pixels. |
190
190
  | `lineHeight` | (Optional) `number` Line-height as a proportional value where `1 == fontSize`. |
191
191
  | `content` | (Optional) `string` The initial content to display. |
192
+ | `direction` | (Optional) `'ltr' \| 'rtl'` Writing direction |
193
+ | `alignment` | (Optional) `'left' \| 'center' \| 'right'` Text alignment |
192
194
  | `features` | (Optional) `string[]` List of opentype feature codes to expose as options to users. (e.g. `['ss01', 'ss02']`) |
195
+ | `axes` | (Optional) `string[]` List of variable axes to expose. (e.g. `['wdth', 'ital']`). You must provide the relevant `variableSettings` for each axis |
193
196
  | `autofit` | (Optional) See `TypeTesters.autofit` above |
197
+ | `featureSettings` | (Optional) `{ feature: string, value: string }[]` List of features already selected, the `value` should be `"1"` to mark the feature as selected. The shape of this data is consistent with the `TypeTester.featureSettings` field in the GraphQL API. e.g. `[{ feature: 'ss01', value: '1' }]` |
198
+ | `variableSettings` | (Optional) `{ axis: string, value: number }[]` List of variable settings selected, consistent with the `TypeTester.variableSettings` field. e.g. `[{ axis: 'wdth', value: 600 }, { axis: 'ital', value: 0.5 }]` |
194
199
 
195
200
  ## `TestFontsForm`
196
201
 
@@ -103,6 +103,20 @@ const StyleSelect = _ref => {
103
103
  onChange: handleChange
104
104
  });
105
105
  };
106
+ function Character(props) {
107
+ const ref = (0, _react.useRef)(null);
108
+ const [size, setSize] = (0, _react.useState)(1);
109
+ (0, _resizeObserver.default)(ref, entry => {
110
+ if (entry.target.scrollWidth > entry.target.clientWidth) {
111
+ setSize(size + 1);
112
+ }
113
+ });
114
+ return /*#__PURE__*/_react.default.createElement("div", _extends({
115
+ ref: ref
116
+ }, props, {
117
+ "data-size": size
118
+ }));
119
+ }
106
120
  function CharacterViewerComponent(_ref3) {
107
121
  var _collection$children, _collection$fontStyle, _collection$children2, _collection$children3, _collection$children4, _fontStyle$characterB, _fontStyle$characterB2, _fontStyle$featureCha, _fontStyle$featureCha2, _fontStyle$featureCha3, _fontStyle$featureCha4, _fontStyle$featureCha5, _fontStyle$characterB3, _fontStyle$featureCha6, _fontStyle$featureCha7, _fontStyle$featureCha8;
108
122
  let {
@@ -218,7 +232,7 @@ function CharacterViewerComponent(_ref3) {
218
232
  className: "character-viewer__block__characters",
219
233
  style: style,
220
234
  onMouseLeave: handleMouseLeave
221
- }, characters.map((chars, j) => /*#__PURE__*/_react.default.createElement("div", {
235
+ }, characters.map((chars, j) => /*#__PURE__*/_react.default.createElement(Character, {
222
236
  key: j,
223
237
  onClick: () => setSelectedCharacter(chars),
224
238
  onMouseEnter: () => setActiveCharacter(chars),
@@ -299,7 +313,7 @@ function CharacterViewerComponent(_ref3) {
299
313
  fontFeatureSettings: `'${feature}' 1`
300
314
  },
301
315
  onMouseLeave: handleFeatureCharacterMouseLeave
302
- }, characters.map((chars, j) => /*#__PURE__*/_react.default.createElement("div", {
316
+ }, characters.map((chars, j) => /*#__PURE__*/_react.default.createElement(Character, {
303
317
  key: j,
304
318
  onClick: () => setSelectedFeatureCharacter([chars, feature]),
305
319
  onMouseEnter: () => setActiveFeatureCharacter([chars, feature]),
@@ -321,7 +335,7 @@ function CharacterViewerComponent(_ref3) {
321
335
  feature,
322
336
  characters
323
337
  } = _ref8;
324
- return characters.map((chars, j) => /*#__PURE__*/_react.default.createElement("div", {
338
+ return characters.map((chars, j) => /*#__PURE__*/_react.default.createElement(Character, {
325
339
  key: `${i}${j}`,
326
340
  style: {
327
341
  fontFeatureSettings: `'${feature}' 1`
@@ -197,7 +197,7 @@ function Precart(_ref3) {
197
197
  type: 'PRECART_SELECT_LICENSE',
198
198
  licenseOptionSpec: spec
199
199
  }));
200
- }, [viewer]);
200
+ }, []);
201
201
  function renderConfirmingModal(subtotal) {
202
202
  var _viewer$precart3, _viewer$precart3$skus;
203
203
  if (!isConfirming) {
@@ -3,11 +3,20 @@ import { Alignment, Direction } from './types';
3
3
  import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery';
4
4
  import { TypeTesterStandaloneQuery } from '__generated__/TypeTesterStandaloneQuery.graphql';
5
5
  interface TypeTesterStandaloneComponent_props {
6
- lineHeight?: number;
7
- fontSize?: number;
8
- features?: string[];
9
- featuresSelected?: string[];
10
- content?: string;
6
+ lineHeight?: number | null;
7
+ fontSize?: number | null;
8
+ axes?: string[] | null;
9
+ features?: string[] | null;
10
+ featuresSelected?: string[] | null;
11
+ featureSettings?: {
12
+ feature: string;
13
+ value: string;
14
+ }[] | null;
15
+ variableSettings?: {
16
+ axis: string;
17
+ value: number;
18
+ }[] | null;
19
+ content?: string | null;
11
20
  direction?: Direction;
12
21
  alignment?: Alignment;
13
22
  autofit?: boolean;
@@ -19,8 +19,11 @@ function TypeTesterStandaloneComponent(_ref) {
19
19
  let {
20
20
  content,
21
21
  direction,
22
+ axes,
22
23
  features,
23
24
  featuresSelected,
25
+ featureSettings = null,
26
+ variableSettings = null,
24
27
  lineHeight,
25
28
  alignment,
26
29
  fontSize,
@@ -37,14 +40,22 @@ function TypeTesterStandaloneComponent(_ref) {
37
40
  size: fontSize ?? 72,
38
41
  lineHeight: lineHeight ?? 1,
39
42
  alignment: alignment ?? 'left',
40
- features: featuresSelected ?? null,
41
- variableSettings: null
43
+ features: (featureSettings === null || featureSettings === void 0 ? void 0 : featureSettings.filter(setting => setting.value === '1').map(setting => setting.feature)) ?? featuresSelected ?? null,
44
+ variableSettings: (variableSettings === null || variableSettings === void 0 ? void 0 : variableSettings.reduce((acc, _ref2) => {
45
+ let {
46
+ axis,
47
+ value
48
+ } = _ref2;
49
+ acc[axis] = value;
50
+ return acc;
51
+ }, {})) ?? null
42
52
  }
43
53
  }
44
54
  }, /*#__PURE__*/_react.default.createElement(_index.default, {
45
55
  id: "standalone",
46
56
  viewer: data.viewer,
47
57
  fontStyle: (_data$viewer = data.viewer) === null || _data$viewer === void 0 ? void 0 : _data$viewer.fontStyle,
58
+ axes: axes,
48
59
  features: features,
49
60
  direction: direction,
50
61
  productId: ((_data$viewer2 = data.viewer) === null || _data$viewer2 === void 0 ? void 0 : (_data$viewer2$fontSty = _data$viewer2.fontStyle) === null || _data$viewer2$fontSty === void 0 ? void 0 : (_data$viewer2$fontSty2 = _data$viewer2$fontSty.family) === null || _data$viewer2$fontSty2 === void 0 ? void 0 : (_data$viewer2$fontSty3 = _data$viewer2$fontSty2.parent) === null || _data$viewer2$fontSty3 === void 0 ? void 0 : _data$viewer2$fontSty3.id) ?? ((_data$viewer3 = data.viewer) === null || _data$viewer3 === void 0 ? void 0 : (_data$viewer3$fontSty = _data$viewer3.fontStyle) === null || _data$viewer3$fontSty === void 0 ? void 0 : (_data$viewer3$fontSty2 = _data$viewer3$fontSty.family) === null || _data$viewer3$fontSty2 === void 0 ? void 0 : _data$viewer3$fontSty2.id),
@@ -54,24 +65,24 @@ function TypeTesterStandaloneComponent(_ref) {
54
65
  }));
55
66
  }
56
67
  const query = _TypeTesterStandaloneQuery !== void 0 ? _TypeTesterStandaloneQuery : (_TypeTesterStandaloneQuery = require("../../__generated__/TypeTesterStandaloneQuery.graphql"), _TypeTesterStandaloneQuery.hash && _TypeTesterStandaloneQuery.hash !== "3ad5c4d856f5d46ddf8a47a2b6d2420a" && console.error("The definition of 'TypeTesterStandaloneQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _TypeTesterStandaloneQuery);
57
- function TypeTesterStandalonePreloadedQueryRenderer(_ref2) {
68
+ function TypeTesterStandalonePreloadedQueryRenderer(_ref3) {
58
69
  let {
59
70
  preloadedQuery,
60
71
  ...rest
61
- } = _ref2;
72
+ } = _ref3;
62
73
  const queryRef = (0, _useSerializablePreloadedQuery.default)(preloadedQuery);
63
74
  const data = (0, _reactRelay.usePreloadedQuery)(query, queryRef);
64
75
  return /*#__PURE__*/_react.default.createElement(TypeTesterStandaloneComponent, _extends({
65
76
  data: data
66
77
  }, rest));
67
78
  }
68
- function TypeTesterStandalone(_ref3) {
79
+ function TypeTesterStandalone(_ref4) {
69
80
  var _data$viewer4;
70
81
  let {
71
82
  familyName,
72
83
  styleName,
73
84
  ...rest
74
- } = _ref3;
85
+ } = _ref4;
75
86
  const data = (0, _reactRelay.useLazyLoadQuery)(query, {
76
87
  familyName,
77
88
  styleName
@@ -5,7 +5,9 @@ interface TypeTesterElement_props {
5
5
  lineHeight?: string;
6
6
  fontSize?: string;
7
7
  features?: string;
8
+ axes?: string;
8
9
  featuresSelected?: string;
10
+ variableSettings?: string;
9
11
  content?: string;
10
12
  direction?: string;
11
13
  alignment?: string;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = exports.TypeTesterStandaloneElement = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _TypeTesterStandalone = _interopRequireDefault(require("./TypeTesterStandalone"));
9
+ var _utils = require("../../utils");
9
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
11
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
11
12
  const isAlignment = str => {
@@ -15,12 +16,31 @@ const isDirection = str => {
15
16
  return str === 'ltr' || str === 'rtl';
16
17
  };
17
18
  const parseBool = input => input === 'true' ? true : false;
19
+
20
+ // parse a string like "wdth 1000, ital 0.5" into
21
+ // [{ axis: "wdth", value: 1000 }, { axis: "ital", value: 0.5 }]
22
+ function parseVariableSettings(input) {
23
+ if (!input) return null;
24
+ return input.split(/\s*,\s*/).map(settingString => {
25
+ const m = settingString.match(/^([A-Za-z0-9]{4}) (\d+(?:\.\d+)?)$/);
26
+ if (m && m.length > 2) {
27
+ return {
28
+ axis: m[1],
29
+ value: parseFloat(m[2])
30
+ };
31
+ } else {
32
+ console.warn(`fontdue-type-tester failed to parse variable-settings value: "${settingString}", ignoring`);
33
+ }
34
+ }).filter(_utils.notEmpty);
35
+ }
18
36
  const TypeTesterStandaloneElement = _ref => {
19
37
  let {
20
38
  lineHeight,
21
39
  fontSize,
40
+ axes,
22
41
  features,
23
42
  featuresSelected,
43
+ variableSettings,
24
44
  alignment,
25
45
  direction,
26
46
  autofit,
@@ -30,10 +50,15 @@ const TypeTesterStandaloneElement = _ref => {
30
50
  autofit: parseBool(autofit),
31
51
  lineHeight: lineHeight ? parseFloat(lineHeight) : undefined,
32
52
  fontSize: fontSize ? parseFloat(fontSize) : undefined,
53
+ axes: (axes === null || axes === void 0 ? void 0 : axes.split(',')) ?? [],
33
54
  features: (features === null || features === void 0 ? void 0 : features.split(',')) ?? [],
34
- featuresSelected: (featuresSelected === null || featuresSelected === void 0 ? void 0 : featuresSelected.split(',')) ?? [],
55
+ featureSettings: featuresSelected === null || featuresSelected === void 0 ? void 0 : featuresSelected.split(',').map(feature => ({
56
+ feature,
57
+ value: '1'
58
+ })),
35
59
  alignment: isAlignment(alignment) ? alignment : undefined,
36
- direction: isDirection(direction) ? direction : undefined
60
+ direction: isDirection(direction) ? direction : undefined,
61
+ variableSettings: parseVariableSettings(variableSettings)
37
62
  }, rest));
38
63
  };
39
64
  exports.TypeTesterStandaloneElement = TypeTesterStandaloneElement;
@@ -32,7 +32,8 @@ const TypeTesterVariableAxes = _ref => {
32
32
  };
33
33
  return /*#__PURE__*/_react.default.createElement("div", {
34
34
  className: "type-tester__variable-axes"
35
- }, axes.map(showAxis => {
35
+ }, axes.filter(showAxis => showAxis in variableSettings) // only show the slider if the value is set
36
+ .map(showAxis => {
36
37
  var _fontStyle$variableAx;
37
38
  return (_fontStyle$variableAx = fontStyle.variableAxes) === null || _fontStyle$variableAx === void 0 ? void 0 : _fontStyle$variableAx.find(_ref2 => {
38
39
  let {
package/dist/fontdue.css CHANGED
@@ -935,23 +935,31 @@ div[data-component=TypeTesters] {
935
935
 
936
936
  .character-viewer__block__characters {
937
937
  display: grid;
938
- grid-template-columns: repeat(calc(var(--width) / 60), 1fr);
938
+ grid-template-columns: repeat(calc(var(--width) / 60), minmax(0, 1fr));
939
939
  font-size: 30px;
940
940
  margin-left: 1px;
941
941
  }
942
942
  .character-viewer__block__characters > div {
943
- border-top: 1px solid;
944
- border-left: 1px solid;
945
- border-bottom: 1px solid;
946
- border-right: 1px solid;
943
+ border: 1px solid;
947
944
  margin-left: -1px;
948
945
  margin-bottom: -1px;
949
- padding-top: 12px;
950
- padding-bottom: 12px;
946
+ padding: 12px 0;
951
947
  text-align: center;
952
948
  cursor: default;
953
949
  white-space: pre;
954
950
  }
951
+ .character-viewer__block__characters > div[data-size="2"] {
952
+ grid-column: span 2;
953
+ }
954
+ .character-viewer__block__characters > div[data-size="3"] {
955
+ grid-column: span 3;
956
+ }
957
+ .character-viewer__block__characters > div[data-size="4"] {
958
+ grid-column: span 4;
959
+ }
960
+ .character-viewer__block__characters > div[data-size="5"] {
961
+ grid-column: span 5;
962
+ }
955
963
  @media screen and (min-width: 600px) {
956
964
  .character-viewer__block__characters > div:hover, .character-viewer__block__characters > div[data-selected=true] {
957
965
  background: var(--primary_text_color);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fontdue-js",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "scripts": {
5
5
  "build": "npm run relay && run-p build-js build-css build-ts-declarations",
6
6
  "build-js": "babel src --out-dir dist --extensions .ts,.tsx,.js,.jsx",