fontdue-js 3.2.5 → 3.3.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 +23 -15
- package/dist/__generated__/CharacterViewerIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerIDQuery.graphql.js +33 -3
- package/dist/__generated__/CharacterViewerSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerSlugQuery.graphql.js +33 -3
- package/dist/__generated__/CharacterViewerStyleRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerStyleRefetchQuery.graphql.js +34 -4
- package/dist/__generated__/CharacterViewer_style.graphql.d.ts +2 -2
- package/dist/__generated__/CharacterViewer_style.graphql.js +6 -2
- package/dist/__generated__/FeatureTesterStandaloneQuery.graphql.d.ts +1 -1
- package/dist/__generated__/FeatureTesterStandaloneQuery.graphql.js +15 -20
- package/dist/__generated__/FeatureTestersIdQuery.graphql.d.ts +1 -1
- package/dist/__generated__/FeatureTestersIdQuery.graphql.js +15 -20
- package/dist/__generated__/FeatureTestersSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/FeatureTestersSlugQuery.graphql.js +15 -20
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.js +14 -20
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.js +14 -20
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.js +14 -20
- package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersIDQuery.graphql.js +17 -23
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +17 -23
- package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersSlugQuery.graphql.js +17 -23
- package/dist/__generated__/useFeaturesData_fontStyle.graphql.d.ts +4 -4
- package/dist/__generated__/useFeaturesData_fontStyle.graphql.js +6 -6
- package/dist/__tests__/trackingRouteChanges.test.js +110 -0
- package/dist/__tests__/typeTestersServerEntry.test.js +98 -0
- package/dist/components/CharacterViewer/index.js +17 -4
- package/dist/components/Tracking/index.js +10 -18
- package/dist/components/Tracking/routeChanges.d.ts +19 -0
- package/dist/components/Tracking/routeChanges.js +62 -0
- package/dist/components/TypeTester/useFeaturesData.d.ts +9 -9
- package/dist/components/TypeTester/useFeaturesData.js +13 -23
- package/dist/components/TypeTesters/index.server.js +14 -2
- package/dist/relay/environment.js +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { useContext, useEffect } from 'react';
|
|
|
4
4
|
import ConfigContext from '../ConfigContext.js';
|
|
5
5
|
import { useFontdueUrl } from '../UrlContext.js';
|
|
6
6
|
import { hasConsent, onConsent, setClientAnonymousId, setEntryAttribution } from '../ConsentBanner/consent.js';
|
|
7
|
+
import { trackRouteChanges } from './routeChanges.js';
|
|
7
8
|
function getCampaignDataFromUrl() {
|
|
8
9
|
const urlParams = new URLSearchParams(window.location.search);
|
|
9
10
|
const campaign = {};
|
|
@@ -155,26 +156,17 @@ const Tracking = () => {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
// Track client-side route changes
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
handleRouteChange();
|
|
167
|
-
};
|
|
168
|
-
history.replaceState = function () {
|
|
169
|
-
originalReplaceState(...arguments);
|
|
170
|
-
handleRouteChange();
|
|
171
|
-
};
|
|
172
|
-
window.addEventListener('popstate', handleRouteChange);
|
|
159
|
+
const untrackRouteChanges = trackRouteChanges({
|
|
160
|
+
history,
|
|
161
|
+
window,
|
|
162
|
+
currentUrl: () => window.location.href,
|
|
163
|
+
onNavigate: () => {
|
|
164
|
+
sendPageView(url);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
173
167
|
return () => {
|
|
174
168
|
var _consentCleanup;
|
|
175
|
-
|
|
176
|
-
history.replaceState = originalReplaceState;
|
|
177
|
-
window.removeEventListener('popstate', handleRouteChange);
|
|
169
|
+
untrackRouteChanges();
|
|
178
170
|
(_consentCleanup = consentCleanup) === null || _consentCleanup === void 0 ? void 0 : _consentCleanup();
|
|
179
171
|
};
|
|
180
172
|
}, []);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type HistoryLike = Pick<History, 'pushState' | 'replaceState'>;
|
|
2
|
+
type WindowLike = Pick<Window, 'addEventListener' | 'removeEventListener'>;
|
|
3
|
+
export type RouteChangeOptions = {
|
|
4
|
+
history: HistoryLike;
|
|
5
|
+
window: WindowLike;
|
|
6
|
+
/** The URL as it stands right now, e.g. `() => window.location.href`. */
|
|
7
|
+
currentUrl: () => string;
|
|
8
|
+
/** Called once per navigation to a URL different from the previous one. */
|
|
9
|
+
onNavigate: () => void;
|
|
10
|
+
/** Overridable so tests can run the check synchronously. */
|
|
11
|
+
defer?: (callback: () => void) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Wrap `pushState`/`replaceState` and call `onNavigate` when the URL changes.
|
|
15
|
+
*
|
|
16
|
+
* Returns a cleanup function that restores the original History methods.
|
|
17
|
+
*/
|
|
18
|
+
export declare function trackRouteChanges({ history, window: windowLike, currentUrl, onNavigate, defer, }: RouteChangeOptions): () => void;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Client-side route-change detection for the Tracking component.
|
|
2
|
+
//
|
|
3
|
+
// There is no navigation event a page can listen to for SPA routing, so the
|
|
4
|
+
// only way to notice one is to wrap the History API and watch for the URL
|
|
5
|
+
// changing underneath us. Kept in its own module — and taking its history,
|
|
6
|
+
// window and clock as arguments — so the wrapping and the de-duplication can
|
|
7
|
+
// be tested without a DOM.
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Wrap `pushState`/`replaceState` and call `onNavigate` when the URL changes.
|
|
11
|
+
*
|
|
12
|
+
* Returns a cleanup function that restores the original History methods.
|
|
13
|
+
*/
|
|
14
|
+
export function trackRouteChanges(_ref) {
|
|
15
|
+
let {
|
|
16
|
+
history,
|
|
17
|
+
window: windowLike,
|
|
18
|
+
currentUrl,
|
|
19
|
+
onNavigate,
|
|
20
|
+
defer = callback => {
|
|
21
|
+
setTimeout(callback, 0);
|
|
22
|
+
}
|
|
23
|
+
} = _ref;
|
|
24
|
+
// The caller has already reported the URL we start on, so it is the first
|
|
25
|
+
// thing we compare against.
|
|
26
|
+
let lastUrl = currentUrl();
|
|
27
|
+
const handleRouteChange = () => {
|
|
28
|
+
// Defer slightly to let document.title update
|
|
29
|
+
defer(() => {
|
|
30
|
+
const url = currentUrl();
|
|
31
|
+
|
|
32
|
+
// A history entry gets rewritten in place for all sorts of reasons that
|
|
33
|
+
// are not navigation: saving scroll position, stashing UI state, marking
|
|
34
|
+
// how the entry was reached. Phoenix LiveView, for one, calls
|
|
35
|
+
// `history.replaceState(state, "", window.location.href)` 100ms after
|
|
36
|
+
// every scroll stop to remember the scroll offset — which billed a page
|
|
37
|
+
// view per scroll pause on the site of anyone running LiveView. Only a
|
|
38
|
+
// URL that actually differs from the last one we reported can be a new
|
|
39
|
+
// page view. Note this compares against the *previous* URL rather than
|
|
40
|
+
// every URL seen, so A → B → A is three page views, as it should be.
|
|
41
|
+
if (url === lastUrl) return;
|
|
42
|
+
lastUrl = url;
|
|
43
|
+
onNavigate();
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const originalPushState = history.pushState.bind(history);
|
|
47
|
+
const originalReplaceState = history.replaceState.bind(history);
|
|
48
|
+
history.pushState = function () {
|
|
49
|
+
originalPushState(...arguments);
|
|
50
|
+
handleRouteChange();
|
|
51
|
+
};
|
|
52
|
+
history.replaceState = function () {
|
|
53
|
+
originalReplaceState(...arguments);
|
|
54
|
+
handleRouteChange();
|
|
55
|
+
};
|
|
56
|
+
windowLike.addEventListener('popstate', handleRouteChange);
|
|
57
|
+
return () => {
|
|
58
|
+
history.pushState = originalPushState;
|
|
59
|
+
history.replaceState = originalReplaceState;
|
|
60
|
+
windowLike.removeEventListener('popstate', handleRouteChange);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { useFeaturesData_fontStyle$key } from '__generated__/useFeaturesData_fontStyle.graphql.js';
|
|
2
2
|
interface useFeatures_props {
|
|
3
|
-
fontStyle: useFeaturesData_fontStyle$key;
|
|
3
|
+
fontStyle: useFeaturesData_fontStyle$key | null | undefined;
|
|
4
4
|
}
|
|
5
|
+
export type FeatureNames = {
|
|
6
|
+
[feature: string]: string;
|
|
7
|
+
};
|
|
5
8
|
declare const useFeaturesData: ({ fontStyle }: useFeatures_props) => {
|
|
6
|
-
featureNames: {
|
|
7
|
-
[feature: string]: string;
|
|
8
|
-
};
|
|
9
9
|
fontFeatures: {
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
10
|
+
readonly featureNames: ReadonlyArray<{
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly tag: string;
|
|
13
13
|
}>;
|
|
14
14
|
readonly supportedFeatures: ReadonlyArray<string>;
|
|
15
|
-
};
|
|
16
|
-
|
|
15
|
+
} | null;
|
|
16
|
+
featureNames: FeatureNames;
|
|
17
17
|
};
|
|
18
18
|
export default useFeaturesData;
|
|
@@ -1,32 +1,22 @@
|
|
|
1
1
|
import _useFeaturesData_fontStyle from "../../__generated__/useFeaturesData_fontStyle.graphql.js";
|
|
2
|
+
import { useMemo } from 'react';
|
|
2
3
|
import { graphql, useFragment } from 'react-relay';
|
|
3
|
-
|
|
4
|
-
const getStylisticSetName = (feature, stylisticSetNames) => stylisticSetNames.find(_ref => {
|
|
5
|
-
let {
|
|
6
|
-
featureName
|
|
7
|
-
} = _ref;
|
|
8
|
-
return featureName === feature;
|
|
9
|
-
});
|
|
10
|
-
const useFeaturesData = _ref2 => {
|
|
11
|
-
var _data$fontFeatures;
|
|
4
|
+
const useFeaturesData = _ref => {
|
|
12
5
|
let {
|
|
13
6
|
fontStyle
|
|
14
|
-
} =
|
|
15
|
-
const data = useFragment((_useFeaturesData_fontStyle.hash && _useFeaturesData_fontStyle.hash !== "
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
featureName = stylisticSetName.humanName;
|
|
24
|
-
}
|
|
25
|
-
acc[feature] = featureName;
|
|
7
|
+
} = _ref;
|
|
8
|
+
const data = useFragment((_useFeaturesData_fontStyle.hash && _useFeaturesData_fontStyle.hash !== "6a05a092096a4a0c1dd10fc0610bbee2" && console.error("The definition of 'useFeaturesData_fontStyle' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _useFeaturesData_fontStyle), fontStyle);
|
|
9
|
+
const fontFeatures = (data === null || data === void 0 ? void 0 : data.fontFeatures) ?? null;
|
|
10
|
+
const featureNames = useMemo(() => (fontFeatures === null || fontFeatures === void 0 ? void 0 : fontFeatures.featureNames.reduce((acc, _ref2) => {
|
|
11
|
+
let {
|
|
12
|
+
tag,
|
|
13
|
+
name
|
|
14
|
+
} = _ref2;
|
|
15
|
+
acc[tag] = name;
|
|
26
16
|
return acc;
|
|
27
|
-
}, {})) ?? [];
|
|
17
|
+
}, {})) ?? {}, [fontFeatures]);
|
|
28
18
|
return {
|
|
29
|
-
|
|
19
|
+
fontFeatures,
|
|
30
20
|
featureNames
|
|
31
21
|
};
|
|
32
22
|
};
|
|
@@ -14,6 +14,14 @@ export function loadTypeTestersQuery() {
|
|
|
14
14
|
// the client `*PreloadedQueryRenderer`. Lets pages just write
|
|
15
15
|
// `<TypeTesters collectionId={id} />` in an RSC without manually invoking
|
|
16
16
|
// `loadTypeTestersQuery` + threading `preloadedQuery` through props.
|
|
17
|
+
//
|
|
18
|
+
// `tags`/`excludeTags` are both query variables *and* component props: the
|
|
19
|
+
// client component needs them to build the refetch variables it hands to
|
|
20
|
+
// `useRefetchOnLicenseChanges`. Destructuring them here takes them out of
|
|
21
|
+
// `...rest`, so both branches pass them on explicitly — otherwise a
|
|
22
|
+
// licence-change refetch re-runs the filtered query unfiltered and the
|
|
23
|
+
// tester list no longer matches the state seeded from the preload. The lazy
|
|
24
|
+
// `TypeTesters*QueryRenderer`s do the same for the same reason.
|
|
17
25
|
export default async function TypeTesters(_ref) {
|
|
18
26
|
let {
|
|
19
27
|
collectionId,
|
|
@@ -29,7 +37,9 @@ export default async function TypeTesters(_ref) {
|
|
|
29
37
|
excludeTags
|
|
30
38
|
});
|
|
31
39
|
return /*#__PURE__*/React.createElement(TypeTestersPreloadedIDQueryRenderer, _extends({
|
|
32
|
-
preloadedQuery: preloadedQuery
|
|
40
|
+
preloadedQuery: preloadedQuery,
|
|
41
|
+
tags: tags,
|
|
42
|
+
excludeTags: excludeTags
|
|
33
43
|
}, rest));
|
|
34
44
|
}
|
|
35
45
|
if (collectionSlug) {
|
|
@@ -39,7 +49,9 @@ export default async function TypeTesters(_ref) {
|
|
|
39
49
|
excludeTags
|
|
40
50
|
});
|
|
41
51
|
return /*#__PURE__*/React.createElement(TypeTestersPreloadedSlugQueryRenderer, _extends({
|
|
42
|
-
preloadedQuery: preloadedQuery
|
|
52
|
+
preloadedQuery: preloadedQuery,
|
|
53
|
+
tags: tags,
|
|
54
|
+
excludeTags: excludeTags
|
|
43
55
|
}, rest));
|
|
44
56
|
}
|
|
45
57
|
return null;
|
|
@@ -8,7 +8,7 @@ import { NODE_ACCESS_HEADER } from '../nodeAccess.js';
|
|
|
8
8
|
// (defineVersionPlugin in .babelrc.cjs) with the literal package.json#version.
|
|
9
9
|
// Exported so UI (the admin toolbar) can surface it without re-reading the
|
|
10
10
|
// build-time global in a 'use client' module.
|
|
11
|
-
export const version = "3.
|
|
11
|
+
export const version = "3.3.0";
|
|
12
12
|
const IS_SERVER = typeof window === typeof undefined;
|
|
13
13
|
|
|
14
14
|
// Opt server fetches into Next's data cache only in production; dev stays
|