@furystack/shades 12.2.5 → 12.4.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 +99 -0
- package/esm/components/lazy-load.d.ts +2 -0
- package/esm/components/lazy-load.d.ts.map +1 -1
- package/esm/components/lazy-load.js +8 -3
- package/esm/components/lazy-load.js.map +1 -1
- package/esm/components/lazy-load.spec.js +59 -1
- package/esm/components/lazy-load.spec.js.map +1 -1
- package/esm/components/nested-router.d.ts +53 -0
- package/esm/components/nested-router.d.ts.map +1 -1
- package/esm/components/nested-router.js +35 -10
- package/esm/components/nested-router.js.map +1 -1
- package/esm/components/nested-router.spec.js +267 -19
- package/esm/components/nested-router.spec.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/services/index.d.ts +2 -0
- package/esm/services/index.d.ts.map +1 -1
- package/esm/services/index.js +2 -0
- package/esm/services/index.js.map +1 -1
- package/esm/services/route-match-service.d.ts +12 -0
- package/esm/services/route-match-service.d.ts.map +1 -0
- package/esm/services/route-match-service.js +24 -0
- package/esm/services/route-match-service.js.map +1 -0
- package/esm/services/route-match-service.spec.d.ts +2 -0
- package/esm/services/route-match-service.spec.d.ts.map +1 -0
- package/esm/services/route-match-service.spec.js +120 -0
- package/esm/services/route-match-service.spec.js.map +1 -0
- package/esm/services/route-meta-utils.d.ts +57 -0
- package/esm/services/route-meta-utils.d.ts.map +1 -0
- package/esm/services/route-meta-utils.js +64 -0
- package/esm/services/route-meta-utils.js.map +1 -0
- package/esm/services/route-meta-utils.spec.d.ts +2 -0
- package/esm/services/route-meta-utils.spec.d.ts.map +1 -0
- package/esm/services/route-meta-utils.spec.js +217 -0
- package/esm/services/route-meta-utils.spec.js.map +1 -0
- package/esm/shade.d.ts.map +1 -1
- package/esm/shade.js +12 -1
- package/esm/shade.js.map +1 -1
- package/esm/shade.spec.js +93 -2
- package/esm/shade.spec.js.map +1 -1
- package/esm/view-transition.d.ts +38 -0
- package/esm/view-transition.d.ts.map +1 -0
- package/esm/view-transition.js +50 -0
- package/esm/view-transition.js.map +1 -0
- package/esm/view-transition.spec.d.ts +2 -0
- package/esm/view-transition.spec.d.ts.map +1 -0
- package/esm/view-transition.spec.js +184 -0
- package/esm/view-transition.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/components/lazy-load.spec.tsx +78 -1
- package/src/components/lazy-load.tsx +10 -3
- package/src/components/nested-router.spec.tsx +389 -35
- package/src/components/nested-router.tsx +93 -10
- package/src/index.ts +1 -0
- package/src/services/index.ts +2 -0
- package/src/services/route-match-service.spec.ts +45 -0
- package/src/services/route-match-service.ts +17 -0
- package/src/services/route-meta-utils.spec.ts +243 -0
- package/src/services/route-meta-utils.ts +85 -0
- package/src/shade.spec.tsx +112 -2
- package/src/shade.ts +11 -1
- package/src/view-transition.spec.ts +218 -0
- package/src/view-transition.ts +66 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,104 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [12.4.0] - 2026-03-05
|
|
4
|
+
|
|
5
|
+
### ✨ Features
|
|
6
|
+
|
|
7
|
+
### View Transition API support in NestedRouter
|
|
8
|
+
|
|
9
|
+
The `NestedRouter` component now integrates with the [View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) to animate route changes with browser-native transitions.
|
|
10
|
+
|
|
11
|
+
Enable globally at the router level with a single prop:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<NestedRouter routes={appRoutes} viewTransition />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or configure transition types for CSS targeting via `:active-view-transition-type()`:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<NestedRouter routes={appRoutes} viewTransition={{ types: ['slide'] }} />
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Individual routes can opt out or override the router-level config:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
'/about': {
|
|
27
|
+
component: () => <AboutPage />,
|
|
28
|
+
viewTransition: false, // disables transitions for this route
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The feature is a progressive enhancement — non-supporting browsers fall back to instant page changes with zero additional code.
|
|
33
|
+
|
|
34
|
+
### View Transition API support in LazyLoad
|
|
35
|
+
|
|
36
|
+
The `LazyLoad` component now accepts a `viewTransition` prop to animate the swap from loader placeholder to loaded content:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<LazyLoad viewTransition loader={<Skeleton />} component={async () => <MyPage />} />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Shared `maybeViewTransition()` utility
|
|
43
|
+
|
|
44
|
+
Added and exported a `maybeViewTransition(config, update)` helper that wraps a synchronous DOM update in `document.startViewTransition()` when the API is available and `config` is truthy, falling back to a direct call otherwise. This utility is used internally by `NestedRouter` and `LazyLoad`, and is available for external consumers.
|
|
45
|
+
|
|
46
|
+
### 📚 Documentation
|
|
47
|
+
|
|
48
|
+
- Added JSDoc descriptions for `onVisit` and `onLeave` lifecycle hooks on `NestedRoute`, clarifying their timing relative to view transitions
|
|
49
|
+
|
|
50
|
+
### 🧪 Tests
|
|
51
|
+
|
|
52
|
+
- Added unit tests for `resolveViewTransition()` covering router-level defaults, per-route overrides, type merging, and opt-out behavior
|
|
53
|
+
- Added integration tests verifying `NestedRouter` calls `document.startViewTransition()` when enabled, passes transition types, respects per-route `viewTransition: false`, and falls back gracefully when the API is unavailable
|
|
54
|
+
- Added tests for `LazyLoad` verifying `startViewTransition` is called when `viewTransition` is enabled and skipped when not set
|
|
55
|
+
|
|
56
|
+
## [12.3.0] - 2026-03-04
|
|
57
|
+
|
|
58
|
+
### ✨ Features
|
|
59
|
+
|
|
60
|
+
### Route Metadata on `NestedRoute`
|
|
61
|
+
|
|
62
|
+
Routes can now carry a `meta` object with a `title` field (static string or async resolver function). The `NestedRouteMeta` interface supports declaration merging so applications can extend it with custom fields (e.g. `icon`, `hidden`).
|
|
63
|
+
|
|
64
|
+
**Usage:**
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import type { NestedRoute } from '@furystack/shades'
|
|
68
|
+
|
|
69
|
+
const routes = {
|
|
70
|
+
'/users/:id': {
|
|
71
|
+
meta: {
|
|
72
|
+
title: ({ match }) => `User ${match.params.id}`,
|
|
73
|
+
},
|
|
74
|
+
component: ({ match }) => <div>User {match.params.id}</div>,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `RouteMatchService` — Observable match chain
|
|
80
|
+
|
|
81
|
+
New singleton service that exposes the current `NestedRouter` match chain as an `ObservableValue`. Consumers like breadcrumbs, document title updaters, and navigation trees can subscribe to `currentMatchChain` instead of re-running route matching themselves.
|
|
82
|
+
|
|
83
|
+
### Route metadata utility functions
|
|
84
|
+
|
|
85
|
+
- `resolveRouteTitle(entry, injector)` — resolves the title for a single match chain entry, supporting static strings, sync functions, and async functions
|
|
86
|
+
- `resolveRouteTitles(chain, injector)` — resolves all titles from a match chain in parallel
|
|
87
|
+
- `buildDocumentTitle(titles, options?)` — composes resolved titles into a single document title string with configurable separator and prefix
|
|
88
|
+
- `extractNavTree(routes, parentPath?)` — extracts a `NavTreeNode[]` tree from route definitions for rendering sidebar navigation or sitemaps
|
|
89
|
+
|
|
90
|
+
### 🧪 Tests
|
|
91
|
+
|
|
92
|
+
- Added unit tests for `RouteMatchService` covering initialization, updates, subscriptions, and disposal
|
|
93
|
+
- Added unit tests for `resolveRouteTitle`, `resolveRouteTitles`, `buildDocumentTitle`, and `extractNavTree`
|
|
94
|
+
- Added integration tests verifying `NestedRouter` publishes the match chain to `RouteMatchService` on navigation
|
|
95
|
+
- Added tests verifying that `updateComponent()` and `updateComponentSync()` are no-ops after the element is removed from the DOM
|
|
96
|
+
- Added tests verifying that observable changes fired during disposal do not trigger additional renders
|
|
97
|
+
|
|
98
|
+
### 🐛 Bug Fixes
|
|
99
|
+
|
|
100
|
+
- Fixed ghost rendering race conditions where `updateComponent()` and `updateComponentSync()` could trigger re-renders on disconnected components. Added disconnected-state guards to both methods so that observable changes fired during disposal no longer cause stale render passes.
|
|
101
|
+
|
|
3
102
|
## [12.2.5] - 2026-03-03
|
|
4
103
|
|
|
5
104
|
### ⬆️ Dependencies
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { ViewTransitionConfig } from '../view-transition.js';
|
|
1
2
|
export interface LazyLoadProps {
|
|
2
3
|
loader: JSX.Element;
|
|
3
4
|
error?: (error: unknown, retry: () => Promise<void>) => JSX.Element;
|
|
4
5
|
component: () => Promise<JSX.Element>;
|
|
6
|
+
viewTransition?: boolean | ViewTransitionConfig;
|
|
5
7
|
}
|
|
6
8
|
export declare const LazyLoad: (props: LazyLoadProps & Omit<Partial<HTMLElement>, "style"> & {
|
|
7
9
|
style?: Partial<CSSStyleDeclaration>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-load.d.ts","sourceRoot":"","sources":["../../src/components/lazy-load.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lazy-load.d.ts","sourceRoot":"","sources":["../../src/components/lazy-load.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAGjE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,CAAA;IACnE,SAAS,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACrC,cAAc,CAAC,EAAE,OAAO,GAAG,oBAAoB,CAAA;CAChD;AAED,eAAO,MAAM,QAAQ;;;;gEAwEnB,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Shade } from '../shade.js';
|
|
2
|
+
import { maybeViewTransition } from '../view-transition.js';
|
|
2
3
|
export const LazyLoad = Shade({
|
|
3
4
|
shadowDomName: 'lazy-load',
|
|
4
5
|
render: ({ props, useState, useDisposable }) => {
|
|
@@ -21,8 +22,10 @@ export const LazyLoad = Shade({
|
|
|
21
22
|
factory()
|
|
22
23
|
.then((loaded) => {
|
|
23
24
|
if (tracker.active && tracker.factory === factory) {
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
void maybeViewTransition(props.viewTransition, () => {
|
|
26
|
+
setError(undefined);
|
|
27
|
+
setComponent(loaded);
|
|
28
|
+
});
|
|
26
29
|
}
|
|
27
30
|
})
|
|
28
31
|
.catch((err) => {
|
|
@@ -43,7 +46,9 @@ export const LazyLoad = Shade({
|
|
|
43
46
|
setComponent(undefined);
|
|
44
47
|
const loaded = await factory();
|
|
45
48
|
if (tracker.active && tracker.factory === factory) {
|
|
46
|
-
|
|
49
|
+
void maybeViewTransition(props.viewTransition, () => {
|
|
50
|
+
setComponent(loaded);
|
|
51
|
+
});
|
|
47
52
|
}
|
|
48
53
|
}
|
|
49
54
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-load.js","sourceRoot":"","sources":["../../src/components/lazy-load.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"lazy-load.js","sourceRoot":"","sources":["../../src/components/lazy-load.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAS3D,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAgB;IAC3C,aAAa,EAAE,WAAW;IAC1B,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,EAAE;QAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAU,OAAO,EAAE,SAAS,CAAC,CAAA;QAC/D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAA0B,WAAW,EAAE,SAAS,CAAC,CAAA;QAE3F,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,EAAE,GAAG,EAAE;YAChD,MAAM,KAAK,GAIP;gBACF,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,IAAI;gBACZ,CAAC,MAAM,CAAC,OAAO,CAAC;oBACd,KAAK,CAAC,MAAM,GAAG,KAAK,CAAA;gBACtB,CAAC;aACF,CAAA;YACD,OAAO,KAAK,CAAA;QACd,CAAC,CAAC,CAAA;QAEF,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,SAAS,CAAA;QAExD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAA;YACjC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAA;YAE/B,OAAO,EAAE;iBACN,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBACf,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;oBAClD,KAAK,mBAAmB,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE;wBAClD,QAAQ,CAAC,SAAS,CAAC,CAAA;wBACnB,YAAY,CAAC,MAAM,CAAC,CAAA;oBACtB,CAAC,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACtB,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;oBAClD,YAAY,CAAC,SAAS,CAAC,CAAA;oBACvB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;wBAChB,QAAQ,CAAC,GAAG,CAAC,CAAA;oBACf,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAA;YAEJ,OAAO,KAAK,CAAC,MAAM,CAAA;QACrB,CAAC;QAED,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;gBACnC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAA;gBAC/B,IAAI,CAAC;oBACH,QAAQ,CAAC,SAAS,CAAC,CAAA;oBACnB,YAAY,CAAC,SAAS,CAAC,CAAA;oBACvB,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAA;oBAC9B,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;wBAClD,KAAK,mBAAmB,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE;4BAClD,YAAY,CAAC,MAAM,CAAC,CAAA;wBACtB,CAAC,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;wBAClD,QAAQ,CAAC,CAAC,CAAC,CAAA;oBACb,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAA;IACrB,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -11,6 +11,7 @@ describe('Lazy Load', () => {
|
|
|
11
11
|
});
|
|
12
12
|
afterEach(() => {
|
|
13
13
|
document.body.innerHTML = '';
|
|
14
|
+
delete document.startViewTransition;
|
|
14
15
|
});
|
|
15
16
|
it('Shuld display the loader and completed state', async () => {
|
|
16
17
|
await usingAsync(new Injector(), async (injector) => {
|
|
@@ -49,7 +50,7 @@ describe('Lazy Load', () => {
|
|
|
49
50
|
expect(load).toBeCalledTimes(2);
|
|
50
51
|
});
|
|
51
52
|
});
|
|
52
|
-
it('
|
|
53
|
+
it('Should succeed on retry after initial failure', async () => {
|
|
53
54
|
await usingAsync(new Injector(), async (injector) => {
|
|
54
55
|
const rootElement = document.getElementById('root');
|
|
55
56
|
let counter = 0;
|
|
@@ -76,5 +77,62 @@ describe('Lazy Load', () => {
|
|
|
76
77
|
expect(document.body.innerHTML).toBe('<div id="root"><lazy-load><div>success</div></lazy-load></div>');
|
|
77
78
|
});
|
|
78
79
|
});
|
|
80
|
+
it('should call startViewTransition when viewTransition is enabled and component loads', async () => {
|
|
81
|
+
const startViewTransitionSpy = vi.fn((optionsOrCallback) => {
|
|
82
|
+
const update = typeof optionsOrCallback === 'function' ? optionsOrCallback : optionsOrCallback.update;
|
|
83
|
+
update?.();
|
|
84
|
+
return {
|
|
85
|
+
finished: Promise.resolve(),
|
|
86
|
+
ready: Promise.resolve(),
|
|
87
|
+
updateCallbackDone: Promise.resolve(),
|
|
88
|
+
skipTransition: vi.fn(),
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
document.startViewTransition = startViewTransitionSpy;
|
|
92
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
93
|
+
const rootElement = document.getElementById('root');
|
|
94
|
+
initializeShadeRoot({
|
|
95
|
+
injector,
|
|
96
|
+
rootElement,
|
|
97
|
+
jsxElement: (createComponent(LazyLoad, { viewTransition: true, loader: createComponent("div", null, "Loading..."), component: async () => {
|
|
98
|
+
await sleepAsync(50);
|
|
99
|
+
return createComponent("div", null, "Loaded");
|
|
100
|
+
} })),
|
|
101
|
+
});
|
|
102
|
+
await flushUpdates();
|
|
103
|
+
expect(document.body.innerHTML).toContain('Loading...');
|
|
104
|
+
await sleepAsync(100);
|
|
105
|
+
expect(startViewTransitionSpy).toHaveBeenCalledTimes(1);
|
|
106
|
+
expect(document.body.innerHTML).toContain('Loaded');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
it('should not call startViewTransition when viewTransition is not set', async () => {
|
|
110
|
+
const startViewTransitionSpy = vi.fn((optionsOrCallback) => {
|
|
111
|
+
const update = typeof optionsOrCallback === 'function' ? optionsOrCallback : optionsOrCallback.update;
|
|
112
|
+
update?.();
|
|
113
|
+
return {
|
|
114
|
+
finished: Promise.resolve(),
|
|
115
|
+
ready: Promise.resolve(),
|
|
116
|
+
updateCallbackDone: Promise.resolve(),
|
|
117
|
+
skipTransition: vi.fn(),
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
document.startViewTransition = startViewTransitionSpy;
|
|
121
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
122
|
+
const rootElement = document.getElementById('root');
|
|
123
|
+
initializeShadeRoot({
|
|
124
|
+
injector,
|
|
125
|
+
rootElement,
|
|
126
|
+
jsxElement: (createComponent(LazyLoad, { loader: createComponent("div", null, "Loading..."), component: async () => {
|
|
127
|
+
await sleepAsync(50);
|
|
128
|
+
return createComponent("div", null, "Loaded");
|
|
129
|
+
} })),
|
|
130
|
+
});
|
|
131
|
+
await flushUpdates();
|
|
132
|
+
await sleepAsync(100);
|
|
133
|
+
expect(startViewTransitionSpy).not.toHaveBeenCalled();
|
|
134
|
+
expect(document.body.innerHTML).toContain('Loaded');
|
|
135
|
+
});
|
|
136
|
+
});
|
|
79
137
|
});
|
|
80
138
|
//# sourceMappingURL=lazy-load.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-load.spec.js","sourceRoot":"","sources":["../../src/components/lazy-load.spec.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,UAAU,CAAC,GAAG,EAAE;QACd,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,uBAAuB,CAAA;IACnD,CAAC,CAAC,CAAA;IACF,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"lazy-load.spec.js","sourceRoot":"","sources":["../../src/components/lazy-load.spec.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,38 @@
|
|
|
1
|
+
import type { Injector } from '@furystack/inject';
|
|
1
2
|
import type { MatchOptions, MatchResult } from 'path-to-regexp';
|
|
2
3
|
import type { RenderOptions } from '../models/render-options.js';
|
|
4
|
+
import type { ViewTransitionConfig } from '../view-transition.js';
|
|
5
|
+
/**
|
|
6
|
+
* Options passed to a dynamic title resolver function.
|
|
7
|
+
* @typeParam TMatchResult - The type of matched URL parameters
|
|
8
|
+
*/
|
|
9
|
+
export type TitleResolverOptions<TMatchResult = unknown> = {
|
|
10
|
+
match: MatchResult<TMatchResult extends object ? TMatchResult : object>;
|
|
11
|
+
injector: Injector;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Metadata associated with a route entry.
|
|
15
|
+
* Used by consumers (breadcrumbs, document title, navigation trees) to
|
|
16
|
+
* derive display information from the route hierarchy.
|
|
17
|
+
*
|
|
18
|
+
* This is an `interface` so that applications can augment it with custom fields
|
|
19
|
+
* via declaration merging:
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* declare module '@furystack/shades' {
|
|
24
|
+
* interface NestedRouteMeta {
|
|
25
|
+
* icon?: IconDefinition
|
|
26
|
+
* hidden?: boolean
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @typeParam TMatchResult - The type of matched URL parameters
|
|
32
|
+
*/
|
|
33
|
+
export interface NestedRouteMeta<TMatchResult = unknown> {
|
|
34
|
+
title?: string | ((options: TitleResolverOptions<TMatchResult>) => string | Promise<string>);
|
|
35
|
+
}
|
|
3
36
|
/**
|
|
4
37
|
* A single route entry in a NestedRouter configuration.
|
|
5
38
|
* Unlike flat `Route`, the URL is the Record key (not a field), and the
|
|
@@ -7,19 +40,32 @@ import type { RenderOptions } from '../models/render-options.js';
|
|
|
7
40
|
* @typeParam TMatchResult - The type of matched URL parameters
|
|
8
41
|
*/
|
|
9
42
|
export type NestedRoute<TMatchResult = unknown> = {
|
|
43
|
+
meta?: NestedRouteMeta<TMatchResult>;
|
|
10
44
|
component: (options: {
|
|
11
45
|
currentUrl: string;
|
|
12
46
|
match: MatchResult<TMatchResult extends object ? TMatchResult : object>;
|
|
13
47
|
outlet?: JSX.Element;
|
|
14
48
|
}) => JSX.Element;
|
|
15
49
|
routingOptions?: MatchOptions;
|
|
50
|
+
/**
|
|
51
|
+
* Called after the route's DOM has been mounted. When view transitions are enabled,
|
|
52
|
+
* this runs after the transition's update callback has completed and the new DOM is in place.
|
|
53
|
+
* Use for imperative side effects like data fetching or focus management — not for visual
|
|
54
|
+
* animations, which are handled by the View Transition API when `viewTransition` is enabled.
|
|
55
|
+
*/
|
|
16
56
|
onVisit?: (options: RenderOptions<unknown> & {
|
|
17
57
|
element: JSX.Element;
|
|
18
58
|
}) => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Called before the route's DOM is removed (and before the view transition starts, if enabled).
|
|
61
|
+
* Use for cleanup or teardown logic — not for exit animations, which are handled by the
|
|
62
|
+
* View Transition API when `viewTransition` is enabled.
|
|
63
|
+
*/
|
|
19
64
|
onLeave?: (options: RenderOptions<unknown> & {
|
|
20
65
|
element: JSX.Element;
|
|
21
66
|
}) => Promise<void>;
|
|
22
67
|
children?: Record<string, NestedRoute<any>>;
|
|
68
|
+
viewTransition?: boolean | ViewTransitionConfig;
|
|
23
69
|
};
|
|
24
70
|
/**
|
|
25
71
|
* Props for the NestedRouter component.
|
|
@@ -28,6 +74,7 @@ export type NestedRoute<TMatchResult = unknown> = {
|
|
|
28
74
|
export type NestedRouterProps = {
|
|
29
75
|
routes: Record<string, NestedRoute<any>>;
|
|
30
76
|
notFound?: JSX.Element;
|
|
77
|
+
viewTransition?: boolean | ViewTransitionConfig;
|
|
31
78
|
};
|
|
32
79
|
/**
|
|
33
80
|
* A single entry in a match chain, pairing a matched route with its match result.
|
|
@@ -86,6 +133,12 @@ export type RenderMatchChainResult = {
|
|
|
86
133
|
* @returns The fully composed JSX element and per-entry rendered elements
|
|
87
134
|
*/
|
|
88
135
|
export declare const renderMatchChain: (chain: MatchChainEntry[], currentUrl: string) => RenderMatchChainResult;
|
|
136
|
+
/**
|
|
137
|
+
* Resolves the effective view transition config for a navigation by merging
|
|
138
|
+
* the router-level default with the innermost (leaf) route's override.
|
|
139
|
+
* A per-route `false` disables transitions even when the router default is on.
|
|
140
|
+
*/
|
|
141
|
+
export declare const resolveViewTransition: (routerConfig: boolean | ViewTransitionConfig | undefined, newChain: MatchChainEntry[]) => ViewTransitionConfig | false;
|
|
89
142
|
/**
|
|
90
143
|
* A nested router component that supports hierarchical route definitions
|
|
91
144
|
* with parent/child relationships. Parent routes receive an `outlet` prop
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nested-router.d.ts","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nested-router.d.ts","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ObservableAlreadyDisposedError } from '@furystack/utils';
|
|
2
2
|
import { match } from 'path-to-regexp';
|
|
3
3
|
import { LocationService } from '../services/location-service.js';
|
|
4
|
+
import { RouteMatchService } from '../services/route-match-service.js';
|
|
4
5
|
import { createComponent, setRenderMode } from '../shade-component.js';
|
|
5
6
|
import { Shade } from '../shade.js';
|
|
7
|
+
import { maybeViewTransition } from '../view-transition.js';
|
|
6
8
|
/**
|
|
7
9
|
* Recursively builds a match chain from outermost to innermost matched route.
|
|
8
10
|
*
|
|
@@ -92,6 +94,24 @@ export const renderMatchChain = (chain, currentUrl) => {
|
|
|
92
94
|
}
|
|
93
95
|
return { jsx: outlet, chainElements };
|
|
94
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Resolves the effective view transition config for a navigation by merging
|
|
99
|
+
* the router-level default with the innermost (leaf) route's override.
|
|
100
|
+
* A per-route `false` disables transitions even when the router default is on.
|
|
101
|
+
*/
|
|
102
|
+
export const resolveViewTransition = (routerConfig, newChain) => {
|
|
103
|
+
if (!routerConfig && routerConfig !== undefined)
|
|
104
|
+
return false;
|
|
105
|
+
const leafRoute = newChain[newChain.length - 1]?.route;
|
|
106
|
+
const routeConfig = leafRoute?.viewTransition;
|
|
107
|
+
if (routeConfig === false)
|
|
108
|
+
return false;
|
|
109
|
+
if (!routerConfig && !routeConfig)
|
|
110
|
+
return false;
|
|
111
|
+
const baseTypes = typeof routerConfig === 'object' ? routerConfig.types : undefined;
|
|
112
|
+
const routeTypes = typeof routeConfig === 'object' ? routeConfig.types : undefined;
|
|
113
|
+
return { types: routeTypes ?? baseTypes };
|
|
114
|
+
};
|
|
95
115
|
/**
|
|
96
116
|
* A nested router component that supports hierarchical route definitions
|
|
97
117
|
* with parent/child relationships. Parent routes receive an `outlet` prop
|
|
@@ -124,7 +144,6 @@ export const NestedRouter = Shade({
|
|
|
124
144
|
lastChainEntries.length !== newChain.length;
|
|
125
145
|
if (hasChanged) {
|
|
126
146
|
const version = ++versionRef.current;
|
|
127
|
-
// Call onLeave for routes that are being left (from divergence point to end of old chain)
|
|
128
147
|
for (let i = lastChainEntries.length - 1; i >= divergeIndex; i--) {
|
|
129
148
|
await lastChainEntries[i].route.onLeave?.({ ...options, element: lastChainElements[i] });
|
|
130
149
|
if (version !== versionRef.current)
|
|
@@ -140,8 +159,12 @@ export const NestedRouter = Shade({
|
|
|
140
159
|
}
|
|
141
160
|
if (version !== versionRef.current)
|
|
142
161
|
return;
|
|
143
|
-
|
|
144
|
-
|
|
162
|
+
const applyUpdate = () => {
|
|
163
|
+
setState({ matchChain: newChain, jsx: newResult.jsx, chainElements: newResult.chainElements });
|
|
164
|
+
injector.getInstance(RouteMatchService).currentMatchChain.setValue(newChain);
|
|
165
|
+
};
|
|
166
|
+
const vtConfig = resolveViewTransition(options.props.viewTransition, newChain);
|
|
167
|
+
await maybeViewTransition(vtConfig === false ? undefined : vtConfig, applyUpdate);
|
|
145
168
|
for (let i = divergeIndex; i < newChain.length; i++) {
|
|
146
169
|
await newChain[i].route.onVisit?.({ ...options, element: newResult.chainElements[i] });
|
|
147
170
|
if (version !== versionRef.current)
|
|
@@ -151,18 +174,20 @@ export const NestedRouter = Shade({
|
|
|
151
174
|
}
|
|
152
175
|
else if (lastChain !== null) {
|
|
153
176
|
const version = ++versionRef.current;
|
|
154
|
-
// No match found — call onLeave for all active routes and show notFound.
|
|
155
|
-
// The null sentinel prevents re-entering this block on re-render.
|
|
156
177
|
for (let i = (lastChain?.length ?? 0) - 1; i >= 0; i--) {
|
|
157
178
|
await lastChain[i].route.onLeave?.({ ...options, element: lastChainElements[i] });
|
|
158
179
|
if (version !== versionRef.current)
|
|
159
180
|
return;
|
|
160
181
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
182
|
+
const applyNotFound = () => {
|
|
183
|
+
setState({
|
|
184
|
+
matchChain: null,
|
|
185
|
+
jsx: options.props.notFound || createComponent("div", null),
|
|
186
|
+
chainElements: [],
|
|
187
|
+
});
|
|
188
|
+
injector.getInstance(RouteMatchService).currentMatchChain.setValue([]);
|
|
189
|
+
};
|
|
190
|
+
await maybeViewTransition(options.props.viewTransition, applyNotFound);
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
193
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nested-router.js","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nested-router.js","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}
|