@quilted/preact-localize 0.4.0 → 0.4.2

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 (46) hide show
  1. package/CHANGELOG.md +243 -0
  2. package/build/esm/hooks/formatting.mjs +4 -2
  3. package/build/esm/hooks/locale.mjs +4 -2
  4. package/build/esm/index.mjs +1 -4
  5. package/build/esm/routing/LocalizedLink.mjs +4 -4
  6. package/build/esm/routing/LocalizedNavigation.mjs +32 -41
  7. package/build/esm/routing/context.mjs +10 -4
  8. package/build/esnext/hooks/formatting.esnext +4 -2
  9. package/build/esnext/hooks/locale.esnext +4 -2
  10. package/build/esnext/index.esnext +1 -4
  11. package/build/esnext/routing/LocalizedLink.esnext +4 -4
  12. package/build/esnext/routing/LocalizedNavigation.esnext +27 -29
  13. package/build/esnext/routing/context.esnext +12 -4
  14. package/build/tsconfig.tsbuildinfo +1 -1
  15. package/build/typescript/context.d.ts +12 -3
  16. package/build/typescript/context.d.ts.map +1 -1
  17. package/build/typescript/hooks/formatting.d.ts +1 -1
  18. package/build/typescript/hooks/formatting.d.ts.map +1 -1
  19. package/build/typescript/hooks/locale.d.ts +1 -1
  20. package/build/typescript/hooks/locale.d.ts.map +1 -1
  21. package/build/typescript/index.d.ts +1 -3
  22. package/build/typescript/index.d.ts.map +1 -1
  23. package/build/typescript/routing/LocalizedLink.d.ts.map +1 -1
  24. package/build/typescript/routing/LocalizedNavigation.d.ts +8 -11
  25. package/build/typescript/routing/LocalizedNavigation.d.ts.map +1 -1
  26. package/build/typescript/routing/context.d.ts +1 -2
  27. package/build/typescript/routing/context.d.ts.map +1 -1
  28. package/build/typescript/routing.d.ts +0 -1
  29. package/build/typescript/routing.d.ts.map +1 -1
  30. package/package.json +7 -7
  31. package/source/context.ts +12 -6
  32. package/source/hooks/formatting.ts +4 -2
  33. package/source/hooks/locale.ts +4 -2
  34. package/source/index.ts +1 -6
  35. package/source/routing/LocalizedLink.tsx +4 -4
  36. package/source/routing/LocalizedNavigation.tsx +45 -59
  37. package/source/routing/context.ts +13 -4
  38. package/source/routing.ts +0 -1
  39. package/build/esm/Localization.mjs +0 -37
  40. package/build/esm/context.mjs +0 -6
  41. package/build/esm/routing/LocalizedRouter.mjs +0 -34
  42. package/build/esnext/Localization.esnext +0 -44
  43. package/build/esnext/context.esnext +0 -6
  44. package/build/esnext/routing/LocalizedRouter.esnext +0 -32
  45. package/source/Localization.tsx +0 -61
  46. package/source/routing/LocalizedRouter.ts +0 -46
package/CHANGELOG.md CHANGED
@@ -1,5 +1,248 @@
1
1
  # @quilted/react-localize
2
2
 
3
+ ## 0.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#894](https://github.com/lemonmade/quilt/pull/894) [`fb998d1`](https://github.com/lemonmade/quilt/commit/fb998d1d0a7fb7981184daa5307320477355ace8) Thanks [@lemonmade](https://github.com/lemonmade)! - Consolidate all framework context into a unified `QuiltContext` architecture.
8
+
9
+ Previously, Quilt's context was fragmented across many standalone provider components (`AsyncContext`, `GraphQLContext`, `EmailContext`, etc.), each backed by its own Preact context object. This release consolidates everything into a single `QuiltContext` interface, augmented by each package via TypeScript module declaration merging, and provided by a single `<QuiltFrameworkContext>` component.
10
+
11
+ ## Breaking changes
12
+
13
+ ### All packages: unified `QuiltContext` interface
14
+
15
+ Each `@quilted/*` package now augments a single `QuiltContext` interface from `@quilted/preact-context` rather than maintaining its own standalone context. If you were accessing any Quilt context values directly via `useContext(SomeSpecificContext)`, switch to the appropriate `use*` hook instead.
16
+
17
+ ### `@quilted/preact-router`: `useRouter` renamed to `useNavigation`
18
+
19
+ ```ts
20
+ // Before
21
+ import {useRouter} from '@quilted/quilt/navigation';
22
+ const router = useRouter();
23
+
24
+ // After
25
+ import {useNavigation} from '@quilted/quilt/navigation';
26
+ const navigation = useNavigation();
27
+ ```
28
+
29
+ ### `@quilted/preact-router`: `router` QuiltContext field renamed to `navigation`
30
+
31
+ The `QuiltContext` field that holds the navigation instance is now `navigation` instead of `router`. This affects any code that reads the field directly, and the prop name on `<QuiltFrameworkContext>`.
32
+
33
+ ```tsx
34
+ // Before
35
+ <QuiltFrameworkContext router={myNavigation} />
36
+
37
+ // After
38
+ <QuiltFrameworkContext navigation={myNavigation} />
39
+ ```
40
+
41
+ ### `@quilted/preact-router`: `TestRouter` renamed to `TestNavigation`
42
+
43
+ ```ts
44
+ // Before
45
+ import {TestRouter} from '@quilted/quilt/navigation/testing';
46
+
47
+ // After
48
+ import {TestNavigation} from '@quilted/quilt/navigation/testing';
49
+ ```
50
+
51
+ ### `@quilted/preact-browser`: `browserDetails` and `browserAssets` QuiltContext fields renamed
52
+
53
+ The `QuiltContext` fields for browser environment details and the asset manifest have shorter, cleaner names:
54
+
55
+ - `browserDetails` → `browser`
56
+ - `browserAssets` → `assets`
57
+
58
+ These affect the props on `<QuiltFrameworkContext>` and any direct reads of the context.
59
+
60
+ ```tsx
61
+ // Before
62
+ <QuiltFrameworkContext browserDetails={browser} browserAssets={assets} />
63
+
64
+ // After
65
+ <QuiltFrameworkContext browser={browser} assets={assets} />
66
+ ```
67
+
68
+ ### `@quilted/preact-localize`: `localize` QuiltContext field renamed to `localization`
69
+
70
+ The QuiltContext field and the corresponding `<QuiltFrameworkContext>` prop are now `localization`:
71
+
72
+ ```tsx
73
+ // Before
74
+ <QuiltFrameworkContext localize={localization} />
75
+
76
+ // After
77
+ <QuiltFrameworkContext localization={localization} />
78
+ ```
79
+
80
+ ### `@quilted/preact-localize`: `createLocalizedFormatting` and `createLocalization` removed
81
+
82
+ These factory functions have been removed. Use the `Localization` class directly:
83
+
84
+ ```ts
85
+ // Before
86
+ import {createLocalization} from '@quilted/preact-localize';
87
+ const localization = createLocalization('en');
88
+
89
+ // After
90
+ import {Localization} from '@quilted/preact-localize';
91
+ const localization = new Localization('en');
92
+ ```
93
+
94
+ ### `@quilted/preact-async`: `AsyncContext` component removed
95
+
96
+ The standalone `<AsyncContext>` provider component has been removed. Pass async context directly to `<QuiltFrameworkContext>` instead:
97
+
98
+ ```tsx
99
+ // Before
100
+ import {AsyncContext, AsyncActionCache} from '@quilted/quilt/async';
101
+
102
+ <AsyncContext cache={cache}>
103
+ <App />
104
+ </AsyncContext>;
105
+
106
+ // After
107
+ import {QuiltFrameworkContext} from '@quilted/quilt/context';
108
+ import {AsyncActionCache} from '@quilted/quilt/async';
109
+
110
+ <QuiltFrameworkContext async={{cache}}>
111
+ <App />
112
+ </QuiltFrameworkContext>;
113
+ ```
114
+
115
+ `QuiltFrameworkContext` handles cache serialization for server-side rendering automatically, so no other changes are required.
116
+
117
+ ### `@quilted/preact-graphql`: `GraphQLContext` component removed
118
+
119
+ The standalone `<GraphQLContext>` provider component has been removed. The two separate `graphqlRun` and `graphqlCache` props on `<QuiltFrameworkContext>` have been replaced with a single `graphql` prop that accepts a `GraphQLClient` instance (or any object with `fetch` and `cache` properties):
120
+
121
+ ```tsx
122
+ // Before
123
+ import {GraphQLContext} from '@quilted/quilt/graphql';
124
+
125
+ <QuiltFrameworkContext navigation={navigation}>
126
+ <GraphQLContext fetch={myFetch} cache={myCache}>
127
+ <App />
128
+ </GraphQLContext>
129
+ </QuiltFrameworkContext>;
130
+
131
+ // After — using the new GraphQLClient class
132
+ import {GraphQLClient} from '@quilted/quilt/graphql';
133
+
134
+ const graphql = new GraphQLClient(myFetch);
135
+
136
+ <QuiltFrameworkContext navigation={navigation} graphql={graphql}>
137
+ <App />
138
+ </QuiltFrameworkContext>;
139
+ ```
140
+
141
+ ### `@quilted/preact-email`: `EmailContext` removed
142
+
143
+ The standalone `EmailContext` Preact context object has been removed. Email components should use the new `useEmailManager()` hook to access the email manager, which reads from the unified `QuiltContext`:
144
+
145
+ ```ts
146
+ // Before
147
+ import {useContext} from 'preact/hooks';
148
+ import {EmailContext} from '@quilted/preact-email';
149
+ const email = useContext(EmailContext);
150
+
151
+ // After
152
+ import {useEmailManager} from '@quilted/preact-email';
153
+ const email = useEmailManager();
154
+ ```
155
+
156
+ ### `@quilted/quilt`: `QuiltContext` component renamed to `QuiltFrameworkContext`
157
+
158
+ The provider component is now named `QuiltFrameworkContext` to avoid a name clash with the `QuiltContext` TypeScript interface:
159
+
160
+ ```tsx
161
+ // Before
162
+ import {QuiltContext} from '@quilted/quilt/context';
163
+ <QuiltContext navigation={navigation}>...</QuiltContext>;
164
+
165
+ // After
166
+ import {QuiltFrameworkContext} from '@quilted/quilt/context';
167
+ <QuiltFrameworkContext navigation={navigation}>...</QuiltFrameworkContext>;
168
+ ```
169
+
170
+ ### `@quilted/quilt`: `QuiltTestContext` renamed to `QuiltFrameworkTestContext`, takes `localization` instead of `locale`
171
+
172
+ The test context helper component is now `QuiltFrameworkTestContext` and accepts a `Localization` instance directly instead of a locale string:
173
+
174
+ ```tsx
175
+ // Before
176
+ import {QuiltTestContext} from '@quilted/quilt/context/testing';
177
+ <QuiltTestContext locale="fr">...</QuiltTestContext>;
178
+
179
+ // After
180
+ import {QuiltFrameworkTestContext} from '@quilted/quilt/context/testing';
181
+ import {Localization} from '@quilted/quilt/localize';
182
+ <QuiltFrameworkTestContext localization={new Localization('fr')}>
183
+ ...
184
+ </QuiltFrameworkTestContext>;
185
+ ```
186
+
187
+ ## New features
188
+
189
+ ### `@quilted/graphql`: `GraphQLClient` class
190
+
191
+ A new `GraphQLClient` class bundles a GraphQL fetch function and an optional result cache into a single object. A cache is created automatically by default, configured to use the same fetch function:
192
+
193
+ ```ts
194
+ import {createGraphQLFetch, GraphQLClient} from '@quilted/quilt/graphql';
195
+
196
+ // Cache created automatically from the fetch function
197
+ const client = new GraphQLClient(createGraphQLFetch({url: '/graphql'}));
198
+
199
+ // Disable caching
200
+ const client = new GraphQLClient(myFetch, {cache: false});
201
+
202
+ // Share an existing cache
203
+ const cache = new GraphQLCache();
204
+ const client = new GraphQLClient(myFetch, {cache});
205
+
206
+ // Use the client
207
+ client.fetch(MyQuery, {variables: {id: '1'}});
208
+ client.cache?.query(MyQuery, {variables: {id: '1'}});
209
+ ```
210
+
211
+ ### `@quilted/preact-router`: `useNavigation()` hook
212
+
213
+ The renamed `useNavigation()` hook returns the active `Navigation` instance from context, providing access to the current URL, navigation history, and programmatic navigation.
214
+
215
+ ### `@quilted/preact-email`: `useEmailManager()` hook
216
+
217
+ A new `useEmailManager()` hook provides access to the `EmailManager` instance from the unified `QuiltContext`. Returns `undefined` outside of an email rendering context.
218
+
219
+ ### `@quilted/preact-async`: signal-backed `async.isHydrated`
220
+
221
+ The `AsyncContext` interface (accessed via `useQuiltContext('async')`) now includes an `isHydrated` boolean getter backed by a Preact signal. Any component that reads `async.isHydrated` will automatically re-render when the client hydration completes, without requiring a manual signal subscription.
222
+
223
+ ### `@quilted/localize`: `Localization` class documentation
224
+
225
+ The `Localization` class now has full JSDoc documentation on the class, constructor, all properties (`locale`, `direction`, `numberFormatter`, `dateTimeFormatter`), and all methods (`formatNumber`, `formatCurrency`, `formatDate`).
226
+
227
+ - Updated dependencies [[`fb998d1`](https://github.com/lemonmade/quilt/commit/fb998d1d0a7fb7981184daa5307320477355ace8)]:
228
+ - @quilted/preact-browser@0.2.7
229
+ - @quilted/preact-context@0.1.5
230
+ - @quilted/preact-router@0.2.16
231
+ - @quilted/localize@0.2.3
232
+
233
+ ## 0.4.1
234
+
235
+ ### Patch Changes
236
+
237
+ - [`e6fa47e`](https://github.com/lemonmade/quilt/commit/e6fa47e93981ce0eaebbe1546659aaa08cc22689) Thanks [@lemonmade](https://github.com/lemonmade)! - Update Preact and Signal dependencies
238
+
239
+ - Updated dependencies [[`b1df5da`](https://github.com/lemonmade/quilt/commit/b1df5daff8441f8435a62b02b4ad3676d3ddcc3b), [`06b43bc`](https://github.com/lemonmade/quilt/commit/06b43bc44d271ce30798dc0b582870208bae1572), [`e6fa47e`](https://github.com/lemonmade/quilt/commit/e6fa47e93981ce0eaebbe1546659aaa08cc22689)]:
240
+ - @quilted/preact-browser@0.2.6
241
+ - @quilted/preact-router@0.2.15
242
+ - @quilted/preact-context@0.1.4
243
+ - @quilted/localize@0.2.2
244
+ - @quilted/signals@0.2.4
245
+
3
246
  ## 0.4.0
4
247
 
5
248
  ### Minor Changes
@@ -1,5 +1,7 @@
1
- import { LocalizedFormattingContext } from '../context.mjs';
1
+ import { useQuiltContext } from '@quilted/preact-context';
2
2
 
3
- const useLocalizedFormatting = LocalizedFormattingContext.use;
3
+ function useLocalizedFormatting() {
4
+ return useQuiltContext('localization');
5
+ }
4
6
 
5
7
  export { useLocalizedFormatting };
@@ -1,5 +1,7 @@
1
- import { LocaleContext } from '../context.mjs';
1
+ import { useQuiltContext } from '@quilted/preact-context';
2
2
 
3
- const useLocale = LocaleContext.use;
3
+ function useLocale() {
4
+ return useQuiltContext('localization').locale;
5
+ }
4
6
 
5
7
  export { useLocale };
@@ -1,13 +1,10 @@
1
- export { MissingTranslationError, MissingTranslationPlaceholderError, createLocalizedFormatting, createTranslate, parseAcceptLanguageHeader } from '@quilted/localize';
2
- export { Localization } from './Localization.mjs';
1
+ export { Localization, MissingTranslationError, MissingTranslationPlaceholderError, createTranslate, parseAcceptLanguageHeader } from '@quilted/localize';
3
2
  export { useLocalizedFormatting } from './hooks/formatting.mjs';
4
3
  export { useLocale } from './hooks/locale.mjs';
5
4
  export { useAlternateURL } from './hooks/alternate-url.mjs';
6
5
  export { AlternateURL } from './components/AlternateURL.mjs';
7
- export { LocalizedFormattingContext } from './context.mjs';
8
6
  export { LocalizedLink } from './routing/LocalizedLink.mjs';
9
7
  export { LocalizedNavigation } from './routing/LocalizedNavigation.mjs';
10
- export { LocalizedRouter } from './routing/LocalizedRouter.mjs';
11
8
  export { useRouteLocalization } from './routing/context.mjs';
12
9
  export { createRouteLocalization } from './routing/localization/by-locale.mjs';
13
10
  export { createRoutePathLocalization } from './routing/localization/by-path.mjs';
@@ -1,5 +1,5 @@
1
1
  import { useMemo } from 'preact/hooks';
2
- import { useRouter, useCurrentURL, Link } from '@quilted/preact-router';
2
+ import { useNavigation, useCurrentURL, Link } from '@quilted/preact-router';
3
3
  import { useRouteLocalization } from './context.mjs';
4
4
  import { jsx } from 'preact/jsx-runtime';
5
5
 
@@ -8,14 +8,14 @@ function LocalizedLink({
8
8
  locale,
9
9
  ...props
10
10
  }) {
11
- const router = useRouter();
11
+ const navigation = useNavigation();
12
12
  const url = useCurrentURL();
13
13
  const {
14
14
  redirectURL
15
15
  } = useRouteLocalization();
16
- const resolvedURL = useMemo(() => redirectURL(to ? router.resolve(to).url : url, {
16
+ const resolvedURL = useMemo(() => redirectURL(to ? navigation.resolve(to).url : url, {
17
17
  to: locale
18
- }), [to, url, locale, redirectURL, router]);
18
+ }), [to, url, locale, redirectURL, navigation]);
19
19
  return jsx(Link, {
20
20
  hrefLang: locale,
21
21
  to: resolvedURL,
@@ -1,47 +1,38 @@
1
- import { useMemo } from 'preact/hooks';
2
- import { useBrowserDetails } from '@quilted/preact-browser';
3
1
  import { Navigation } from '@quilted/preact-router';
4
- import { Localization } from '../Localization.mjs';
5
- import { LocalizedRouter } from './LocalizedRouter.mjs';
6
- import { RouteLocalizationContext } from './context.mjs';
7
- import { jsx } from 'preact/jsx-runtime';
8
2
 
9
- function LocalizedNavigation({
10
- locale: explicitLocale,
11
- router,
12
- routes,
13
- context,
14
- localization,
15
- children
16
- }) {
17
- const browser = useBrowserDetails({
18
- optional: true
19
- });
20
- const resolvedRouter = useMemo(() => router ?? new LocalizedRouter(browser?.request.url, {
21
- localization: localization
22
- }), [router]);
23
- const resolvedLocalization = resolvedRouter.localization;
24
- const localeFromEnvironment = browser?.locale.value;
25
- let resolvedLocale;
26
- if (explicitLocale) {
27
- resolvedLocale = explicitLocale;
28
- } else if (localeFromEnvironment != null && localeFromEnvironment.toLowerCase().startsWith(resolvedLocalization.locale.toLowerCase())) {
29
- resolvedLocale = localeFromEnvironment;
30
- } else {
31
- resolvedLocale = resolvedLocalization.locale;
3
+ class LocalizedNavigation extends Navigation {
4
+ get locale() {
5
+ return this.routes.locale;
6
+ }
7
+ constructor(initial, {
8
+ routes,
9
+ isExternal: explicitIsExternal
10
+ }) {
11
+ const {
12
+ localeFromURL
13
+ } = routes;
14
+ let matchedLocale;
15
+ super(initial, {
16
+ isExternal(url, currentURL) {
17
+ return matchedLocale !== localeFromURL(url) || (explicitIsExternal?.(url, currentURL) ?? false);
18
+ }
19
+ });
20
+ const currentURL = this.currentRequest.url;
21
+ matchedLocale = localeFromURL(currentURL);
22
+ const resolvedLocalization = {
23
+ locale: matchedLocale ?? routes.defaultLocale,
24
+ ...routes
25
+ };
26
+ this.routes = resolvedLocalization;
27
+ const {
28
+ pathname: rootPath
29
+ } = routes.redirectURL(new URL('/', currentURL), {
30
+ to: resolvedLocalization.locale
31
+ });
32
+ if (rootPath.length > 1) Object.assign(this, {
33
+ base: rootPath
34
+ });
32
35
  }
33
- return jsx(Localization, {
34
- locale: resolvedLocale,
35
- children: jsx(RouteLocalizationContext.Provider, {
36
- value: resolvedLocalization,
37
- children: jsx(Navigation, {
38
- router: resolvedRouter,
39
- routes: routes,
40
- context: context,
41
- children: children
42
- })
43
- })
44
- });
45
36
  }
46
37
 
47
38
  export { LocalizedNavigation };
@@ -1,6 +1,12 @@
1
- import { createOptionalContext } from '@quilted/preact-context';
1
+ import { useNavigation } from '@quilted/preact-router';
2
+ import { LocalizedNavigation } from './LocalizedNavigation.mjs';
2
3
 
3
- const RouteLocalizationContext = createOptionalContext();
4
- const useRouteLocalization = RouteLocalizationContext.use;
4
+ function useRouteLocalization() {
5
+ const navigation = useNavigation();
6
+ if (!(navigation instanceof LocalizedNavigation)) {
7
+ throw new Error('useRouteLocalization() requires a LocalizedNavigation instance to be provided in context. ' + 'Make sure you are passing a LocalizedNavigation to QuiltFrameworkContext.');
8
+ }
9
+ return navigation.routes;
10
+ }
5
11
 
6
- export { RouteLocalizationContext, useRouteLocalization };
12
+ export { useRouteLocalization };
@@ -1,5 +1,7 @@
1
- import { LocalizedFormattingContext } from '../context.esnext';
1
+ import { useQuiltContext } from '@quilted/preact-context';
2
2
 
3
- const useLocalizedFormatting = LocalizedFormattingContext.use;
3
+ function useLocalizedFormatting() {
4
+ return useQuiltContext("localization");
5
+ }
4
6
 
5
7
  export { useLocalizedFormatting };
@@ -1,5 +1,7 @@
1
- import { LocaleContext } from '../context.esnext';
1
+ import { useQuiltContext } from '@quilted/preact-context';
2
2
 
3
- const useLocale = LocaleContext.use;
3
+ function useLocale() {
4
+ return useQuiltContext("localization").locale;
5
+ }
4
6
 
5
7
  export { useLocale };
@@ -1,13 +1,10 @@
1
- export { MissingTranslationError, MissingTranslationPlaceholderError, createLocalizedFormatting, createTranslate, parseAcceptLanguageHeader } from '@quilted/localize';
2
- export { Localization } from './Localization.esnext';
1
+ export { Localization, MissingTranslationError, MissingTranslationPlaceholderError, createTranslate, parseAcceptLanguageHeader } from '@quilted/localize';
3
2
  export { useLocalizedFormatting } from './hooks/formatting.esnext';
4
3
  export { useLocale } from './hooks/locale.esnext';
5
4
  export { useAlternateURL } from './hooks/alternate-url.esnext';
6
5
  export { AlternateURL } from './components/AlternateURL.esnext';
7
- export { LocalizedFormattingContext } from './context.esnext';
8
6
  export { LocalizedLink } from './routing/LocalizedLink.esnext';
9
7
  export { LocalizedNavigation } from './routing/LocalizedNavigation.esnext';
10
- export { LocalizedRouter } from './routing/LocalizedRouter.esnext';
11
8
  export { useRouteLocalization } from './routing/context.esnext';
12
9
  export { createRouteLocalization } from './routing/localization/by-locale.esnext';
13
10
  export { createRoutePathLocalization } from './routing/localization/by-path.esnext';
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'preact/jsx-runtime';
2
2
  import { useMemo } from 'preact/hooks';
3
- import { useRouter, useCurrentURL, Link } from '@quilted/preact-router';
3
+ import { useNavigation, useCurrentURL, Link } from '@quilted/preact-router';
4
4
  import { useRouteLocalization } from './context.esnext';
5
5
 
6
6
  function LocalizedLink({
@@ -8,12 +8,12 @@ function LocalizedLink({
8
8
  locale,
9
9
  ...props
10
10
  }) {
11
- const router = useRouter();
11
+ const navigation = useNavigation();
12
12
  const url = useCurrentURL();
13
13
  const { redirectURL } = useRouteLocalization();
14
14
  const resolvedURL = useMemo(
15
- () => redirectURL(to ? router.resolve(to).url : url, { to: locale }),
16
- [to, url, locale, redirectURL, router]
15
+ () => redirectURL(to ? navigation.resolve(to).url : url, { to: locale }),
16
+ [to, url, locale, redirectURL, navigation]
17
17
  );
18
18
  return /* @__PURE__ */ jsx(Link, { hrefLang: locale, to: resolvedURL, ...props });
19
19
  }
@@ -1,35 +1,33 @@
1
- import { jsx } from 'preact/jsx-runtime';
2
- import { useMemo } from 'preact/hooks';
3
- import { useBrowserDetails } from '@quilted/preact-browser';
4
1
  import { Navigation } from '@quilted/preact-router';
5
- import { Localization } from '../Localization.esnext';
6
- import { LocalizedRouter } from './LocalizedRouter.esnext';
7
- import { RouteLocalizationContext } from './context.esnext';
8
2
 
9
- function LocalizedNavigation({
10
- locale: explicitLocale,
11
- router,
12
- routes,
13
- context,
14
- localization,
15
- children
16
- }) {
17
- const browser = useBrowserDetails({ optional: true });
18
- const resolvedRouter = useMemo(
19
- () => router ?? new LocalizedRouter(browser?.request.url, { localization }),
20
- [router]
21
- );
22
- const resolvedLocalization = resolvedRouter.localization;
23
- const localeFromEnvironment = browser?.locale.value;
24
- let resolvedLocale;
25
- if (explicitLocale) {
26
- resolvedLocale = explicitLocale;
27
- } else if (localeFromEnvironment != null && localeFromEnvironment.toLowerCase().startsWith(resolvedLocalization.locale.toLowerCase())) {
28
- resolvedLocale = localeFromEnvironment;
29
- } else {
30
- resolvedLocale = resolvedLocalization.locale;
3
+ class LocalizedNavigation extends Navigation {
4
+ routes;
5
+ get locale() {
6
+ return this.routes.locale;
7
+ }
8
+ constructor(initial, {
9
+ routes,
10
+ isExternal: explicitIsExternal
11
+ }) {
12
+ const { localeFromURL } = routes;
13
+ let matchedLocale;
14
+ super(initial, {
15
+ isExternal(url, currentURL2) {
16
+ return matchedLocale !== localeFromURL(url) || (explicitIsExternal?.(url, currentURL2) ?? false);
17
+ }
18
+ });
19
+ const currentURL = this.currentRequest.url;
20
+ matchedLocale = localeFromURL(currentURL);
21
+ const resolvedLocalization = {
22
+ locale: matchedLocale ?? routes.defaultLocale,
23
+ ...routes
24
+ };
25
+ this.routes = resolvedLocalization;
26
+ const { pathname: rootPath } = routes.redirectURL(new URL("/", currentURL), {
27
+ to: resolvedLocalization.locale
28
+ });
29
+ if (rootPath.length > 1) Object.assign(this, { base: rootPath });
31
30
  }
32
- return /* @__PURE__ */ jsx(Localization, { locale: resolvedLocale, children: /* @__PURE__ */ jsx(RouteLocalizationContext.Provider, { value: resolvedLocalization, children: /* @__PURE__ */ jsx(Navigation, { router: resolvedRouter, routes, context, children }) }) });
33
31
  }
34
32
 
35
33
  export { LocalizedNavigation };
@@ -1,6 +1,14 @@
1
- import { createOptionalContext } from '@quilted/preact-context';
1
+ import { useNavigation } from '@quilted/preact-router';
2
+ import { LocalizedNavigation } from './LocalizedNavigation.esnext';
2
3
 
3
- const RouteLocalizationContext = createOptionalContext();
4
- const useRouteLocalization = RouteLocalizationContext.use;
4
+ function useRouteLocalization() {
5
+ const navigation = useNavigation();
6
+ if (!(navigation instanceof LocalizedNavigation)) {
7
+ throw new Error(
8
+ "useRouteLocalization() requires a LocalizedNavigation instance to be provided in context. Make sure you are passing a LocalizedNavigation to QuiltFrameworkContext."
9
+ );
10
+ }
11
+ return navigation.routes;
12
+ }
5
13
 
6
- export { RouteLocalizationContext, useRouteLocalization };
14
+ export { useRouteLocalization };