intelliwaketssveltekitv25 1.0.81 → 1.0.83

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 (53) hide show
  1. package/INTEGRATION.md +574 -0
  2. package/README.md +199 -45
  3. package/dist/ArrayTable.stories.js +215 -0
  4. package/dist/ArrayTable.svelte +46 -0
  5. package/dist/ArrayTable.svelte.d.ts +44 -0
  6. package/dist/DropDown.stories.d.ts +96 -0
  7. package/dist/DropDown.stories.js +192 -0
  8. package/dist/DropDown.svelte +32 -0
  9. package/dist/DropDown.svelte.d.ts +30 -0
  10. package/dist/InputNumber.stories.d.ts +122 -0
  11. package/dist/InputNumber.stories.js +186 -0
  12. package/dist/InputNumber.svelte +52 -0
  13. package/dist/InputNumber.svelte.d.ts +27 -0
  14. package/dist/Modal.stories.d.ts +114 -0
  15. package/dist/Modal.stories.js +139 -0
  16. package/dist/Modal.svelte +34 -3
  17. package/dist/Modal.svelte.d.ts +35 -3
  18. package/dist/MultiSelect.stories.js +338 -0
  19. package/dist/MultiSelect.svelte +81 -0
  20. package/dist/MultiSelect.svelte.d.ts +38 -0
  21. package/dist/Switch.stories.d.ts +81 -0
  22. package/dist/Switch.stories.js +99 -0
  23. package/dist/Switch.svelte +40 -0
  24. package/dist/Switch.svelte.d.ts +26 -0
  25. package/dist/TextArea.stories.d.ts +180 -0
  26. package/dist/TextArea.stories.js +216 -0
  27. package/dist/TextArea.svelte +32 -0
  28. package/dist/TextArea.svelte.d.ts +24 -0
  29. package/dist/app.css +1 -1
  30. package/docs/DateRangePicker.md +272 -0
  31. package/docs/DisplayHTML.md +249 -0
  32. package/docs/DropDown.md +269 -0
  33. package/docs/Functions.md +796 -0
  34. package/docs/Home.md +109 -0
  35. package/docs/Icon.md +203 -0
  36. package/docs/Importer.md +328 -0
  37. package/docs/ImporterAnalysis.md +249 -0
  38. package/docs/ImporterLoad.md +288 -0
  39. package/docs/InputNumber.md +159 -0
  40. package/docs/Integration.md +215 -0
  41. package/docs/Modal.md +207 -0
  42. package/docs/MultiSelect.md +304 -0
  43. package/docs/Paginator.md +332 -0
  44. package/docs/Search.md +364 -0
  45. package/docs/SlideDown.md +358 -0
  46. package/docs/Svelte-5-Patterns.md +364 -0
  47. package/docs/Switch.md +107 -0
  48. package/docs/TabHeader.md +333 -0
  49. package/docs/TabHref.md +370 -0
  50. package/docs/TextArea.md +118 -0
  51. package/docs/_Sidebar.md +38 -0
  52. package/llms.txt +113 -0
  53. package/package.json +7 -2
@@ -0,0 +1,333 @@
1
+ # TabHeader Component
2
+
3
+ **Purpose:** Client-side tab navigation with animated indicator
4
+
5
+ **When to Use:**
6
+ - Switch between views without URL changes
7
+ - Local state tab management
8
+ - Modal or component-level tabs
9
+ - Conditional content display
10
+
11
+ ## Key Props
12
+
13
+ - `tabItems: ITabItem<T>[]` (required) - Array of tab definitions
14
+ - `currentKey: T | undefined` ($bindable, required) - Active tab key
15
+ - `printAllTabs?: boolean` (default: false) - Print all tabs or just active
16
+ - `rounded?: boolean` (default: false) - Rounded pill style vs underline style
17
+ - `onchange?: (key: T) => void` - Callback when tab changes
18
+
19
+ ## ITabItem Interface
20
+
21
+ ```typescript
22
+ interface ITabItem<T> {
23
+ key: T // Unique tab identifier (any type via generics)
24
+ title?: string // Display text (falls back to key if omitted)
25
+ hidden?: boolean // Hide this tab
26
+ disabled?: boolean // Disable interaction
27
+ faProps?: IFAProps // FontAwesome icon
28
+ action?: (key: T) => void // Custom action instead of tab switch
29
+ }
30
+ ```
31
+
32
+ ## Tab Styles
33
+
34
+ ### Default (Underline)
35
+ ```
36
+ ─────────────────────────
37
+ Tab 1 Tab 2 Tab 3
38
+ ══════
39
+ ```
40
+ - Animated underline indicator
41
+ - Clean, modern look
42
+ - Default style
43
+
44
+ ### Rounded
45
+ ```
46
+ ┌─────┐ ┌─────┐ ┌─────┐
47
+ │Tab 1│ │Tab 2│ │Tab 3│
48
+ └─────┘ └─────┘ └─────┘
49
+ ```
50
+ - Pill-shaped buttons
51
+ - Gray background for active tab
52
+ - Set `rounded={true}`
53
+
54
+ ## Usage Examples
55
+
56
+ ```svelte
57
+ <script>
58
+ import { TabHeader } from 'intelliwaketssveltekitv25';
59
+
60
+ let activeTab = $state<string>('overview');
61
+
62
+ const tabs = [
63
+ { key: 'overview', title: 'Overview' },
64
+ { key: 'details', title: 'Details' },
65
+ { key: 'settings', title: 'Settings' }
66
+ ];
67
+ </script>
68
+
69
+ <!-- Basic tabs -->
70
+ <TabHeader
71
+ tabItems={tabs}
72
+ bind:currentKey={activeTab}
73
+ />
74
+
75
+ {#if activeTab === 'overview'}
76
+ <Overview />
77
+ {:else if activeTab === 'details'}
78
+ <Details />
79
+ {:else if activeTab === 'settings'}
80
+ <Settings />
81
+ {/if}
82
+
83
+ <!-- With icons -->
84
+ <script>
85
+ import { faUser, faCog, faChartBar } from '@fortawesome/free-solid-svg-icons';
86
+ </script>
87
+
88
+ <TabHeader
89
+ bind:currentKey={activeTab}
90
+ tabItems={[
91
+ { key: 'profile', title: 'Profile', faProps: { icon: faUser } },
92
+ { key: 'settings', title: 'Settings', faProps: { icon: faCog } },
93
+ { key: 'analytics', title: 'Analytics', faProps: { icon: faChartBar } }
94
+ ]}
95
+ />
96
+
97
+ <!-- Rounded style -->
98
+ <TabHeader
99
+ bind:currentKey={activeTab}
100
+ tabItems={tabs}
101
+ rounded
102
+ />
103
+
104
+ <!-- With callback -->
105
+ <TabHeader
106
+ bind:currentKey={activeTab}
107
+ tabItems={tabs}
108
+ onchange={(key) => {
109
+ console.log('Tab changed to:', key);
110
+ trackTabChange(key);
111
+ }}
112
+ />
113
+
114
+ <!-- Conditional tabs -->
115
+ <script>
116
+ let isPremium = $state(true);
117
+ </script>
118
+
119
+ <TabHeader
120
+ bind:currentKey={activeTab}
121
+ tabItems={[
122
+ { key: 'basic', title: 'Basic Features' },
123
+ { key: 'premium', title: 'Premium', hidden: !isPremium },
124
+ { key: 'admin', title: 'Admin', disabled: !isAdmin }
125
+ ]}
126
+ />
127
+
128
+ <!-- Custom action (doesn't switch tabs) -->
129
+ <TabHeader
130
+ bind:currentKey={activeTab}
131
+ tabItems={[
132
+ { key: 'tab1', title: 'Tab 1' },
133
+ { key: 'tab2', title: 'Tab 2' },
134
+ {
135
+ key: 'refresh',
136
+ title: 'Refresh',
137
+ faProps: { icon: faRefresh },
138
+ action: () => refreshData()
139
+ }
140
+ ]}
141
+ />
142
+
143
+ <!-- TypeScript generics support -->
144
+ <script lang="ts">
145
+ type TabKey = 'home' | 'about' | 'contact';
146
+ let current = $state<TabKey>('home');
147
+ </script>
148
+
149
+ <TabHeader<TabKey>
150
+ bind:currentKey={current}
151
+ tabItems={[
152
+ { key: 'home', title: 'Home' },
153
+ { key: 'about', title: 'About' },
154
+ { key: 'contact', title: 'Contact' }
155
+ ]}
156
+ />
157
+ ```
158
+
159
+ ## Common Patterns
160
+
161
+ ### Modal Tabs
162
+ ```svelte
163
+ <Modal show={showModal} title="User Settings">
164
+ <TabHeader
165
+ bind:currentKey={modalTab}
166
+ tabItems={[
167
+ { key: 'general', title: 'General' },
168
+ { key: 'security', title: 'Security' },
169
+ { key: 'notifications', title: 'Notifications' }
170
+ ]}
171
+ />
172
+
173
+ <div class="mt-4">
174
+ {#if modalTab === 'general'}
175
+ <GeneralSettings />
176
+ {:else if modalTab === 'security'}
177
+ <SecuritySettings />
178
+ {:else}
179
+ <NotificationSettings />
180
+ {/if}
181
+ </div>
182
+ </Modal>
183
+ ```
184
+
185
+ ### Wizard Steps
186
+ ```svelte
187
+ <script>
188
+ let step = $state(1);
189
+ let canProceed = $derived(validateStep(step));
190
+ </script>
191
+
192
+ <TabHeader
193
+ bind:currentKey={step}
194
+ tabItems={[
195
+ { key: 1, title: 'Step 1: Info' },
196
+ { key: 2, title: 'Step 2: Details', disabled: step < 2 },
197
+ { key: 3, title: 'Step 3: Confirm', disabled: step < 3 }
198
+ ]}
199
+ />
200
+
201
+ <button
202
+ disabled={!canProceed}
203
+ onclick={() => step++}
204
+ >
205
+ Next
206
+ </button>
207
+ ```
208
+
209
+ ### Dashboard Tabs
210
+ ```svelte
211
+ <script>
212
+ let dashboardView = $state('stats');
213
+ </script>
214
+
215
+ <TabHeader
216
+ bind:currentKey={dashboardView}
217
+ tabItems={[
218
+ { key: 'stats', title: 'Statistics', faProps: { icon: faChartLine } },
219
+ { key: 'users', title: 'Users', faProps: { icon: faUsers } },
220
+ { key: 'reports', title: 'Reports', faProps: { icon: faFileAlt } }
221
+ ]}
222
+ />
223
+
224
+ {#if dashboardView === 'stats'}
225
+ <StatsPanel />
226
+ {:else if dashboardView === 'users'}
227
+ <UsersPanel />
228
+ {:else}
229
+ <ReportsPanel />
230
+ {/if}
231
+ ```
232
+
233
+ ### Numbered Tabs
234
+ ```svelte
235
+ <TabHeader
236
+ bind:currentKey={activeTab}
237
+ tabItems={[
238
+ { key: 1, title: '1. Select Items' },
239
+ { key: 2, title: '2. Configure' },
240
+ { key: 3, title: '3. Review' },
241
+ { key: 4, title: '4. Complete' }
242
+ ]}
243
+ />
244
+ ```
245
+
246
+ ## Auto-Selection Behavior
247
+
248
+ - If `currentKey` is undefined, first visible tab is selected
249
+ - If `currentKey` references hidden tab, switches to first visible
250
+ - If all tabs are hidden, `currentKey` becomes undefined
251
+
252
+ ## Print Behavior
253
+
254
+ ### Default (`printAllTabs={false}`)
255
+ - Only active tab button visible in print
256
+ - Inactive tabs hidden
257
+
258
+ ### With `printAllTabs={true}`
259
+ - All tab buttons visible in print
260
+ - Active tab still highlighted
261
+
262
+ ## Animated Indicator
263
+
264
+ The component includes a smooth animated indicator:
265
+ - Slides to active tab position
266
+ - 300ms transition with easing
267
+ - Calculates position based on button width/position
268
+ - Border-bottom indicator (2px)
269
+ - Uses `primary-selected` color
270
+
271
+ ## Common Mistakes
272
+
273
+ - ❌ Not using `bind:currentKey` for two-way binding
274
+ ✅ Correct: `bind:currentKey={activeTab}`
275
+
276
+ - ❌ Forgetting to handle tab content switching
277
+ ✅ Correct: Use `{#if currentKey === 'tab1'}` to show/hide content
278
+
279
+ - ❌ Using same key for multiple tabs
280
+ ✅ Correct: Each tab must have unique key
281
+
282
+ - ❌ Not providing title (shows key instead)
283
+ ✅ Correct: Set `title` property for display text
284
+
285
+ - ❌ Using TabHeader when TabHref is more appropriate
286
+ ✅ Correct: Use TabHref for URL-based navigation
287
+
288
+ ## Comparison: TabHeader vs TabHref
289
+
290
+ | Feature | TabHeader | TabHref |
291
+ |---------|-----------|---------|
292
+ | Navigation | Local state | URL-based |
293
+ | Persistence | Session only | URL shareable |
294
+ | Use case | Modal, components | Page navigation |
295
+ | Browser back | No effect | Works naturally |
296
+ | Performance | Instant | Page load |
297
+
298
+ ## Related Components
299
+
300
+ - **TabHref** - URL-based tab navigation
301
+ - **Icon** - Used for tab icons
302
+ - **ITabItem** - Tab configuration interface
303
+
304
+ ## Props Reference
305
+
306
+ | Prop | Type | Default | Description |
307
+ |------|------|---------|-------------|
308
+ | `tabItems` | `ITabItem<T>[]` | (required) | Tab definitions |
309
+ | `currentKey` | `T \| undefined` | (required) | Active tab ($bindable) |
310
+ | `printAllTabs` | `boolean` | `false` | Show all tabs in print |
311
+ | `rounded` | `boolean` | `false` | Pill style vs underline |
312
+ | `onchange` | `(key: T) => void` | - | Tab change callback |
313
+
314
+ ## Styling
315
+
316
+ ### Default Style
317
+ - Border bottom: `border-b-2 border-b-slate-200`
318
+ - Active: `border-b-primary-selected`
319
+ - Text: Black for active, `text-slate-600` for inactive
320
+ - Indicator: Animated border-bottom
321
+
322
+ ### Rounded Style
323
+ - Background: `bg-gray-200` for active
324
+ - Text: `text-gray-900 font-semibold` for active
325
+ - Padding: `px-2.5`
326
+ - Rounded: `rounded-md`
327
+
328
+ ## Accessibility
329
+
330
+ - Keyboard navigable (standard button behavior)
331
+ - Visual indicator for active state
332
+ - Disabled state prevents interaction
333
+ - Print-friendly with visibility controls
@@ -0,0 +1,370 @@
1
+ # TabHref Component
2
+
3
+ **Purpose:** URL-based tab navigation with SvelteKit routing and session/local storage persistence
4
+
5
+ **When to Use:**
6
+ - Page-level tab navigation with URL sync
7
+ - Shareable tab states via URL
8
+ - Persistent tab selection across page refreshes
9
+ - Master-detail layouts with sub-navigation
10
+
11
+ ## Key Props
12
+
13
+ - `tabHrefs: ITabHref[]` (required) - Array of tab definitions
14
+ - `basePath?: string` - Base path for tab navigation (optional)
15
+ - `slug?: string | null` ($bindable) - Current tab slug
16
+ - `storage?: 'local' | 'session' | null` (default: 'session') - Persistence method
17
+ - `saveKey?: string | null` - Custom storage key
18
+ - `noIDRemember?: boolean` (default: false) - Disable ID persistence
19
+ - `noTabAdjustments?: boolean` (default: false) - Skip 'Tab' prefix in URLs
20
+ - `reclickToClose?: boolean` (default: false) - Allow closing active tab
21
+ - `bottomMargin?: boolean` (default: true) - Add bottom margin
22
+ - `consoleLogs?: boolean` (default: false) - Enable debug logging
23
+ - `noResolveHidden?: boolean` (default: false) - Don't auto-redirect from hidden tabs
24
+ - `printAllTabs?: boolean` (default: false) - Print all tabs or just active
25
+ - `rounded?: boolean` (default: false) - Rounded pill style
26
+
27
+ ## ITabHref Interface
28
+
29
+ ```typescript
30
+ interface ITabHref {
31
+ key: string // Tab identifier
32
+ title?: string // Display text (falls back to key)
33
+ href?: string // Custom URL (overrides default)
34
+ hidden?: boolean // Hide this tab
35
+ disabled?: boolean // Disable interaction
36
+ isInitial?: boolean // Default tab when none selected
37
+ isOpen?: boolean // Manually control open state
38
+ faProps?: IFAProps // FontAwesome icon
39
+ dataSvelteKitPreloadData?: string // Preload strategy
40
+ }
41
+ ```
42
+
43
+ ## Key Features
44
+
45
+ ### URL Integration
46
+ - Automatically generates tab URLs: `{basePath}/Tab{key}`
47
+ - Custom hrefs override default URL generation
48
+ - Works with SvelteKit's `goto()` and preloading
49
+ - Clean URLs (removes trailing slashes)
50
+
51
+ ### Persistence
52
+ - **Session Storage** (default): Persists within browser session
53
+ - **Local Storage**: Persists across browser sessions
54
+ - **None**: No persistence
55
+ - Remembers last tab per base path
56
+ - Optional ID-based memory (e.g., /Users/123 remembers tab separately from /Users/456)
57
+
58
+ ### PathAnalyzer Integration
59
+ Uses `PathAnalyzer` utility for:
60
+ - Route parsing and navigation
61
+ - Predecessor/successor patterns (`~/`)
62
+ - Active state detection
63
+ - Dynamic URL generation
64
+
65
+ ## Usage Examples
66
+
67
+ ```svelte
68
+ <script>
69
+ import { TabHref } from 'intelliwaketssveltekitv25';
70
+ import { faUser, faCog, faChartBar } from '@fortawesome/free-solid-svg-icons';
71
+
72
+ const tabs = [
73
+ { key: 'Profile', faProps: { icon: faUser } },
74
+ { key: 'Settings', faProps: { icon: faCog } },
75
+ { key: 'Analytics', faProps: { icon: faChartBar } }
76
+ ];
77
+ </script>
78
+
79
+ <!-- Basic usage -->
80
+ <TabHref
81
+ tabHrefs={tabs}
82
+ basePath="Dashboard"
83
+ />
84
+ <!-- Generates: /Dashboard/TabProfile, /Dashboard/TabSettings, /Dashboard/TabAnalytics -->
85
+
86
+ <!-- Custom hrefs -->
87
+ <TabHref
88
+ tabHrefs={[
89
+ { key: 'Overview', href: '/dashboard' },
90
+ { key: 'Details', href: '/dashboard/details' },
91
+ { key: 'History', href: '/dashboard/history' }
92
+ ]}
93
+ basePath="Dashboard"
94
+ />
95
+
96
+ <!-- With initial tab -->
97
+ <TabHref
98
+ tabHrefs={[
99
+ { key: 'Info', isInitial: true },
100
+ { key: 'Details' },
101
+ { key: 'Settings' }
102
+ ]}
103
+ basePath="Product"
104
+ />
105
+ <!-- If no tab in URL, redirects to /Product/TabInfo -->
106
+
107
+ <!-- Local storage persistence -->
108
+ <TabHref
109
+ tabHrefs={tabs}
110
+ basePath="Settings"
111
+ storage="local"
112
+ />
113
+ <!-- Persists across browser sessions -->
114
+
115
+ <!-- No persistence -->
116
+ <TabHref
117
+ tabHrefs={tabs}
118
+ basePath="Wizard"
119
+ storage={null}
120
+ />
121
+
122
+ <!-- Custom save key -->
123
+ <TabHref
124
+ tabHrefs={tabs}
125
+ basePath="Users"
126
+ saveKey="userDetailTabs"
127
+ />
128
+
129
+ <!-- Rounded style -->
130
+ <TabHref
131
+ tabHrefs={tabs}
132
+ basePath="Profile"
133
+ rounded
134
+ />
135
+
136
+ <!-- Without Tab prefix in URLs -->
137
+ <TabHref
138
+ tabHrefs={tabs}
139
+ basePath="Admin"
140
+ noTabAdjustments
141
+ />
142
+ <!-- Generates: /Admin/Profile, /Admin/Settings (no "Tab" prefix) -->
143
+
144
+ <!-- Bind to slug -->
145
+ <script>
146
+ let currentSlug = $state<string | null>(null);
147
+ </script>
148
+
149
+ <TabHref
150
+ tabHrefs={tabs}
151
+ basePath="Dashboard"
152
+ bind:slug={currentSlug}
153
+ />
154
+ <div>Current tab: {currentSlug}</div>
155
+
156
+ <!-- Debug mode -->
157
+ <TabHref
158
+ tabHrefs={tabs}
159
+ basePath="Debug"
160
+ consoleLogs
161
+ />
162
+ ```
163
+
164
+ ## Common Patterns
165
+
166
+ ### User Profile Tabs
167
+ ```svelte
168
+ <!-- src/routes/Users/User[user_id=integer]/+page.svelte -->
169
+ <script>
170
+ export let data;
171
+ </script>
172
+
173
+ <h1>{data.user.name}</h1>
174
+
175
+ <TabHref
176
+ tabHrefs={[
177
+ { key: 'Info', faProps: { icon: faUser } },
178
+ { key: 'Activity', faProps: { icon: faChartLine } },
179
+ { key: 'Settings', faProps: { icon: faCog } }
180
+ ]}
181
+ basePath="Users/User{data.user.id}"
182
+ storage="session"
183
+ />
184
+ <!-- URLs: /Users/User123/TabInfo, /Users/User123/TabActivity, etc. -->
185
+ ```
186
+
187
+ ### Master-Detail Layout
188
+ ```svelte
189
+ <MasterDetailLayout basePath="Products">
190
+ {#snippet list()}
191
+ {#each products as product}
192
+ <ProductCard {product} />
193
+ {/each}
194
+ {/snippet}
195
+
196
+ {#snippet detail()}
197
+ <TabHref
198
+ tabHrefs={[
199
+ { key: 'Overview', isInitial: true },
200
+ { key: 'Specs' },
201
+ { key: 'Reviews' }
202
+ ]}
203
+ basePath="Products/Product{selectedId}"
204
+ />
205
+ {/snippet}
206
+ </MasterDetailLayout>
207
+ ```
208
+
209
+ ### Conditional Tabs
210
+ ```svelte
211
+ <script>
212
+ let isAdmin = $state(false);
213
+ </script>
214
+
215
+ <TabHref
216
+ tabHrefs={[
217
+ { key: 'Public', title: 'Public Info' },
218
+ { key: 'Private', title: 'Private Info', hidden: !isAdmin },
219
+ { key: 'Admin', title: 'Admin Panel', hidden: !isAdmin }
220
+ ]}
221
+ basePath="Dashboard"
222
+ />
223
+ ```
224
+
225
+ ### Nested Routes
226
+ ```svelte
227
+ <!-- Parent: /Settings -->
228
+ <TabHref
229
+ tabHrefs={[
230
+ { key: 'Profile' },
231
+ { key: 'Security' },
232
+ { key: 'Billing' }
233
+ ]}
234
+ basePath="Settings"
235
+ />
236
+
237
+ <!-- Each tab can have its own route file: -->
238
+ <!-- src/routes/Settings/TabProfile/+page.svelte -->
239
+ <!-- src/routes/Settings/TabSecurity/+page.svelte -->
240
+ <!-- src/routes/Settings/TabBilling/+page.svelte -->
241
+ ```
242
+
243
+ ## Persistence Behavior
244
+
245
+ ### Session Storage (Default)
246
+ ```
247
+ Key: Tab{basePath}
248
+ Example: "TabDashboard" → "TabProfile"
249
+ Lifetime: Until tab/window closed
250
+ ```
251
+
252
+ ### Local Storage
253
+ ```
254
+ Key: Tab{basePath}
255
+ Example: "TabSettings" → "TabSecurity"
256
+ Lifetime: Permanent (until cleared)
257
+ ```
258
+
259
+ ### ID Memory (noIDRemember=false)
260
+ ```
261
+ Key: IDTab{basePath}
262
+ Example: "IDTabUsers/User" → "123"
263
+ Remembers: Which user ID you were viewing
264
+ Use case: Return to last viewed user on page revisit
265
+ ```
266
+
267
+ ## URL Generation
268
+
269
+ ### Default (with Tab prefix)
270
+ ```
271
+ basePath="Dashboard"
272
+ key="Profile"
273
+ → /Dashboard/TabProfile
274
+ ```
275
+
276
+ ### Without Tab prefix (noTabAdjustments=true)
277
+ ```
278
+ basePath="Admin"
279
+ key="Users"
280
+ → /Admin/Users
281
+ ```
282
+
283
+ ### Custom href
284
+ ```
285
+ basePath="Reports"
286
+ key="Sales"
287
+ href="/reports/sales-summary"
288
+ → /reports/sales-summary
289
+ ```
290
+
291
+ ## Auto-Redirect Behavior
292
+
293
+ When landing on base path without tab slug:
294
+ 1. Check session/local storage for last tab
295
+ 2. Use tab with `isInitial: true`
296
+ 3. Fall back to first visible tab
297
+ 4. Redirect using `replaceState` (no history entry)
298
+
299
+ ## Common Mistakes
300
+
301
+ - ❌ Not matching route structure to tab paths
302
+ ✅ Correct: Ensure route files match generated URLs
303
+
304
+ - ❌ Using TabHref for local state tabs
305
+ ✅ Correct: Use TabHeader for non-URL tabs
306
+
307
+ - ❌ Not providing basePath correctly
308
+ ✅ Correct: Match your SvelteKit route structure
309
+
310
+ - ❌ Conflicting saveKey across different tab sets
311
+ ✅ Correct: Use unique saveKey for each TabHref instance
312
+
313
+ - ❌ Expecting immediate tab switch (it uses goto)
314
+ ✅ Correct: Navigation is async, uses SvelteKit routing
315
+
316
+ ## Comparison: TabHref vs TabHeader
317
+
318
+ | Feature | TabHref | TabHeader |
319
+ |---------|---------|-----------|
320
+ | Navigation | URL-based | State-based |
321
+ | Shareable | ✅ Yes | ❌ No |
322
+ | Browser back | ✅ Works | ❌ No effect |
323
+ | Persistence | Storage + URL | Session only |
324
+ | Speed | Page load | Instant |
325
+ | Use case | Pages | Components |
326
+
327
+ ## Related Components
328
+
329
+ - **TabHeader** - Local state tab navigation
330
+ - **PathAnalyzer** - URL parsing utility
331
+ - **MasterDetailLayout** - Common container
332
+ - **Icon** - Tab icons
333
+
334
+ ## Props Reference
335
+
336
+ | Prop | Type | Default | Description |
337
+ |------|------|---------|-------------|
338
+ | `tabHrefs` | `ITabHref[]` | (required) | Tab definitions |
339
+ | `basePath` | `string` | - | Base route path |
340
+ | `slug` | `string \| null` | `null` | Current tab slug ($bindable) |
341
+ | `storage` | `'local' \| 'session' \| null` | `'session'` | Persistence method |
342
+ | `saveKey` | `string \| null` | `null` | Custom storage key |
343
+ | `noIDRemember` | `boolean` | `false` | Disable ID persistence |
344
+ | `noTabAdjustments` | `boolean` | `false` | Skip 'Tab' prefix |
345
+ | `reclickToClose` | `boolean` | `false` | Allow closing active |
346
+ | `bottomMargin` | `boolean` | `true` | Add margin-bottom |
347
+ | `consoleLogs` | `boolean` | `false` | Debug logging |
348
+ | `noResolveHidden` | `boolean` | `false` | Skip hidden redirect |
349
+ | `printAllTabs` | `boolean` | `false` | Print behavior |
350
+ | `rounded` | `boolean` | `false` | Rounded style |
351
+
352
+ ## Styling
353
+
354
+ Same as TabHeader:
355
+ - Underline style (default)
356
+ - Rounded pill style (rounded=true)
357
+ - Animated indicator
358
+ - `primary-selected` color for active state
359
+
360
+ ## Advanced: PathAnalyzer
361
+
362
+ The component uses PathAnalyzer for navigation:
363
+ ```typescript
364
+ const analyzer = new PathAnalyzer(page, basePath);
365
+ analyzer.open('TabProfile') // Generate URL
366
+ analyzer.activePageSlug // Current tab slug
367
+ analyzer.isOpen('TabProfile') // Check if active
368
+ ```
369
+
370
+ See PathAnalyzer utility documentation for advanced usage.