@mdxui/terminal 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/README.md +571 -0
  2. package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
  3. package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
  4. package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
  5. package/dist/chunk-3EFDH7PK.js +5235 -0
  6. package/dist/chunk-3RG5ZIWI.js +10 -0
  7. package/dist/chunk-3X5IR6WE.js +884 -0
  8. package/dist/chunk-4FV5ZDCE.js +5236 -0
  9. package/dist/chunk-4OVMSF2J.js +243 -0
  10. package/dist/chunk-63FEETIS.js +4048 -0
  11. package/dist/chunk-B43KP7XJ.js +884 -0
  12. package/dist/chunk-BMTJXWUV.js +655 -0
  13. package/dist/chunk-C3SVH4N7.js +882 -0
  14. package/dist/chunk-EVWR7Y47.js +874 -0
  15. package/dist/chunk-F6A5VWUC.js +1285 -0
  16. package/dist/chunk-FD7KW7GE.js +882 -0
  17. package/dist/chunk-GBQ6UD6I.js +655 -0
  18. package/dist/chunk-GMDD3M6U.js +5227 -0
  19. package/dist/chunk-JBHRXOXM.js +1058 -0
  20. package/dist/chunk-JFOO3EYO.js +1182 -0
  21. package/dist/chunk-JQ5H3WXL.js +1291 -0
  22. package/dist/chunk-JQD5NASE.js +234 -0
  23. package/dist/chunk-KRHJP5R7.js +592 -0
  24. package/dist/chunk-KWF6WVJE.js +962 -0
  25. package/dist/chunk-LHYQVN3H.js +1038 -0
  26. package/dist/chunk-M3TLQLGC.js +1032 -0
  27. package/dist/chunk-MVW4Q5OP.js +240 -0
  28. package/dist/chunk-NXCZSWLU.js +1294 -0
  29. package/dist/chunk-O25TNRO6.js +607 -0
  30. package/dist/chunk-PNECDA2I.js +884 -0
  31. package/dist/chunk-QIHWRLJR.js +962 -0
  32. package/dist/chunk-QW5YMQ7K.js +882 -0
  33. package/dist/chunk-R5U7XKVJ.js +16 -0
  34. package/dist/chunk-RP2MVQLR.js +962 -0
  35. package/dist/chunk-TP6RXGXA.js +1087 -0
  36. package/dist/chunk-TQQSTITZ.js +655 -0
  37. package/dist/chunk-X24GWXQV.js +1281 -0
  38. package/dist/components/index.d.ts +802 -0
  39. package/dist/components/index.js +149 -0
  40. package/dist/data/index.d.ts +2554 -0
  41. package/dist/data/index.js +51 -0
  42. package/dist/forms/index.d.ts +1596 -0
  43. package/dist/forms/index.js +464 -0
  44. package/dist/index-CQRFZntR.d.ts +867 -0
  45. package/dist/index.d.ts +579 -0
  46. package/dist/index.js +786 -0
  47. package/dist/interactive-D0JkWosD.d.ts +217 -0
  48. package/dist/keyboard/index.d.ts +2 -0
  49. package/dist/keyboard/index.js +43 -0
  50. package/dist/renderers/index.d.ts +546 -0
  51. package/dist/renderers/index.js +2157 -0
  52. package/dist/storybook/index.d.ts +396 -0
  53. package/dist/storybook/index.js +641 -0
  54. package/dist/theme/index.d.ts +1339 -0
  55. package/dist/theme/index.js +123 -0
  56. package/dist/types-Bxu5PAgA.d.ts +710 -0
  57. package/dist/types-CIlop5Ji.d.ts +701 -0
  58. package/dist/types-Ca8p_p5X.d.ts +710 -0
  59. package/package.json +90 -0
  60. package/src/__tests__/components/data/card.test.ts +458 -0
  61. package/src/__tests__/components/data/list.test.ts +473 -0
  62. package/src/__tests__/components/data/metrics.test.ts +541 -0
  63. package/src/__tests__/components/data/table.test.ts +448 -0
  64. package/src/__tests__/components/input/field.test.ts +555 -0
  65. package/src/__tests__/components/input/form.test.ts +870 -0
  66. package/src/__tests__/components/input/search.test.ts +1238 -0
  67. package/src/__tests__/components/input/select.test.ts +658 -0
  68. package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
  69. package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
  70. package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
  71. package/src/__tests__/components/navigation/tabs.test.ts +995 -0
  72. package/src/__tests__/components.test.tsx +1197 -0
  73. package/src/__tests__/core/compiler.test.ts +986 -0
  74. package/src/__tests__/core/parser.test.ts +785 -0
  75. package/src/__tests__/core/tier-switcher.test.ts +1103 -0
  76. package/src/__tests__/core/types.test.ts +1398 -0
  77. package/src/__tests__/data/collections.test.ts +1337 -0
  78. package/src/__tests__/data/db.test.ts +1265 -0
  79. package/src/__tests__/data/reactive.test.ts +1010 -0
  80. package/src/__tests__/data/sync.test.ts +1614 -0
  81. package/src/__tests__/errors.test.ts +660 -0
  82. package/src/__tests__/forms/integration.test.ts +444 -0
  83. package/src/__tests__/integration.test.ts +905 -0
  84. package/src/__tests__/keyboard.test.ts +1791 -0
  85. package/src/__tests__/renderer.test.ts +489 -0
  86. package/src/__tests__/renderers/ansi-css.test.ts +948 -0
  87. package/src/__tests__/renderers/ansi.test.ts +1366 -0
  88. package/src/__tests__/renderers/ascii.test.ts +1360 -0
  89. package/src/__tests__/renderers/interactive.test.ts +2353 -0
  90. package/src/__tests__/renderers/markdown.test.ts +1483 -0
  91. package/src/__tests__/renderers/text.test.ts +1369 -0
  92. package/src/__tests__/renderers/unicode.test.ts +1307 -0
  93. package/src/__tests__/theme.test.ts +639 -0
  94. package/src/__tests__/utils/assertions.ts +685 -0
  95. package/src/__tests__/utils/index.ts +115 -0
  96. package/src/__tests__/utils/test-renderer.ts +381 -0
  97. package/src/__tests__/utils/utils.test.ts +560 -0
  98. package/src/components/containers/card.ts +56 -0
  99. package/src/components/containers/dialog.ts +53 -0
  100. package/src/components/containers/index.ts +9 -0
  101. package/src/components/containers/panel.ts +59 -0
  102. package/src/components/feedback/badge.ts +40 -0
  103. package/src/components/feedback/index.ts +8 -0
  104. package/src/components/feedback/spinner.ts +23 -0
  105. package/src/components/helpers.ts +81 -0
  106. package/src/components/index.ts +153 -0
  107. package/src/components/layout/breadcrumb.ts +31 -0
  108. package/src/components/layout/index.ts +10 -0
  109. package/src/components/layout/list.ts +29 -0
  110. package/src/components/layout/sidebar.ts +79 -0
  111. package/src/components/layout/table.ts +62 -0
  112. package/src/components/primitives/box.ts +95 -0
  113. package/src/components/primitives/button.ts +54 -0
  114. package/src/components/primitives/index.ts +11 -0
  115. package/src/components/primitives/input.ts +88 -0
  116. package/src/components/primitives/select.ts +97 -0
  117. package/src/components/primitives/text.ts +60 -0
  118. package/src/components/render.ts +155 -0
  119. package/src/components/templates/app.ts +43 -0
  120. package/src/components/templates/index.ts +8 -0
  121. package/src/components/templates/site.ts +54 -0
  122. package/src/components/types.ts +777 -0
  123. package/src/core/compiler.ts +718 -0
  124. package/src/core/parser.ts +127 -0
  125. package/src/core/tier-switcher.ts +607 -0
  126. package/src/core/types.ts +672 -0
  127. package/src/data/collection.ts +316 -0
  128. package/src/data/collections.ts +50 -0
  129. package/src/data/context.tsx +174 -0
  130. package/src/data/db.ts +127 -0
  131. package/src/data/hooks.ts +532 -0
  132. package/src/data/index.ts +138 -0
  133. package/src/data/reactive.ts +1225 -0
  134. package/src/data/saas-collections.ts +375 -0
  135. package/src/data/sync.ts +1213 -0
  136. package/src/data/types.ts +660 -0
  137. package/src/forms/converters.ts +512 -0
  138. package/src/forms/index.ts +133 -0
  139. package/src/forms/schemas.ts +403 -0
  140. package/src/forms/types.ts +476 -0
  141. package/src/index.ts +542 -0
  142. package/src/keyboard/focus.ts +748 -0
  143. package/src/keyboard/index.ts +96 -0
  144. package/src/keyboard/integration.ts +371 -0
  145. package/src/keyboard/manager.ts +377 -0
  146. package/src/keyboard/presets.ts +90 -0
  147. package/src/renderers/ansi-css.ts +576 -0
  148. package/src/renderers/ansi.ts +802 -0
  149. package/src/renderers/ascii.ts +680 -0
  150. package/src/renderers/breadcrumb.ts +480 -0
  151. package/src/renderers/command-palette.ts +802 -0
  152. package/src/renderers/components/field.ts +210 -0
  153. package/src/renderers/components/form.ts +327 -0
  154. package/src/renderers/components/index.ts +21 -0
  155. package/src/renderers/components/search.ts +449 -0
  156. package/src/renderers/components/select.ts +222 -0
  157. package/src/renderers/index.ts +101 -0
  158. package/src/renderers/interactive/component-handlers.ts +622 -0
  159. package/src/renderers/interactive/cursor-manager.ts +147 -0
  160. package/src/renderers/interactive/focus-manager.ts +279 -0
  161. package/src/renderers/interactive/index.ts +661 -0
  162. package/src/renderers/interactive/input-handler.ts +164 -0
  163. package/src/renderers/interactive/keyboard-handler.ts +212 -0
  164. package/src/renderers/interactive/mouse-handler.ts +167 -0
  165. package/src/renderers/interactive/state-manager.ts +109 -0
  166. package/src/renderers/interactive/types.ts +338 -0
  167. package/src/renderers/interactive-string.ts +299 -0
  168. package/src/renderers/interactive.ts +59 -0
  169. package/src/renderers/markdown.ts +950 -0
  170. package/src/renderers/sidebar.ts +549 -0
  171. package/src/renderers/tabs.ts +682 -0
  172. package/src/renderers/text.ts +791 -0
  173. package/src/renderers/unicode.ts +917 -0
  174. package/src/renderers/utils.ts +942 -0
  175. package/src/router/adapters.ts +383 -0
  176. package/src/router/types.ts +140 -0
  177. package/src/router/utils.ts +452 -0
  178. package/src/schemas.ts +205 -0
  179. package/src/storybook/index.ts +91 -0
  180. package/src/storybook/interactive-decorator.tsx +659 -0
  181. package/src/storybook/keyboard-simulator.ts +501 -0
  182. package/src/theme/ansi-codes.ts +80 -0
  183. package/src/theme/box-drawing.ts +132 -0
  184. package/src/theme/color-convert.ts +254 -0
  185. package/src/theme/color-support.ts +321 -0
  186. package/src/theme/index.ts +134 -0
  187. package/src/theme/strip-ansi.ts +50 -0
  188. package/src/theme/tailwind-map.ts +469 -0
  189. package/src/theme/text-styles.ts +206 -0
  190. package/src/theme/theme-system.ts +568 -0
  191. package/src/types.ts +103 -0
@@ -0,0 +1,383 @@
1
+ /**
2
+ * @mdxui/terminal Router Adapters
3
+ *
4
+ * Pre-built router adapters for common routing libraries and patterns.
5
+ */
6
+
7
+ import type {
8
+ RouterAdapter,
9
+ RouteMatchMode,
10
+ RouterConfig,
11
+ MemoryRouterState,
12
+ HistoryEntry,
13
+ } from './types'
14
+ import { matchPath, normalizePath } from './utils'
15
+
16
+ /**
17
+ * Creates a callback-based router adapter.
18
+ * Use when you want to handle navigation with custom callbacks.
19
+ *
20
+ * @param config - Configuration with callbacks
21
+ * @returns RouterAdapter instance
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const [currentPath, setCurrentPath] = useState('/')
26
+ *
27
+ * const router = createCallbackRouterAdapter({
28
+ * currentPath,
29
+ * onNavigate: setCurrentPath,
30
+ * })
31
+ * ```
32
+ */
33
+ export function createCallbackRouterAdapter(config: {
34
+ currentPath?: string
35
+ onNavigate?: (path: string) => void
36
+ onReplace?: (path: string) => void
37
+ }): RouterAdapter {
38
+ return {
39
+ getCurrentPath: () => config.currentPath || '/',
40
+ navigate: (path: string) => config.onNavigate?.(path),
41
+ replace: (path: string) => (config.onReplace || config.onNavigate)?.(path),
42
+ isActive: (path: string, mode: RouteMatchMode = 'exact') => {
43
+ const current = config.currentPath || '/'
44
+ return matchPath(current, path, mode)
45
+ },
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Creates an in-memory router adapter with full history support.
51
+ * Useful for testing, CLI applications, and server-side rendering.
52
+ *
53
+ * @param config - Router configuration
54
+ * @returns RouterAdapter with additional memory router methods
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const router = createMemoryRouterAdapter({ initialPath: '/home' })
59
+ *
60
+ * router.navigate('/products')
61
+ * router.back() // Returns to /home
62
+ *
63
+ * const unsubscribe = router.subscribe?.((path) => {
64
+ * console.log('Navigated to:', path)
65
+ * })
66
+ * ```
67
+ */
68
+ export function createMemoryRouterAdapter(config?: RouterConfig): RouterAdapter & {
69
+ getState(): MemoryRouterState
70
+ getHistory(): HistoryEntry[]
71
+ reset(path?: string): void
72
+ } {
73
+ const state: MemoryRouterState = {
74
+ entries: [{
75
+ path: normalizePath(config?.initialPath || '/'),
76
+ timestamp: Date.now(),
77
+ }],
78
+ index: 0,
79
+ listeners: new Set(),
80
+ }
81
+
82
+ const basePath = config?.basePath || ''
83
+ const defaultMode = config?.defaultMatchMode || 'exact'
84
+
85
+ function notifyListeners() {
86
+ const currentPath = state.entries[state.index]?.path || '/'
87
+ state.listeners.forEach(listener => listener(currentPath))
88
+ }
89
+
90
+ function resolvePath(path: string): string {
91
+ if (basePath && !path.startsWith(basePath)) {
92
+ return normalizePath(basePath + path)
93
+ }
94
+ return normalizePath(path)
95
+ }
96
+
97
+ return {
98
+ getCurrentPath: () => state.entries[state.index]?.path || '/',
99
+
100
+ navigate: (path: string) => {
101
+ const resolved = resolvePath(path)
102
+ // Truncate forward history when navigating from a point in history
103
+ state.entries = state.entries.slice(0, state.index + 1)
104
+ state.entries.push({ path: resolved, timestamp: Date.now() })
105
+ state.index = state.entries.length - 1
106
+ notifyListeners()
107
+ },
108
+
109
+ replace: (path: string) => {
110
+ const resolved = resolvePath(path)
111
+ state.entries[state.index] = { path: resolved, timestamp: Date.now() }
112
+ notifyListeners()
113
+ },
114
+
115
+ isActive: (path: string, mode: RouteMatchMode = defaultMode) => {
116
+ const current = state.entries[state.index]?.path || '/'
117
+ return matchPath(current, resolvePath(path), mode)
118
+ },
119
+
120
+ subscribe: (callback: (path: string) => void) => {
121
+ state.listeners.add(callback)
122
+ return () => {
123
+ state.listeners.delete(callback)
124
+ }
125
+ },
126
+
127
+ back: () => {
128
+ if (state.index > 0) {
129
+ state.index--
130
+ notifyListeners()
131
+ }
132
+ },
133
+
134
+ forward: () => {
135
+ if (state.index < state.entries.length - 1) {
136
+ state.index++
137
+ notifyListeners()
138
+ }
139
+ },
140
+
141
+ getParams: () => ({}), // Would need route patterns to extract params
142
+
143
+ getQuery: () => {
144
+ const current = state.entries[state.index]?.path || '/'
145
+ const queryStart = current.indexOf('?')
146
+ if (queryStart === -1) return {}
147
+
148
+ const queryString = current.slice(queryStart + 1)
149
+ const params: Record<string, string> = {}
150
+ for (const pair of queryString.split('&')) {
151
+ const [key, value] = pair.split('=')
152
+ if (key) {
153
+ params[decodeURIComponent(key)] = decodeURIComponent(value || '')
154
+ }
155
+ }
156
+ return params
157
+ },
158
+
159
+ // Memory router specific methods
160
+ getState: () => ({ ...state, listeners: new Set(state.listeners) }),
161
+ getHistory: () => [...state.entries],
162
+ reset: (path?: string) => {
163
+ state.entries = [{
164
+ path: normalizePath(path || config?.initialPath || '/'),
165
+ timestamp: Date.now(),
166
+ }]
167
+ state.index = 0
168
+ notifyListeners()
169
+ },
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Creates a URL-sync router adapter that syncs with browser URL.
175
+ * Falls back to in-memory routing when window is not available.
176
+ *
177
+ * @param config - Router configuration
178
+ * @returns RouterAdapter that syncs with browser URL
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const router = createUrlSyncRouterAdapter({
183
+ * basePath: '/app',
184
+ * })
185
+ *
186
+ * // Navigating updates browser URL
187
+ * router.navigate('/dashboard')
188
+ * // URL becomes: /app/dashboard
189
+ * ```
190
+ */
191
+ export function createUrlSyncRouterAdapter(config?: RouterConfig): RouterAdapter {
192
+ // Check if we're in a browser environment
193
+ const isBrowser = typeof window !== 'undefined' && typeof window.history !== 'undefined'
194
+
195
+ if (!isBrowser) {
196
+ // Fall back to memory router in non-browser environments
197
+ return createMemoryRouterAdapter(config)
198
+ }
199
+
200
+ const basePath = config?.basePath || ''
201
+ const defaultMode = config?.defaultMatchMode || 'exact'
202
+ const listeners = new Set<(path: string) => void>()
203
+
204
+ function getCurrentPath(): string {
205
+ const path = window.location.pathname
206
+ if (basePath && path.startsWith(basePath)) {
207
+ return normalizePath(path.slice(basePath.length) || '/')
208
+ }
209
+ return normalizePath(path)
210
+ }
211
+
212
+ function resolvePath(path: string): string {
213
+ if (basePath) {
214
+ return basePath + normalizePath(path)
215
+ }
216
+ return normalizePath(path)
217
+ }
218
+
219
+ // Listen for popstate events (back/forward)
220
+ if (isBrowser) {
221
+ window.addEventListener('popstate', () => {
222
+ const path = getCurrentPath()
223
+ listeners.forEach(listener => listener(path))
224
+ })
225
+ }
226
+
227
+ return {
228
+ getCurrentPath,
229
+
230
+ navigate: (path: string) => {
231
+ const resolved = resolvePath(path)
232
+ window.history.pushState(null, '', resolved)
233
+ listeners.forEach(listener => listener(normalizePath(path)))
234
+ },
235
+
236
+ replace: (path: string) => {
237
+ const resolved = resolvePath(path)
238
+ window.history.replaceState(null, '', resolved)
239
+ listeners.forEach(listener => listener(normalizePath(path)))
240
+ },
241
+
242
+ isActive: (path: string, mode: RouteMatchMode = defaultMode) => {
243
+ return matchPath(getCurrentPath(), path, mode)
244
+ },
245
+
246
+ subscribe: (callback: (path: string) => void) => {
247
+ listeners.add(callback)
248
+ return () => {
249
+ listeners.delete(callback)
250
+ }
251
+ },
252
+
253
+ back: () => {
254
+ window.history.back()
255
+ },
256
+
257
+ forward: () => {
258
+ window.history.forward()
259
+ },
260
+
261
+ getParams: () => ({}),
262
+
263
+ getQuery: () => {
264
+ const params: Record<string, string> = {}
265
+ const searchParams = new URLSearchParams(window.location.search)
266
+ searchParams.forEach((value, key) => {
267
+ params[key] = value
268
+ })
269
+ return params
270
+ },
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Creates a hash-based router adapter using URL hash for routing.
276
+ * Useful for static hosting where server-side routing is not available.
277
+ *
278
+ * @param config - Router configuration
279
+ * @returns RouterAdapter that uses URL hash
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const router = createHashRouterAdapter()
284
+ *
285
+ * router.navigate('/products')
286
+ * // URL becomes: /#/products
287
+ * ```
288
+ */
289
+ export function createHashRouterAdapter(config?: RouterConfig): RouterAdapter {
290
+ // Check if we're in a browser environment
291
+ const isBrowser = typeof window !== 'undefined'
292
+
293
+ if (!isBrowser) {
294
+ return createMemoryRouterAdapter(config)
295
+ }
296
+
297
+ const defaultMode = config?.defaultMatchMode || 'exact'
298
+ const listeners = new Set<(path: string) => void>()
299
+
300
+ function getCurrentPath(): string {
301
+ const hash = window.location.hash
302
+ const path = hash.startsWith('#') ? hash.slice(1) : hash
303
+ return normalizePath(path || '/')
304
+ }
305
+
306
+ // Listen for hashchange events
307
+ if (isBrowser) {
308
+ window.addEventListener('hashchange', () => {
309
+ const path = getCurrentPath()
310
+ listeners.forEach(listener => listener(path))
311
+ })
312
+ }
313
+
314
+ return {
315
+ getCurrentPath,
316
+
317
+ navigate: (path: string) => {
318
+ window.location.hash = normalizePath(path)
319
+ },
320
+
321
+ replace: (path: string) => {
322
+ const url = new URL(window.location.href)
323
+ url.hash = normalizePath(path)
324
+ window.history.replaceState(null, '', url.toString())
325
+ listeners.forEach(listener => listener(normalizePath(path)))
326
+ },
327
+
328
+ isActive: (path: string, mode: RouteMatchMode = defaultMode) => {
329
+ return matchPath(getCurrentPath(), path, mode)
330
+ },
331
+
332
+ subscribe: (callback: (path: string) => void) => {
333
+ listeners.add(callback)
334
+ return () => {
335
+ listeners.delete(callback)
336
+ }
337
+ },
338
+
339
+ back: () => {
340
+ window.history.back()
341
+ },
342
+
343
+ forward: () => {
344
+ window.history.forward()
345
+ },
346
+
347
+ getParams: () => ({}),
348
+
349
+ getQuery: () => {
350
+ const hash = window.location.hash
351
+ const queryStart = hash.indexOf('?')
352
+ if (queryStart === -1) return {}
353
+
354
+ const params: Record<string, string> = {}
355
+ const searchParams = new URLSearchParams(hash.slice(queryStart + 1))
356
+ searchParams.forEach((value, key) => {
357
+ params[key] = value
358
+ })
359
+ return params
360
+ },
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Creates a static router adapter for server-side rendering or testing.
366
+ * The path never changes - it's purely read-only.
367
+ *
368
+ * @param path - Static path to use
369
+ * @returns Read-only RouterAdapter
370
+ */
371
+ export function createStaticRouterAdapter(path: string = '/'): RouterAdapter {
372
+ const normalizedPath = normalizePath(path)
373
+
374
+ return {
375
+ getCurrentPath: () => normalizedPath,
376
+ navigate: () => {
377
+ // No-op in static router
378
+ },
379
+ isActive: (targetPath: string, mode: RouteMatchMode = 'exact') => {
380
+ return matchPath(normalizedPath, targetPath, mode)
381
+ },
382
+ }
383
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @mdxui/terminal Router Types
3
+ *
4
+ * Type definitions for the router integration system.
5
+ * These types enable router-agnostic navigation across all navigation components.
6
+ */
7
+
8
+ /**
9
+ * Route matching mode for navigation components.
10
+ * - `exact`: Path must match exactly
11
+ * - `prefix`: Path starts with target (for nested routes)
12
+ * - `pattern`: Path matches pattern with :param and * wildcards
13
+ */
14
+ export type RouteMatchMode = 'exact' | 'prefix' | 'pattern'
15
+
16
+ /**
17
+ * Router adapter interface - implement this to integrate with any router library.
18
+ * This abstraction allows components to work with React Router, Next.js, Vue Router,
19
+ * or any custom routing solution.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // React Router adapter
24
+ * const reactRouterAdapter: RouterAdapter = {
25
+ * getCurrentPath: () => location.pathname,
26
+ * navigate: (path) => navigate(path),
27
+ * isActive: (path, mode) => matchPath(location.pathname, path, mode),
28
+ * subscribe: (callback) => {
29
+ * return history.listen(({ location }) => callback(location.pathname))
30
+ * },
31
+ * }
32
+ *
33
+ * // Next.js adapter
34
+ * const nextAdapter: RouterAdapter = {
35
+ * getCurrentPath: () => router.asPath,
36
+ * navigate: (path) => router.push(path),
37
+ * isActive: (path, mode) => matchPath(router.asPath, path, mode),
38
+ * }
39
+ * ```
40
+ */
41
+ export interface RouterAdapter {
42
+ /** Get the current path/location */
43
+ getCurrentPath(): string
44
+ /** Navigate to a path */
45
+ navigate(path: string): void
46
+ /** Check if a path matches the current route */
47
+ isActive(path: string, mode?: RouteMatchMode): boolean
48
+ /** Subscribe to route changes (returns unsubscribe function) */
49
+ subscribe?(callback: (path: string) => void): () => void
50
+ /** Replace current history entry instead of push */
51
+ replace?(path: string): void
52
+ /** Go back in history */
53
+ back?(): void
54
+ /** Go forward in history */
55
+ forward?(): void
56
+ /** Get route parameters */
57
+ getParams?(): Record<string, string>
58
+ /** Get query parameters */
59
+ getQuery?(): Record<string, string>
60
+ }
61
+
62
+ /**
63
+ * Router context value for React context integration.
64
+ */
65
+ export interface RouterContextValue {
66
+ /** Current path */
67
+ path: string
68
+ /** Router adapter instance */
69
+ adapter: RouterAdapter
70
+ /** Route parameters */
71
+ params: Record<string, string>
72
+ /** Query parameters */
73
+ query: Record<string, string>
74
+ }
75
+
76
+ /**
77
+ * Configuration for creating router adapters.
78
+ */
79
+ export interface RouterConfig {
80
+ /** Initial path */
81
+ initialPath?: string
82
+ /** Base path for all routes */
83
+ basePath?: string
84
+ /** Default route match mode */
85
+ defaultMatchMode?: RouteMatchMode
86
+ }
87
+
88
+ /**
89
+ * History entry for in-memory router.
90
+ */
91
+ export interface HistoryEntry {
92
+ path: string
93
+ state?: unknown
94
+ timestamp: number
95
+ }
96
+
97
+ /**
98
+ * In-memory router state.
99
+ */
100
+ export interface MemoryRouterState {
101
+ entries: HistoryEntry[]
102
+ index: number
103
+ listeners: Set<(path: string) => void>
104
+ }
105
+
106
+ /**
107
+ * Navigation item with optional path for router integration.
108
+ */
109
+ export interface NavigableItem {
110
+ id: string
111
+ path?: string
112
+ label?: string
113
+ icon?: string
114
+ disabled?: boolean
115
+ }
116
+
117
+ /**
118
+ * Breadcrumb segment with path information.
119
+ */
120
+ export interface BreadcrumbSegment {
121
+ label: string
122
+ path?: string
123
+ icon?: string
124
+ }
125
+
126
+ /**
127
+ * Options for generating breadcrumbs from a path.
128
+ */
129
+ export interface BreadcrumbGeneratorOptions {
130
+ /** Custom labels for specific paths (e.g., { '/products': 'Shop' }) */
131
+ labels?: Record<string, string>
132
+ /** Function to generate label from segment (default: capitalize) */
133
+ labelGenerator?: (segment: string, fullPath: string) => string
134
+ /** Whether to include home segment */
135
+ includeHome?: boolean
136
+ /** Home segment label */
137
+ homeLabel?: string
138
+ /** Home segment icon */
139
+ homeIcon?: string
140
+ }