@finsweet/webflow-apps-utils 1.0.3 → 1.0.5

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 (116) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/providers/GlobalProvider.stories.d.ts +5 -0
  4. package/dist/providers/GlobalProvider.stories.js +419 -0
  5. package/dist/providers/GlobalProviderDemo.svelte +266 -0
  6. package/dist/providers/GlobalProviderDemo.svelte.d.ts +3 -0
  7. package/dist/providers/configuratorUtils.d.ts +11 -14
  8. package/dist/providers/configuratorUtils.js +68 -115
  9. package/dist/providers/index.d.ts +1 -1
  10. package/dist/providers/index.js +1 -1
  11. package/dist/router/Router.stories.d.ts +6 -0
  12. package/dist/router/Router.stories.js +564 -0
  13. package/dist/router/examples/RouterExample.svelte +271 -0
  14. package/dist/router/examples/RouterExample.svelte.d.ts +18 -0
  15. package/dist/router/examples/index.d.ts +4 -0
  16. package/dist/router/examples/index.js +4 -0
  17. package/dist/router/examples/pages/AboutPage.svelte +568 -0
  18. package/dist/router/examples/pages/AboutPage.svelte.d.ts +13 -0
  19. package/dist/router/examples/pages/HomePage.svelte +200 -0
  20. package/dist/router/examples/pages/HomePage.svelte.d.ts +14 -0
  21. package/dist/router/examples/pages/NotFoundPage.svelte +307 -0
  22. package/dist/router/examples/pages/NotFoundPage.svelte.d.ts +17 -0
  23. package/dist/router/hooks.svelte.d.ts +2 -2
  24. package/dist/router/index.d.ts +3 -0
  25. package/dist/router/index.js +3 -0
  26. package/dist/router/{Link.svelte → providers/Link.svelte} +1 -1
  27. package/dist/router/{Route.svelte → providers/Route.svelte} +1 -1
  28. package/dist/router/{Route.svelte.d.ts → providers/Route.svelte.d.ts} +1 -1
  29. package/dist/router/{Router.svelte → providers/RouterProvider.svelte} +22 -5
  30. package/dist/router/{Router.svelte.d.ts → providers/RouterProvider.svelte.d.ts} +8 -4
  31. package/dist/router/providers/index.d.ts +3 -0
  32. package/dist/router/providers/index.js +3 -0
  33. package/dist/router/{index.svelte.d.ts → router.svelte.d.ts} +1 -3
  34. package/dist/router/{index.svelte.js → router.svelte.js} +1 -4
  35. package/dist/stores/forms/Form.stories.d.ts +5 -0
  36. package/dist/stores/forms/Form.stories.js +342 -0
  37. package/dist/stores/forms/FormDemo.svelte +545 -0
  38. package/dist/stores/forms/FormDemo.svelte.d.ts +18 -0
  39. package/dist/stores/forms.d.ts +41 -4
  40. package/dist/stores/forms.js +86 -32
  41. package/dist/types/customCode.d.ts +1 -1
  42. package/dist/types/window.d.ts +1 -0
  43. package/dist/ui/components/button/Button.svelte +1 -1
  44. package/dist/ui/components/copy-text/CopyText.stories.d.ts +70 -0
  45. package/dist/ui/components/copy-text/CopyText.stories.js +241 -0
  46. package/dist/ui/components/copy-text/CopyText.svelte +247 -0
  47. package/dist/ui/components/copy-text/CopyText.svelte.d.ts +4 -0
  48. package/dist/ui/components/copy-text/index.d.ts +2 -0
  49. package/dist/ui/components/copy-text/index.js +1 -0
  50. package/dist/ui/components/copy-text/types.d.ts +52 -0
  51. package/dist/ui/components/copy-text/types.js +1 -0
  52. package/dist/ui/components/index.d.ts +1 -0
  53. package/dist/ui/components/index.js +1 -0
  54. package/dist/ui/components/input/Input.stories.d.ts +9 -0
  55. package/dist/ui/components/input/Input.stories.js +78 -0
  56. package/dist/ui/components/input/Input.svelte +39 -3
  57. package/dist/ui/components/input/types.d.ts +6 -0
  58. package/dist/ui/components/layout/Layout.svelte +45 -64
  59. package/dist/ui/components/layout/Layout.svelte.d.ts +26 -3
  60. package/dist/ui/components/layout/examples/ExampleLayout.svelte +32 -27
  61. package/dist/ui/components/layout/index.d.ts +1 -1
  62. package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte +20 -0
  63. package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte.d.ts +7 -0
  64. package/dist/ui/components/layout/types.d.ts +1 -10
  65. package/dist/ui/components/notification/Notification.stories.svelte +12 -1
  66. package/dist/ui/components/notification/Notification.svelte +10 -5
  67. package/dist/ui/components/notification/Notification.svelte.d.ts +1 -1
  68. package/dist/ui/components/notification/types.d.ts +1 -1
  69. package/dist/ui/components/section/Section.svelte +8 -4
  70. package/dist/ui/components/section/types.d.ts +8 -0
  71. package/dist/ui/components/text/Text.stories.svelte +67 -1
  72. package/dist/ui/components/text/Text.svelte +209 -8
  73. package/dist/ui/components/text/types.d.ts +4 -0
  74. package/dist/ui/index.css +6 -2
  75. package/dist/utils/animations/factory.d.ts +7 -0
  76. package/dist/utils/animations/factory.js +101 -0
  77. package/dist/utils/animations/index.d.ts +7 -0
  78. package/dist/utils/animations/index.js +62 -0
  79. package/dist/utils/animations/types.d.ts +39 -0
  80. package/dist/utils/animations/types.js +1 -0
  81. package/dist/utils/custom-code/configs.d.ts +22 -0
  82. package/dist/utils/custom-code/configs.js +40 -0
  83. package/dist/utils/custom-code/index.d.ts +1 -0
  84. package/dist/utils/custom-code/index.js +1 -0
  85. package/dist/utils/diff-mapper/DiffMapper.stories.d.ts +5 -0
  86. package/dist/utils/diff-mapper/DiffMapper.stories.js +185 -0
  87. package/dist/utils/diff-mapper/DiffMapperDemo.svelte +351 -0
  88. package/dist/utils/diff-mapper/DiffMapperDemo.svelte.d.ts +18 -0
  89. package/dist/utils/diff-mapper/deepDiffMapper.d.ts +31 -0
  90. package/dist/utils/diff-mapper/deepDiffMapper.js +264 -0
  91. package/dist/utils/diff-mapper/index.d.ts +1 -0
  92. package/dist/utils/diff-mapper/index.js +1 -0
  93. package/dist/utils/helpers/capitalizeFirstLetter.d.ts +4 -0
  94. package/dist/utils/helpers/capitalizeFirstLetter.js +9 -0
  95. package/dist/utils/helpers/getTimeNow.d.ts +4 -0
  96. package/dist/utils/helpers/getTimeNow.js +8 -0
  97. package/dist/utils/helpers/index.d.ts +4 -0
  98. package/dist/utils/helpers/index.js +4 -0
  99. package/dist/utils/helpers/minifyCode.d.ts +10 -0
  100. package/dist/utils/helpers/minifyCode.js +73 -0
  101. package/dist/utils/helpers/objectsToModuleExports.d.ts +1 -1
  102. package/dist/utils/helpers/objectsToModuleExports.js +1 -0
  103. package/dist/utils/helpers/toHumanReadableList.d.ts +4 -0
  104. package/dist/utils/helpers/toHumanReadableList.js +11 -0
  105. package/dist/utils/index.d.ts +2 -0
  106. package/dist/utils/index.js +2 -0
  107. package/dist/utils/webflow-canvas/getAllChildren.d.ts +16 -0
  108. package/dist/utils/webflow-canvas/getAllChildren.js +65 -0
  109. package/dist/utils/webflow-canvas/getElementClassList.d.ts +9 -0
  110. package/dist/utils/webflow-canvas/getElementClassList.js +19 -0
  111. package/dist/utils/webflow-canvas/index.d.ts +2 -0
  112. package/dist/utils/webflow-canvas/index.js +2 -0
  113. package/package.json +6 -1
  114. package/dist/providers/GlobalProvider.mdx +0 -322
  115. package/dist/router/README.md +0 -397
  116. /package/dist/router/{Link.svelte.d.ts → providers/Link.svelte.d.ts} +0 -0
@@ -0,0 +1,564 @@
1
+ import RouterExample from './examples/RouterExample.svelte';
2
+ const meta = {
3
+ title: 'Utils/Router',
4
+ component: RouterExample,
5
+ parameters: {
6
+ layout: 'fullscreen',
7
+ docs: {
8
+ description: {
9
+ component: `
10
+ # Router API Documentation
11
+
12
+ A comprehensive client-side router for Svelte 5 applications with support for reactive state management, dynamic routing, and app version persistence.
13
+
14
+ ## Installation
15
+
16
+ \`\`\`typescript
17
+ import {
18
+ createRouter,
19
+ RouterProvider,
20
+ Route,
21
+ Link,
22
+ useRouter,
23
+ useLocation,
24
+ useNavigate
25
+ } from '@finsweet/webflow-apps-utils';
26
+ \`\`\`
27
+
28
+ ## Core Classes
29
+
30
+ ### Router
31
+
32
+ The main router class that handles navigation, route matching, and state management.
33
+
34
+ #### Constructor
35
+
36
+ \`\`\`typescript
37
+ new Router(config?: RouterConfig)
38
+ \`\`\`
39
+
40
+ #### Configuration Options
41
+
42
+ \`\`\`typescript
43
+ interface RouterConfig {
44
+ basePath?: string; // Base path for all routes (default: '')
45
+ hashMode?: boolean; // Use hash-based routing (default: false)
46
+ fallbackRoute?: string; // Fallback route when no match (default: '/')
47
+ autoInit?: boolean; // Auto-initialize on creation (default: true)
48
+ }
49
+ \`\`\`
50
+
51
+ #### Methods
52
+
53
+ ##### Navigation Methods
54
+
55
+ \`\`\`typescript
56
+ // Navigate to a path
57
+ navigate(pathname: string, options?: { replace?: boolean; state?: any }): void
58
+
59
+ // Navigate back in history
60
+ back(): void
61
+
62
+ // Navigate forward in history
63
+ forward(): void
64
+
65
+ // Navigate to root path
66
+ gotoRootPath(): void
67
+ \`\`\`
68
+
69
+ ##### Route Management
70
+
71
+ \`\`\`typescript
72
+ // Add a single route
73
+ addRoute(route: RouteConfig): void
74
+
75
+ // Add multiple routes
76
+ addRoutes(routes: RouteConfig[]): void
77
+ \`\`\`
78
+
79
+ ##### State Access Methods
80
+
81
+ \`\`\`typescript
82
+ // Get reactive location information
83
+ useLocation(): LocationInfo
84
+
85
+ // Get reactive current route
86
+ useRoute(): RouteConfig | null
87
+
88
+ // Get reactive navigation state
89
+ useNavigating(): boolean
90
+
91
+ // Get reactive navigation history
92
+ useHistory(): HistoryEntry[]
93
+
94
+ // Check if path is active
95
+ isActive(path: string, exact?: boolean): boolean
96
+
97
+ // Get current route parameters
98
+ getParams(): RouteParams
99
+
100
+ // Get current query parameters
101
+ getQuery(): URLSearchParams
102
+ \`\`\`
103
+
104
+ ##### App Version Methods
105
+
106
+ \`\`\`typescript
107
+ // Initialize app version path persistence
108
+ initAppVersion(appVersionPath: string): void
109
+
110
+ // Get current app version path
111
+ getAppVersionPath(): string
112
+
113
+ // Get full pathname including app version
114
+ getFullPathname(): string
115
+
116
+ // Get active path with app version
117
+ getActivePath(): string
118
+ \`\`\`
119
+
120
+ ### createRouter()
121
+
122
+ Factory function to create a new router instance.
123
+
124
+ \`\`\`typescript
125
+ function createRouter(config?: RouterConfig): Router;
126
+ \`\`\`
127
+
128
+ ## Components
129
+
130
+ ### RouterProvider
131
+
132
+ Root component that provides router context to child components and manages router lifecycle.
133
+
134
+ \`\`\`typescript
135
+ interface RouterProviderProps {
136
+ router: Router; // Router instance
137
+ autoInit?: boolean; // Auto-initialize router (default: true)
138
+ loading?: boolean; // Show loading screen
139
+ loadingMessage?: string; // Loading message text
140
+ children?: Snippet<[RouterContext]>; // Children with router context
141
+ }
142
+ \`\`\`
143
+
144
+ ### Route
145
+
146
+ Component for defining and rendering routes based on path patterns.
147
+
148
+ \`\`\`typescript
149
+ interface RouteProps {
150
+ path: string; // Path pattern (supports :params)
151
+ component?: any; // Component to render when active
152
+ meta?: Record<string, any>; // Route metadata
153
+ exact?: boolean; // Exact path matching (default: true)
154
+ children?: Snippet<[RouteContext]>; // Children with route context
155
+ }
156
+ \`\`\`
157
+
158
+ ### Link
159
+
160
+ Navigation component that generates proper links with active state management.
161
+
162
+ \`\`\`typescript
163
+ interface LinkProps {
164
+ to: string; // Target path
165
+ replace?: boolean; // Replace history entry (default: false)
166
+ activeClass?: string; // CSS class when active
167
+ exact?: boolean; // Exact matching for active state
168
+ disabled?: boolean; // Disable the link
169
+ class?: string; // Additional CSS classes
170
+ state?: any; // State to pass with navigation
171
+ element?: 'a' | 'button'; // HTML element type (default: 'a')
172
+ children?: Snippet; // Link content
173
+ onclick?: (event: MouseEvent) => void; // Click handler
174
+ }
175
+ \`\`\`
176
+
177
+ ## Hooks
178
+
179
+ ### useRouter()
180
+
181
+ Get the router instance from context.
182
+
183
+ \`\`\`typescript
184
+ function useRouter(): Router;
185
+ \`\`\`
186
+
187
+ ### useLocation()
188
+
189
+ Get reactive location information.
190
+
191
+ \`\`\`typescript
192
+ function useLocation(): LocationInfo;
193
+ \`\`\`
194
+
195
+ ### useRoute()
196
+
197
+ Get reactive current route information.
198
+
199
+ \`\`\`typescript
200
+ function useRoute(): RouteConfig | null;
201
+ \`\`\`
202
+
203
+ ### useParams()
204
+
205
+ Get reactive route parameters.
206
+
207
+ \`\`\`typescript
208
+ function useParams(): RouteParams;
209
+ \`\`\`
210
+
211
+ ### useQuery()
212
+
213
+ Get reactive query parameters.
214
+
215
+ \`\`\`typescript
216
+ function useQuery(): URLSearchParams;
217
+ \`\`\`
218
+
219
+ ### useNavigate()
220
+
221
+ Get a navigation function.
222
+
223
+ \`\`\`typescript
224
+ function useNavigate(): (pathname: string, options?: NavigateOptions) => void;
225
+
226
+ interface NavigateOptions {
227
+ replace?: boolean;
228
+ state?: any;
229
+ }
230
+ \`\`\`
231
+
232
+ ### useNavigating()
233
+
234
+ Get reactive navigation state.
235
+
236
+ \`\`\`typescript
237
+ function useNavigating(): boolean;
238
+ \`\`\`
239
+
240
+ ### useHistory()
241
+
242
+ Get reactive navigation history.
243
+
244
+ \`\`\`typescript
245
+ function useHistory(): HistoryEntry[];
246
+ \`\`\`
247
+
248
+ ### useIsActiveRoute()
249
+
250
+ Get a function to check if routes are active.
251
+
252
+ \`\`\`typescript
253
+ function useIsActiveRoute(): (path: string, exact?: boolean) => boolean;
254
+ \`\`\`
255
+
256
+ ### useRouteWatcher()
257
+
258
+ Watch for route changes and execute callbacks.
259
+
260
+ \`\`\`typescript
261
+ function useRouteWatcher(
262
+ callback: (location: LocationInfo, route: RouteConfig | null) => void,
263
+ immediate?: boolean
264
+ ): void;
265
+ \`\`\`
266
+
267
+ ### useSearchParams()
268
+
269
+ Get search params helper with reactive updates.
270
+
271
+ \`\`\`typescript
272
+ function useSearchParams(): SearchParamsHelper;
273
+
274
+ interface SearchParamsHelper {
275
+ get(key: string): string | null;
276
+ set(key: string, value: string): void;
277
+ delete(key: string): void;
278
+ has(key: string): boolean;
279
+ toString(): string;
280
+ getAll(): Record<string, string>;
281
+ }
282
+ \`\`\`
283
+
284
+ ### useAppVersion()
285
+
286
+ Get the current app version path.
287
+
288
+ \`\`\`typescript
289
+ function useAppVersion(): string;
290
+ \`\`\`
291
+
292
+ ### useFullPathname()
293
+
294
+ Get the full pathname including app version.
295
+
296
+ \`\`\`typescript
297
+ function useFullPathname(): string;
298
+ \`\`\`
299
+
300
+ ## Interfaces
301
+
302
+ ### RouteConfig
303
+
304
+ \`\`\`typescript
305
+ interface RouteConfig {
306
+ path: string; // Path pattern ('/users/:id')
307
+ component?: any; // Svelte component
308
+ meta?: Record<string, any>; // Route metadata
309
+ }
310
+ \`\`\`
311
+
312
+ ### LocationInfo
313
+
314
+ \`\`\`typescript
315
+ interface LocationInfo {
316
+ pathname: string; // Current pathname
317
+ search: string; // Query string
318
+ hash: string; // URL hash
319
+ url: URL; // Complete URL object
320
+ params: RouteParams; // Route parameters
321
+ query: URLSearchParams; // Query parameters object
322
+ }
323
+ \`\`\`
324
+
325
+ ### RouteParams
326
+
327
+ \`\`\`typescript
328
+ interface RouteParams {
329
+ [key: string]: string; // Parameter name to value mapping
330
+ }
331
+ \`\`\`
332
+
333
+ ### HistoryEntry
334
+
335
+ \`\`\`typescript
336
+ interface HistoryEntry {
337
+ pathname: string; // Path of history entry
338
+ timestamp: number; // Entry creation time
339
+ state?: any; // Optional state data
340
+ }
341
+ \`\`\`
342
+
343
+ ## Usage Examples
344
+
345
+ ### Complete Application Setup
346
+
347
+ \`\`\`typescript
348
+ <!-- App.svelte -->
349
+ <script lang="ts">
350
+ import { onMount } from 'svelte';
351
+ import { createRouter, RouterProvider, Route, Link } from '@finsweet/webflow-apps-utils';
352
+
353
+ // Import page components
354
+ import HomePage from './pages/HomePage.svelte';
355
+ import AboutPage from './pages/AboutPage.svelte';
356
+ import UserPage from './pages/UserPage.svelte';
357
+ import NotFoundPage from './pages/NotFoundPage.svelte';
358
+
359
+ // Create router with configuration
360
+ const router = createRouter({
361
+ basePath: '',
362
+ fallbackRoute: '/'
363
+ });
364
+
365
+ // Define routes
366
+ router.addRoutes([
367
+ { path: '/', component: HomePage, meta: { title: 'Home' } },
368
+ { path: '/about', component: AboutPage, meta: { title: 'About' } },
369
+ { path: '/users/:id', component: UserPage, meta: { title: 'User Profile' } },
370
+ { path: '*', component: NotFoundPage, meta: { title: 'Not Found' } }
371
+ ]);
372
+
373
+ onMount(() => {
374
+ // Initialize app version if needed
375
+ router.initAppVersion('/v1');
376
+ });
377
+ </script>
378
+
379
+ <RouterProvider {router}>
380
+ {#snippet children({ router, currentRoute, isNavigating })}
381
+ <div class="app">
382
+ <!-- Navigation -->
383
+ <nav class="navbar">
384
+ <div class="nav-brand">
385
+ <Link to="/">My App</Link>
386
+ </div>
387
+ <ul class="nav-links">
388
+ <li><Link to="/" exact activeClass="active">Home</Link></li>
389
+ <li><Link to="/about" activeClass="active">About</Link></li>
390
+ <li><Link to="/users/123" activeClass="active">Profile</Link></li>
391
+ </ul>
392
+ </nav>
393
+
394
+ <!-- Loading indicator -->
395
+ {#if isNavigating}
396
+ <div class="loading-bar"></div>
397
+ {/if}
398
+
399
+ <!-- Page title -->
400
+ <title>{currentRoute?.meta?.title || 'My App'}</title>
401
+
402
+ <!-- Main content -->
403
+ <main class="main-content">
404
+ <!-- Routes -->
405
+ <Route path="/" component={HomePage} />
406
+ <Route path="/about" component={AboutPage} />
407
+ <Route path="/users/:id">
408
+ {#snippet children({ params, isActive })}
409
+ {#if isActive}
410
+ <UserPage userId={params.id} />
411
+ {/if}
412
+ {/snippet}
413
+ </Route>
414
+ <Route path="*" exact={false} component={NotFoundPage} />
415
+ </main>
416
+ </div>
417
+ {/snippet}
418
+ </RouterProvider>
419
+ \`\`\`
420
+
421
+ ### Using Hooks in Components
422
+
423
+ \`\`\`typescript
424
+ <!-- UserProfile.svelte -->
425
+ <script lang="ts">
426
+ import { useParams, useNavigate, useSearchParams } from '@finsweet/webflow-apps-utils';
427
+
428
+ const params = useParams();
429
+ const navigate = useNavigate();
430
+ const searchParams = useSearchParams();
431
+
432
+ // Reactive values
433
+ $: userId = params.id;
434
+ $: tab = searchParams.get('tab') || 'profile';
435
+
436
+ function switchTab(newTab: string) {
437
+ searchParams.set('tab', newTab);
438
+ }
439
+
440
+ function goBack() {
441
+ navigate('/users');
442
+ }
443
+ </script>
444
+
445
+ <div class="user-profile">
446
+ <header>
447
+ <button onclick={goBack}>← Back to Users</button>
448
+ <h1>User Profile: {userId}</h1>
449
+ </header>
450
+
451
+ <nav class="tabs">
452
+ <button
453
+ class:active={tab === 'profile'}
454
+ onclick={() => switchTab('profile')}
455
+ >
456
+ Profile
457
+ </button>
458
+ <button
459
+ class:active={tab === 'settings'}
460
+ onclick={() => switchTab('settings')}
461
+ >
462
+ Settings
463
+ </button>
464
+ </nav>
465
+
466
+ <main>
467
+ {#if tab === 'profile'}
468
+ <div>Profile content for user {userId}</div>
469
+ {:else if tab === 'settings'}
470
+ <div>Settings for user {userId}</div>
471
+ {/if}
472
+ </main>
473
+ </div>
474
+ \`\`\`
475
+
476
+ ### Programmatic Navigation
477
+
478
+ \`\`\`typescript
479
+ <script lang="ts">
480
+ import { useRouter, useNavigate, useLocation } from '@finsweet/webflow-apps-utils';
481
+
482
+ const router = useRouter();
483
+ const navigate = useNavigate();
484
+ const location = useLocation();
485
+
486
+ async function handleLogin(userData: any) {
487
+ // Simulate login
488
+ await loginUser(userData);
489
+
490
+ // Navigate to dashboard after login
491
+ navigate('/dashboard', {
492
+ replace: true,
493
+ state: { loginTime: Date.now() }
494
+ });
495
+ }
496
+
497
+ function handleLogout() {
498
+ // Clear user data
499
+ clearUserSession();
500
+
501
+ // Navigate to home and replace history
502
+ router.navigate('/', { replace: true });
503
+ }
504
+
505
+ function goToUserProfile(userId: string) {
506
+ navigate(\`/users/\${userId}?tab=profile\`);
507
+ }
508
+
509
+ function navigateWithState() {
510
+ navigate('/results', {
511
+ state: {
512
+ searchQuery: 'example',
513
+ timestamp: Date.now()
514
+ }
515
+ });
516
+ }
517
+ </script>
518
+ \`\`\`
519
+
520
+ Explore the complete router implementation in the interactive demo below!
521
+ `
522
+ }
523
+ }
524
+ },
525
+ tags: ['autodocs'],
526
+ argTypes: {}
527
+ };
528
+ export default meta;
529
+ export const CompleteExample = {
530
+ args: {},
531
+ parameters: {
532
+ docs: {
533
+ description: {
534
+ story: `
535
+ ## Complete Router Example
536
+
537
+ This is a full-featured router implementation demonstrating:
538
+
539
+ ### Routes Implemented:
540
+ - **Home Route** (\`/\`) - Landing page with feature overview
541
+ - **About Route** (\`/about\`) - Main about page with navigation cards
542
+ - **About Sections** (\`/about/:section\`) - Dynamic sections (team, history, mission)
543
+ - **404 Route** - Custom not found page with helpful navigation
544
+
545
+ ### Features Demonstrated:
546
+ - **Link Components** - Active state management and navigation
547
+ - **Programmatic Navigation** - Using \`useNavigate()\` hook
548
+ - **Route Parameters** - Dynamic \`:section\` parameter handling
549
+ - **App Version Support** - Persistent version hash across all navigation
550
+ - **Debug Information** - Real-time route and parameter display
551
+ - **History Management** - Back/forward navigation support
552
+
553
+ ### Navigation Examples:
554
+ - Click navigation links to see active states
555
+ - Use back/forward buttons to test history
556
+ - Try direct URL changes to test route matching
557
+ - Visit invalid routes to see 404 handling
558
+
559
+ The example shows how the router maintains app version hashes automatically while providing clean route definitions and reactive state management.
560
+ `
561
+ }
562
+ }
563
+ }
564
+ };