@finsweet/webflow-apps-utils 1.0.4 → 1.0.6

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 (36) hide show
  1. package/dist/providers/GlobalProvider.stories.d.ts +5 -0
  2. package/dist/providers/GlobalProvider.stories.js +419 -0
  3. package/dist/providers/GlobalProviderDemo.svelte +266 -0
  4. package/dist/providers/GlobalProviderDemo.svelte.d.ts +3 -0
  5. package/dist/providers/configuratorUtils.d.ts +11 -14
  6. package/dist/providers/configuratorUtils.js +68 -115
  7. package/dist/providers/index.d.ts +1 -1
  8. package/dist/providers/index.js +1 -1
  9. package/dist/router/Router.stories.js +519 -2
  10. package/dist/stores/forms/Form.stories.d.ts +5 -0
  11. package/dist/stores/forms/Form.stories.js +342 -0
  12. package/dist/stores/forms/FormDemo.svelte +545 -0
  13. package/dist/stores/forms/FormDemo.svelte.d.ts +18 -0
  14. package/dist/ui/components/button/Button.svelte +1 -1
  15. package/dist/ui/components/copy-text/CopyText.stories.js +1 -1
  16. package/dist/ui/components/copy-text/CopyText.svelte +17 -19
  17. package/dist/ui/components/input/Input.svelte +18 -22
  18. package/dist/ui/components/layout/Layout.svelte +38 -5
  19. package/dist/ui/components/layout/Layout.svelte.d.ts +24 -1
  20. package/dist/ui/components/layout/examples/ExampleLayout.svelte +12 -12
  21. package/dist/ui/components/section/Section.svelte +4 -2
  22. package/dist/ui/index.css +6 -2
  23. package/dist/utils/diff-mapper/DiffMapper.stories.d.ts +5 -0
  24. package/dist/utils/diff-mapper/DiffMapper.stories.js +185 -0
  25. package/dist/utils/diff-mapper/DiffMapperDemo.svelte +351 -0
  26. package/dist/utils/diff-mapper/DiffMapperDemo.svelte.d.ts +18 -0
  27. package/dist/utils/diff-mapper/deepDiffMapper.d.ts +31 -0
  28. package/dist/utils/diff-mapper/deepDiffMapper.js +264 -0
  29. package/dist/utils/diff-mapper/index.d.ts +1 -0
  30. package/dist/utils/diff-mapper/index.js +1 -0
  31. package/dist/utils/index.d.ts +1 -0
  32. package/dist/utils/index.js +1 -0
  33. package/package.json +1 -1
  34. package/dist/providers/GlobalProvider.mdx +0 -322
  35. package/dist/router/Router.mdx +0 -958
  36. package/dist/stores/docs/Form.mdx +0 -542
@@ -1,958 +0,0 @@
1
- # Router API Documentation
2
-
3
- A comprehensive client-side router for Svelte 5 applications with support for reactive state management, dynamic routing, and app version persistence.
4
-
5
- ## Table of Contents
6
-
7
- - [Installation](#installation)
8
- - [Core Classes](#core-classes)
9
- - [Router](#router)
10
- - [createRouter()](#createrouter)
11
- - [Components](#components)
12
- - [RouterProvider](#routerprovider)
13
- - [Route](#route)
14
- - [Link](#link)
15
- - [Hooks](#hooks)
16
- - [Interfaces](#interfaces)
17
- - [Examples](#examples)
18
-
19
- ## Installation
20
-
21
- ```typescript
22
- import {
23
- createRouter,
24
- RouterProvider,
25
- Route,
26
- Link,
27
- useRouter,
28
- useLocation,
29
- useNavigate
30
- } from '@finsweet/webflow-apps-utils';
31
- ```
32
-
33
- ## Core Classes
34
-
35
- ### Router
36
-
37
- The main router class that handles navigation, route matching, and state management.
38
-
39
- #### Constructor
40
-
41
- ```typescript
42
- new Router(config?: RouterConfig)
43
- ```
44
-
45
- #### Configuration Options
46
-
47
- ```typescript
48
- interface RouterConfig {
49
- basePath?: string; // Base path for all routes (default: '')
50
- hashMode?: boolean; // Use hash-based routing (default: false)
51
- fallbackRoute?: string; // Fallback route when no match (default: '/')
52
- autoInit?: boolean; // Auto-initialize on creation (default: true)
53
- }
54
- ```
55
-
56
- #### Methods
57
-
58
- ##### Navigation Methods
59
-
60
- ```typescript
61
- // Navigate to a path
62
- navigate(pathname: string, options?: { replace?: boolean; state?: any }): void
63
-
64
- // Navigate back in history
65
- back(): void
66
-
67
- // Navigate forward in history
68
- forward(): void
69
-
70
- // Navigate to root path
71
- gotoRootPath(): void
72
- ```
73
-
74
- ##### Route Management
75
-
76
- ```typescript
77
- // Add a single route
78
- addRoute(route: RouteConfig): void
79
-
80
- // Add multiple routes
81
- addRoutes(routes: RouteConfig[]): void
82
- ```
83
-
84
- ##### State Access Methods
85
-
86
- ```typescript
87
- // Get reactive location information
88
- useLocation(): LocationInfo
89
-
90
- // Get reactive current route
91
- useRoute(): RouteConfig | null
92
-
93
- // Get reactive navigation state
94
- useNavigating(): boolean
95
-
96
- // Get reactive navigation history
97
- useHistory(): HistoryEntry[]
98
-
99
- // Check if path is active
100
- isActive(path: string, exact?: boolean): boolean
101
-
102
- // Get current route parameters
103
- getParams(): RouteParams
104
-
105
- // Get current query parameters
106
- getQuery(): URLSearchParams
107
- ```
108
-
109
- ##### App Version Methods
110
-
111
- ```typescript
112
- // Initialize app version path persistence
113
- initAppVersion(appVersionPath: string): void
114
-
115
- // Get current app version path
116
- getAppVersionPath(): string
117
-
118
- // Get full pathname including app version
119
- getFullPathname(): string
120
-
121
- // Get active path with app version
122
- getActivePath(): string
123
- ```
124
-
125
- ##### Lifecycle Methods
126
-
127
- ```typescript
128
- // Initialize the router
129
- init(): void
130
-
131
- // Clean up and destroy router
132
- destroy(): void
133
- ```
134
-
135
- #### Example Usage
136
-
137
- ```typescript
138
- import { createRouter } from '@finsweet/webflow-apps-utils';
139
-
140
- // Create router with configuration
141
- const router = createRouter({
142
- basePath: '/app',
143
- hashMode: false,
144
- fallbackRoute: '/home',
145
- autoInit: true
146
- });
147
-
148
- // Add routes
149
- router.addRoutes([
150
- { path: '/', component: HomePage, meta: { title: 'Home' } },
151
- { path: '/users/:id', component: UserPage, meta: { title: 'User Profile' } },
152
- { path: '/about', component: AboutPage, meta: { title: 'About' } }
153
- ]);
154
-
155
- // Initialize app version for persistence
156
- router.initAppVersion('/v1');
157
-
158
- // Navigate programmatically
159
- router.navigate('/users/123');
160
- router.navigate('/about', { replace: true, state: { from: 'home' } });
161
- ```
162
-
163
- ### createRouter()
164
-
165
- Factory function to create a new router instance.
166
-
167
- ```typescript
168
- function createRouter(config?: RouterConfig): Router;
169
- ```
170
-
171
- #### Example
172
-
173
- ```typescript
174
- const router = createRouter({
175
- basePath: '/my-app',
176
- fallbackRoute: '/dashboard'
177
- });
178
- ```
179
-
180
- ## Components
181
-
182
- ### RouterProvider
183
-
184
- Root component that provides router context to child components and manages router lifecycle.
185
-
186
- #### Props
187
-
188
- ```typescript
189
- interface RouterProviderProps {
190
- router: Router; // Router instance
191
- autoInit?: boolean; // Auto-initialize router (default: true)
192
- loading?: boolean; // Show loading screen
193
- loadingMessage?: string; // Loading message text
194
- children?: Snippet<[RouterContext]>; // Children with router context
195
- }
196
-
197
- interface RouterContext {
198
- router: Router;
199
- currentRoute: RouteConfig | null;
200
- currentLocation: LocationInfo;
201
- isNavigating: boolean;
202
- }
203
- ```
204
-
205
- #### Example
206
-
207
- ```typescript
208
- <script lang="ts">
209
- import { createRouter, RouterProvider } from '@finsweet/webflow-apps-utils';
210
-
211
- const router = createRouter();
212
- </script>
213
-
214
- <RouterProvider {router} loading={false}>
215
- {#snippet children({ router, currentRoute, currentLocation, isNavigating })}
216
- <nav>
217
- <!-- Navigation content -->
218
- </nav>
219
-
220
- <main class:navigating={isNavigating}>
221
- <!-- Route content -->
222
- </main>
223
- {/snippet}
224
- </RouterProvider>
225
- ```
226
-
227
- ### Route
228
-
229
- Component for defining and rendering routes based on path patterns.
230
-
231
- #### Props
232
-
233
- ```typescript
234
- interface RouteProps {
235
- path: string; // Path pattern (supports :params)
236
- component?: any; // Component to render when active
237
- meta?: Record<string, any>; // Route metadata
238
- exact?: boolean; // Exact path matching (default: true)
239
- children?: Snippet<[RouteContext]>; // Children with route context
240
- }
241
-
242
- interface RouteContext {
243
- params: Record<string, string>; // Route parameters
244
- location: LocationInfo; // Current location
245
- router: Router; // Router instance
246
- isActive: boolean; // Whether route is active
247
- }
248
- ```
249
-
250
- #### Example
251
-
252
- ```typescript
253
- <!-- Using component prop -->
254
- <Route path="/users/:id" component={UserProfile} />
255
-
256
- <!-- Using children snippet -->
257
- <Route path="/dashboard">
258
- {#snippet children({ params, location, router, isActive })}
259
- {#if isActive}
260
- <Dashboard userId={params.id} />
261
- {/if}
262
- {/snippet}
263
- </Route>
264
-
265
- <!-- Wildcard route for 404 -->
266
- <Route path="*" exact={false}>
267
- {#snippet children({ isActive })}
268
- {#if isActive}
269
- <NotFoundPage />
270
- {/if}
271
- {/snippet}
272
- </Route>
273
- ```
274
-
275
- ### Link
276
-
277
- Navigation component that generates proper links with active state management.
278
-
279
- #### Props
280
-
281
- ```typescript
282
- interface LinkProps {
283
- to: string; // Target path
284
- replace?: boolean; // Replace history entry (default: false)
285
- activeClass?: string; // CSS class when active
286
- exact?: boolean; // Exact matching for active state
287
- disabled?: boolean; // Disable the link
288
- class?: string; // Additional CSS classes
289
- state?: any; // State to pass with navigation
290
- element?: 'a' | 'button'; // HTML element type (default: 'a')
291
- children?: Snippet; // Link content
292
- onclick?: (event: MouseEvent) => void; // Click handler
293
- }
294
- ```
295
-
296
- #### Example
297
-
298
- ```typescript
299
- <!-- Basic link -->
300
- <Link to="/about">About Us</Link>
301
-
302
- <!-- Link with active styling -->
303
- <Link to="/dashboard" activeClass="nav-active" exact>
304
- Dashboard
305
- </Link>
306
-
307
- <!-- Button-style link -->
308
- <Link to="/settings" element="button" class="btn btn-primary">
309
- Settings
310
- </Link>
311
-
312
- <!-- Link with custom click handler -->
313
- <Link
314
- to="/profile"
315
- onclick={(e) => console.log('Navigating to profile')}
316
- >
317
- My Profile
318
- </Link>
319
-
320
- <!-- Disabled link -->
321
- <Link to="/admin" disabled>
322
- Admin Panel
323
- </Link>
324
- ```
325
-
326
- ## Hooks
327
-
328
- ### useRouter()
329
-
330
- Get the router instance from context.
331
-
332
- ```typescript
333
- function useRouter(): Router;
334
- ```
335
-
336
- #### Example
337
-
338
- ```typescript
339
- <script lang="ts">
340
- import { useRouter } from '@finsweet/webflow-apps-utils';
341
-
342
- const router = useRouter();
343
-
344
- function handleLogout() {
345
- router.navigate('/login', { replace: true });
346
- }
347
- </script>
348
- ```
349
-
350
- ### useLocation()
351
-
352
- Get reactive location information.
353
-
354
- ```typescript
355
- function useLocation(): LocationInfo;
356
- ```
357
-
358
- #### Example
359
-
360
- ```typescript
361
- <script lang="ts">
362
- import { useLocation } from '@finsweet/webflow-apps-utils';
363
-
364
- const location = useLocation();
365
- </script>
366
-
367
- <div>
368
- Current path: {location.pathname}
369
- Query params: {location.search}
370
- Route params: {JSON.stringify(location.params)}
371
- </div>
372
- ```
373
-
374
- ### useRoute()
375
-
376
- Get reactive current route information.
377
-
378
- ```typescript
379
- function useRoute(): RouteConfig | null;
380
- ```
381
-
382
- #### Example
383
-
384
- ```typescript
385
- <script lang="ts">
386
- import { useRoute } from '@finsweet/webflow-apps-utils';
387
-
388
- const route = useRoute();
389
- </script>
390
-
391
- {#if route}
392
- <title>{route.meta?.title || 'My App'}</title>
393
- {/if}
394
- ```
395
-
396
- ### useParams()
397
-
398
- Get reactive route parameters.
399
-
400
- ```typescript
401
- function useParams(): RouteParams;
402
- ```
403
-
404
- #### Example
405
-
406
- ```typescript
407
- <script lang="ts">
408
- import { useParams } from '@finsweet/webflow-apps-utils';
409
-
410
- const params = useParams();
411
-
412
- $: userId = params.id;
413
- </script>
414
-
415
- <h1>User Profile: {userId}</h1>
416
- ```
417
-
418
- ### useQuery()
419
-
420
- Get reactive query parameters.
421
-
422
- ```typescript
423
- function useQuery(): URLSearchParams;
424
- ```
425
-
426
- #### Example
427
-
428
- ```typescript
429
- <script lang="ts">
430
- import { useQuery } from '@finsweet/webflow-apps-utils';
431
-
432
- const query = useQuery();
433
-
434
- $: page = query.get('page') || '1';
435
- $: sort = query.get('sort') || 'name';
436
- </script>
437
- ```
438
-
439
- ### useNavigate()
440
-
441
- Get a navigation function.
442
-
443
- ```typescript
444
- function useNavigate(): (pathname: string, options?: NavigateOptions) => void;
445
-
446
- interface NavigateOptions {
447
- replace?: boolean;
448
- state?: any;
449
- }
450
- ```
451
-
452
- #### Example
453
-
454
- ```typescript
455
- <script lang="ts">
456
- import { useNavigate } from '@finsweet/webflow-apps-utils';
457
-
458
- const navigate = useNavigate();
459
-
460
- function goToProfile() {
461
- navigate('/profile');
462
- }
463
-
464
- function goToSettings() {
465
- navigate('/settings', { replace: true });
466
- }
467
- </script>
468
- ```
469
-
470
- ### useNavigating()
471
-
472
- Get reactive navigation state.
473
-
474
- ```typescript
475
- function useNavigating(): boolean;
476
- ```
477
-
478
- #### Example
479
-
480
- ```typescript
481
- <script lang="ts">
482
- import { useNavigating } from '@finsweet/webflow-apps-utils';
483
-
484
- const isNavigating = useNavigating();
485
- </script>
486
-
487
- {#if isNavigating}
488
- <div class="loading-spinner">Navigating...</div>
489
- {/if}
490
- ```
491
-
492
- ### useHistory()
493
-
494
- Get reactive navigation history.
495
-
496
- ```typescript
497
- function useHistory(): HistoryEntry[];
498
- ```
499
-
500
- #### Example
501
-
502
- ```typescript
503
- <script lang="ts">
504
- import { useHistory } from '@finsweet/webflow-apps-utils';
505
-
506
- const history = useHistory();
507
- </script>
508
-
509
- <div>
510
- <h3>Navigation History:</h3>
511
- {#each history.slice(-5) as entry}
512
- <div>{entry.pathname} - {new Date(entry.timestamp).toLocaleTimeString()}</div>
513
- {/each}
514
- </div>
515
- ```
516
-
517
- ### useIsActiveRoute()
518
-
519
- Get a function to check if routes are active.
520
-
521
- ```typescript
522
- function useIsActiveRoute(): (path: string, exact?: boolean) => boolean;
523
- ```
524
-
525
- #### Example
526
-
527
- ```typescript
528
- <script lang="ts">
529
- import { useIsActiveRoute } from '@finsweet/webflow-apps-utils';
530
-
531
- const isActive = useIsActiveRoute();
532
- </script>
533
-
534
- <nav>
535
- <a href="/home" class:active={isActive('/home')}>Home</a>
536
- <a href="/about" class:active={isActive('/about')}>About</a>
537
- </nav>
538
- ```
539
-
540
- ### useRouteWatcher()
541
-
542
- Watch for route changes and execute callbacks.
543
-
544
- ```typescript
545
- function useRouteWatcher(
546
- callback: (location: LocationInfo, route: RouteConfig | null) => void,
547
- immediate?: boolean
548
- ): void;
549
- ```
550
-
551
- #### Example
552
-
553
- ```typescript
554
- <script lang="ts">
555
- import { useRouteWatcher } from '@finsweet/webflow-apps-utils';
556
-
557
- useRouteWatcher((location, route) => {
558
- console.log('Route changed:', location.pathname);
559
-
560
- // Update page title
561
- if (route?.meta?.title) {
562
- document.title = route.meta.title;
563
- }
564
-
565
- // Analytics tracking
566
- analytics.track('page_view', { path: location.pathname });
567
- });
568
- </script>
569
- ```
570
-
571
- ### useSearchParams()
572
-
573
- Get search params helper with reactive updates.
574
-
575
- ```typescript
576
- function useSearchParams(): SearchParamsHelper;
577
-
578
- interface SearchParamsHelper {
579
- get(key: string): string | null;
580
- set(key: string, value: string): void;
581
- delete(key: string): void;
582
- has(key: string): boolean;
583
- toString(): string;
584
- getAll(): Record<string, string>;
585
- }
586
- ```
587
-
588
- #### Example
589
-
590
- ```typescript
591
- <script lang="ts">
592
- import { useSearchParams } from '@finsweet/webflow-apps-utils';
593
-
594
- const searchParams = useSearchParams();
595
-
596
- function updatePage(page: number) {
597
- searchParams.set('page', page.toString());
598
- }
599
-
600
- function clearFilters() {
601
- searchParams.delete('filter');
602
- searchParams.delete('sort');
603
- }
604
- </script>
605
-
606
- <div>
607
- Current page: {searchParams.get('page') || '1'}
608
- <button onclick={() => updatePage(2)}>Go to Page 2</button>
609
- <button onclick={clearFilters}>Clear Filters</button>
610
- </div>
611
- ```
612
-
613
- ### useAppVersion()
614
-
615
- Get the current app version path.
616
-
617
- ```typescript
618
- function useAppVersion(): string;
619
- ```
620
-
621
- #### Example
622
-
623
- ```typescript
624
- <script lang="ts">
625
- import { useAppVersion } from '@finsweet/webflow-apps-utils';
626
-
627
- const appVersion = useAppVersion();
628
- </script>
629
-
630
- <div>App Version: {appVersion}</div>
631
- ```
632
-
633
- ### useFullPathname()
634
-
635
- Get the full pathname including app version.
636
-
637
- ```typescript
638
- function useFullPathname(): string;
639
- ```
640
-
641
- #### Example
642
-
643
- ```typescript
644
- <script lang="ts">
645
- import { useFullPathname } from '@finsweet/webflow-apps-utils';
646
-
647
- const fullPathname = useFullPathname();
648
- </script>
649
-
650
- <div>Full URL Path: {fullPathname}</div>
651
- ```
652
-
653
- ## Interfaces
654
-
655
- ### RouteConfig
656
-
657
- ```typescript
658
- interface RouteConfig {
659
- path: string; // Path pattern ('/users/:id')
660
- component?: any; // Svelte component
661
- meta?: Record<string, any>; // Route metadata
662
- }
663
- ```
664
-
665
- ### LocationInfo
666
-
667
- ```typescript
668
- interface LocationInfo {
669
- pathname: string; // Current pathname
670
- search: string; // Query string
671
- hash: string; // URL hash
672
- url: URL; // Complete URL object
673
- params: RouteParams; // Route parameters
674
- query: URLSearchParams; // Query parameters object
675
- }
676
- ```
677
-
678
- ### RouteParams
679
-
680
- ```typescript
681
- interface RouteParams {
682
- [key: string]: string; // Parameter name to value mapping
683
- }
684
- ```
685
-
686
- ### HistoryEntry
687
-
688
- ```typescript
689
- interface HistoryEntry {
690
- pathname: string; // Path of history entry
691
- timestamp: number; // Entry creation time
692
- state?: any; // Optional state data
693
- }
694
- ```
695
-
696
- ## Examples
697
-
698
- ### Complete Application Setup
699
-
700
- ```typescript
701
- <!-- App.svelte -->
702
- <script lang="ts">
703
- import { onMount } from 'svelte';
704
- import { createRouter, RouterProvider, Route, Link } from '@finsweet/webflow-apps-utils';
705
-
706
- // Import page components
707
- import HomePage from './pages/HomePage.svelte';
708
- import AboutPage from './pages/AboutPage.svelte';
709
- import UserPage from './pages/UserPage.svelte';
710
- import NotFoundPage from './pages/NotFoundPage.svelte';
711
-
712
- // Create router with configuration
713
- const router = createRouter({
714
- basePath: '',
715
- fallbackRoute: '/'
716
- });
717
-
718
- // Define routes
719
- router.addRoutes([
720
- { path: '/', component: HomePage, meta: { title: 'Home' } },
721
- { path: '/about', component: AboutPage, meta: { title: 'About' } },
722
- { path: '/users/:id', component: UserPage, meta: { title: 'User Profile' } },
723
- { path: '*', component: NotFoundPage, meta: { title: 'Not Found' } }
724
- ]);
725
-
726
- onMount(() => {
727
- // Initialize app version if needed
728
- router.initAppVersion('/v1');
729
- });
730
- </script>
731
-
732
- <RouterProvider {router}>
733
- {#snippet children({ router, currentRoute, isNavigating })}
734
- <div class="app">
735
- <!-- Navigation -->
736
- <nav class="navbar">
737
- <div class="nav-brand">
738
- <Link to="/">My App</Link>
739
- </div>
740
- <ul class="nav-links">
741
- <li><Link to="/" exact activeClass="active">Home</Link></li>
742
- <li><Link to="/about" activeClass="active">About</Link></li>
743
- <li><Link to="/users/123" activeClass="active">Profile</Link></li>
744
- </ul>
745
- </nav>
746
-
747
- <!-- Loading indicator -->
748
- {#if isNavigating}
749
- <div class="loading-bar"></div>
750
- {/if}
751
-
752
- <!-- Page title -->
753
- <title>{currentRoute?.meta?.title || 'My App'}</title>
754
-
755
- <!-- Main content -->
756
- <main class="main-content">
757
- <!-- Home Route -->
758
- <Route path="/">
759
- {#snippet children({ isActive })}
760
- {#if isActive}
761
- <HomePage />
762
- {/if}
763
- {/snippet}
764
- </Route>
765
-
766
- <!-- About Route -->
767
- <Route path="/about" component={AboutPage} />
768
-
769
- <!-- User Profile Route -->
770
- <Route path="/users/:id">
771
- {#snippet children({ params, isActive })}
772
- {#if isActive}
773
- <UserPage userId={params.id} />
774
- {/if}
775
- {/snippet}
776
- </Route>
777
-
778
- <!-- 404 Route -->
779
- <Route path="*" exact={false} component={NotFoundPage} />
780
- </main>
781
- </div>
782
- {/snippet}
783
- </RouterProvider>
784
-
785
- <style>
786
- .app {
787
- min-height: 100vh;
788
- display: flex;
789
- flex-direction: column;
790
- }
791
-
792
- .navbar {
793
- display: flex;
794
- justify-content: space-between;
795
- align-items: center;
796
- padding: 1rem 2rem;
797
- background: #f8f9fa;
798
- border-bottom: 1px solid #dee2e6;
799
- }
800
-
801
- .nav-links {
802
- display: flex;
803
- list-style: none;
804
- gap: 1rem;
805
- margin: 0;
806
- padding: 0;
807
- }
808
-
809
- .nav-links :global(a) {
810
- padding: 0.5rem 1rem;
811
- text-decoration: none;
812
- color: #495057;
813
- border-radius: 4px;
814
- transition: all 0.2s;
815
- }
816
-
817
- .nav-links :global(a:hover) {
818
- background: #e9ecef;
819
- }
820
-
821
- .nav-links :global(a.active) {
822
- background: #007bff;
823
- color: white;
824
- }
825
-
826
- .loading-bar {
827
- height: 3px;
828
- background: linear-gradient(90deg, #007bff, #6610f2);
829
- animation: slide 1s ease-in-out infinite;
830
- }
831
-
832
- @keyframes slide {
833
- 0% { transform: translateX(-100%); }
834
- 100% { transform: translateX(100vw); }
835
- }
836
-
837
- .main-content {
838
- flex: 1;
839
- padding: 2rem;
840
- }
841
- </style>
842
- ```
843
-
844
- ### Using Hooks in Components
845
-
846
- ```typescript
847
- <!-- UserProfile.svelte -->
848
- <script lang="ts">
849
- import { useParams, useNavigate, useSearchParams } from '@finsweet/webflow-apps-utils';
850
-
851
- const params = useParams();
852
- const navigate = useNavigate();
853
- const searchParams = useSearchParams();
854
-
855
- // Reactive values
856
- $: userId = params.id;
857
- $: tab = searchParams.get('tab') || 'profile';
858
-
859
- function switchTab(newTab: string) {
860
- searchParams.set('tab', newTab);
861
- }
862
-
863
- function goBack() {
864
- navigate('/users');
865
- }
866
- </script>
867
-
868
- <div class="user-profile">
869
- <header>
870
- <button onclick={goBack}>← Back to Users</button>
871
- <h1>User Profile: {userId}</h1>
872
- </header>
873
-
874
- <nav class="tabs">
875
- <button
876
- class:active={tab === 'profile'}
877
- onclick={() => switchTab('profile')}
878
- >
879
- Profile
880
- </button>
881
- <button
882
- class:active={tab === 'settings'}
883
- onclick={() => switchTab('settings')}
884
- >
885
- Settings
886
- </button>
887
- </nav>
888
-
889
- <main>
890
- {#if tab === 'profile'}
891
- <div>Profile content for user {userId}</div>
892
- {:else if tab === 'settings'}
893
- <div>Settings for user {userId}</div>
894
- {/if}
895
- </main>
896
- </div>
897
- ```
898
-
899
- ### Programmatic Navigation
900
-
901
- ```typescript
902
- <!-- NavigationExample.svelte -->
903
- <script lang="ts">
904
- import { useRouter, useNavigate, useLocation } from '@finsweet/webflow-apps-utils';
905
-
906
- const router = useRouter();
907
- const navigate = useNavigate();
908
- const location = useLocation();
909
-
910
- async function handleLogin(userData: any) {
911
- // Simulate login
912
- await loginUser(userData);
913
-
914
- // Navigate to dashboard after login
915
- navigate('/dashboard', {
916
- replace: true,
917
- state: { loginTime: Date.now() }
918
- });
919
- }
920
-
921
- function handleLogout() {
922
- // Clear user data
923
- clearUserSession();
924
-
925
- // Navigate to home and replace history
926
- router.navigate('/', { replace: true });
927
- }
928
-
929
- function goToUserProfile(userId: string) {
930
- navigate(`/users/${userId}?tab=profile`);
931
- }
932
-
933
- function navigateWithState() {
934
- navigate('/results', {
935
- state: {
936
- searchQuery: 'example',
937
- timestamp: Date.now()
938
- }
939
- });
940
- }
941
- </script>
942
-
943
- <div>
944
- <p>Current path: {location.pathname}</p>
945
-
946
- <button onclick={() => goToUserProfile('123')}>
947
- View User 123
948
- </button>
949
-
950
- <button onclick={navigateWithState}>
951
- Search with State
952
- </button>
953
-
954
- <button onclick={handleLogout}>
955
- Logout
956
- </button>
957
- </div>
958
- ```