@furystack/shades 12.2.5 → 12.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/esm/components/nested-router.d.ts +33 -0
  3. package/esm/components/nested-router.d.ts.map +1 -1
  4. package/esm/components/nested-router.js +3 -0
  5. package/esm/components/nested-router.js.map +1 -1
  6. package/esm/components/nested-router.spec.js +100 -18
  7. package/esm/components/nested-router.spec.js.map +1 -1
  8. package/esm/services/index.d.ts +2 -0
  9. package/esm/services/index.d.ts.map +1 -1
  10. package/esm/services/index.js +2 -0
  11. package/esm/services/index.js.map +1 -1
  12. package/esm/services/route-match-service.d.ts +12 -0
  13. package/esm/services/route-match-service.d.ts.map +1 -0
  14. package/esm/services/route-match-service.js +24 -0
  15. package/esm/services/route-match-service.js.map +1 -0
  16. package/esm/services/route-match-service.spec.d.ts +2 -0
  17. package/esm/services/route-match-service.spec.d.ts.map +1 -0
  18. package/esm/services/route-match-service.spec.js +120 -0
  19. package/esm/services/route-match-service.spec.js.map +1 -0
  20. package/esm/services/route-meta-utils.d.ts +57 -0
  21. package/esm/services/route-meta-utils.d.ts.map +1 -0
  22. package/esm/services/route-meta-utils.js +64 -0
  23. package/esm/services/route-meta-utils.js.map +1 -0
  24. package/esm/services/route-meta-utils.spec.d.ts +2 -0
  25. package/esm/services/route-meta-utils.spec.d.ts.map +1 -0
  26. package/esm/services/route-meta-utils.spec.js +217 -0
  27. package/esm/services/route-meta-utils.spec.js.map +1 -0
  28. package/esm/shade.d.ts.map +1 -1
  29. package/esm/shade.js +12 -1
  30. package/esm/shade.js.map +1 -1
  31. package/esm/shade.spec.js +93 -2
  32. package/esm/shade.spec.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/components/nested-router.spec.tsx +140 -35
  35. package/src/components/nested-router.tsx +38 -0
  36. package/src/services/index.ts +2 -0
  37. package/src/services/route-match-service.spec.ts +45 -0
  38. package/src/services/route-match-service.ts +17 -0
  39. package/src/services/route-meta-utils.spec.ts +243 -0
  40. package/src/services/route-meta-utils.ts +85 -0
  41. package/src/shade.spec.tsx +112 -2
  42. package/src/shade.ts +11 -1
package/esm/shade.spec.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject';
2
- import { sleepAsync, usingAsync } from '@furystack/utils';
3
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
2
+ import { ObservableValue, sleepAsync, usingAsync } from '@furystack/utils';
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
  import { initializeShadeRoot } from './initialize.js';
5
5
  import { createComponent } from './shade-component.js';
6
6
  import { flushUpdates, Shade } from './shade.js';
@@ -82,6 +82,97 @@ describe('Shade edge cases', () => {
82
82
  });
83
83
  });
84
84
  });
85
+ describe('disconnected component should not re-render', () => {
86
+ it('should not re-render when updateComponent is called after removal', async () => {
87
+ await usingAsync(new Injector(), async (injector) => {
88
+ const rootElement = document.getElementById('root');
89
+ const renderCounter = vi.fn();
90
+ const ExampleComponent = Shade({
91
+ shadowDomName: 'shade-no-render-after-disconnect',
92
+ render: () => {
93
+ renderCounter();
94
+ return createComponent("div", null, "content");
95
+ },
96
+ });
97
+ initializeShadeRoot({
98
+ injector,
99
+ rootElement,
100
+ jsxElement: createComponent(ExampleComponent, null),
101
+ });
102
+ await flushUpdates();
103
+ const element = document.querySelector('shade-no-render-after-disconnect');
104
+ expect(element.getRenderCount()).toBe(1);
105
+ expect(renderCounter).toBeCalledTimes(1);
106
+ element.remove();
107
+ await flushUpdates();
108
+ element.updateComponent();
109
+ await flushUpdates();
110
+ expect(element.getRenderCount()).toBe(1);
111
+ expect(renderCounter).toBeCalledTimes(1);
112
+ });
113
+ });
114
+ it('should not re-render when updateComponentSync is called after removal', async () => {
115
+ await usingAsync(new Injector(), async (injector) => {
116
+ const rootElement = document.getElementById('root');
117
+ const renderCounter = vi.fn();
118
+ const ExampleComponent = Shade({
119
+ shadowDomName: 'shade-no-sync-render-after-disconnect',
120
+ render: () => {
121
+ renderCounter();
122
+ return createComponent("div", null, "content");
123
+ },
124
+ });
125
+ initializeShadeRoot({
126
+ injector,
127
+ rootElement,
128
+ jsxElement: createComponent(ExampleComponent, null),
129
+ });
130
+ await flushUpdates();
131
+ const element = document.querySelector('shade-no-sync-render-after-disconnect');
132
+ expect(element.getRenderCount()).toBe(1);
133
+ expect(renderCounter).toBeCalledTimes(1);
134
+ element.remove();
135
+ await flushUpdates();
136
+ element.updateComponentSync();
137
+ expect(element.getRenderCount()).toBe(1);
138
+ expect(renderCounter).toBeCalledTimes(1);
139
+ });
140
+ });
141
+ it('should not re-render when an observable fires during disposal', async () => {
142
+ await usingAsync(new Injector(), async (injector) => {
143
+ const rootElement = document.getElementById('root');
144
+ const renderCounter = vi.fn();
145
+ const obs = new ObservableValue(0);
146
+ const ExampleComponent = Shade({
147
+ shadowDomName: 'shade-no-render-during-disposal',
148
+ render: ({ useObservable, useDisposable }) => {
149
+ useObservable('obs', obs);
150
+ useDisposable('cleanup', () => ({
151
+ [Symbol.dispose]: () => {
152
+ obs.setValue(999);
153
+ },
154
+ }));
155
+ renderCounter();
156
+ return createComponent("div", null, obs.getValue());
157
+ },
158
+ });
159
+ initializeShadeRoot({
160
+ injector,
161
+ rootElement,
162
+ jsxElement: createComponent(ExampleComponent, null),
163
+ });
164
+ await flushUpdates();
165
+ const element = document.querySelector('shade-no-render-during-disposal');
166
+ expect(element.getRenderCount()).toBe(1);
167
+ expect(renderCounter).toBeCalledTimes(1);
168
+ element.remove();
169
+ await flushUpdates();
170
+ await sleepAsync(10);
171
+ expect(element.getRenderCount()).toBe(1);
172
+ expect(renderCounter).toBeCalledTimes(1);
173
+ });
174
+ });
175
+ });
85
176
  describe('BroadcastChannel cross-tab communication', () => {
86
177
  it('should update stored state when receiving BroadcastChannel message with matching key', async () => {
87
178
  const mockedStorage = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"shade.spec.js","sourceRoot":"","sources":["../src/shade.spec.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shade.spec.js","sourceRoot":"","sources":["../src/shade.spec.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/shades",
3
- "version": "12.2.5",
3
+ "version": "12.3.0",
4
4
  "description": "A lightweight UI framework for FuryStack with JSX support",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -4,6 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
4
4
  import { initializeShadeRoot } from '../initialize.js'
5
5
  import { createComponent } from '../shade-component.js'
6
6
  import { flushUpdates } from '../shade.js'
7
+ import { RouteMatchService } from '../services/route-match-service.js'
7
8
  import {
8
9
  buildMatchChain,
9
10
  findDivergenceIndex,
@@ -12,7 +13,7 @@ import {
12
13
  type MatchChainEntry,
13
14
  type NestedRoute,
14
15
  } from './nested-router.js'
15
- import { RouteLink } from './route-link.js'
16
+ import { NestedRouteLink } from './nested-route-link.js'
16
17
 
17
18
  describe('buildMatchChain', () => {
18
19
  it('should match a simple leaf route', () => {
@@ -320,18 +321,18 @@ describe('NestedRouter lifecycle hooks', () => {
320
321
  rootElement,
321
322
  jsxElement: (
322
323
  <div>
323
- <RouteLink id="child-a" href="/parent/child-a">
324
+ <NestedRouteLink id="child-a" href="/parent/child-a">
324
325
  child-a
325
- </RouteLink>
326
- <RouteLink id="child-b" href="/parent/child-b">
326
+ </NestedRouteLink>
327
+ <NestedRouteLink id="child-b" href="/parent/child-b">
327
328
  child-b
328
- </RouteLink>
329
- <RouteLink id="other" href="/other">
329
+ </NestedRouteLink>
330
+ <NestedRouteLink id="other" href="/other">
330
331
  other
331
- </RouteLink>
332
- <RouteLink id="nowhere" href="/nowhere">
332
+ </NestedRouteLink>
333
+ <NestedRouteLink id="nowhere" href="/nowhere">
333
334
  nowhere
334
- </RouteLink>
335
+ </NestedRouteLink>
335
336
  <NestedRouter
336
337
  routes={{
337
338
  '/parent': {
@@ -456,15 +457,15 @@ describe('NestedRouter latest-wins on rapid navigation', () => {
456
457
  rootElement,
457
458
  jsxElement: (
458
459
  <div>
459
- <RouteLink id="go-a" href="/route-a">
460
+ <NestedRouteLink id="go-a" href="/route-a">
460
461
  a
461
- </RouteLink>
462
- <RouteLink id="go-b" href="/route-b">
462
+ </NestedRouteLink>
463
+ <NestedRouteLink id="go-b" href="/route-b">
463
464
  b
464
- </RouteLink>
465
- <RouteLink id="go-c" href="/route-c">
465
+ </NestedRouteLink>
466
+ <NestedRouteLink id="go-c" href="/route-c">
466
467
  c
467
- </RouteLink>
468
+ </NestedRouteLink>
468
469
  <NestedRouter
469
470
  routes={{
470
471
  '/route-a': {
@@ -538,12 +539,12 @@ describe('NestedRouter lifecycle element scope', () => {
538
539
  rootElement,
539
540
  jsxElement: (
540
541
  <div>
541
- <RouteLink id="child-a" href="/parent/child-a">
542
+ <NestedRouteLink id="child-a" href="/parent/child-a">
542
543
  child-a
543
- </RouteLink>
544
- <RouteLink id="child-b" href="/parent/child-b">
544
+ </NestedRouteLink>
545
+ <NestedRouteLink id="child-b" href="/parent/child-b">
545
546
  child-b
546
- </RouteLink>
547
+ </NestedRouteLink>
547
548
  <NestedRouter
548
549
  routes={{
549
550
  '/parent': {
@@ -631,15 +632,15 @@ describe('NestedRouter flat routes', () => {
631
632
  rootElement,
632
633
  jsxElement: (
633
634
  <div>
634
- <RouteLink id="home" href="/">
635
+ <NestedRouteLink id="home" href="/">
635
636
  home
636
- </RouteLink>
637
- <RouteLink id="about" href="/about">
637
+ </NestedRouteLink>
638
+ <NestedRouteLink id="about" href="/about">
638
639
  about
639
- </RouteLink>
640
- <RouteLink id="contact" href="/contact">
640
+ </NestedRouteLink>
641
+ <NestedRouteLink id="contact" href="/contact">
641
642
  contact
642
- </RouteLink>
643
+ </NestedRouteLink>
643
644
  <NestedRouter
644
645
  routes={{
645
646
  '/about': { component: () => <div id="content">about-page</div> },
@@ -790,15 +791,15 @@ describe('NestedRouter route param changes', () => {
790
791
  rootElement,
791
792
  jsxElement: (
792
793
  <div>
793
- <RouteLink id="user-1" href="/users/1">
794
+ <NestedRouteLink id="user-1" href="/users/1">
794
795
  User 1
795
- </RouteLink>
796
- <RouteLink id="user-2" href="/users/2">
796
+ </NestedRouteLink>
797
+ <NestedRouteLink id="user-2" href="/users/2">
797
798
  User 2
798
- </RouteLink>
799
- <RouteLink id="user-3" href="/users/3">
799
+ </NestedRouteLink>
800
+ <NestedRouteLink id="user-3" href="/users/3">
800
801
  User 3
801
- </RouteLink>
802
+ </NestedRouteLink>
802
803
  <NestedRouter
803
804
  routes={{
804
805
  '/users/:id': {
@@ -866,12 +867,12 @@ describe('NestedRouter route param changes', () => {
866
867
  rootElement,
867
868
  jsxElement: (
868
869
  <div>
869
- <RouteLink id="alpha-dash" href="/org/alpha/dashboard">
870
+ <NestedRouteLink id="alpha-dash" href="/org/alpha/dashboard">
870
871
  Alpha Dashboard
871
- </RouteLink>
872
- <RouteLink id="beta-dash" href="/org/beta/dashboard">
872
+ </NestedRouteLink>
873
+ <NestedRouteLink id="beta-dash" href="/org/beta/dashboard">
873
874
  Beta Dashboard
874
- </RouteLink>
875
+ </NestedRouteLink>
875
876
  <NestedRouter
876
877
  routes={{
877
878
  '/org/:orgId': {
@@ -919,3 +920,107 @@ describe('NestedRouter route param changes', () => {
919
920
  })
920
921
  })
921
922
  })
923
+
924
+ describe('NestedRouter + RouteMatchService integration', () => {
925
+ beforeEach(() => {
926
+ document.body.innerHTML = '<div id="root"></div>'
927
+ })
928
+ afterEach(() => {
929
+ document.body.innerHTML = ''
930
+ })
931
+
932
+ it('should update RouteMatchService with the current match chain on navigation', async () => {
933
+ history.pushState(null, '', '/parent/child-a')
934
+
935
+ await usingAsync(new Injector(), async (injector) => {
936
+ const rootElement = document.getElementById('root') as HTMLDivElement
937
+ const routeMatchService = injector.getInstance(RouteMatchService)
938
+
939
+ const parentRoute: NestedRoute = {
940
+ meta: { title: 'Parent' },
941
+ component: ({ outlet }) => <div>{outlet ?? <div>parent-index</div>}</div>,
942
+ children: {
943
+ '/child-a': {
944
+ meta: { title: 'Child A' },
945
+ component: () => <div id="content">child-a</div>,
946
+ },
947
+ '/child-b': {
948
+ meta: { title: 'Child B' },
949
+ component: () => <div id="content">child-b</div>,
950
+ },
951
+ },
952
+ }
953
+
954
+ initializeShadeRoot({
955
+ injector,
956
+ rootElement,
957
+ jsxElement: (
958
+ <div>
959
+ <NestedRouteLink id="child-a" href="/parent/child-a">
960
+ child-a
961
+ </NestedRouteLink>
962
+ <NestedRouteLink id="child-b" href="/parent/child-b">
963
+ child-b
964
+ </NestedRouteLink>
965
+ <NestedRouteLink id="nowhere" href="/nowhere">
966
+ nowhere
967
+ </NestedRouteLink>
968
+ <NestedRouter routes={{ '/parent': parentRoute }} notFound={<div id="content">not found</div>} />
969
+ </div>
970
+ ),
971
+ })
972
+
973
+ // Initial load
974
+ await flushUpdates()
975
+ const initialChain = routeMatchService.currentMatchChain.getValue()
976
+ expect(initialChain).toHaveLength(2)
977
+ expect(initialChain[0].route.meta?.title).toBe('Parent')
978
+ expect(initialChain[1].route.meta?.title).toBe('Child A')
979
+
980
+ // Navigate to sibling child
981
+ document.getElementById('child-b')?.click()
982
+ await flushUpdates()
983
+ const updatedChain = routeMatchService.currentMatchChain.getValue()
984
+ expect(updatedChain).toHaveLength(2)
985
+ expect(updatedChain[0].route.meta?.title).toBe('Parent')
986
+ expect(updatedChain[1].route.meta?.title).toBe('Child B')
987
+
988
+ // Navigate to not-found
989
+ document.getElementById('nowhere')?.click()
990
+ await flushUpdates()
991
+ const notFoundChain = routeMatchService.currentMatchChain.getValue()
992
+ expect(notFoundChain).toEqual([])
993
+ })
994
+ })
995
+
996
+ it('should expose match params through RouteMatchService', async () => {
997
+ history.pushState(null, '', '/users/42')
998
+
999
+ await usingAsync(new Injector(), async (injector) => {
1000
+ const rootElement = document.getElementById('root') as HTMLDivElement
1001
+ const routeMatchService = injector.getInstance(RouteMatchService)
1002
+
1003
+ initializeShadeRoot({
1004
+ injector,
1005
+ rootElement,
1006
+ jsxElement: (
1007
+ <NestedRouter
1008
+ routes={{
1009
+ '/users/:id': {
1010
+ meta: {
1011
+ title: ({ match }: { match: { params: Record<string, string> } }) => `User ${match.params.id}`,
1012
+ },
1013
+ component: ({ match }) => <div id="content">user-{(match.params as { id: string }).id}</div>,
1014
+ },
1015
+ }}
1016
+ />
1017
+ ),
1018
+ })
1019
+
1020
+ await flushUpdates()
1021
+ const chain = routeMatchService.currentMatchChain.getValue()
1022
+ expect(chain).toHaveLength(1)
1023
+ expect(chain[0].match.params).toEqual({ id: '42' })
1024
+ })
1025
+ })
1026
+ })
@@ -1,11 +1,46 @@
1
+ import type { Injector } from '@furystack/inject'
1
2
  import { ObservableAlreadyDisposedError } from '@furystack/utils'
2
3
  import type { MatchOptions, MatchResult } from 'path-to-regexp'
3
4
  import { match } from 'path-to-regexp'
4
5
  import type { RenderOptions } from '../models/render-options.js'
5
6
  import { LocationService } from '../services/location-service.js'
7
+ import { RouteMatchService } from '../services/route-match-service.js'
6
8
  import { createComponent, setRenderMode } from '../shade-component.js'
7
9
  import { Shade } from '../shade.js'
8
10
 
11
+ /**
12
+ * Options passed to a dynamic title resolver function.
13
+ * @typeParam TMatchResult - The type of matched URL parameters
14
+ */
15
+ export type TitleResolverOptions<TMatchResult = unknown> = {
16
+ match: MatchResult<TMatchResult extends object ? TMatchResult : object>
17
+ injector: Injector
18
+ }
19
+
20
+ /**
21
+ * Metadata associated with a route entry.
22
+ * Used by consumers (breadcrumbs, document title, navigation trees) to
23
+ * derive display information from the route hierarchy.
24
+ *
25
+ * This is an `interface` so that applications can augment it with custom fields
26
+ * via declaration merging:
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * declare module '@furystack/shades' {
31
+ * interface NestedRouteMeta {
32
+ * icon?: IconDefinition
33
+ * hidden?: boolean
34
+ * }
35
+ * }
36
+ * ```
37
+ *
38
+ * @typeParam TMatchResult - The type of matched URL parameters
39
+ */
40
+ export interface NestedRouteMeta<TMatchResult = unknown> {
41
+ title?: string | ((options: TitleResolverOptions<TMatchResult>) => string | Promise<string>)
42
+ }
43
+
9
44
  /**
10
45
  * A single route entry in a NestedRouter configuration.
11
46
  * Unlike flat `Route`, the URL is the Record key (not a field), and the
@@ -13,6 +48,7 @@ import { Shade } from '../shade.js'
13
48
  * @typeParam TMatchResult - The type of matched URL parameters
14
49
  */
15
50
  export type NestedRoute<TMatchResult = unknown> = {
51
+ meta?: NestedRouteMeta<TMatchResult>
16
52
  component: (options: {
17
53
  currentUrl: string
18
54
  match: MatchResult<TMatchResult extends object ? TMatchResult : object>
@@ -216,6 +252,7 @@ export const NestedRouter = Shade<NestedRouterProps>({
216
252
  }
217
253
  if (version !== versionRef.current) return
218
254
  setState({ matchChain: newChain, jsx: newResult.jsx, chainElements: newResult.chainElements })
255
+ injector.getInstance(RouteMatchService).currentMatchChain.setValue(newChain)
219
256
 
220
257
  // Call onVisit for routes that are being entered (from divergence point to end of new chain)
221
258
  for (let i = divergeIndex; i < newChain.length; i++) {
@@ -237,6 +274,7 @@ export const NestedRouter = Shade<NestedRouterProps>({
237
274
  jsx: options.props.notFound || <div />,
238
275
  chainElements: [],
239
276
  })
277
+ injector.getInstance(RouteMatchService).currentMatchChain.setValue([])
240
278
  }
241
279
  } catch (e) {
242
280
  if (!(e instanceof ObservableAlreadyDisposedError)) {
@@ -1,2 +1,4 @@
1
1
  export * from './location-service.js'
2
+ export * from './route-match-service.js'
3
+ export * from './route-meta-utils.js'
2
4
  export * from './screen-service.js'
@@ -0,0 +1,45 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import type { MatchChainEntry } from '../components/nested-router.js'
3
+ import { RouteMatchService } from './route-match-service.js'
4
+
5
+ describe('RouteMatchService', () => {
6
+ it('should start with an empty match chain', () => {
7
+ using service = new RouteMatchService()
8
+ expect(service.currentMatchChain.getValue()).toEqual([])
9
+ })
10
+
11
+ it('should update the match chain', () => {
12
+ using service = new RouteMatchService()
13
+ const chain: MatchChainEntry[] = [
14
+ {
15
+ route: { component: () => ({}) as JSX.Element },
16
+ match: { path: '/about', params: {} },
17
+ },
18
+ ]
19
+ service.currentMatchChain.setValue(chain)
20
+ expect(service.currentMatchChain.getValue()).toBe(chain)
21
+ })
22
+
23
+ it('should notify subscribers on match chain change', () => {
24
+ using service = new RouteMatchService()
25
+ const listener = vi.fn()
26
+ using _subscription = service.currentMatchChain.subscribe(listener)
27
+
28
+ const chain: MatchChainEntry[] = [
29
+ {
30
+ route: { meta: { title: 'Home' }, component: () => ({}) as JSX.Element },
31
+ match: { path: '/', params: {} },
32
+ },
33
+ ]
34
+ service.currentMatchChain.setValue(chain)
35
+
36
+ expect(listener).toHaveBeenCalledWith(chain)
37
+ })
38
+
39
+ it('should dispose the observable on service disposal', () => {
40
+ const service = new RouteMatchService()
41
+ service[Symbol.dispose]()
42
+
43
+ expect(() => service.currentMatchChain.setValue([])).toThrow()
44
+ })
45
+ })
@@ -0,0 +1,17 @@
1
+ import { Injectable } from '@furystack/inject'
2
+ import { ObservableValue } from '@furystack/utils'
3
+ import type { MatchChainEntry } from '../components/nested-router.js'
4
+
5
+ /**
6
+ * Singleton service that exposes the current match chain from the nearest
7
+ * NestedRouter as an observable. Consumers (breadcrumbs, document title,
8
+ * navigation trees) subscribe to this instead of re-running route matching.
9
+ */
10
+ @Injectable({ lifetime: 'singleton' })
11
+ export class RouteMatchService implements Disposable {
12
+ public readonly currentMatchChain = new ObservableValue<MatchChainEntry[]>([])
13
+
14
+ public [Symbol.dispose]() {
15
+ this.currentMatchChain[Symbol.dispose]()
16
+ }
17
+ }