fontdue-js 2.22.4 → 2.23.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/__generated__/CartItemAdditionalLicenses_orderItem.graphql.d.ts +4 -1
  3. package/dist/__generated__/CartItemAdditionalLicenses_orderItem.graphql.js +34 -22
  4. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.d.ts +1 -1
  5. package/dist/__generated__/CartOrderCompleteOrderMutation.graphql.js +13 -4
  6. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.d.ts +1 -1
  7. package/dist/__generated__/CartOrderRemoveDiscountMutation.graphql.js +13 -4
  8. package/dist/__generated__/CartOrderUpdateMutation.graphql.d.ts +1 -1
  9. package/dist/__generated__/CartOrderUpdateMutation.graphql.js +13 -4
  10. package/dist/__generated__/CartQuery.graphql.d.ts +1 -1
  11. package/dist/__generated__/CartQuery.graphql.js +13 -4
  12. package/dist/__generated__/CartStateUpdateMutation.graphql.d.ts +1 -1
  13. package/dist/__generated__/CartStateUpdateMutation.graphql.js +13 -4
  14. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.d.ts +1 -1
  15. package/dist/__generated__/CheckoutUpdateCustomerMutation.graphql.js +13 -4
  16. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.d.ts +1 -1
  17. package/dist/__generated__/CheckoutUpdateOrderMutation.graphql.js +13 -4
  18. package/dist/__generated__/FontdueProviderQuery.graphql.d.ts +19 -0
  19. package/dist/__generated__/FontdueProviderQuery.graphql.js +140 -0
  20. package/dist/__generated__/PrecartAddToCartMutation.graphql.d.ts +1 -1
  21. package/dist/__generated__/PrecartAddToCartMutation.graphql.js +34 -25
  22. package/dist/__generated__/PrecartQuery.graphql.d.ts +1 -1
  23. package/dist/__generated__/PrecartQuery.graphql.js +17 -7
  24. package/dist/__generated__/Precart_collection.graphql.d.ts +4 -1
  25. package/dist/__generated__/Precart_collection.graphql.js +13 -3
  26. package/dist/__generated__/Precart_license.graphql.d.ts +4 -1
  27. package/dist/__generated__/Precart_license.graphql.js +19 -9
  28. package/dist/__generated__/ServerConfigProvider_viewer.graphql.d.ts +23 -0
  29. package/dist/__generated__/ServerConfigProvider_viewer.graphql.js +57 -0
  30. package/dist/__generated__/StoreModalCartQuery.graphql.d.ts +1 -1
  31. package/dist/__generated__/StoreModalCartQuery.graphql.js +13 -4
  32. package/dist/__generated__/StoreModalProductLicense_license.graphql.d.ts +4 -1
  33. package/dist/__generated__/StoreModalProductLicense_license.graphql.js +11 -2
  34. package/dist/__generated__/StoreModalProductQuery.graphql.d.ts +1 -1
  35. package/dist/__generated__/StoreModalProductQuery.graphql.js +12 -3
  36. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.d.ts +1 -1
  37. package/dist/__generated__/StoreModalProductRefetchQuery.graphql.js +42 -32
  38. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.d.ts +1 -1
  39. package/dist/__generated__/TestFontsFormUpdateCustomerMutation.graphql.js +13 -4
  40. package/dist/__generated__/TestModeBanner_viewer.graphql.d.ts +19 -0
  41. package/dist/__generated__/TestModeBanner_viewer.graphql.js +36 -0
  42. package/dist/__generated__/ThemeConfig_viewer.graphql.d.ts +19 -0
  43. package/dist/__generated__/ThemeConfig_viewer.graphql.js +36 -0
  44. package/dist/__tests__/licenseExclusions.test.js +161 -0
  45. package/dist/components/BuyingOptions/index.d.ts +9 -0
  46. package/dist/components/Cart/CartItem/CartItemAdditionalLicenses.js +11 -5
  47. package/dist/components/CookieNotification/index.d.ts +13 -0
  48. package/dist/components/FontdueContextProvider/index.d.ts +17 -0
  49. package/dist/components/FontdueContextProvider/index.js +108 -0
  50. package/dist/components/FontdueContextProvider/index.server.d.ts +4 -0
  51. package/dist/components/FontdueContextProvider/index.server.js +7 -0
  52. package/dist/components/Precart/index.js +12 -7
  53. package/dist/components/StoreModalProductLicenseSelection/StoreModalProductLicense.js +10 -4
  54. package/dist/components/TypeTester/TypeTesterStandalone.preload.d.ts +3 -3
  55. package/dist/components/TypeTester/TypeTesterStandalone.preload.js +10 -9
  56. package/dist/config.d.ts +2 -1
  57. package/dist/config.js +17 -6
  58. package/dist/hooks/useResizeObserver.d.ts +11 -0
  59. package/dist/hooks/useResizeObserver.js +23 -0
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.js +1 -1
  62. package/dist/loadFontdueProviderQuery.d.ts +3 -0
  63. package/dist/loadFontdueProviderQuery.js +10 -0
  64. package/dist/reducer.d.ts +2 -0
  65. package/dist/reducer.js +3 -1
  66. package/dist/vite.d.ts +2 -0
  67. package/dist/vite.js +139 -0
  68. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import loadSerializableQuery from '../../relay/loadSerializableQuery';
3
- import TypeTesterStandaloneQueryNode from '../../__generated__/TypeTesterStandaloneQuery.graphql';
4
- import FontdueProvider from '../FontdueProvider';
5
- import { TypeTesterStandalonePreloadedQueryRenderer } from './TypeTesterStandalone';
2
+ import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
3
+ import TypeTesterStandaloneQueryNode from '../../__generated__/TypeTesterStandaloneQuery.graphql.js';
4
+ import FontdueContextProvider from '../FontdueContextProvider/index.js';
5
+ import { TypeTesterStandalonePreloadedQueryRenderer } from './TypeTesterStandalone.js';
6
6
  export async function loadTypeTesterQuery(variables, options) {
7
7
  return loadSerializableQuery(TypeTesterStandaloneQueryNode, {
8
8
  familyName: variables.familyName,
@@ -10,10 +10,11 @@ export async function loadTypeTesterQuery(variables, options) {
10
10
  selectable: variables.selectable ?? true
11
11
  }, options);
12
12
  }
13
- // Self-wraps with FontdueProvider so consumers don't need to. The provider
14
- // state is a module-level singleton under the hood, so multiple
15
- // TypeTesterPreloaded (or other *Preloaded) components on a page all share
16
- // one Relay env + Redux store + auxiliary UI.
13
+ // Self-wraps with FontdueContextProvider so consumers don't need to wire up
14
+ // Relay env / Redux store / contexts at the call site. Aux UI (theme,
15
+ // test-mode banner, consent, tracking) is NOT rendered here that belongs
16
+ // to a single layout-level `<FontdueProvider>` per page. State is shared
17
+ // across multiple preloaded components on a page via module-level singletons.
17
18
  export function TypeTesterPreloaded(props) {
18
- return /*#__PURE__*/React.createElement(FontdueProvider, null, /*#__PURE__*/React.createElement(TypeTesterStandalonePreloadedQueryRenderer, props));
19
+ return /*#__PURE__*/React.createElement(FontdueContextProvider, null, /*#__PURE__*/React.createElement(TypeTesterStandalonePreloadedQueryRenderer, props));
19
20
  }
package/dist/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export interface FontdueConfig {
1
+ import type { Config } from './components/ConfigContext.js';
2
+ export interface FontdueConfig extends Config {
2
3
  url?: string;
3
4
  stripeIntegration?: 'card-element' | 'dynamic';
4
5
  }
package/dist/config.js CHANGED
@@ -1,14 +1,25 @@
1
1
  // Module-level global configuration. Consumers call `configure()` once at
2
- // app startup (e.g. Astro middleware, Next layout, Vite entry) and every
3
- // fontdue-js entry point reads defaults from here. Explicit options passed
4
- // to loadSerializableQuery / FontdueProvider still override.
2
+ // app startup (Astro layout, Next layout, Vite entry) and every fontdue-js
3
+ // entry point reads defaults from here.
4
+ //
5
+ // Precedence (low to high):
6
+ // 1. Server admin config (from the tenant dashboard, fetched via Relay)
7
+ // 2. configure({...}) — module-level code defaults
8
+ // 3. <FontdueProvider config={...}> — per-instance prop override
5
9
  //
6
10
  // Per-request isolation note: `configure` sets module-level state. That's
7
- // fine for single-tenant apps (one URL for the whole site). Multi-tenant
8
- // servers that switch URL per request should pass `url` explicitly to
9
- // loadSerializableQuery rather than rely on configure().
11
+ // fine for single-tenant apps. Multi-tenant servers that switch URL per
12
+ // request should pass `url` explicitly to loadSerializableQuery rather than
13
+ // rely on configure().
14
+
15
+ // Network-layer + UI config in one bag. UI fields come from `Config` (the
16
+ // shape passed to ConfigContext); URL + stripeIntegration are network-layer.
10
17
 
11
18
  let current = {};
19
+
20
+ // Shallow-merges with prior values. Calling `configure({tracking: {...}})`
21
+ // replaces the whole `tracking` subtree; pass nested fields fully populated
22
+ // when partial-updating.
12
23
  export function configure(opts) {
13
24
  current = {
14
25
  ...current,
@@ -0,0 +1,11 @@
1
+ type ResizeObserverCtor = new (callback: ResizeObserverCallback) => {
2
+ observe: (target: Element) => void;
3
+ unobserve?: (target: Element) => void;
4
+ disconnect?: () => void;
5
+ };
6
+ export type UseResizeObserverOptions = {
7
+ polyfill?: ResizeObserverCtor | null;
8
+ };
9
+ export type UseResizeObserverCallback = (entry: ResizeObserverEntry, observer: ResizeObserver) => void;
10
+ export default function useResizeObserver<T extends Element>(target: React.RefObject<T | null> | T | null, callback: UseResizeObserverCallback, options?: UseResizeObserverOptions): void;
11
+ export {};
@@ -0,0 +1,23 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ // Loose constructor type so the SSR no-op polyfills used as fallbacks (which
4
+ // don't implement `disconnect`) still type-check.
5
+
6
+ export default function useResizeObserver(target, callback) {
7
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
8
+ const callbackRef = useRef(callback);
9
+ callbackRef.current = callback;
10
+ useEffect(() => {
11
+ const element = target && 'current' in target ? target.current : target;
12
+ if (!element) return;
13
+ const Ctor = options.polyfill ?? (typeof ResizeObserver !== 'undefined' ? ResizeObserver : null);
14
+ if (!Ctor) return;
15
+ const observer = new Ctor(entries => {
16
+ for (const entry of entries) callbackRef.current(entry, observer);
17
+ });
18
+ observer.observe(element);
19
+ return () => {
20
+ if (observer.disconnect) observer.disconnect();else if (observer.unobserve) observer.unobserve(element);
21
+ };
22
+ }, [target, options.polyfill]);
23
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { configure, getConfig } from './config';
2
- export type { FontdueConfig } from './config';
1
+ export { default as loadFontdueProviderQuery } from './loadFontdueProviderQuery.js';
2
+ export type { FontdueProviderPreloadedQuery } from './loadFontdueProviderQuery.js';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { configure, getConfig } from './config';
1
+ export { default as loadFontdueProviderQuery } from './loadFontdueProviderQuery.js';
@@ -0,0 +1,3 @@
1
+ import type { FontdueProviderPreloadedQuery } from './components/FontdueProvider/index.js';
2
+ export type { FontdueProviderPreloadedQuery };
3
+ export default function loadFontdueProviderQuery(): Promise<FontdueProviderPreloadedQuery>;
@@ -0,0 +1,10 @@
1
+ import loadSerializableQuery from './relay/loadSerializableQuery.js';
2
+ import FontdueProviderQueryNode from './__generated__/FontdueProviderQuery.graphql.js';
3
+ // Fetches the data aux UI (theme custom properties, test-mode flag) needs to
4
+ // render synchronously on the server and on hydration. Pass the result to
5
+ // `<FontdueProvider preloadedQuery={…}>` in your layout. Without it, aux UI
6
+ // falls back to lazy-fetching on first client render — which causes a visible
7
+ // theming flash because `ThemeConfig` injects CSS variables.
8
+ export default async function loadFontdueProviderQuery() {
9
+ return loadSerializableQuery(FontdueProviderQueryNode, {});
10
+ }
package/dist/reducer.d.ts CHANGED
@@ -57,10 +57,12 @@ export type FontdueAction = {
57
57
  type: 'PRECART_TOGGLE_LICENSE';
58
58
  licenseId: string;
59
59
  licenseOptionSpec: LicenseOptionSpec;
60
+ excludedLicenseIds?: readonly string[];
60
61
  checked: boolean;
61
62
  } | {
62
63
  type: 'PRECART_SELECT_LICENSE';
63
64
  licenseOptionSpec: LicenseOptionSpec;
65
+ excludedLicenseIds?: readonly string[];
64
66
  } | {
65
67
  type: 'PRECART_SELECT_LICENSE_OPTION';
66
68
  licenseId: string;
package/dist/reducer.js CHANGED
@@ -34,9 +34,11 @@ const selectLicense = (state, action) => {
34
34
  if (!(action.type === 'PRECART_SELECT_LICENSE' || action.type === 'PRECART_TOGGLE_LICENSE')) return state;
35
35
  const existingLicenseOption = state.licenseOptions.findIndex(option => option.licenseId === action.licenseOptionSpec.licenseId);
36
36
  if (existingLicenseOption >= 0) return state;
37
+ const excludedIds = action.excludedLicenseIds ?? [];
38
+ const filtered = excludedIds.length > 0 ? state.licenseOptions.filter(option => !excludedIds.includes(option.licenseId)) : state.licenseOptions;
37
39
  return {
38
40
  ...state,
39
- licenseOptions: state.licenseOptions.concat(action.licenseOptionSpec)
41
+ licenseOptions: filtered.concat(action.licenseOptionSpec)
40
42
  };
41
43
  };
42
44
  const toggleLicense = (state, action) => {
package/dist/vite.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { PluginOption } from 'vite';
2
+ export default function fontdueJs(): PluginOption[];
package/dist/vite.js ADDED
@@ -0,0 +1,139 @@
1
+ // Vite plugin that fixes the SSR-side CJS interop fontdue-js's deps need.
2
+ //
3
+ // fontdue-js itself is published as transpiled (not bundled) ESM. Its Relay
4
+ // + draft-js + fbjs deps still ship as CJS using `module.exports = require(…)`
5
+ // re-export shapes that Node's strict ESM-CJS interop (and Vite's dev SSR
6
+ // module-runner) can't named-import from. Without help, `import { graphql }
7
+ // from 'react-relay'` blows up at SSR time with `Named export 'graphql' not
8
+ // found` or `module is not defined`.
9
+ //
10
+ // `vite-plugin-cjs-interop` is the canonical fix for this — referenced by the
11
+ // Relay maintainers in https://github.com/facebook/relay/issues/4548. It
12
+ // rewrites named imports of the listed packages to read from `.default` after
13
+ // CJS load, which is what Node + Vite actually expose.
14
+ //
15
+ // Consumers wire it up like:
16
+ //
17
+ // // vite.config.ts
18
+ // import fontdueJs from 'fontdue-js/vite';
19
+ // export default defineConfig({ plugins: [fontdueJs()] });
20
+ //
21
+ // Returned shape is structurally a Vite Plugin (or array of plugins).
22
+ //
23
+ // @ts-ignore — vite-plugin-cjs-interop has no bundled types but exports
24
+ // cjsInterop at runtime.
25
+ import { cjsInterop } from 'vite-plugin-cjs-interop';
26
+ import { createRequire } from 'node:module';
27
+
28
+ // Packages whose imports cjsInterop should rewrite to default-import +
29
+ // destructure shape. Limit this to packages that genuinely ship as CJS-only
30
+ // with `module.exports = require('./lib')` shapes that defeat named-import
31
+ // resolution. React-redux is real ESM and must NOT be in this list — its
32
+ // ESM build has true named exports.
33
+ const CJS_DEPS = ['react-relay', 'relay-runtime', 'draft-js', 'fbjs'];
34
+
35
+ // Packages to pre-bundle for the browser via Vite's optimizer. Pre-bundling
36
+ // pulls a package's transitive deps into one esbuild output, which sidesteps
37
+ // the cjs-module-lexer trap when an ESM package (react-redux) imports a CJS
38
+ // transitive (use-sync-external-store). Without this, the browser dev path
39
+ // fails with "does not provide an export named useSyncExternalStoreWithSelector".
40
+ //
41
+ // `react-google-recaptcha` and `@stripe/react-stripe-js` are pulled into the
42
+ // StoreModal subtree (checkout flow). Both transitively import `prop-types`,
43
+ // whose `module.exports = require('./factoryWithTypeCheckers')(...)` shape
44
+ // hides exports behind a runtime call — cjs-module-lexer can't see them, so
45
+ // the optimizer's auto-generated wrapper omits a `default` export. Including
46
+ // the consumers + setting `needsInterop` on `prop-types` forces Vite to
47
+ // synthesize a default export so `import PropTypes from 'prop-types'` resolves.
48
+ const CLIENT_OPTIMIZE = [...CJS_DEPS, 'react-redux', 'react-google-recaptcha', '@stripe/react-stripe-js', 'prop-types',
49
+ // Transitive deps that Vite would otherwise discover late, after fontdue-js
50
+ // subpaths are first imported. Each late discovery triggers a re-optimize
51
+ // and a new browserHash for `react`, which produces the dual-React bug
52
+ // described above `getFontdueJsSubpaths`. Pinning them here keeps the
53
+ // initial scan complete.
54
+ '@sentry/react', '@stripe/stripe-js', 'react-error-boundary', 'redux'];
55
+ const NEEDS_INTEROP = ['prop-types'];
56
+
57
+ // Every public `fontdue-js/*` entry from package.json `exports`. Pre-including
58
+ // them in `optimizeDeps` forces Vite to scan them on the first dev startup
59
+ // instead of discovering them later when a route lazy-loads.
60
+ //
61
+ // Why this matters: when Vite finds a new dep mid-session it re-runs the
62
+ // optimizer, which mints a new `?v=` browserHash for every dep chunk. Chunks
63
+ // already loaded in the page keep their old `?v=` baked into their imports,
64
+ // so a freshly-fetched chunk that imports `react?v=NEW` ends up coexisting
65
+ // with the previously-loaded `react?v=OLD`. Two physical React modules in
66
+ // the same page → two `ReactCurrentDispatcher`s → `useContext` returns null
67
+ // → "Invalid hook call" on first navigation to an uncached route.
68
+ //
69
+ // Frameworks that lazy-load modules (RR7's route splitter, Astro's per-island
70
+ // hydration) make this near-certain unless the optimizer sees the full set
71
+ // up front. Vite's glob form (`fontdue-js/*`) walks the filesystem and gets
72
+ // confused by our `exports`-mapped layout (the dist files don't sit at the
73
+ // subpath names), so we read `exports` directly — that's the authoritative
74
+ // list.
75
+ function getFontdueJsSubpaths() {
76
+ const require = createRequire(import.meta.url);
77
+ const pkg = require('../package.json');
78
+ const out = [];
79
+ for (const key of Object.keys(pkg.exports ?? {})) {
80
+ if (!key.startsWith('./')) continue;
81
+ if (key.endsWith('.css')) continue;
82
+ if (key === './vite') continue;
83
+ out.push(`fontdue-js/${key.slice(2)}`);
84
+ }
85
+ return out;
86
+ }
87
+ export default function fontdueJs() {
88
+ const fontdueSubpaths = getFontdueJsSubpaths();
89
+ return [cjsInterop({
90
+ dependencies: CJS_DEPS
91
+ }), {
92
+ name: 'fontdue-js',
93
+ config() {
94
+ return {
95
+ // Pre-bundle the CJS-shaped deps via esbuild for the client
96
+ // bundle. Without this, Astro dev's browser pass tries to
97
+ // ESM-import `Environment` from `relay-runtime` and fails —
98
+ // its `module.exports = require('./lib/index.js')` shape can't
99
+ // be statically analyzed for named exports.
100
+ optimizeDeps: {
101
+ include: [...fontdueSubpaths, ...CLIENT_OPTIMIZE],
102
+ needsInterop: [...NEEDS_INTEROP]
103
+ },
104
+ // fbjs (transitive via draft-js) references Node's `global` at
105
+ // module init. Browsers don't define it, so the pre-bundled chunk
106
+ // throws `ReferenceError: global is not defined`. Aliasing
107
+ // `global` to `globalThis` at compile time covers both browser
108
+ // and SSR paths.
109
+ define: {
110
+ global: 'globalThis'
111
+ }
112
+ };
113
+ },
114
+ // Apply `noExternal` to every server-side Vite environment so
115
+ // fontdue-js source flows through Vite's transform pipeline and
116
+ // cjsInterop can rewrite its imports of CJS-shaped Relay/draft-js/
117
+ // fbjs. The legacy `ssr.noExternal` only covered the default `ssr`
118
+ // environment, so Astro 6's separate `prerender` build externalized
119
+ // fontdue-js and `import { graphql } from 'react-relay'` ran against
120
+ // unrewritten CJS at prerender time.
121
+ //
122
+ // `config.consumer` would be the principled check, but at
123
+ // `configEnvironment` time Vite hasn't populated it yet (undefined
124
+ // for ssr/prerender/client alike). Match by name instead:
125
+ // - 'ssr': default Vite SSR env (plain Vite SSR, RR7)
126
+ // - 'prerender': Astro 6's static-prerender env
127
+ // The `consumer` fallback is kept as future-proofing if a framework
128
+ // ever names its server env something else but does populate consumer.
129
+ configEnvironment(name, config) {
130
+ if (name === 'ssr' || name === 'prerender' || config.consumer === 'server') {
131
+ return {
132
+ resolve: {
133
+ noExternal: ['fontdue-js']
134
+ }
135
+ };
136
+ }
137
+ }
138
+ }];
139
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fontdue-js",
3
- "version": "2.22.4",
3
+ "version": "2.23.0",
4
4
  "scripts": {
5
5
  "build": "npm run relay && run-p build-js build-css build-ts",
6
6
  "build-js": "babel src --out-dir dist --extensions .ts,.tsx,.js,.jsx",