@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
@@ -1,322 +0,0 @@
1
- # GlobalProvider
2
-
3
- The `GlobalProvider` is a context management system built on Svelte 5 that manages multiple application contexts in a type-safe and reactive way.
4
-
5
- ## Features
6
-
7
- - **Multiple Contexts**: Manage different types of state (form, app, data, etc.) in separate contexts
8
- - **Type Safety**: Full TypeScript support with branded types and generics
9
- - **Reactive**: Built on Svelte 5 runes for optimal reactivity
10
- - **Event System**: Subscribe to context changes and global events (batched for performance)
11
-
12
- ## Basic Usage
13
-
14
- ### Wrap Your App
15
-
16
- ```svelte
17
- <script lang="ts">
18
- import { GlobalProvider } from '$lib/providers';
19
-
20
- const initialContexts = {
21
- app: {
22
- editMode: false,
23
- repairMode: false,
24
- title: 'My App'
25
- },
26
- form: {
27
- formKey: null,
28
- formUpdateKey: null
29
- }
30
- };
31
- </script>
32
-
33
- <GlobalProvider {initialContexts} debug={true}>
34
- <App />
35
- </GlobalProvider>
36
- ```
37
-
38
- ### Default Contexts
39
-
40
- The `GlobalProvider` automatically creates these default contexts:
41
-
42
- - **`app`**: Application state (editMode, repairMode, title, configurator)
43
- - **`form`**: Form state (formKey, formUpdateKey)
44
- - **`data`**: General data state
45
-
46
- ### Use Contexts in Components
47
-
48
- ```svelte
49
- <script lang="ts">
50
- import { useAppContext, useFormContext, useDataContext } from '$lib/providers';
51
-
52
- const appContext = useAppContext();
53
- const formContext = useFormContext();
54
- const dataContext = useDataContext();
55
-
56
- let appData = $derived(appContext.get());
57
- let formData = $derived(formContext.get());
58
-
59
- function toggleEditMode() {
60
- appContext.update((current) => ({
61
- ...current,
62
- editMode: !current?.editMode
63
- }));
64
- }
65
- </script>
66
-
67
- <div>
68
- <p>Edit Mode: {appData?.editMode}</p>
69
- <p>Form Key: {formData?.formKey}</p>
70
- <button onclick={toggleEditMode}>Toggle Edit Mode</button>
71
- </div>
72
- ```
73
-
74
- ## API Reference
75
-
76
- ### Context Operations
77
-
78
- #### `get(): T | null`
79
-
80
- Returns the current context data. Returns `undefined` if the context has been reset (completely removed).
81
-
82
- #### `set(data: Partial<T>): void`
83
-
84
- Sets context data (merges with existing data).
85
-
86
- #### `update(updater: (current: T | null) => T): void`
87
-
88
- Updates context data using an updater function.
89
-
90
- #### `clear(): void`
91
-
92
- Clears context data (sets to null). The context remains active but with null data.
93
-
94
- #### `reset(): void`
95
-
96
- Completely removes the context. After reset, `hasContext()` returns false and `get()` returns `undefined`.
97
-
98
- #### `subscribe(callback: (data: T | null) => void): () => void`
99
-
100
- Subscribes to context changes. Returns unsubscribe function. **Note**: Events are batched and emitted asynchronously for performance.
101
-
102
- ### Global Operations
103
-
104
- - `getContext<T>(key: string): ContextOperations<T>` - Get context operations for a key
105
- - `hasContext(key: string): boolean` - Check if context exists
106
- - `removeContext(key: string): void` - Remove a specific context
107
- - `clearAll(): void` - Clear all context data (set to null)
108
- - `resetAll(): void` - Reset all contexts (completely remove them)
109
- - `resetByKey(key: string): void` - Reset a specific context by key
110
- - `getActiveContexts(): string[]` - Get list of active context keys
111
- - `getAllContexts(): Record<string, unknown>` - Get all context data
112
- - `getContextMetadata(key: string)` - Get metadata (version, updatedAt, isActive) for a context
113
- - `subscribe(callback): () => void` - Subscribe to global context events
114
-
115
- ## Examples
116
-
117
- ### App State Management
118
-
119
- ```svelte
120
- <script lang="ts">
121
- import { useAppContext } from '$lib/providers';
122
-
123
- const appContext = useAppContext();
124
- let appData = $derived(appContext.get());
125
-
126
- function handleSubmit() {
127
- appContext.set({ editMode: true });
128
- }
129
- </script>
130
-
131
- <form onsubmit={handleSubmit}>
132
- <p>Edit Mode: {appData?.editMode}</p>
133
- <button type="submit">Submit</button>
134
- </form>
135
- ```
136
-
137
- ### Custom Context
138
-
139
- ```svelte
140
- <script lang="ts">
141
- import { useContext } from '$lib/providers';
142
-
143
- type UserContext = {
144
- id: string;
145
- name: string;
146
- preferences: { theme: 'light' | 'dark' };
147
- };
148
-
149
- const userContext = useContext<UserContext>('user');
150
- let userData = $derived(userContext.get());
151
-
152
- function updateTheme(theme: 'light' | 'dark') {
153
- userContext.update((current) => ({
154
- ...current!,
155
- preferences: { ...current!.preferences, theme }
156
- }));
157
- }
158
- </script>
159
- ```
160
-
161
- ### Typed Data Context
162
-
163
- ```svelte
164
- <script lang="ts">
165
- import { useDataContext } from '$lib/providers';
166
-
167
- type AppDataType = {
168
- users: Array<{ id: string; name: string; email: string }>;
169
- products: Array<{ id: string; title: string; price: number }>;
170
- currentPage: number;
171
- totalPages: number;
172
- };
173
-
174
- const dataContext = useDataContext<AppDataType>();
175
- let appData = $derived(dataContext.get());
176
-
177
- function loadUsers(users: AppDataType['users']) {
178
- dataContext.set({
179
- state: {
180
- ...appData?.state,
181
- users,
182
- currentPage: 1
183
- }
184
- });
185
- }
186
-
187
- function nextPage() {
188
- if (appData?.state && appData.state.currentPage < appData.state.totalPages) {
189
- dataContext.update((current) => ({
190
- state: {
191
- ...current!.state!,
192
- currentPage: current!.state!.currentPage + 1
193
- }
194
- }));
195
- }
196
- }
197
- </script>
198
-
199
- <div>
200
- <p>Users: {appData?.state?.users?.length || 0}</p>
201
- <p>Page: {appData?.state?.currentPage || 1} of {appData?.state?.totalPages || 1}</p>
202
- <button onclick={nextPage}>Next Page</button>
203
- </div>
204
- ```
205
-
206
- ## Configurator Support
207
-
208
- The `GlobalProvider` includes built-in support for configurator state management with automatic change detection.
209
-
210
- ### Using the Configurator Context
211
-
212
- ```svelte
213
- <script lang="ts">
214
- import { useConfiguratorContext, useAppContext } from '$lib/providers';
215
-
216
- // Define your configurator type
217
- type MyConfiguratorType = {
218
- theme: 'light' | 'dark';
219
- layout: 'grid' | 'list';
220
- itemsPerPage: number;
221
- };
222
-
223
- // Use typed configurator context
224
- const configurator = useConfiguratorContext<MyConfiguratorType>();
225
-
226
- // Or use typed app context
227
- const appContext = useAppContext<MyConfiguratorType>();
228
-
229
- // Set configurator data with watch options (fully typed)
230
- configurator.setConfigurator(
231
- { theme: 'dark', layout: 'grid', itemsPerPage: 10 },
232
- { watchKeys: ['theme'], debounceMs: 100 }
233
- );
234
-
235
- // Check if configurator has changed
236
- let hasChanged = $derived(configurator.hasChanged);
237
- let currentConfig = $derived(configurator.configurator); // Type: MyConfiguratorType | null
238
- let cachedConfig = $derived(configurator.configuratorCache); // Type: MyConfiguratorType | null
239
-
240
- // Save current state to cache
241
- function saveToCache() {
242
- configurator.saveToCache();
243
- }
244
- </script>
245
-
246
- <div>
247
- <p>Has Changed: {hasChanged}</p>
248
- <p>Current Theme: {currentConfig?.theme}</p>
249
- <p>Cached Theme: {cachedConfig?.theme}</p>
250
- <button onclick={saveToCache}>Save to Cache</button>
251
- </div>
252
- ```
253
-
254
- ### Configurator API
255
-
256
- - `configurator` - Current configurator data
257
- - `configuratorCache` - Cached configurator data
258
- - `hasChanged` - Boolean indicating if configurator differs from cache
259
- - `watchOptions` - Current watch configuration
260
- - `setConfigurator(data, watchOptions?)` - Set configurator data
261
- - `setConfiguratorCache(data)` - Set cache data
262
- - `saveToCache()` - Save current configurator to cache
263
- - `updateWatchOptions(options)` - Update watch configuration
264
-
265
- ### Watch Options
266
-
267
- ```typescript
268
- interface ConfiguratorWatchOptions {
269
- watchAll?: boolean; // Watch all keys (default: true)
270
- watchKeys?: string[]; // Specific keys to watch
271
- debounceMs?: number; // Debounce delay (default: 50ms)
272
- }
273
- ```
274
-
275
- ## TypeScript Support
276
-
277
- ### Generic Context Usage
278
-
279
- ```typescript
280
- import type { ContextOperations, AppContextData, DataContextData } from '$lib/providers';
281
-
282
- // For custom contexts
283
- const userContext: ContextOperations<UserType> = useContext<UserType>('user');
284
-
285
- // For typed app context with configurator
286
- type MyConfiguratorType = {
287
- theme: 'light' | 'dark';
288
- layout: 'grid' | 'list';
289
- };
290
-
291
- const appContext = useAppContext<MyConfiguratorType>();
292
- const configurator = useConfiguratorContext<MyConfiguratorType>();
293
-
294
- // For typed data context
295
- type MyDataType = {
296
- users: User[];
297
- products: Product[];
298
- currentPage: number;
299
- };
300
-
301
- const dataContext = useDataContext<MyDataType>();
302
-
303
- // The configurator and configuratorCache will both be typed as MyConfiguratorType | null
304
- // The data context state will be typed as MyDataType | null
305
- ```
306
-
307
- ### Type Definitions
308
-
309
- ```typescript
310
- // Your configurator type
311
- type MyConfiguratorType = {
312
- theme: 'light' | 'dark';
313
- layout: 'grid' | 'list';
314
- itemsPerPage: number;
315
- };
316
-
317
- // App context will be typed as AppContextData<MyConfiguratorType>
318
- type MyAppContextType = AppContextData<MyConfiguratorType>;
319
-
320
- // Data context will be typed as DataContextData<MyDataType>
321
- type MyDataContextType = DataContextData<MyDataType>;
322
- ```
@@ -1,397 +0,0 @@
1
- # Custom Svelte 5 Router
2
-
3
- A lightweight, type-safe client-side router built specifically for Svelte 5 using runes. Designed to replace svelte-routing with modern reactivity patterns and support for persistent app version hashes.
4
-
5
- ## Features
6
-
7
- - 🚀 **Svelte 5 Native**: Built with runes for optimal reactivity
8
- - 🎯 **Type-Safe**: Full TypeScript support with comprehensive type definitions
9
- - 📦 **Lightweight**: Minimal bundle size with no external dependencies
10
- - 🔄 **Reactive**: All router state is reactive using Svelte 5 runes
11
- - 🛣️ **Parameter Support**: URL parameters like `/users/:id`
12
- - 🔍 **Query Params**: Built-in query parameter handling
13
- - 🏠 **App Version Support**: Persistent app version hashes across navigation
14
- - 📱 **Hash Mode**: Optional hash-based routing
15
- - 🎣 **Rich Hooks**: Comprehensive set of utility hooks
16
- - ♿ **Accessible**: Built-in accessibility features for navigation
17
-
18
- ## Installation
19
-
20
- The router is included in your project. Import from:
21
-
22
- ```typescript
23
- import { Router, RouterComponent, Route, Link } from './router';
24
- ```
25
-
26
- ## Quick Start
27
-
28
- ### 1. Create and Configure Router
29
-
30
- ```typescript
31
- // router.ts
32
- import { createRouter } from './lib/router';
33
-
34
- export const appRouter = createRouter({
35
- autoInit: true
36
- });
37
-
38
- // Export the router instance for use throughout the app
39
- export default appRouter;
40
- ```
41
-
42
- ### 2. Initialize with App Version
43
-
44
- ```typescript
45
- // In your app initialization
46
- const awaitRouter = async () => {
47
- const current = new URL(window.location.href);
48
- const appVersionID = current.pathname.split('/')[1] || 'dev-mode';
49
-
50
- // Initialize app version - this persists across all navigation
51
- appRouter.initAppVersion(`/${appVersionID}`);
52
-
53
- // Define routes without app version prefix
54
- appRouter.addRoutes([
55
- { path: '/', component: MyComponentsLinks },
56
- { path: '/finsweetbuilder', component: BuilderLinks },
57
- { path: '/finsweetlibrary', component: LibraryLinks },
58
- { path: '/finsweetlibrary-admin', component: LibraryAdminLinks }
59
- ]);
60
-
61
- // Update your existing router store
62
- routerStore.set({
63
- hash: appVersionID,
64
- url: current
65
- });
66
- };
67
- ```
68
-
69
- ### 3. Setup Router in Your App
70
-
71
- ```svelte
72
- <!-- App.svelte -->
73
- <script lang="ts">
74
- import { RouterComponent, Route } from './lib/router';
75
- import appRouter from './router.ts';
76
- import { routerStore } from '@finsweet/components-utils';
77
-
78
- const awaitRouter = async () => {
79
- const current = new URL(window.location.href);
80
- const appVersionID = current.pathname.split('/')[1] || 'dev-mode';
81
-
82
- // Initialize app version - this persists across all navigation
83
- appRouter.initAppVersion(`/${appVersionID}`);
84
-
85
- // Update your existing router store
86
- routerStore.set({
87
- hash: appVersionID,
88
- url: current
89
- });
90
-
91
- // Update configurator if needed
92
- configurator.update((state) => ({
93
- ...state,
94
- pathname: current.pathname,
95
- appVersionID: appVersionID
96
- }));
97
-
98
- await delay(50);
99
- };
100
-
101
- // ... rest of your init logic
102
- </script>
103
-
104
- <!-- Replace your existing Router with RouterComponent -->
105
- <RouterComponent router={appRouter}>
106
- <!-- Define routes without app version prefix -->
107
- <Route path="/" component={MyComponentsLinks} />
108
- <Route path="/finsweetbuilder" component={BuilderLinks} />
109
- <Route path="/finsweetlibrary" component={LibraryLinks} />
110
- <Route path="/finsweetlibrary-admin" component={LibraryAdminLinks} />
111
-
112
- <!-- Dynamic component routes -->
113
- {#each $finsweetComponentsList as { solution, live, key }}
114
- {#if live}
115
- <Route path="/finsweetbuilder/{key}" component={solution} />
116
- {/if}
117
- {/each}
118
- </RouterComponent>
119
- ```
120
-
121
- ### 4. Navigate with Links
122
-
123
- ```svelte
124
- <!-- LeftNavBarLinks.svelte -->
125
- <script lang="ts">
126
- import { Link, useAppVersion, useLocation } from '../lib/router';
127
-
128
- const appVersionPath = useAppVersion();
129
- const location = useLocation();
130
-
131
- // Routes are now clean without app version prefix
132
- const navLinks = [
133
- { path: '/', label: 'My Components', icon: ComponentsIcon },
134
- { path: '/finsweetbuilder', label: 'Builder', icon: BuilderIcon },
135
- { path: '/finsweetlibrary', label: 'Library', icon: FinsweetLibraryIcon }
136
- ];
137
- </script>
138
-
139
- <div class="nav-container">
140
- {#each navLinks as link}
141
- <Link to={link.path} activeClass="active" class="nav-links parent-link">
142
- <svelte:component this={link.icon} />
143
- <Text label={link.label} fontSize="normal" />
144
- </Link>
145
- {/each}
146
- </div>
147
-
148
- <style>
149
- .active {
150
- font-weight: bold;
151
- color: blue;
152
- }
153
- </style>
154
- ```
155
-
156
- ### 5. Use Router Hooks for Navigation
157
-
158
- ```svelte
159
- <!-- BackNavLink.svelte -->
160
- <script lang="ts">
161
- import { useNavigate, useAppVersion } from '../lib/router';
162
-
163
- export let fsComponent: string;
164
-
165
- const navigate = useNavigate();
166
- const appVersionPath = useAppVersion();
167
-
168
- const goBack = () => {
169
- // Navigate to builder page - app version is automatically included
170
- navigate('/finsweetbuilder');
171
-
172
- // Update your existing store if needed
173
- const appVersionID = appVersionPath.slice(1); // Remove leading slash
174
- routerStore.set({
175
- hash: appVersionID,
176
- url: new URL(`${appVersionPath}/finsweetbuilder`, window.location.origin)
177
- });
178
- };
179
- </script>
180
-
181
- <div class="nav-links-wrapper">
182
- <Section clickable onclick={goBack}>
183
- <!-- ... rest of your template -->
184
- </Section>
185
- </div>
186
- ```
187
-
188
- ## Core Concepts
189
-
190
- ### App Version Hash Support
191
-
192
- The router's key feature is maintaining app version hashes across all navigation:
193
-
194
- ```typescript
195
- // Once initialized, all routes automatically include the app version
196
- appRouter.initAppVersion('/test-app-hash');
197
-
198
- // These routes work automatically with app version:
199
- navigate('/'); // Goes to /test-app-hash/
200
- navigate('/finsweetbuilder'); // Goes to /test-app-hash/finsweetbuilder
201
- ```
202
-
203
- ### Links with App Version
204
-
205
- Links automatically include the app version prefix:
206
-
207
- ```svelte
208
- <!-- These automatically include the app version prefix -->
209
- <Link to="/">Home</Link>
210
- <!-- Renders as href="/test-app-hash/" -->
211
-
212
- <Link to="/finsweetbuilder">Builder</Link>
213
- <!-- Renders as href="/test-app-hash/finsweetbuilder" -->
214
- ```
215
-
216
- ### App Version Utility Hooks
217
-
218
- ```svelte
219
- <script lang="ts">
220
- import { useAppVersion, useFullPathname, useLocation } from './router';
221
-
222
- const appVersionPath = useAppVersion(); // Returns '/test-app-hash'
223
- const fullPathname = useFullPathname(); // Returns '/test-app-hash/users/123'
224
- const location = useLocation(); // location.pathname is clean: '/users/123'
225
- </script>
226
-
227
- <p>App Version: {appVersionPath}</p>
228
- <p>Full Path: {fullPathname}</p>
229
- <p>Clean Path: {location.pathname}</p>
230
- ```
231
-
232
- ### Working with Route Parameters
233
-
234
- ```svelte
235
- <!-- UserDetail.svelte -->
236
- <script lang="ts">
237
- import { useParams, useNavigate, useLocation } from './router';
238
-
239
- const params = useParams();
240
- const navigate = useNavigate();
241
- const location = useLocation();
242
-
243
- // Reactive access to route parameters
244
- $: userId = params.id;
245
-
246
- function goBack() {
247
- navigate('/users');
248
- }
249
- </script>
250
-
251
- <h1>User {userId}</h1>
252
- <button onclick={goBack}>Back to Users</button>
253
- <p>Current path: {location.pathname}</p>
254
- ```
255
-
256
- ### Component Modal Updates
257
-
258
- ```svelte
259
- <!-- NewComponent.svelte -->
260
- <script lang="ts">
261
- import { useNavigate } from '../lib/router';
262
-
263
- const navigate = useNavigate();
264
-
265
- const handleBuilderClick = () => {
266
- // Navigate to builder - app version automatically included
267
- navigate('/finsweetbuilder');
268
- };
269
-
270
- const handleLibraryClick = () => {
271
- // Navigate to library - app version automatically included
272
- navigate('/finsweetlibrary');
273
- };
274
- </script>
275
-
276
- <!-- Navigation calls with new navigate function -->
277
- <WebflowTooltip>
278
- <div slot="tooltip">
279
- <Section clickable on:click={handleBuilderClick}>
280
- <!-- Builder option -->
281
- </Section>
282
- <Section clickable on:click={handleLibraryClick}>
283
- <!-- Library option -->
284
- </Section>
285
- </div>
286
- </WebflowTooltip>
287
- ```
288
-
289
- ## API Reference
290
-
291
- ### Router Class
292
-
293
- ```typescript
294
- const router = createRouter({
295
- basePath: '/app', // Optional base path
296
- hashMode: false, // Use hash-based routing
297
- fallbackRoute: '/404', // Fallback for unmatched routes
298
- autoInit: true // Auto-initialize in browser
299
- });
300
-
301
- // Methods
302
- router.navigate('/path', { replace: false, state: {} });
303
- router.addRoute({ path: '/users/:id', component: UserComponent });
304
- router.addRoutes([...routes]);
305
- router.initAppVersion('/app-version'); // Set persistent app version
306
- router.isActive('/path', (exact = false));
307
- router.getParams();
308
- router.getQuery();
309
- router.back();
310
- router.forward();
311
- ```
312
-
313
- ### Hooks
314
-
315
- ```typescript
316
- // Get router instance
317
- const router = useRouter();
318
-
319
- // Reactive location information
320
- const location = useLocation();
321
-
322
- // Current route information
323
- const route = useRoute();
324
-
325
- // Route parameters
326
- const params = useParams();
327
-
328
- // Query parameters
329
- const query = useQuery();
330
-
331
- // Navigation function
332
- const navigate = useNavigate();
333
-
334
- // Check if path is active
335
- const isActive = useIsActiveRoute();
336
-
337
- // App version utilities
338
- const appVersionPath = useAppVersion();
339
- const fullPathname = useFullPathname();
340
-
341
- // Navigation state
342
- const isNavigating = useNavigating();
343
-
344
- // History tracking
345
- const history = useHistory();
346
-
347
- // Search params helper
348
- const search = useSearchParams();
349
- search.set('page', '2');
350
- search.get('page');
351
- search.delete('page');
352
- ```
353
-
354
- ### Components
355
-
356
- #### RouterComponent
357
-
358
- ```svelte
359
- <RouterComponent {router} autoInit={true}>
360
- <!-- Route components go here -->
361
- </RouterComponent>
362
- ```
363
-
364
- #### Route
365
-
366
- ```svelte
367
- <Route path="/users/:id" component={UserComponent} exact={true} meta={{ requiresAuth: true }} />
368
-
369
- <!-- Or with slot content -->
370
- <Route path="/about">
371
- <AboutPage />
372
- </Route>
373
- ```
374
-
375
- #### Link
376
-
377
- ```svelte
378
- <Link
379
- to="/users/123"
380
- activeClass="active"
381
- exact={false}
382
- replace={false}
383
- disabled={false}
384
- element="a">View User</Link
385
- >
386
- ```
387
-
388
- ## Key Benefits
389
-
390
- 1. **Persistent App Version**: Once `initAppVersion` is called, the app version hash persists across all navigation
391
- 2. **Clean Route Definitions**: Define routes without app version prefixes (`/finsweetbuilder` instead of `/{appVersionID}/finsweetbuilder`)
392
- 3. **Automatic URL Generation**: Links and navigation automatically include the app version prefix
393
- 4. **Backward Compatibility**: Works with your existing `routerStore` and other components
394
- 5. **Type Safety**: Full TypeScript support with proper typing
395
- 6. **Modern Reactivity**: Built on Svelte 5 runes for optimal performance
396
-
397
- The router handles all the app version complexity automatically while maintaining compatibility with your existing application structure and providing a modern, type-safe routing solution for Svelte 5.