fontdue-js 3.0.0-alpha1 → 3.0.0-alpha2

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 (58) hide show
  1. package/dist/__generated__/FontdueProviderQuery.graphql.d.ts +19 -0
  2. package/dist/__generated__/FontdueProviderQuery.graphql.js +140 -0
  3. package/dist/__generated__/ServerConfigProvider_viewer.graphql.d.ts +23 -0
  4. package/dist/__generated__/ServerConfigProvider_viewer.graphql.js +57 -0
  5. package/dist/__generated__/TestModeBanner_viewer.graphql.d.ts +19 -0
  6. package/dist/__generated__/TestModeBanner_viewer.graphql.js +36 -0
  7. package/dist/__generated__/ThemeConfig_viewer.graphql.d.ts +19 -0
  8. package/dist/__generated__/ThemeConfig_viewer.graphql.js +36 -0
  9. package/dist/components/BuyButton/index.d.ts +24 -4
  10. package/dist/components/BuyButton/index.js +58 -15
  11. package/dist/components/BuyButton/index.server.d.ts +4 -1
  12. package/dist/components/BuyButton/index.server.js +5 -0
  13. package/dist/components/CartButton/index.d.ts +9 -6
  14. package/dist/components/CartButton/index.js +19 -16
  15. package/dist/components/CartButton/index.server.js +5 -0
  16. package/dist/components/CharacterViewer/index.d.ts +26 -6
  17. package/dist/components/CharacterViewer/index.js +63 -13
  18. package/dist/components/CharacterViewer/index.server.d.ts +4 -1
  19. package/dist/components/CharacterViewer/index.server.js +6 -0
  20. package/dist/components/FontdueContextProvider/index.d.ts +17 -0
  21. package/dist/components/FontdueContextProvider/index.js +108 -0
  22. package/dist/components/FontdueContextProvider/index.server.d.ts +4 -0
  23. package/dist/components/FontdueContextProvider/index.server.js +7 -0
  24. package/dist/components/FontdueProvider/index.d.ts +9 -3
  25. package/dist/components/FontdueProvider/index.js +61 -23
  26. package/dist/components/FontdueProvider/index.server.d.ts +3 -3
  27. package/dist/components/FontdueProvider/index.server.js +14 -24
  28. package/dist/components/NewsletterSignup/index.d.ts +9 -6
  29. package/dist/components/NewsletterSignup/index.js +16 -1
  30. package/dist/components/NewsletterSignup/index.server.js +5 -0
  31. package/dist/components/ServerConfigProvider/index.d.ts +3 -1
  32. package/dist/components/ServerConfigProvider/index.js +7 -6
  33. package/dist/components/StoreModal/index.js +9 -2
  34. package/dist/components/TestFontsForm/index.d.ts +8 -3
  35. package/dist/components/TestFontsForm/index.js +16 -1
  36. package/dist/components/TestFontsForm/index.server.js +5 -0
  37. package/dist/components/TestModeBanner/index.d.ts +4 -1
  38. package/dist/components/TestModeBanner/index.js +9 -17
  39. package/dist/components/ThemeConfig/index.d.ts +3 -5
  40. package/dist/components/ThemeConfig/index.js +10 -28
  41. package/dist/components/TypeTester/TypeTesterStandalone.d.ts +19 -5
  42. package/dist/components/TypeTester/TypeTesterStandalone.js +21 -2
  43. package/dist/components/TypeTester/TypeTesterStandalone.preload.js +7 -6
  44. package/dist/components/TypeTester/TypeTesterStandalone.server.d.ts +4 -2
  45. package/dist/components/TypeTester/TypeTesterStandalone.server.js +11 -4
  46. package/dist/components/TypeTesters/index.d.ts +18 -2
  47. package/dist/components/TypeTesters/index.js +58 -8
  48. package/dist/components/TypeTesters/index.server.js +5 -0
  49. package/dist/config.d.ts +2 -1
  50. package/dist/config.js +17 -6
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.js +1 -1
  53. package/dist/loadFontdueProviderQuery.d.ts +4 -0
  54. package/dist/loadFontdueProviderQuery.js +10 -0
  55. package/dist/relay/environment.js +4 -5
  56. package/dist/vite.d.ts +2 -1
  57. package/dist/vite.js +13 -4
  58. package/package.json +3 -2
@@ -1,15 +1,35 @@
1
1
  import React from 'react';
2
- import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
3
- import { CharacterViewerIDQuery } from '__generated__/CharacterViewerIDQuery.graphql.js';
4
- import { CharacterViewerSlugQuery } from '__generated__/CharacterViewerSlugQuery.graphql.js';
2
+ import { LoadSerializableQueryOptions, SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
3
+ import { CharacterViewerIDQuery } from '../../__generated__/CharacterViewerIDQuery.graphql.js';
4
+ import { CharacterViewerSlugQuery } from '../../__generated__/CharacterViewerSlugQuery.graphql.js';
5
5
  export interface CharacterViewer_props {
6
- collectionId?: string;
7
- collectionSlug?: string;
8
6
  }
7
+ export type CharacterViewerPreloadedQuery = SerializablePreloadedQuery<CharacterViewerIDQuery> | SerializablePreloadedQuery<CharacterViewerSlugQuery>;
8
+ export type LoadCharacterViewerQueryVariables = {
9
+ collectionId: string;
10
+ collectionSlug?: never;
11
+ } | {
12
+ collectionId?: never;
13
+ collectionSlug: string;
14
+ };
15
+ export declare function loadCharacterViewerQuery(variables: LoadCharacterViewerQueryVariables, options?: LoadSerializableQueryOptions): Promise<CharacterViewerPreloadedQuery>;
9
16
  export declare function CharacterViewerPreloadedIDQueryRenderer({ preloadedQuery, ...rest }: CharacterViewer_props & {
10
17
  preloadedQuery: SerializablePreloadedQuery<CharacterViewerIDQuery>;
11
18
  }): React.JSX.Element | null;
12
19
  export declare function CharacterViewerPreloadedSlugQueryRenderer({ preloadedQuery, ...rest }: CharacterViewer_props & {
13
20
  preloadedQuery: SerializablePreloadedQuery<CharacterViewerSlugQuery>;
14
21
  }): React.JSX.Element | null;
15
- export default function CharacterViewer({ collectionId, collectionSlug, }: CharacterViewer_props): React.JSX.Element;
22
+ export type CharacterViewer_unifiedProps = CharacterViewer_props & ({
23
+ preloadedQuery: CharacterViewerPreloadedQuery;
24
+ collectionId?: never;
25
+ collectionSlug?: never;
26
+ } | {
27
+ preloadedQuery?: never;
28
+ collectionId: string;
29
+ collectionSlug?: never;
30
+ } | {
31
+ preloadedQuery?: never;
32
+ collectionId?: never;
33
+ collectionSlug: string;
34
+ });
35
+ export default function CharacterViewer(props: CharacterViewer_unifiedProps): React.JSX.Element;
@@ -13,9 +13,13 @@ import retryImport from '../../retryImport.js';
13
13
  import { notEmpty, variableInstanceSettings, variableSettingsCSS } from '../../utils.js';
14
14
  import useFontStyle from '../useFontStyle.js';
15
15
  import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQuery.js';
16
+ import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
17
+ import CharacterViewerIDQueryNode from '../../__generated__/CharacterViewerIDQuery.graphql.js';
18
+ import CharacterViewerSlugQueryNode from '../../__generated__/CharacterViewerSlugQuery.graphql.js';
16
19
  import StyleSelect from './StyleSelect.js';
17
20
  import Checkbox from '../Checkbox/index.js';
18
21
  import CharacterViewerStyleRefetchQueryNode from '../../__generated__/CharacterViewerStyleRefetchQuery.graphql.js';
22
+ import { EnsureFontdueContext } from '../FontdueContextProvider/index.js';
19
23
  function useSize() {
20
24
  const ref = useRef(null);
21
25
  const [size, setSize] = React.useState();
@@ -394,6 +398,20 @@ function CharacterViewerComponent(_ref3) {
394
398
  }))));
395
399
  }
396
400
  const idQuery = (_CharacterViewerIDQuery.hash && _CharacterViewerIDQuery.hash !== "f90b09a4df6d95307b0a5d5fda487cdc" && console.error("The definition of 'CharacterViewerIDQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CharacterViewerIDQuery);
401
+ const slugQuery = (_CharacterViewerSlugQuery.hash && _CharacterViewerSlugQuery.hash !== "afa08a8f050e0434308892fea6e3c267" && console.error("The definition of 'CharacterViewerSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CharacterViewerSlugQuery);
402
+ export async function loadCharacterViewerQuery(variables, options) {
403
+ if (variables.collectionId) {
404
+ return loadSerializableQuery(CharacterViewerIDQueryNode, {
405
+ collectionId: variables.collectionId
406
+ }, options);
407
+ }
408
+ if (variables.collectionSlug) {
409
+ return loadSerializableQuery(CharacterViewerSlugQueryNode, {
410
+ collectionSlug: variables.collectionSlug
411
+ }, options);
412
+ }
413
+ throw new Error('loadCharacterViewerQuery expected either collectionId or collectionSlug');
414
+ }
397
415
  function CharacterViewerIdQueryRenderer(_ref7) {
398
416
  let {
399
417
  collectionId
@@ -423,7 +441,7 @@ function CharacterViewerSlugQueryRenderer(_ref9) {
423
441
  let {
424
442
  collectionSlug
425
443
  } = _ref9;
426
- const data = useLazyLoadQuery((_CharacterViewerSlugQuery.hash && _CharacterViewerSlugQuery.hash !== "afa08a8f050e0434308892fea6e3c267" && console.error("The definition of 'CharacterViewerSlugQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _CharacterViewerSlugQuery), {
444
+ const data = useLazyLoadQuery(slugQuery, {
427
445
  collectionSlug
428
446
  });
429
447
  const collection = data === null || data === void 0 ? void 0 : (_data$viewer = data.viewer) === null || _data$viewer === void 0 ? void 0 : (_data$viewer$slug = _data$viewer.slug) === null || _data$viewer$slug === void 0 ? void 0 : _data$viewer$slug.fontCollection;
@@ -439,27 +457,59 @@ export function CharacterViewerPreloadedSlugQueryRenderer(_ref10) {
439
457
  ...rest
440
458
  } = _ref10;
441
459
  const queryRef = useSerializablePreloadedQuery(preloadedQuery);
442
- const data = usePreloadedQuery(idQuery, queryRef);
460
+ const data = usePreloadedQuery(slugQuery, queryRef);
443
461
  const collection = data === null || data === void 0 ? void 0 : (_data$viewer2 = data.viewer) === null || _data$viewer2 === void 0 ? void 0 : (_data$viewer2$slug = _data$viewer2.slug) === null || _data$viewer2$slug === void 0 ? void 0 : _data$viewer2$slug.fontCollection;
444
462
  if (!collection) return null;
445
463
  return /*#__PURE__*/React.createElement(CharacterViewerComponent, _extends({}, rest, {
446
464
  collection: collection
447
465
  }));
448
466
  }
449
- export default function CharacterViewer(_ref11) {
467
+ function CharacterViewerPreloadedRenderer(_ref11) {
450
468
  let {
451
- collectionId,
452
- collectionSlug
469
+ preloadedQuery,
470
+ ...rest
453
471
  } = _ref11;
454
- if (collectionId) {
455
- return /*#__PURE__*/React.createElement(CharacterViewerIdQueryRenderer, {
456
- collectionId: collectionId
457
- });
472
+ if (preloadedQuery.params.name === 'CharacterViewerIDQuery') {
473
+ return /*#__PURE__*/React.createElement(CharacterViewerPreloadedIDQueryRenderer, _extends({
474
+ preloadedQuery: preloadedQuery
475
+ }, rest));
458
476
  }
459
- if (collectionSlug) {
460
- return /*#__PURE__*/React.createElement(CharacterViewerSlugQueryRenderer, {
477
+ return /*#__PURE__*/React.createElement(CharacterViewerPreloadedSlugQueryRenderer, _extends({
478
+ preloadedQuery: preloadedQuery
479
+ }, rest));
480
+ }
481
+ // Unified CharacterViewer entry. Accepts a preloaded query (server-side
482
+ // preload path) or `{collectionId}`/`{collectionSlug}` for lazy fetch.
483
+ // `EnsureFontdueContext` only self-wraps with `FontdueContextProvider` when
484
+ // no parent Fontdue context is present.
485
+ export default function CharacterViewer(props) {
486
+ let inner;
487
+ if ('preloadedQuery' in props && props.preloadedQuery) {
488
+ const {
489
+ preloadedQuery,
490
+ ...rest
491
+ } = props;
492
+ inner = /*#__PURE__*/React.createElement(CharacterViewerPreloadedRenderer, _extends({
493
+ preloadedQuery: preloadedQuery
494
+ }, rest));
495
+ } else if ('collectionId' in props && props.collectionId) {
496
+ const {
497
+ collectionId,
498
+ ...rest
499
+ } = props;
500
+ inner = /*#__PURE__*/React.createElement(CharacterViewerIdQueryRenderer, _extends({
501
+ collectionId: collectionId
502
+ }, rest));
503
+ } else if ('collectionSlug' in props && props.collectionSlug) {
504
+ const {
505
+ collectionSlug,
506
+ ...rest
507
+ } = props;
508
+ inner = /*#__PURE__*/React.createElement(CharacterViewerSlugQueryRenderer, _extends({
461
509
  collectionSlug: collectionSlug
462
- });
510
+ }, rest));
511
+ } else {
512
+ throw new Error('CharacterViewer expected one of preloadedQuery, collectionId, or collectionSlug');
463
513
  }
464
- throw new Error('CharacterViewer expected either a collectionId or collectionSlug prop');
514
+ return /*#__PURE__*/React.createElement(EnsureFontdueContext, null, inner);
465
515
  }
@@ -1,3 +1,6 @@
1
1
  import React from 'react';
2
2
  import { CharacterViewer_props } from './index.js';
3
- export default function CharacterViewer({ collectionId, collectionSlug, ...rest }: CharacterViewer_props): Promise<React.JSX.Element | null>;
3
+ export default function CharacterViewer({ collectionId, collectionSlug, ...rest }: CharacterViewer_props & {
4
+ collectionId?: string | null;
5
+ collectionSlug?: string | null;
6
+ }): Promise<React.JSX.Element | null>;
@@ -4,6 +4,12 @@ import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
4
4
  import { CharacterViewerPreloadedIDQueryRenderer, CharacterViewerPreloadedSlugQueryRenderer } from './index.js';
5
5
  import CharacterViewerIDQueryNode from '../../__generated__/CharacterViewerIDQuery.graphql.js';
6
6
  import CharacterViewerSlugQueryNode from '../../__generated__/CharacterViewerSlugQuery.graphql.js';
7
+
8
+ // Next RSC variant: awaits the query on the server and hands the response to
9
+ // the client `*PreloadedQueryRenderer`. Lets pages just write
10
+ // `<CharacterViewer collectionId={id} />` in an RSC without manually
11
+ // invoking `loadCharacterViewerQuery` + threading `preloadedQuery` through
12
+ // props.
7
13
  export default async function CharacterViewer(_ref) {
8
14
  let {
9
15
  collectionId,
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Store } from 'redux';
3
+ import { Config } from '../ConfigContext.js';
4
+ import { FontdueAction, FontdueState } from '../../reducer.js';
5
+ import { Components } from '../ComponentsContext.js';
6
+ export declare function EnsureFontdueContext({ children }: {
7
+ children: React.ReactNode;
8
+ }): React.JSX.Element;
9
+ export interface FontdueContextProvider_props {
10
+ children?: React.ReactNode;
11
+ url?: string;
12
+ stripeIntegration?: 'card-element' | 'dynamic';
13
+ config?: Config;
14
+ components?: Components;
15
+ store?: Store<FontdueState, FontdueAction>;
16
+ }
17
+ export default function FontdueContextProvider({ children, url, stripeIntegration, config, components, store, }: FontdueContextProvider_props): React.JSX.Element;
@@ -0,0 +1,108 @@
1
+ 'use client';
2
+
3
+ import React, { Suspense, createContext, useContext, useRef } from 'react';
4
+ import { Provider } from 'react-redux';
5
+ import { RelayEnvironmentProvider } from 'react-relay';
6
+ import { useCurrentEnvironment } from '../../relay/environment.js';
7
+ import ConfigContext, { makeConfig } from '../ConfigContext.js';
8
+ import { createDefaultStore } from '../../reducer.js';
9
+ import ComponentsContext from '../ComponentsContext.js';
10
+ import UrlContext from '../UrlContext.js';
11
+ import { setCorsModalEnabled } from '../../corsError.js';
12
+
13
+ // Marker context used by self-wrapping components to detect a parent
14
+ // FontdueContextProvider/FontdueProvider. When the marker is `true`, a
15
+ // self-wrapping component skips its inner FontdueContextProvider so the
16
+ // outer config/url/store/relay-env flow through. Internal — do not export
17
+ // from the package.
18
+ const FontdueContextMarker = /*#__PURE__*/createContext(false);
19
+
20
+ // Wraps `children` in `FontdueContextProvider` only when no parent
21
+ // FontdueContextProvider/FontdueProvider is present. Self-wrapping components
22
+ // (`<TypeTester>`, `<StoreModal>`, etc.) use this so they Just Work as
23
+ // standalone islands while staying lightweight inside an outer
24
+ // `<FontdueProvider>` tree.
25
+ export function EnsureFontdueContext(_ref) {
26
+ let {
27
+ children
28
+ } = _ref;
29
+ const isInsideContext = useContext(FontdueContextMarker);
30
+ if (isInsideContext) return /*#__PURE__*/React.createElement(React.Fragment, null, children);
31
+ return /*#__PURE__*/React.createElement(FontdueContextProvider, null, children);
32
+ }
33
+ const IS_SERVER = typeof window === typeof undefined;
34
+
35
+ // === Multi-island state-sharing contract ===
36
+ //
37
+ // Frameworks that hydrate per-island (Astro, Vike, Qwik) mount one
38
+ // `FontdueContextProvider` per fontdue-js component on the page. Each island
39
+ // runs its own React reconciler and gets its own copy of every context, so
40
+ // state that lives inside the component tree is duplicated — adding to the
41
+ // cart in one island wouldn't update the CartButton in a different island.
42
+ //
43
+ // Any stateful client to be shared *across islands* (a Redux store, a Relay
44
+ // Environment, or any future cache) must be a module-level singleton on the
45
+ // client and per-render on the server. SSR has the opposite constraint: a
46
+ // client-shared singleton would leak state between concurrent requests.
47
+ //
48
+ // The pattern (see also `relay/environment.ts → useCurrentEnvironment`):
49
+ //
50
+ // let clientThing: Thing | null = null;
51
+ // function useSharedThing() {
52
+ // if (IS_SERVER) return createThing(); // per-render, no leakage
53
+ // if (clientThing == null) clientThing = createThing();
54
+ // return clientThing; // shared across islands
55
+ // }
56
+ //
57
+ // If you add a new context provider here that holds mutable client state,
58
+ // follow this pattern. If it's purely deriving from props (no state), a
59
+ // vanilla `Context.Provider` is fine — each island will compute the same
60
+ // value.
61
+ let clientStore = null;
62
+ function useSharedStore(providedStore, config) {
63
+ const ref = useRef(null);
64
+ if (providedStore) return providedStore;
65
+ if (IS_SERVER) {
66
+ if (ref.current == null) ref.current = createDefaultStore(config);
67
+ return ref.current;
68
+ }
69
+ if (clientStore == null) clientStore = createDefaultStore(config);
70
+ return clientStore;
71
+ }
72
+ // Lightweight wrapper that sets up Fontdue's React contexts (Relay env,
73
+ // Redux store, config, url, components) without rendering any aux UI.
74
+ // `*Preloaded` self-wrapping components use this so they can stand alone
75
+ // without claiming the page-level aux UI slot. Pages that need aux UI
76
+ // (theme/test-mode/consent/tracking) wrap with `FontdueProvider` instead.
77
+ export default function FontdueContextProvider(_ref2) {
78
+ let {
79
+ children,
80
+ url,
81
+ stripeIntegration,
82
+ config,
83
+ components,
84
+ store
85
+ } = _ref2;
86
+ const environment = useCurrentEnvironment({
87
+ url,
88
+ stripeIntegration
89
+ });
90
+ const configValue = makeConfig(config);
91
+ setCorsModalEnabled(configValue.corsErrorModal);
92
+ const sharedStore = useSharedStore(store, config);
93
+ return /*#__PURE__*/React.createElement(FontdueContextMarker.Provider, {
94
+ value: true
95
+ }, /*#__PURE__*/React.createElement(RelayEnvironmentProvider, {
96
+ environment: environment
97
+ }, /*#__PURE__*/React.createElement(Provider, {
98
+ store: sharedStore
99
+ }, /*#__PURE__*/React.createElement(Suspense, {
100
+ fallback: null
101
+ }, /*#__PURE__*/React.createElement(ConfigContext.Provider, {
102
+ value: configValue
103
+ }, /*#__PURE__*/React.createElement(UrlContext.Provider, {
104
+ value: url ?? (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FONTDUE_URL : undefined) ?? ''
105
+ }, /*#__PURE__*/React.createElement(ComponentsContext.Provider, {
106
+ value: components ?? {}
107
+ }, children)))))));
108
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { FontdueContextProvider_props } from './index.js';
3
+ export type { FontdueContextProvider_props } from './index.js';
4
+ export default function FontdueContextProviderServer(props: FontdueContextProvider_props): Promise<React.JSX.Element>;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import FontdueContextProvider from './index.js';
3
+ // RSC entry. The client component does the work; this exists so the
4
+ // `react-server` export condition resolves to a server-renderable file.
5
+ export default async function FontdueContextProviderServer(props) {
6
+ return /*#__PURE__*/React.createElement(FontdueContextProvider, props);
7
+ }
@@ -1,5 +1,11 @@
1
1
  import React from 'react';
2
- import type { FontdueProvider_props } from './FontdueProviderClientComponent.js';
3
- declare const FontdueProvider: ({ children, ...rest }: FontdueProvider_props) => React.JSX.Element;
4
- export type { FontdueProvider_props };
2
+ import type { FontdueContextProvider_props } from '../FontdueContextProvider/index.js';
3
+ import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
4
+ import { FontdueProviderQuery } from '../../__generated__/FontdueProviderQuery.graphql.js';
5
+ export declare const fontdueProviderQuery: import("react-relay").GraphQLTaggedNode;
6
+ export type FontdueProviderPreloadedQuery = SerializablePreloadedQuery<FontdueProviderQuery>;
7
+ export interface FontdueProvider_props extends FontdueContextProvider_props {
8
+ preloadedQuery?: FontdueProviderPreloadedQuery;
9
+ }
10
+ declare const FontdueProvider: ({ children, preloadedQuery, ...rest }: FontdueProvider_props) => React.JSX.Element;
5
11
  export default FontdueProvider;
@@ -1,37 +1,75 @@
1
1
  'use client';
2
2
 
3
- 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); }
4
- import React, { Suspense } from 'react';
3
+ import _FontdueProviderQuery from "../../__generated__/FontdueProviderQuery.graphql.js";
4
+ import React, { Suspense, lazy } from 'react';
5
5
  import { ErrorBoundary } from 'react-error-boundary';
6
+ import { graphql, useLazyLoadQuery, usePreloadedQuery } from 'react-relay';
6
7
  import TestModeBanner from '../TestModeBanner/index.js';
7
8
  import ThemeConfig from '../ThemeConfig/index.js';
8
- import FontdueProviderClientComponent from './FontdueProviderClientComponent.js';
9
- import useAuxUIOwner from './useAuxUIOwner.js';
9
+ import ServerConfigProvider from '../ServerConfigProvider/index.js';
10
+ import FontdueContextProvider from '../FontdueContextProvider/index.js';
11
+ import retryImport from '../../retryImport.js';
12
+ import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQuery.js';
13
+ const ConsentBanner = /*#__PURE__*/lazy(() => retryImport(() => import('../ConsentBanner/index.js')));
14
+ const Tracking = /*#__PURE__*/lazy(() => retryImport(() => import('../Tracking/index.js')));
10
15
 
11
- // Wrap each aux UI component in its own Suspense + ErrorBoundary so that its
12
- // query suspending (useLazyLoadQuery fetches on first client render) or
13
- // failing (CORS / offline / etc.) can't blank out the consumer's rendered
14
- // children. Without this, TestModeBanner's TestModeBannerQuery suspends the
15
- // whole provider subtree on hydration and the user sees a visible
16
- // unmount/remount flash on the TypeTester.
17
- function IsolatedAuxUI(_ref) {
16
+ // Single layout-level query that spreads every aux UI component's fragment.
17
+ // Components declare their own data needs via fragments — adding a new aux
18
+ // component is one fragment + one fragment spread, no duplicated selections.
19
+ export const fontdueProviderQuery = (_FontdueProviderQuery.hash && _FontdueProviderQuery.hash !== "5cbd582990daa28a99839c20abbc8bda" && console.error("The definition of 'FontdueProviderQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _FontdueProviderQuery);
20
+ const FontdueProvider = _ref => {
18
21
  let {
19
- children
22
+ children,
23
+ preloadedQuery,
24
+ ...rest
20
25
  } = _ref;
21
- return /*#__PURE__*/React.createElement(ErrorBoundary, {
26
+ return /*#__PURE__*/React.createElement(FontdueContextProvider, rest, /*#__PURE__*/React.createElement(ErrorBoundary, {
22
27
  fallback: null
23
28
  }, /*#__PURE__*/React.createElement(Suspense, {
24
29
  fallback: null
25
- }, children));
26
- }
27
- const FontdueProvider = _ref2 => {
30
+ }, preloadedQuery ? /*#__PURE__*/React.createElement(AuxUIPreloaded, {
31
+ preloadedQuery: preloadedQuery,
32
+ codeConfig: rest.config
33
+ }) : /*#__PURE__*/React.createElement(AuxUILazy, {
34
+ codeConfig: rest.config
35
+ }))), children);
36
+ };
37
+ function AuxUIPreloaded(_ref2) {
28
38
  let {
29
- children,
30
- ...rest
39
+ preloadedQuery,
40
+ codeConfig
31
41
  } = _ref2;
32
- const isAuxOwner = useAuxUIOwner();
33
- return /*#__PURE__*/React.createElement(FontdueProviderClientComponent, _extends({}, rest, {
34
- renderAuxUI: isAuxOwner
35
- }), isAuxOwner && /*#__PURE__*/React.createElement(IsolatedAuxUI, null, /*#__PURE__*/React.createElement(TestModeBanner, null)), isAuxOwner && /*#__PURE__*/React.createElement(IsolatedAuxUI, null, /*#__PURE__*/React.createElement(ThemeConfig, null)), children);
36
- };
42
+ const queryRef = useSerializablePreloadedQuery(preloadedQuery, undefined, fontdueProviderQuery);
43
+ const data = usePreloadedQuery(fontdueProviderQuery, queryRef);
44
+ return /*#__PURE__*/React.createElement(AuxUI, {
45
+ viewer: data.viewer,
46
+ codeConfig: codeConfig
47
+ });
48
+ }
49
+ function AuxUILazy(_ref3) {
50
+ let {
51
+ codeConfig
52
+ } = _ref3;
53
+ const data = useLazyLoadQuery(fontdueProviderQuery, {});
54
+ return /*#__PURE__*/React.createElement(AuxUI, {
55
+ viewer: data.viewer,
56
+ codeConfig: codeConfig
57
+ });
58
+ }
59
+ function AuxUI(_ref4) {
60
+ let {
61
+ viewer,
62
+ codeConfig
63
+ } = _ref4;
64
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ThemeConfig, {
65
+ viewer: viewer
66
+ }), /*#__PURE__*/React.createElement(TestModeBanner, {
67
+ viewer: viewer
68
+ }), /*#__PURE__*/React.createElement(ServerConfigProvider, {
69
+ viewer: viewer,
70
+ codeConfig: codeConfig
71
+ }, /*#__PURE__*/React.createElement(Suspense, {
72
+ fallback: null
73
+ }, /*#__PURE__*/React.createElement(ConsentBanner, null), /*#__PURE__*/React.createElement(Tracking, null))));
74
+ }
37
75
  export default FontdueProvider;
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
- import type { FontdueProvider_props } from './FontdueProviderClientComponent.js';
3
- export type { FontdueProvider_props } from './FontdueProviderClientComponent.js';
4
- export default function FontdueProvider({ children, ...rest }: FontdueProvider_props): Promise<React.JSX.Element>;
2
+ import type { FontdueProvider_props } from './index.js';
3
+ export type { FontdueProvider_props } from './index.js';
4
+ export default function FontdueProviderServer({ preloadedQuery, ...rest }: FontdueProvider_props): Promise<React.JSX.Element>;
@@ -1,28 +1,18 @@
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
- import React, { Suspense } from 'react';
3
- import { ErrorBoundary } from 'react-error-boundary';
4
- import TestModeBanner from '../TestModeBanner/index.js';
5
- import ThemeConfig from '../ThemeConfig/index.server.js';
6
- import FontdueProviderClientComponent from './FontdueProviderClientComponent.js';
7
- // Each aux UI component gets its own Suspense + ErrorBoundary so its query
8
- // suspending/failing can't blank out the consumer's rendered children during
9
- // hydration. See the non-RSC index.tsx for the same treatment.
10
- function IsolatedAuxUI(_ref) {
2
+ import React from 'react';
3
+ import FontdueProvider from './index.js';
4
+ import loadFontdueProviderQuery from '../../loadFontdueProviderQuery.js';
5
+ // RSC entry. When no preloadedQuery is passed, fetch one server-side so the
6
+ // Next.js App Router path stays "drop the provider in your layout, done."
7
+ export default async function FontdueProviderServer(_ref) {
11
8
  let {
12
- children
13
- } = _ref;
14
- return /*#__PURE__*/React.createElement(ErrorBoundary, {
15
- fallback: null
16
- }, /*#__PURE__*/React.createElement(Suspense, {
17
- fallback: null
18
- }, children));
19
- }
20
- export default async function FontdueProvider(_ref2) {
21
- let {
22
- children,
9
+ preloadedQuery,
23
10
  ...rest
24
- } = _ref2;
25
- return /*#__PURE__*/React.createElement(FontdueProviderClientComponent, _extends({}, rest, {
26
- renderAuxUI: true
27
- }), /*#__PURE__*/React.createElement(IsolatedAuxUI, null, /*#__PURE__*/React.createElement(TestModeBanner, null)), /*#__PURE__*/React.createElement(IsolatedAuxUI, null, /*#__PURE__*/React.createElement(ThemeConfig, null)), children);
11
+ } = _ref;
12
+ const resolved = preloadedQuery ?? (await loadFontdueProviderQuery({
13
+ url: rest.url
14
+ }));
15
+ return /*#__PURE__*/React.createElement(FontdueProvider, _extends({}, rest, {
16
+ preloadedQuery: resolved
17
+ }));
28
18
  }
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
3
- import { NewsletterSignupQuery } from '__generated__/NewsletterSignupQuery.graphql.js';
4
- type PreloadedQuery = SerializablePreloadedQuery<NewsletterSignupQuery>;
2
+ import { LoadSerializableQueryOptions, SerializablePreloadedQuery } from '../../relay/loadSerializableQuery.js';
3
+ import { NewsletterSignupQuery } from '../../__generated__/NewsletterSignupQuery.graphql.js';
4
+ export type NewsletterSignupPreloadedQuery = SerializablePreloadedQuery<NewsletterSignupQuery>;
5
+ export declare function loadNewsletterSignupQuery(options?: LoadSerializableQueryOptions): Promise<NewsletterSignupPreloadedQuery>;
5
6
  export interface NewsletterSignup_props {
6
7
  optInLabel?: string;
7
8
  successLabel?: string;
@@ -11,7 +12,9 @@ export interface NewsletterSignup_props {
11
12
  intro?: string;
12
13
  }
13
14
  export declare function NewsletterSignupPreloadedQueryRenderer({ preloadedQuery, ...props }: {
14
- preloadedQuery: PreloadedQuery;
15
+ preloadedQuery: NewsletterSignupPreloadedQuery;
15
16
  } & NewsletterSignup_props): React.JSX.Element;
16
- export default function NewsletterSignup(props: NewsletterSignup_props): React.JSX.Element;
17
- export {};
17
+ export type NewsletterSignup_unifiedProps = NewsletterSignup_props & {
18
+ preloadedQuery?: NewsletterSignupPreloadedQuery;
19
+ };
20
+ export default function NewsletterSignup(props: NewsletterSignup_unifiedProps): React.JSX.Element;
@@ -8,8 +8,14 @@ import { graphql, commitMutation, useRelayEnvironment, useLazyLoadQuery, usePrel
8
8
  import { ReCAPTCHA } from 'react-google-recaptcha';
9
9
  import TextField from '../TextField/index.js';
10
10
  import Check from '../Icons/Check.js';
11
+ import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
11
12
  import useSerializablePreloadedQuery from '../../relay/useSerializablePreloadedQuery.js';
13
+ import NewsletterSignupQueryNode from '../../__generated__/NewsletterSignupQuery.graphql.js';
14
+ import { EnsureFontdueContext } from '../FontdueContextProvider/index.js';
12
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(options) {
17
+ return loadSerializableQuery(NewsletterSignupQueryNode, {}, options);
18
+ }
13
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);
14
20
  function NewsletterSignupComponent(_ref) {
15
21
  var _data$viewer, _data$viewer$settings, _data$viewer2, _data$viewer2$setting, _data$viewer3, _data$viewer3$setting, _data$viewer4, _data$viewer4$setting;
@@ -182,9 +188,18 @@ export function NewsletterSignupPreloadedQueryRenderer(_ref3) {
182
188
  data: data
183
189
  }, props));
184
190
  }
185
- export default function NewsletterSignup(props) {
191
+ function NewsletterSignupLazyQueryRenderer(props) {
186
192
  const data = useLazyLoadQuery(query, {});
187
193
  return /*#__PURE__*/React.createElement(NewsletterSignupComponent, _extends({}, props, {
188
194
  data: data
189
195
  }));
196
+ }
197
+ // Unified NewsletterSignup entry. Accepts an optional preloaded query
198
+ // (server-side preload path) or fetches lazily on mount. `EnsureFontdueContext`
199
+ // only self-wraps with `FontdueContextProvider` when no parent Fontdue
200
+ // context is present.
201
+ export default function NewsletterSignup(props) {
202
+ return /*#__PURE__*/React.createElement(EnsureFontdueContext, null, props.preloadedQuery ? /*#__PURE__*/React.createElement(NewsletterSignupPreloadedQueryRenderer, _extends({}, props, {
203
+ preloadedQuery: props.preloadedQuery
204
+ })) : /*#__PURE__*/React.createElement(NewsletterSignupLazyQueryRenderer, props));
190
205
  }
@@ -3,6 +3,11 @@ import React from 'react';
3
3
  import loadSerializableQuery from '../../relay/loadSerializableQuery.js';
4
4
  import { NewsletterSignupPreloadedQueryRenderer } from './index.js';
5
5
  import NewsletterSignupQueryNode from '../../__generated__/NewsletterSignupQuery.graphql.js';
6
+
7
+ // Next RSC variant: awaits the query on the server and hands the response to
8
+ // the client `NewsletterSignupPreloadedQueryRenderer`. Lets pages just write
9
+ // `<NewsletterSignup />` in an RSC without manually invoking
10
+ // `loadNewsletterSignupQuery` + threading `preloadedQuery` through props.
6
11
  export default async function NewsletterSignup(props) {
7
12
  const preloadedQuery = await loadSerializableQuery(NewsletterSignupQueryNode, {});
8
13
  return /*#__PURE__*/React.createElement(NewsletterSignupPreloadedQueryRenderer, _extends({}, props, {
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import { Config } from '../ConfigContext.js';
3
+ import type { ServerConfigProvider_viewer$key } from '../../__generated__/ServerConfigProvider_viewer.graphql.js';
3
4
  interface Props {
5
+ viewer: ServerConfigProvider_viewer$key;
4
6
  codeConfig?: Config;
5
7
  children: React.ReactNode;
6
8
  }
7
- declare const ServerConfigProvider: ({ codeConfig, children }: Props) => React.JSX.Element;
9
+ declare const ServerConfigProvider: ({ viewer, codeConfig, children }: Props) => React.JSX.Element;
8
10
  export default ServerConfigProvider;
@@ -1,18 +1,19 @@
1
1
  'use client';
2
2
 
3
- import _ServerConfigProviderQuery from "../../__generated__/ServerConfigProviderQuery.graphql.js";
3
+ import _ServerConfigProvider_viewer from "../../__generated__/ServerConfigProvider_viewer.graphql.js";
4
4
  import React from 'react';
5
- import { graphql, useLazyLoadQuery } from 'react-relay';
5
+ import { graphql, useFragment } from 'react-relay';
6
6
  import ConfigContext, { makeConfig } from '../ConfigContext.js';
7
- const query = (_ServerConfigProviderQuery.hash && _ServerConfigProviderQuery.hash !== "b20ad9bdada6a425ee660a8662a78840" && console.error("The definition of 'ServerConfigProviderQuery' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _ServerConfigProviderQuery);
7
+ const fragment = (_ServerConfigProvider_viewer.hash && _ServerConfigProvider_viewer.hash !== "6afcb0c3813a418a470e48415f963064" && console.error("The definition of 'ServerConfigProvider_viewer' appears to have changed. Run `relay-compiler` to update the generated files to receive the expected data."), _ServerConfigProvider_viewer);
8
8
  const ServerConfigProvider = _ref => {
9
- var _data$viewer, _data$viewer$fontdueC;
9
+ var _data$fontdueConfig;
10
10
  let {
11
+ viewer,
11
12
  codeConfig,
12
13
  children
13
14
  } = _ref;
14
- const data = useLazyLoadQuery(query, {});
15
- const tracking = (_data$viewer = data.viewer) === null || _data$viewer === void 0 ? void 0 : (_data$viewer$fontdueC = _data$viewer.fontdueConfig) === null || _data$viewer$fontdueC === void 0 ? void 0 : _data$viewer$fontdueC.tracking;
15
+ const data = useFragment(fragment, viewer);
16
+ const tracking = (_data$fontdueConfig = data.fontdueConfig) === null || _data$fontdueConfig === void 0 ? void 0 : _data$fontdueConfig.tracking;
16
17
 
17
18
  // Server config is the base; code config overrides.
18
19
  const merged = {
@@ -5,7 +5,8 @@ import StoreModalLoader from './StoreModalLoader.js';
5
5
  import StoreModalContainer from './StoreModalContainer.js';
6
6
  import StoreModalRouter from './StoreModalRouter.js';
7
7
  import { useDispatch } from 'react-redux';
8
- const StoreModal = () => {
8
+ import { EnsureFontdueContext } from '../FontdueContextProvider/index.js';
9
+ function StoreModalInner() {
9
10
  const dispatch = useDispatch();
10
11
 
11
12
  // Check for store-modal=open URL parameter and open cart automatically
@@ -26,5 +27,11 @@ const StoreModal = () => {
26
27
  return /*#__PURE__*/React.createElement(StoreModalLoader, null, /*#__PURE__*/React.createElement(Suspense, {
27
28
  fallback: null
28
29
  }, /*#__PURE__*/React.createElement(StoreModalContainer, null, /*#__PURE__*/React.createElement(StoreModalRouter, null))));
29
- };
30
+ }
31
+
32
+ // Self-wraps with FontdueContextProvider so it can stand alone as an island
33
+ // (e.g. in Astro/Vike/etc.). When already inside a `<FontdueProvider>` tree
34
+ // (e.g. Next layouts), `EnsureFontdueContext` skips the inner wrap so the
35
+ // outer config/url/store flow through.
36
+ const StoreModal = () => /*#__PURE__*/React.createElement(EnsureFontdueContext, null, /*#__PURE__*/React.createElement(StoreModalInner, null));
30
37
  export default StoreModal;