fontdue-js 3.0.0-alpha8 → 3.0.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 -0
- package/README.md +253 -1
- package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.js +9 -3
- package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.js +9 -3
- package/dist/__generated__/CartOrderUpdateMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartOrderUpdateMutation.graphql.js +9 -3
- package/dist/__generated__/CartQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CartQuery.graphql.js +9 -3
- package/dist/__generated__/CartStateUpdateMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CartStateUpdateMutation.graphql.js +9 -3
- package/dist/__generated__/CharacterViewerIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerIDQuery.graphql.js +9 -3
- package/dist/__generated__/CharacterViewerSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerSlugQuery.graphql.js +9 -3
- package/dist/__generated__/CharacterViewerStyleRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/CharacterViewerStyleRefetchQuery.graphql.js +9 -3
- package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.js +9 -3
- package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.d.ts +1 -1
- package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.js +9 -3
- package/dist/__generated__/CollectionAa_Query.graphql.d.ts +1 -1
- package/dist/__generated__/CollectionAa_Query.graphql.js +9 -3
- package/dist/__generated__/FontFamiliesQuery.graphql.d.ts +1 -1
- package/dist/__generated__/FontFamiliesQuery.graphql.js +9 -3
- package/dist/__generated__/FontdueAdminToolbarQuery.graphql.d.ts +20 -0
- package/dist/__generated__/FontdueAdminToolbarQuery.graphql.js +80 -0
- package/dist/__generated__/FontdueAdminToolbarTokenMutation.graphql.d.ts +18 -0
- package/dist/__generated__/FontdueAdminToolbarTokenMutation.graphql.js +56 -0
- package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +1 -1
- package/dist/__generated__/PrecartAddToCartMutation.graphql.js +9 -3
- package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalCartQuery.graphql.js +9 -3
- package/dist/__generated__/StoreModalContainerQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalContainerQuery.graphql.js +9 -3
- package/dist/__generated__/StoreModalIndexQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalIndexQuery.graphql.js +9 -3
- package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalProductQuery.graphql.js +9 -3
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +9 -3
- package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
- package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +9 -3
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTesterStandaloneChangedStylesQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTesterStandaloneQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersChangedStylesQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersIDQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersIDQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersRefetchQuery.graphql.js +9 -3
- package/dist/__generated__/TypeTestersSlugQuery.graphql.d.ts +1 -1
- package/dist/__generated__/TypeTestersSlugQuery.graphql.js +9 -3
- package/dist/__generated__/orderTrackingUpdateOrderTrackingMutation.graphql.js +1 -8
- package/dist/__generated__/useFontStyle_fontStyle.graphql.d.ts +2 -1
- package/dist/__generated__/useFontStyle_fontStyle.graphql.js +8 -2
- package/dist/__tests__/createFontdueFetch.test.js +276 -0
- package/dist/__tests__/imageLoader.test.js +62 -0
- package/dist/__tests__/metricFallback.test.js +74 -0
- package/dist/__tests__/networkFetch.test.js +188 -0
- package/dist/__tests__/nextAdapter.test.js +273 -18
- package/dist/__tests__/preview.test.js +217 -0
- package/dist/__tests__/previewServer.test.js +118 -0
- package/dist/__tests__/previewState.test.js +63 -0
- package/dist/__tests__/serverConfig.test.js +62 -0
- package/dist/components/BuyButton/index.d.ts +2 -2
- package/dist/components/BuyButton/index.js +3 -3
- package/dist/components/Cart/CartOrder.js +9 -1
- package/dist/components/Cart/orderTracking.js +8 -15
- package/dist/components/CharacterViewer/index.d.ts +2 -2
- package/dist/components/CharacterViewer/index.js +20 -11
- package/dist/components/ConfigContext.d.ts +21 -2
- package/dist/components/ConfigContext.js +12 -2
- package/dist/components/ConnectionErrorToolbar.d.ts +1 -0
- package/dist/components/ConnectionErrorToolbar.js +106 -0
- package/dist/components/FontStyle/index.d.ts +2 -0
- package/dist/components/FontStyle/index.js +4 -2
- package/dist/components/FontdueAdminToolbar/index.d.ts +2 -0
- package/dist/components/FontdueAdminToolbar/index.js +299 -0
- package/dist/components/FontdueAdminToolbar/previewState.d.ts +7 -0
- package/dist/components/FontdueAdminToolbar/previewState.js +58 -0
- package/dist/components/FontdueContextProvider/index.js +4 -2
- package/dist/components/FontdueProvider/index.js +6 -1
- package/dist/components/FontdueProvider/index.server.d.ts +1 -0
- package/dist/components/FontdueProvider/index.server.js +10 -0
- package/dist/components/NewsletterSignup/index.d.ts +2 -2
- package/dist/components/NewsletterSignup/index.js +2 -2
- package/dist/components/Root/index.js +16 -2
- package/dist/components/TestFontsForm/index.d.ts +2 -2
- package/dist/components/TestFontsForm/index.js +2 -2
- package/dist/components/TypeTester/TypeTesterStandalone.d.ts +2 -2
- package/dist/components/TypeTester/TypeTesterStandalone.js +2 -2
- package/dist/components/TypeTester/index.js +3 -1
- package/dist/components/TypeTester/useTypeTesterStyler.d.ts +3 -1
- package/dist/components/TypeTester/useTypeTesterStyler.js +70 -20
- package/dist/components/TypeTesters/index.d.ts +2 -2
- package/dist/components/TypeTesters/index.js +3 -3
- package/dist/components/elements/StoreModalUnifiedCheckout.js +8 -0
- package/dist/components/useFontStyle.d.ts +8 -0
- package/dist/components/useFontStyle.js +14 -4
- package/dist/corsError.d.ts +1 -5
- package/dist/corsError.js +23 -13
- package/dist/data/unicodeNamesUrl.d.ts +2 -0
- package/dist/data/unicodeNamesUrl.js +18 -0
- package/dist/data/unicodeNamesVersion.d.ts +1 -0
- package/dist/data/unicodeNamesVersion.js +4 -0
- package/dist/fallbackFontData.d.ts +2 -0
- package/dist/fallbackFontData.js +10 -0
- package/dist/fontdue.css +231 -4
- package/dist/loadFontdueProviderQuery.d.ts +2 -1
- package/dist/loadFontdueProviderQuery.js +5 -2
- package/dist/metricFallback.d.ts +48 -0
- package/dist/metricFallback.js +98 -0
- package/dist/next/config.d.ts +1 -5
- package/dist/next/config.js +14 -1
- package/dist/next/image-loader.js +22 -3
- package/dist/next/index.d.ts +1 -2
- package/dist/next/index.js +14 -6
- package/dist/next/registerSingleTenantResolver.d.ts +1 -0
- package/dist/next/registerSingleTenantResolver.js +35 -0
- package/dist/next/revalidate.js +1 -1
- package/dist/next/tenant.d.ts +10 -2
- package/dist/next/tenant.js +111 -16
- package/dist/preview/constants.d.ts +9 -0
- package/dist/preview/constants.js +117 -0
- package/dist/preview/index.d.ts +53 -0
- package/dist/preview/index.js +190 -0
- package/dist/preview/server.d.ts +20 -0
- package/dist/preview/server.js +89 -0
- package/dist/relay/environment.d.ts +8 -0
- package/dist/relay/environment.js +81 -25
- package/dist/relay/loadSerializableQuery.d.ts +13 -3
- package/dist/relay/loadSerializableQuery.js +2 -0
- package/dist/relay/serverConfig.d.ts +5 -1
- package/dist/relay/serverConfig.js +83 -8
- package/dist/scripts/publishUnicodeData.js +68 -0
- package/dist/scripts/updateUnicodeData.js +41 -6
- package/dist/server/index.d.ts +37 -0
- package/dist/server/index.js +160 -0
- package/package.json +5 -1
- package/types/next-headers.d.ts +9 -0
- package/types/next-navigation.d.ts +10 -0
- package/vitest.config.ts +9 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { FontdueProvider_props } from './index.js';
|
|
3
|
+
import '../../next/registerSingleTenantResolver.js';
|
|
3
4
|
export type { FontdueProvider_props } from './index.js';
|
|
4
5
|
export type { FontdueProviderPreloadedQuery } from '../../loadFontdueProviderQuery.js';
|
|
5
6
|
export type { FontdueServerConfig } from '../../relay/serverConfig.js';
|
|
@@ -3,6 +3,16 @@ import React from 'react';
|
|
|
3
3
|
import FontdueProvider from './index.js';
|
|
4
4
|
import loadFontdueProviderQueryImpl from '../../loadFontdueProviderQuery.js';
|
|
5
5
|
import { setFontdueServerConfig } from '../../relay/serverConfig.js';
|
|
6
|
+
// Side-effect import: registers the single-tenant ambient config resolver so a
|
|
7
|
+
// single-tenant foundry that mounts <FontdueProvider> never has to call a
|
|
8
|
+
// per-render setup function. The module statically pulls in only browser-safe
|
|
9
|
+
// code and lazy-loads the Next request APIs (next/headers, next/navigation)
|
|
10
|
+
// behind a dynamic import that runs only when the resolver resolves config —
|
|
11
|
+
// keeping next/* off this react-server entrypoint's eager graph. The resolver
|
|
12
|
+
// no-ops in multi-tenant mode (which drives config through the slot) and is
|
|
13
|
+
// inert in the default build Astro/RR7 use. See
|
|
14
|
+
// ../../next/registerSingleTenantResolver.ts.
|
|
15
|
+
import '../../next/registerSingleTenantResolver.js';
|
|
6
16
|
// Stub for the RSC export condition. The default `<FontdueProvider>` server
|
|
7
17
|
// entrypoint (this file) awaits the query for consumers, so RSC users should
|
|
8
18
|
// never call it manually. Re-exporting a throwing stub makes the mistake
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
|
|
2
|
+
import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
|
|
3
3
|
import { NewsletterSignupQuery } from '../../__generated__/NewsletterSignupQuery.graphql.js';
|
|
4
4
|
import { Config } from '../ConfigContext.js';
|
|
5
5
|
export type NewsletterSignupPreloadedQuery = SerializablePreloadedQuery<NewsletterSignupQuery>;
|
|
6
|
-
export declare function loadNewsletterSignupQuery(): Promise<NewsletterSignupPreloadedQuery>;
|
|
6
|
+
export declare function loadNewsletterSignupQuery(options?: LoadQueryOptions): Promise<NewsletterSignupPreloadedQuery>;
|
|
7
7
|
export interface NewsletterSignup_props {
|
|
8
8
|
optInLabel?: string;
|
|
9
9
|
successLabel?: string;
|
|
@@ -13,8 +13,8 @@ import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQ
|
|
|
13
13
|
import NewsletterSignupQueryNode from '../../__generated__/NewsletterSignupQuery.graphql.js';
|
|
14
14
|
import { EnsureFontdueContext } from '../FontdueContextProvider/index.js';
|
|
15
15
|
const updateCustomerMutation = (_NewsletterSignupUpdateCustomerMutation.hash && _NewsletterSignupUpdateCustomerMutation.hash !== "769087891b6f263122bbb630b3f2ca6c" && console.error("The definition of 'NewsletterSignupUpdateCustomerMutation' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NewsletterSignupUpdateCustomerMutation);
|
|
16
|
-
export async function loadNewsletterSignupQuery() {
|
|
17
|
-
return loadSerializableQuery(NewsletterSignupQueryNode, {});
|
|
16
|
+
export async function loadNewsletterSignupQuery(options) {
|
|
17
|
+
return loadSerializableQuery(NewsletterSignupQueryNode, {}, options);
|
|
18
18
|
}
|
|
19
19
|
const query = (_NewsletterSignupQuery.hash && _NewsletterSignupQuery.hash !== "24b303198a6038318723fc0124548862" && console.error("The definition of 'NewsletterSignupQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _NewsletterSignupQuery);
|
|
20
20
|
function NewsletterSignupComponent(_ref) {
|
|
@@ -71,11 +71,25 @@ const getInitialElements = () => {
|
|
|
71
71
|
return map;
|
|
72
72
|
};
|
|
73
73
|
const Root = props => {
|
|
74
|
+
var _props$config;
|
|
75
|
+
// The script-tag integration is client-only — there is no server render to
|
|
76
|
+
// forward a preview token to — so the admin toolbar must enter/exit preview
|
|
77
|
+
// by toggling the marker cookie in the browser. Force it on here, where the
|
|
78
|
+
// integration is unambiguously client-side. (The admin's Fontdue session
|
|
79
|
+
// rides the credentialed cross-origin GraphQL fetch and gates the reveal.)
|
|
80
|
+
const config = {
|
|
81
|
+
...props.config,
|
|
82
|
+
preview: {
|
|
83
|
+
...((_props$config = props.config) === null || _props$config === void 0 ? void 0 : _props$config.preview),
|
|
84
|
+
clientSide: true
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
74
88
|
// use a Map here instead of an array in case we register the same element
|
|
75
89
|
// more than once (otherwise we run into issues rendering the component
|
|
76
90
|
// twice into the same element). this also gives us a way to set unique keys.
|
|
77
91
|
const [elements, setElements] = useState(getInitialElements());
|
|
78
|
-
const store = useRef(createDefaultStore(
|
|
92
|
+
const store = useRef(createDefaultStore(config));
|
|
79
93
|
useEffect(() => {
|
|
80
94
|
// watch for any new or removed fontdue elements
|
|
81
95
|
|
|
@@ -190,7 +204,7 @@ const Root = props => {
|
|
|
190
204
|
return /*#__PURE__*/React.createElement(FontdueProvider, {
|
|
191
205
|
url: props.url,
|
|
192
206
|
stripeIntegration: props.stripeIntegration,
|
|
193
|
-
config:
|
|
207
|
+
config: config,
|
|
194
208
|
components: props.components,
|
|
195
209
|
store: store.current
|
|
196
210
|
}, /*#__PURE__*/React.createElement(React.Fragment, null, Array.from(elements).map(_ref => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TestFontsForm_Query } from '../../__generated__/TestFontsForm_Query.graphql.js';
|
|
3
|
-
import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
|
|
3
|
+
import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
|
|
4
4
|
import { Config } from '../ConfigContext.js';
|
|
5
5
|
export interface TestFontsForm_props {
|
|
6
6
|
agreementLabel?: string;
|
|
@@ -8,7 +8,7 @@ export interface TestFontsForm_props {
|
|
|
8
8
|
newsletterCheckboxChecked?: boolean;
|
|
9
9
|
}
|
|
10
10
|
export type TestFontsFormPreloadedQuery = SerializablePreloadedQuery<TestFontsForm_Query>;
|
|
11
|
-
export declare function loadTestFontsFormQuery(): Promise<TestFontsFormPreloadedQuery>;
|
|
11
|
+
export declare function loadTestFontsFormQuery(options?: LoadQueryOptions): Promise<TestFontsFormPreloadedQuery>;
|
|
12
12
|
export declare function TestFontsFormPreloadedQueryRenderer({ preloadedQuery, ...rest }: TestFontsForm_props & {
|
|
13
13
|
preloadedQuery: TestFontsFormPreloadedQuery;
|
|
14
14
|
}): React.JSX.Element;
|
|
@@ -194,8 +194,8 @@ const TestFontsFormComponent = _ref2 => {
|
|
|
194
194
|
}));
|
|
195
195
|
};
|
|
196
196
|
const query = (_TestFontsForm_Query.hash && _TestFontsForm_Query.hash !== "cd43f0cacc4dcf01cf94fb1ff97197ca" && 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);
|
|
197
|
-
export async function loadTestFontsFormQuery() {
|
|
198
|
-
return loadSerializableQuery(TestFontsFormQueryNode, {});
|
|
197
|
+
export async function loadTestFontsFormQuery(options) {
|
|
198
|
+
return loadSerializableQuery(TestFontsFormQueryNode, {}, options);
|
|
199
199
|
}
|
|
200
200
|
export function TestFontsFormPreloadedQueryRenderer(_ref4) {
|
|
201
201
|
let {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Alignment, Direction, FeaturesProp } from './types.js';
|
|
3
|
-
import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
|
|
3
|
+
import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
|
|
4
4
|
import { TypeTesterStandaloneQuery } from '../../__generated__/TypeTesterStandaloneQuery.graphql.js';
|
|
5
5
|
import { Config } from '../ConfigContext.js';
|
|
6
6
|
interface TypeTesterStandaloneComponent_props {
|
|
@@ -30,7 +30,7 @@ export interface LoadTypeTesterQueryVariables {
|
|
|
30
30
|
familyName: string;
|
|
31
31
|
styleName: string;
|
|
32
32
|
}
|
|
33
|
-
export declare function loadTypeTesterQuery(variables: LoadTypeTesterQueryVariables): Promise<TypeTesterPreloadedQuery>;
|
|
33
|
+
export declare function loadTypeTesterQuery(variables: LoadTypeTesterQueryVariables, options?: LoadQueryOptions): Promise<TypeTesterPreloadedQuery>;
|
|
34
34
|
export declare function TypeTesterStandalonePreloadedQueryRenderer({ preloadedQuery, ...rest }: TypeTesterStandaloneComponent_props & {
|
|
35
35
|
preloadedQuery: TypeTesterPreloadedQuery;
|
|
36
36
|
}): React.JSX.Element;
|
|
@@ -100,11 +100,11 @@ function TypeTesterStandaloneComponent(_ref) {
|
|
|
100
100
|
}));
|
|
101
101
|
}
|
|
102
102
|
const query = (_TypeTesterStandaloneQuery.hash && _TypeTesterStandaloneQuery.hash !== "951214eacb2370ea3ca0b19bebe7fbe7" && console.error("The definition of 'TypeTesterStandaloneQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _TypeTesterStandaloneQuery);
|
|
103
|
-
export async function loadTypeTesterQuery(variables) {
|
|
103
|
+
export async function loadTypeTesterQuery(variables, options) {
|
|
104
104
|
return loadSerializableQuery(TypeTesterStandaloneQueryNode, {
|
|
105
105
|
familyName: variables.familyName,
|
|
106
106
|
styleName: variables.styleName
|
|
107
|
-
});
|
|
107
|
+
}, options);
|
|
108
108
|
}
|
|
109
109
|
export function TypeTesterStandalonePreloadedQueryRenderer(_ref3) {
|
|
110
110
|
let {
|
|
@@ -142,12 +142,14 @@ const TypeTester = _ref => {
|
|
|
142
142
|
}, _ref3 => {
|
|
143
143
|
let {
|
|
144
144
|
loaded,
|
|
145
|
-
style
|
|
145
|
+
style,
|
|
146
|
+
verticalMetrics
|
|
146
147
|
} = _ref3;
|
|
147
148
|
if (loaded) {
|
|
148
149
|
return /*#__PURE__*/React.createElement(TypeTesterContent, _extends({}, props, {
|
|
149
150
|
ref: contentRef,
|
|
150
151
|
fontStyles: style,
|
|
152
|
+
verticalMetrics: verticalMetrics,
|
|
151
153
|
truncate: config.truncate,
|
|
152
154
|
direction: props.direction,
|
|
153
155
|
min: config.size.min,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EditorState } from 'draft-js';
|
|
2
2
|
import { Alignment } from './types.js';
|
|
3
3
|
import { VariableSettings } from '../../utils.js';
|
|
4
|
+
import { VerticalMetrics } from '../useFontStyle.js';
|
|
4
5
|
export type ColumnsConfig = false | {
|
|
5
6
|
count: 'auto' | number;
|
|
6
7
|
width: string;
|
|
@@ -21,13 +22,14 @@ export interface UseTypeTesterStylerProps {
|
|
|
21
22
|
focused: boolean;
|
|
22
23
|
truncate: boolean | number;
|
|
23
24
|
fontStyles: React.CSSProperties;
|
|
25
|
+
verticalMetrics?: VerticalMetrics | null;
|
|
24
26
|
content: EditorState;
|
|
25
27
|
contentEdited: boolean;
|
|
26
28
|
alignment: Alignment;
|
|
27
29
|
variableSettings: VariableSettings | null;
|
|
28
30
|
columns: ColumnsConfig;
|
|
29
31
|
}
|
|
30
|
-
declare const useTypeTesterStyler: ({ size, autofit, autofitOnChange, features, setSize, min, max, truncate, focused, lineHeight, letterSpacing, fontStyles, content, contentEdited, alignment, variableSettings, columns, }: UseTypeTesterStylerProps) => {
|
|
32
|
+
declare const useTypeTesterStyler: ({ size, autofit, autofitOnChange, features, setSize, min, max, truncate, focused, lineHeight, letterSpacing, fontStyles, verticalMetrics, content, contentEdited, alignment, variableSettings, columns, }: UseTypeTesterStylerProps) => {
|
|
31
33
|
ref: import("react").RefObject<HTMLDivElement | null>;
|
|
32
34
|
style: import("react").CSSProperties;
|
|
33
35
|
};
|
|
@@ -15,6 +15,7 @@ const useTypeTesterStyler = _ref => {
|
|
|
15
15
|
lineHeight,
|
|
16
16
|
letterSpacing,
|
|
17
17
|
fontStyles,
|
|
18
|
+
verticalMetrics,
|
|
18
19
|
content,
|
|
19
20
|
contentEdited,
|
|
20
21
|
alignment,
|
|
@@ -58,33 +59,82 @@ const useTypeTesterStyler = _ref => {
|
|
|
58
59
|
const truncateLines = truncate === true ? 1 : typeof truncate === 'number' ? Math.max(0, Math.floor(truncate)) : 0;
|
|
59
60
|
const shouldTruncate = truncateLines > 0 && !focused;
|
|
60
61
|
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
|
|
62
|
+
// How far a line's ink spills past its line-box, top and bottom, as a fraction
|
|
63
|
+
// of the font-size (em). `fontLoader` feeds these exact metrics into the
|
|
64
|
+
// @font-face as ascent/descent-override, so this matches the browser's line
|
|
65
|
+
// geometry precisely. It is 0 once the line-height is at least the font's
|
|
66
|
+
// natural content height ((ascender − descender) / unitsPerEm) — i.e. for any
|
|
67
|
+
// normal reading line-height — and only grows for tight, overlapping setting.
|
|
68
|
+
// Kept in em (not px) so it scales with the *rendered* size, including the
|
|
69
|
+
// `--type-tester--adjustment` that shrinks the preview on mobile.
|
|
70
|
+
const lineOverflowEm = shouldTruncate && verticalMetrics && verticalMetrics.unitsPerEm > 0 ? Math.max(0, ((verticalMetrics.ascender - verticalMetrics.descender) / verticalMetrics.unitsPerEm - lineHeight) / 2) : 0;
|
|
71
|
+
|
|
72
|
+
// Columns are what make truncation overflow flow sideways — into clipped,
|
|
73
|
+
// off-screen columns — instead of stacking below the last visible line. That
|
|
74
|
+
// is what lets the metric padding reveal descenders/ascenders cleanly, and it
|
|
75
|
+
// means a multi-column tester (e.g. a 3-column specimen) truncates to
|
|
76
|
+
// `truncateLines` lines *per column*. When truncating with columns disabled we
|
|
77
|
+
// still establish a single column so the clipped overflow behaves the same way.
|
|
78
|
+
const columnStyle = columns ? {
|
|
79
|
+
columnCount: columns.count,
|
|
80
|
+
columnWidth: columns.width,
|
|
81
|
+
columnGap: columns.gap
|
|
82
|
+
} : undefined;
|
|
83
|
+
|
|
84
|
+
// A glyph's side bearings — ink that sits outside its advance width, like a
|
|
85
|
+
// leading lowercase 'j' or an italic overhang — would be shorn by the inline
|
|
86
|
+
// clip. Per-glyph bearings aren't in the font metrics, so reserve a flat 0.1em
|
|
87
|
+
// on each inline edge and cancel it with a negative margin so
|
|
88
|
+
// wrapping and text position stay put.
|
|
89
|
+
const sideBearing = shouldTruncate ? '0.1em' : '0px';
|
|
65
90
|
const style = {
|
|
66
91
|
fontSize: autofit ? `${size}px` : `calc(var(--type-tester--adjustment, 1) * ${size}px)`,
|
|
67
92
|
lineHeight: `${lineHeight}`,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
93
|
+
...(shouldTruncate ? {
|
|
94
|
+
// Cap each column at `truncateLines` lines. `max-height` (not `height`)
|
|
95
|
+
// lets shorter paragraphs collapse to their content instead of padding
|
|
96
|
+
// out to N lines of whitespace. Columns send the clipped overflow
|
|
97
|
+
// sideways (into off-screen columns) rather than below, so the last
|
|
98
|
+
// visible line of every column is never partially covered by the next
|
|
99
|
+
// one. That lets the symmetric `lineOverflowEm` padding fully reveal the
|
|
100
|
+
// first line's ascenders/accents and the last line's descenders at any
|
|
101
|
+
// line-height; the negative margins cancel that padding in layout so a
|
|
102
|
+
// collapsed paragraph still occupies exactly its line count.
|
|
103
|
+
//
|
|
104
|
+
// Everything is in `em` so it tracks the rendered font-size (including
|
|
105
|
+
// the mobile `--type-tester--adjustment`); the `+ 2px` is slack that
|
|
106
|
+
// keeps sub-pixel rounding from dropping the Nth line (the extra never
|
|
107
|
+
// reveals line N+1 because that line is clipped out to the side).
|
|
108
|
+
boxSizing: 'border-box',
|
|
109
|
+
maxHeight: `calc(${truncateLines * lineHeight + 2 * lineOverflowEm}em + 2px)`,
|
|
110
|
+
paddingTop: `${lineOverflowEm}em`,
|
|
111
|
+
paddingBottom: `${lineOverflowEm}em`,
|
|
112
|
+
paddingLeft: sideBearing,
|
|
113
|
+
paddingRight: sideBearing,
|
|
114
|
+
marginTop: `${-lineOverflowEm}em`,
|
|
115
|
+
marginBottom: `${-lineOverflowEm}em`,
|
|
116
|
+
overflow: 'hidden',
|
|
117
|
+
// Fill each column to its full N lines before spilling to the next, and
|
|
118
|
+
// allow a final column with a single line — otherwise the default
|
|
119
|
+
// `widows: 2` / `column-fill: balance` rebalance a 4-line paragraph into
|
|
120
|
+
// two columns of 2, showing N−1 lines instead of N.
|
|
121
|
+
columnFill: 'auto',
|
|
122
|
+
widows: 1,
|
|
123
|
+
orphans: 1,
|
|
124
|
+
...(columnStyle ?? {
|
|
125
|
+
columnCount: 1
|
|
126
|
+
})
|
|
127
|
+
} : {
|
|
128
|
+
height: 'auto',
|
|
129
|
+
overflow: 'visible',
|
|
130
|
+
...columnStyle
|
|
76
131
|
}),
|
|
77
132
|
fontFeatureSettings,
|
|
78
|
-
marginRight: alignment !== 'right' ? -sideBuffer : 0
|
|
79
|
-
marginLeft: alignment === 'right' ? -sideBuffer : 0
|
|
133
|
+
marginRight: `calc(${alignment !== 'right' ? -sideBuffer : 0}px - ${sideBearing})`,
|
|
134
|
+
marginLeft: `calc(${alignment === 'right' ? -sideBuffer : 0}px - ${sideBearing})`,
|
|
80
135
|
letterSpacing: `${letterSpacing}em`,
|
|
81
136
|
fontVariationSettings,
|
|
82
|
-
textAlign: alignment
|
|
83
|
-
...(columns && {
|
|
84
|
-
columnCount: columns.count,
|
|
85
|
-
columnWidth: columns.width,
|
|
86
|
-
columnGap: columns.gap
|
|
87
|
-
})
|
|
137
|
+
textAlign: alignment
|
|
88
138
|
};
|
|
89
139
|
return {
|
|
90
140
|
ref,
|
|
@@ -3,7 +3,7 @@ import { TypeTestersIDQuery } from '../../__generated__/TypeTestersIDQuery.graph
|
|
|
3
3
|
import { TypeTestersSlugQuery } from '../../__generated__/TypeTestersSlugQuery.graphql.js';
|
|
4
4
|
import { Config } from '../ConfigContext.js';
|
|
5
5
|
import { FeaturesProp } from '../TypeTester/types.js';
|
|
6
|
-
import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
|
|
6
|
+
import { SerializablePreloadedQuery, type LoadQueryOptions } from '../../relay/loadSerializableQuery.js';
|
|
7
7
|
export interface TypeTesters_props {
|
|
8
8
|
collectionId?: string;
|
|
9
9
|
collectionSlug?: string;
|
|
@@ -33,7 +33,7 @@ export type LoadTypeTestersQueryVariables = ({
|
|
|
33
33
|
tags?: string[] | null;
|
|
34
34
|
excludeTags?: string[] | null;
|
|
35
35
|
};
|
|
36
|
-
export declare function loadTypeTestersQuery(variables: LoadTypeTestersQueryVariables): Promise<TypeTestersPreloadedQuery>;
|
|
36
|
+
export declare function loadTypeTestersQuery(variables: LoadTypeTestersQueryVariables, options?: LoadQueryOptions): Promise<TypeTestersPreloadedQuery>;
|
|
37
37
|
export type TypeTesters_unifiedProps = TypeTesters_props & {
|
|
38
38
|
preloadedQuery?: TypeTestersPreloadedQuery;
|
|
39
39
|
config?: Config;
|
|
@@ -251,7 +251,7 @@ function TypeTestersSlugQueryRenderer(_ref6) {
|
|
|
251
251
|
excludeTags: excludeTags
|
|
252
252
|
}));
|
|
253
253
|
}
|
|
254
|
-
export async function loadTypeTestersQuery(variables) {
|
|
254
|
+
export async function loadTypeTestersQuery(variables, options) {
|
|
255
255
|
const tags = variables.tags ?? null;
|
|
256
256
|
const excludeTags = variables.excludeTags ?? null;
|
|
257
257
|
if (variables.collectionId) {
|
|
@@ -259,14 +259,14 @@ export async function loadTypeTestersQuery(variables) {
|
|
|
259
259
|
collectionId: variables.collectionId,
|
|
260
260
|
tags,
|
|
261
261
|
excludeTags
|
|
262
|
-
});
|
|
262
|
+
}, options);
|
|
263
263
|
}
|
|
264
264
|
if (variables.collectionSlug) {
|
|
265
265
|
return loadSerializableQuery(TypeTestersSlugQueryNode, {
|
|
266
266
|
collectionSlug: variables.collectionSlug,
|
|
267
267
|
tags,
|
|
268
268
|
excludeTags
|
|
269
|
-
});
|
|
269
|
+
}, options);
|
|
270
270
|
}
|
|
271
271
|
throw new Error('loadTypeTestersQuery expected either collectionId or collectionSlug');
|
|
272
272
|
}
|
|
@@ -75,6 +75,7 @@ import StripeLogo from '../StripeLogo.js';
|
|
|
75
75
|
import { Check, X } from '../Icons/index.js';
|
|
76
76
|
import ConfigContext from '../ConfigContext.js';
|
|
77
77
|
import { Price } from '../Price/index.js';
|
|
78
|
+
import { sendOrderTracking } from '../Cart/orderTracking.js';
|
|
78
79
|
|
|
79
80
|
/* const LICENSEE_REQUIRED_FIELDS = ['organization', 'country'] as (keyof Identity)[]; */
|
|
80
81
|
|
|
@@ -274,6 +275,13 @@ export default function StoreModalUnifiedCheckout(_ref2) {
|
|
|
274
275
|
}));
|
|
275
276
|
}, [setLicenseeIdentity]);
|
|
276
277
|
const environment = useRelayEnvironment();
|
|
278
|
+
|
|
279
|
+
// Capture analytics consent + attribution on the order for the purchase
|
|
280
|
+
// event the server emits on completion (from a Stripe webhook, where no
|
|
281
|
+
// browser context exists).
|
|
282
|
+
useEffect(() => {
|
|
283
|
+
sendOrderTracking(environment);
|
|
284
|
+
}, [environment]);
|
|
277
285
|
const [error, setError] = useState(null);
|
|
278
286
|
const [errorsObject, setErrorsObject] = useState(null);
|
|
279
287
|
const [customerErrorsObject, setCustomerErrorsObject] = useState(null);
|
|
@@ -3,8 +3,16 @@ import { useFontStyle_fontStyle$key } from '../__generated__/useFontStyle_fontSt
|
|
|
3
3
|
interface UseFontStyle_props {
|
|
4
4
|
fontStyle: useFontStyle_fontStyle$key | null | undefined;
|
|
5
5
|
}
|
|
6
|
+
export type VerticalMetrics = {
|
|
7
|
+
readonly unitsPerEm: number;
|
|
8
|
+
readonly ascender: number;
|
|
9
|
+
readonly descender: number;
|
|
10
|
+
readonly lineGap: number | null;
|
|
11
|
+
readonly avgCharWidth: number | null;
|
|
12
|
+
};
|
|
6
13
|
declare const useFontStyle: ({ fontStyle: fontStyleKey, }: UseFontStyle_props) => {
|
|
7
14
|
style: React.CSSProperties;
|
|
8
15
|
loaded: boolean;
|
|
16
|
+
verticalMetrics: VerticalMetrics | null;
|
|
9
17
|
};
|
|
10
18
|
export default useFontStyle;
|
|
@@ -2,12 +2,13 @@ import _useFontStyle_fontStyle from "../__generated__/useFontStyle_fontStyle.gra
|
|
|
2
2
|
import { useState, useRef, useEffect } from 'react';
|
|
3
3
|
import { graphql, useFragment } from 'react-relay';
|
|
4
4
|
import { loadFont, isFontLoaded } from '../fontLoader.js';
|
|
5
|
+
import { ensureMetricFallback, metricFallbackFamily } from '../metricFallback.js';
|
|
5
6
|
const FALLBACK_FAMILY = 'Fallback';
|
|
6
7
|
const useFontStyle = _ref => {
|
|
7
8
|
let {
|
|
8
9
|
fontStyle: fontStyleKey
|
|
9
10
|
} = _ref;
|
|
10
|
-
const fontStyle = useFragment((_useFontStyle_fontStyle.hash && _useFontStyle_fontStyle.hash !== "
|
|
11
|
+
const fontStyle = useFragment((_useFontStyle_fontStyle.hash && _useFontStyle_fontStyle.hash !== "171c546f40909692656c5e143a98d8a3" && console.error("The definition of 'useFontStyle_fontStyle' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _useFontStyle_fontStyle), fontStyleKey ?? null);
|
|
11
12
|
const fontFamily = fontStyle ? `${fontStyle.cssFamily} ${fontStyle.name}` : null;
|
|
12
13
|
const sources = fontStyle === null || fontStyle === void 0 ? void 0 : fontStyle.webfontSources;
|
|
13
14
|
const verticalMetrics = fontStyle === null || fontStyle === void 0 ? void 0 : fontStyle.verticalMetrics;
|
|
@@ -24,6 +25,10 @@ const useFontStyle = _ref => {
|
|
|
24
25
|
}, []);
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
if (!fontFamily) return;
|
|
28
|
+
|
|
29
|
+
// Register a metric-matched fallback so the placeholder dots occupy this
|
|
30
|
+
// font's box (no reflow on swap-in, matched dots for missing glyphs).
|
|
31
|
+
if (verticalMetrics) ensureMetricFallback(fontFamily, verticalMetrics);
|
|
27
32
|
if (isFontLoaded(fontFamily)) {
|
|
28
33
|
setLoaded(true);
|
|
29
34
|
return;
|
|
@@ -34,18 +39,23 @@ const useFontStyle = _ref => {
|
|
|
34
39
|
if (mounted.current) setLoaded(true);
|
|
35
40
|
}).catch(console.error);
|
|
36
41
|
}, [fontFamily]);
|
|
42
|
+
|
|
43
|
+
// Prefer the metric-matched fallback (when this font has metrics), with the
|
|
44
|
+
// generic Fallback as the ultimate catch-all.
|
|
45
|
+
const fallbackChain = fontFamily && verticalMetrics && verticalMetrics.unitsPerEm > 0 ? `"${metricFallbackFamily(fontFamily)}", ${FALLBACK_FAMILY}` : FALLBACK_FAMILY;
|
|
37
46
|
const cssStyle = loaded && fontFamily ? {
|
|
38
|
-
fontFamily: `"${fontFamily}", ${
|
|
47
|
+
fontFamily: `"${fontFamily}", ${fallbackChain}`,
|
|
39
48
|
fontWeight: 400,
|
|
40
49
|
fontStyle: 'normal'
|
|
41
50
|
} : {
|
|
42
|
-
fontFamily:
|
|
51
|
+
fontFamily: fallbackChain,
|
|
43
52
|
fontWeight: 'normal',
|
|
44
53
|
fontStyle: 'normal'
|
|
45
54
|
};
|
|
46
55
|
return {
|
|
47
56
|
style: cssStyle,
|
|
48
|
-
loaded
|
|
57
|
+
loaded,
|
|
58
|
+
verticalMetrics: verticalMetrics ?? null
|
|
49
59
|
};
|
|
50
60
|
};
|
|
51
61
|
export default useFontStyle;
|
package/dist/corsError.d.ts
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
export declare function
|
|
2
|
-
export interface CorsError {
|
|
3
|
-
origin: string;
|
|
4
|
-
fontdueUrl: string;
|
|
5
|
-
}
|
|
1
|
+
export declare function setConnectionErrorUiEnabled(enabled: boolean): void;
|
|
6
2
|
export declare function handlePossibleCorsError(error: unknown, fetchUrl: string): boolean;
|
package/dist/corsError.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import retryImport from './retryImport.js';
|
|
2
2
|
let detected = false;
|
|
3
3
|
let navigating = false;
|
|
4
|
-
let
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
let connectionErrorUiEnabled = true;
|
|
5
|
+
|
|
6
|
+
// Gate for the visible connection-error UI (the admin toolbar's status). Wired
|
|
7
|
+
// from the `corsErrorModal` config option (legacy name, kept for
|
|
8
|
+
// compatibility). When disabled we still log and keep polling for recovery — we
|
|
9
|
+
// just never publish a status for the toolbar to surface.
|
|
10
|
+
export function setConnectionErrorUiEnabled(enabled) {
|
|
11
|
+
connectionErrorUiEnabled = enabled;
|
|
7
12
|
}
|
|
8
13
|
if (typeof window !== 'undefined') {
|
|
9
14
|
window.addEventListener('beforeunload', () => {
|
|
@@ -45,17 +50,22 @@ async function isCorsBlocked(fetchUrl) {
|
|
|
45
50
|
return false; // server unreachable, network error
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
|
-
function
|
|
49
|
-
console.error(`[Fontdue] Cross-origin request to ${fetchUrl} was blocked.\n\n` + `Your website (${origin}) is not listed as an allowed
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
function publishConnectionError(origin, fetchUrl) {
|
|
54
|
+
console.error(`[Fontdue] Cross-origin request to ${fetchUrl} was blocked.\n\n` + `Your website (${origin}) is most likely not listed as an allowed ` + `origin in your Fontdue settings.\n\n` + `To fix this:\n` + `1. Log in to your Fontdue dashboard\n` + `2. Go to Settings → Integration\n` + `3. Add "${origin}" to your allowed origins\n` + `4. Save — this page will reload automatically\n\n` + `If "${origin}" is already listed, the connection may be failing for ` + `another reason (a network problem or a temporary Fontdue outage).`);
|
|
55
|
+
|
|
56
|
+
// Surface the connection status as a compact, toolbar-styled widget (red
|
|
57
|
+
// button + alert glyph) rather than the old full-screen modal. It mounts in
|
|
58
|
+
// its own React root — see ConnectionErrorToolbar for why it isn't part of
|
|
59
|
+
// the in-tree admin toolbar.
|
|
60
|
+
if (connectionErrorUiEnabled) {
|
|
61
|
+
retryImport(() => import('./components/ConnectionErrorToolbar.js')).then(_ref => {
|
|
52
62
|
let {
|
|
53
|
-
|
|
63
|
+
renderConnectionErrorToolbar
|
|
54
64
|
} = _ref;
|
|
55
|
-
|
|
65
|
+
renderConnectionErrorToolbar(origin, fetchUrl);
|
|
56
66
|
}).catch(() => {
|
|
57
|
-
// Chunk failed to load — the console.error above already
|
|
58
|
-
//
|
|
67
|
+
// Chunk failed to load — the console.error above already told the
|
|
68
|
+
// developer what's wrong.
|
|
59
69
|
});
|
|
60
70
|
}
|
|
61
71
|
startPolling(fetchUrl);
|
|
@@ -72,10 +82,10 @@ export function handlePossibleCorsError(error, fetchUrl) {
|
|
|
72
82
|
// Verify this is actually a CORS error and not a network failure.
|
|
73
83
|
// We do this async — handlePossibleCorsError still returns true
|
|
74
84
|
// synchronously so the caller can return a stub response instead
|
|
75
|
-
// of throwing, but we only
|
|
85
|
+
// of throwing, but we only surface a status if CORS is confirmed.
|
|
76
86
|
isCorsBlocked(fetchUrl).then(blocked => {
|
|
77
87
|
if (blocked) {
|
|
78
|
-
|
|
88
|
+
publishConnectionError(origin, fetchUrl);
|
|
79
89
|
} else {
|
|
80
90
|
// Network error, not CORS — reset so a real CORS error
|
|
81
91
|
// can still be detected if connectivity recovers.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { UNICODE_NAMES_VERSION } from './unicodeNamesVersion.js';
|
|
2
|
+
|
|
3
|
+
// The unicode code-point→name map (~1.2 MB) is not bundled — it's served as a
|
|
4
|
+
// static, immutable JSON asset from the Fontdue CDN and fetched at runtime by
|
|
5
|
+
// CharacterViewer. The filename is content-hashed (UNICODE_NAMES_VERSION) so it
|
|
6
|
+
// can be cached forever; a data change produces a new filename.
|
|
7
|
+
//
|
|
8
|
+
// The asset is uploaded to the CDN under `/js/dist/` by the data-refresh flow
|
|
9
|
+
// (`npm run update-unicode-data`, which also runs `npm run publish-unicode-data`)
|
|
10
|
+
// — not by the npm publish or the app deploy. See fontdue-js/src/scripts.
|
|
11
|
+
//
|
|
12
|
+
// `/js/dist/` is the path every Fontdue CDN asset is served from on the cdn.*
|
|
13
|
+
// hosts (the bucket's `js/` prefix served at root); it is NOT a bare `/dist/`.
|
|
14
|
+
export const FONTDUE_CDN_URL = 'https://cdn.fontdue.com';
|
|
15
|
+
export function unicodeNamesUrl() {
|
|
16
|
+
let cdnUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : FONTDUE_CDN_URL;
|
|
17
|
+
return `${cdnUrl.replace(/\/+$/, '')}/js/dist/unicode-names.${UNICODE_NAMES_VERSION}.json`;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const UNICODE_NAMES_VERSION = "3132bac0592155bd";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const FALLBACK_FONT_WOFF2_BASE64 = "d09GMgABAAAAAADYAAoAAAAAAfAAAACQAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABk4AKAoYNwsGAAE2AiQDBgQgBQYHIBtSAciuDmzHfIwcg7zyGj36BfE8dGnv70xqs5AX4ZCucZY0yTXRgFyjzRELyQwA4SlI9ET4Ii+c/07ghH6YVABETR5hoAGnbXd2cSn13Et3RDHF3AIcAQHrPgIaUBFUDAEVkHqdmd4ObdsCQfj6X6u/lfICANClyCgaEMqrR546XQgAIHmiEzSqgAYAAAwVAAAA";
|
|
2
|
+
export declare const FALLBACK_ADVANCE_PER_EM = 0.458;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Generated by scripts/generate_fallback_font.py — do not edit by hand.
|
|
2
|
+
//
|
|
3
|
+
// The universal minimal fallback font (renders a dot for every Unicode
|
|
4
|
+
// codepoint), embedded as base64 so per-family metric-matched fallbacks can
|
|
5
|
+
// be built at runtime via the FontFace API (see metricFallback.ts).
|
|
6
|
+
export const FALLBACK_FONT_WOFF2_BASE64 = 'd09GMgABAAAAAADYAAoAAAAAAfAAAACQAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABk4AKAoYNwsGAAE2AiQDBgQgBQYHIBtSAciuDmzHfIwcg7zyGj36BfE8dGnv70xqs5AX4ZCucZY0yTXRgFyjzRELyQwA4SlI9ET4Ii+c/07ghH6YVABETR5hoAGnbXd2cSn13Et3RDHF3AIcAQHrPgIaUBFUDAEVkHqdmd4ObdsCQfj6X6u/lfICANClyCgaEMqrR546XQgAIHmiEzSqgAYAAAwVAAAA';
|
|
7
|
+
|
|
8
|
+
// The dot font's intrinsic average advance, in em — every glyph advances
|
|
9
|
+
// 458/1000 em. Used as the denominator when computing `size-adjust`.
|
|
10
|
+
export const FALLBACK_ADVANCE_PER_EM = 0.458;
|