@torch-ui/solid 0.1.3

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 (118) hide show
  1. package/README.md +166 -0
  2. package/package.json +67 -0
  3. package/src/components/actions/Button.tsx +612 -0
  4. package/src/components/actions/ButtonGroup.tsx +728 -0
  5. package/src/components/actions/Copy.tsx +98 -0
  6. package/src/components/actions/DarkModeToggle.tsx +80 -0
  7. package/src/components/actions/Link.tsx +37 -0
  8. package/src/components/actions/index.ts +19 -0
  9. package/src/components/actions/useCopyToClipboard.ts +90 -0
  10. package/src/components/charts/Chart.tsx +331 -0
  11. package/src/components/charts/Sparkline.tsx +156 -0
  12. package/src/components/charts/index.ts +13 -0
  13. package/src/components/data-display/Avatar.tsx +208 -0
  14. package/src/components/data-display/AvatarGroup.tsx +228 -0
  15. package/src/components/data-display/Badge.tsx +70 -0
  16. package/src/components/data-display/Carousel.tsx +214 -0
  17. package/src/components/data-display/ColorSwatch.tsx +56 -0
  18. package/src/components/data-display/DataTable.tsx +886 -0
  19. package/src/components/data-display/EmptyState.tsx +61 -0
  20. package/src/components/data-display/Image.tsx +277 -0
  21. package/src/components/data-display/Kbd.tsx +114 -0
  22. package/src/components/data-display/Persona.tsx +78 -0
  23. package/src/components/data-display/StatCard.tsx +338 -0
  24. package/src/components/data-display/Table.tsx +147 -0
  25. package/src/components/data-display/Tag.tsx +91 -0
  26. package/src/components/data-display/Timeline.tsx +200 -0
  27. package/src/components/data-display/TreeView.tsx +172 -0
  28. package/src/components/data-display/Video.tsx +95 -0
  29. package/src/components/data-display/avatar-utils.ts +32 -0
  30. package/src/components/data-display/index.ts +81 -0
  31. package/src/components/feedback/Loading.tsx +159 -0
  32. package/src/components/feedback/Progress.tsx +321 -0
  33. package/src/components/feedback/Skeleton.tsx +62 -0
  34. package/src/components/feedback/SkeletonBlocks.tsx +222 -0
  35. package/src/components/feedback/Toast.tsx +648 -0
  36. package/src/components/feedback/index.ts +44 -0
  37. package/src/components/feedback/password/PasswordStrengthIndicator.tsx +232 -0
  38. package/src/components/feedback/password/password-strength.ts +115 -0
  39. package/src/components/feedback/password/password-validation-data.ts +66 -0
  40. package/src/components/feedback/password/password-validation.ts +93 -0
  41. package/src/components/forms/Autocomplete.tsx +268 -0
  42. package/src/components/forms/Checkbox.tsx +155 -0
  43. package/src/components/forms/CodeInput.tsx +237 -0
  44. package/src/components/forms/ColorPicker/ColorPicker.tsx +469 -0
  45. package/src/components/forms/ColorPicker/color-utils.ts +75 -0
  46. package/src/components/forms/ColorPicker/index.ts +2 -0
  47. package/src/components/forms/DatePicker.tsx +516 -0
  48. package/src/components/forms/DateRangePicker.tsx +464 -0
  49. package/src/components/forms/FieldPicker.tsx +64 -0
  50. package/src/components/forms/FileUpload.tsx +614 -0
  51. package/src/components/forms/FilterBuilder/FilterGroupBlock.ts +6 -0
  52. package/src/components/forms/FilterBuilder.tsx +16 -0
  53. package/src/components/forms/FilterRuleRow.tsx +68 -0
  54. package/src/components/forms/Input.tsx +200 -0
  55. package/src/components/forms/MultiSelect.tsx +361 -0
  56. package/src/components/forms/NumberField.tsx +145 -0
  57. package/src/components/forms/RadioGroup.tsx +135 -0
  58. package/src/components/forms/RelativeDateDefaultInput.tsx +62 -0
  59. package/src/components/forms/ReorderableList.tsx +163 -0
  60. package/src/components/forms/Select.tsx +268 -0
  61. package/src/components/forms/Slider.tsx +260 -0
  62. package/src/components/forms/Switch.tsx +135 -0
  63. package/src/components/forms/TextArea.tsx +202 -0
  64. package/src/components/forms/ViewCustomizer.tsx +44 -0
  65. package/src/components/forms/index.ts +43 -0
  66. package/src/components/layout/Accordion.tsx +110 -0
  67. package/src/components/layout/Alert.tsx +156 -0
  68. package/src/components/layout/BlockQuote.tsx +70 -0
  69. package/src/components/layout/Card.tsx +166 -0
  70. package/src/components/layout/CodeBlock/CodeBlock.tsx +477 -0
  71. package/src/components/layout/CodeBlock/code-block-tokens.css +104 -0
  72. package/src/components/layout/CodeBlock/prism.ts +81 -0
  73. package/src/components/layout/Collapsible.tsx +84 -0
  74. package/src/components/layout/Container.tsx +55 -0
  75. package/src/components/layout/Divider.tsx +64 -0
  76. package/src/components/layout/Form.tsx +39 -0
  77. package/src/components/layout/FormActions.tsx +50 -0
  78. package/src/components/layout/Grid.tsx +53 -0
  79. package/src/components/layout/PageHeading.tsx +46 -0
  80. package/src/components/layout/PromptWithAction.tsx +49 -0
  81. package/src/components/layout/Section.tsx +60 -0
  82. package/src/components/layout/TablePanel.tsx +24 -0
  83. package/src/components/layout/TableView/TableView.tsx +1018 -0
  84. package/src/components/layout/TableView/index.ts +3 -0
  85. package/src/components/layout/TableView/types.ts +51 -0
  86. package/src/components/layout/WizardStep.tsx +40 -0
  87. package/src/components/layout/WizardStepper.tsx +173 -0
  88. package/src/components/layout/index.ts +96 -0
  89. package/src/components/navigation/Breadcrumbs.tsx +66 -0
  90. package/src/components/navigation/DropdownMenu.tsx +86 -0
  91. package/src/components/navigation/MegaMenu.tsx +480 -0
  92. package/src/components/navigation/NavigationMenu.tsx +305 -0
  93. package/src/components/navigation/Pagination.tsx +298 -0
  94. package/src/components/navigation/Sidebar.tsx +280 -0
  95. package/src/components/navigation/Tabs.tsx +122 -0
  96. package/src/components/navigation/ViewSwitcher.tsx +314 -0
  97. package/src/components/navigation/index.ts +66 -0
  98. package/src/components/overlays/AlertDialog.tsx +174 -0
  99. package/src/components/overlays/ContextMenu.tsx +65 -0
  100. package/src/components/overlays/Dialog.tsx +279 -0
  101. package/src/components/overlays/Drawer.tsx +370 -0
  102. package/src/components/overlays/HoverCard.tsx +107 -0
  103. package/src/components/overlays/Popover.tsx +73 -0
  104. package/src/components/overlays/Tooltip.tsx +31 -0
  105. package/src/components/overlays/index.ts +71 -0
  106. package/src/components/typography/Code.tsx +72 -0
  107. package/src/components/typography/Icon.tsx +36 -0
  108. package/src/components/typography/index.ts +10 -0
  109. package/src/env.d.ts +9 -0
  110. package/src/index.ts +13 -0
  111. package/src/styles/theme.css +226 -0
  112. package/src/types/avatar-types.ts +11 -0
  113. package/src/types/filter-types.ts +35 -0
  114. package/src/utilities/classNames.ts +6 -0
  115. package/src/utilities/componentSize.ts +46 -0
  116. package/src/utilities/i18n.tsx +60 -0
  117. package/src/utilities/mergeRefs.ts +12 -0
  118. package/src/utilities/relativeDateDefault.ts +14 -0
@@ -0,0 +1,648 @@
1
+ import { createSignal, createContext, useContext, onCleanup, For, Show, splitProps, onMount, createEffect, type JSX } from 'solid-js'
2
+
3
+ import { Portal } from 'solid-js/web'
4
+
5
+ import { X } from 'lucide-solid'
6
+
7
+ import { cn } from '../../utilities/classNames'
8
+
9
+
10
+
11
+ export type ToastVariant = 'default' | 'success' | 'error' | 'warning' | 'info'
12
+
13
+
14
+
15
+ export interface ToastItem {
16
+
17
+ id: string
18
+
19
+ title?: string
20
+
21
+ description?: string
22
+
23
+ /** Legacy: for backward compatibility */
24
+
25
+ message?: string
26
+
27
+ variant?: ToastVariant
28
+
29
+ /** Auto-dismiss duration in ms. Default 5000. Set to 0 to disable auto-dismiss. */
30
+
31
+ duration?: number
32
+
33
+ /** Show progress bar for countdown. Default true when duration > 0. */
34
+
35
+ showProgress?: boolean
36
+
37
+ /** Optional action label; when set, onAction is called when clicked. */
38
+
39
+ actionLabel?: string
40
+
41
+ onAction?: () => void
42
+
43
+ }
44
+
45
+
46
+
47
+ export interface ToastContextValue {
48
+
49
+ toasts: () => ToastItem[]
50
+
51
+ show: (title: string, description?: string, options?: { variant?: ToastVariant; duration?: number; showProgress?: boolean; actionLabel?: string; onAction?: () => void }) => string
52
+
53
+ dismiss: (id: string) => void
54
+
55
+ }
56
+
57
+
58
+
59
+ let toastSeq = 0
60
+
61
+ const newToastId = () => `toast-${++toastSeq}`
62
+
63
+
64
+
65
+ const MAX_TOASTS = 5
66
+
67
+
68
+
69
+ interface TimerEntry {
70
+
71
+ timer: ReturnType<typeof setTimeout> | null
72
+
73
+ remaining: number
74
+
75
+ startedAt: number
76
+
77
+ paused: boolean
78
+
79
+ }
80
+
81
+
82
+
83
+ const ToastContext = createContext<ToastContextValue | null>(null)
84
+
85
+
86
+
87
+ export function useToast() {
88
+
89
+ const ctx = useContext(ToastContext)
90
+
91
+ if (!ctx) throw new Error('useToast must be used within ToastProvider')
92
+
93
+ return ctx
94
+
95
+ }
96
+
97
+
98
+
99
+ export interface ToastProviderProps {
100
+
101
+ children: JSX.Element
102
+
103
+ /** Position of the toast container. Default bottom-right. */
104
+
105
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
106
+
107
+ /** Hotkey to jump to toast region. Default Alt+T. */
108
+
109
+ hotkey?: string
110
+
111
+ }
112
+
113
+
114
+
115
+ export function ToastProvider(props: ToastProviderProps) {
116
+
117
+ const [local] = splitProps(props, ['children', 'position', 'hotkey'])
118
+
119
+
120
+
121
+ const [toasts, setToasts] = createSignal<ToastItem[]>([])
122
+
123
+ const timers = new Map<string, TimerEntry>()
124
+
125
+ const [regionRef, setRegionRef] = createSignal<HTMLDivElement | null>(null)
126
+
127
+ const position = () => local.position ?? 'bottom-right'
128
+
129
+ const hotkey = () => local.hotkey ?? 'Alt+T'
130
+
131
+
132
+
133
+ const startTimer = (id: string, duration: number) => {
134
+
135
+ const existing = timers.get(id)
136
+
137
+ if (existing?.timer != null) clearTimeout(existing.timer)
138
+
139
+ const timer = setTimeout(() => {
140
+
141
+ if (!timers.has(id)) return
142
+
143
+ timers.delete(id)
144
+
145
+ setToasts((prev) => prev.filter((t) => t.id !== id))
146
+
147
+ }, duration)
148
+
149
+ if (existing) {
150
+
151
+ existing.timer = timer
152
+
153
+ existing.remaining = duration
154
+
155
+ existing.startedAt = Date.now()
156
+
157
+ existing.paused = false
158
+
159
+ } else {
160
+
161
+ timers.set(id, { timer, remaining: duration, startedAt: Date.now(), paused: false })
162
+
163
+ }
164
+
165
+ }
166
+
167
+
168
+
169
+ const clearTimer = (id: string) => {
170
+
171
+ const entry = timers.get(id)
172
+
173
+ if (entry != null) {
174
+
175
+ if (entry.timer != null) clearTimeout(entry.timer)
176
+
177
+ timers.delete(id)
178
+
179
+ }
180
+
181
+ }
182
+
183
+
184
+
185
+ const pauseTimer = (id: string) => {
186
+
187
+ const entry = timers.get(id)
188
+
189
+ if (entry == null || entry.paused) return
190
+
191
+ if (entry.timer != null) clearTimeout(entry.timer)
192
+
193
+ entry.timer = null
194
+
195
+ entry.remaining = Math.max(0, entry.remaining - (Date.now() - entry.startedAt))
196
+
197
+ entry.paused = true
198
+
199
+ }
200
+
201
+
202
+
203
+ const resumeTimer = (id: string) => {
204
+
205
+ const entry = timers.get(id)
206
+
207
+ if (entry == null || !entry.paused) return
208
+
209
+ if (entry.remaining <= 0) {
210
+
211
+ timers.delete(id)
212
+
213
+ setToasts((prev) => prev.filter((t) => t.id !== id))
214
+
215
+ return
216
+
217
+ }
218
+
219
+ startTimer(id, entry.remaining)
220
+
221
+ }
222
+
223
+
224
+
225
+ const show: ToastContextValue['show'] = (title, description, options) => {
226
+
227
+ const id = newToastId()
228
+
229
+ // Backward compatibility: if only title is provided and no description, treat as message
230
+
231
+ const isLegacyMessage = title && !description && !options?.variant
232
+
233
+ const item: ToastItem = {
234
+
235
+ id,
236
+
237
+ title: isLegacyMessage ? undefined : title,
238
+
239
+ description: isLegacyMessage ? undefined : description,
240
+
241
+ message: isLegacyMessage ? title : undefined,
242
+
243
+ variant: options?.variant ?? 'default',
244
+
245
+ duration: options?.duration ?? 5000,
246
+
247
+ showProgress: options?.showProgress,
248
+
249
+ actionLabel: options?.actionLabel,
250
+
251
+ onAction: options?.onAction,
252
+
253
+ }
254
+
255
+ const prev = toasts()
256
+
257
+ const next = [...prev, item].slice(-MAX_TOASTS)
258
+
259
+ if (prev.length >= MAX_TOASTS) {
260
+
261
+ const nextIds = new Set(next.map((t) => t.id))
262
+
263
+ for (const t of prev) {
264
+
265
+ if (!nextIds.has(t.id)) clearTimer(t.id)
266
+
267
+ }
268
+
269
+ }
270
+
271
+ setToasts(next)
272
+
273
+ if (item.duration && item.duration > 0) {
274
+
275
+ startTimer(id, item.duration)
276
+
277
+ }
278
+
279
+ return id
280
+
281
+ }
282
+
283
+
284
+
285
+ const dismiss = (id: string) => {
286
+
287
+ clearTimer(id)
288
+
289
+ setToasts((prev) => prev.filter((t) => t.id !== id))
290
+
291
+ }
292
+
293
+
294
+
295
+ // Hotkey handler to jump to toast region
296
+
297
+ onMount(() => {
298
+
299
+ const handleKeyDown = (e: KeyboardEvent) => {
300
+
301
+ const keys = hotkey().split('+').map(k => k.toLowerCase())
302
+
303
+ const alt = keys.includes('alt') && e.altKey
304
+
305
+ const ctrl = keys.includes('ctrl') && e.ctrlKey
306
+
307
+ const shift = keys.includes('shift') && e.shiftKey
308
+
309
+ const meta = keys.includes('meta') && e.metaKey
310
+
311
+ const key = keys.find(k => !['alt', 'ctrl', 'shift', 'meta'].includes(k))
312
+
313
+
314
+
315
+ if (key && e.key.toLowerCase() === key && alt && !ctrl && !shift && !meta) {
316
+
317
+ e.preventDefault()
318
+
319
+ regionRef()?.focus()
320
+
321
+ }
322
+
323
+ }
324
+
325
+ document.addEventListener('keydown', handleKeyDown)
326
+
327
+ onCleanup(() => document.removeEventListener('keydown', handleKeyDown))
328
+
329
+ })
330
+
331
+
332
+
333
+ onCleanup(() => {
334
+
335
+ for (const entry of timers.values()) { if (entry.timer != null) clearTimeout(entry.timer) }
336
+
337
+ timers.clear()
338
+
339
+ })
340
+
341
+
342
+
343
+ const value: ToastContextValue = { toasts, show, dismiss }
344
+
345
+
346
+
347
+ return (
348
+
349
+ <ToastContext.Provider value={value}>
350
+
351
+ {local.children}
352
+
353
+ <Portal>
354
+
355
+ <div
356
+
357
+ ref={setRegionRef}
358
+
359
+ tabIndex={-1}
360
+
361
+ class={cn(
362
+
363
+ 'pointer-events-none fixed z-[100] flex gap-2 p-4',
364
+
365
+ position().startsWith('bottom') ? 'flex-col-reverse' : 'flex-col',
366
+
367
+ position() === 'top-left' && 'left-4 top-4',
368
+
369
+ position() === 'top-right' && 'right-4 top-4',
370
+
371
+ position() === 'bottom-left' && 'left-4 bottom-4',
372
+
373
+ position() === 'bottom-right' && 'right-4 bottom-4'
374
+
375
+ )}
376
+
377
+ role="region"
378
+
379
+ aria-label="Notifications"
380
+
381
+ >
382
+
383
+ <For each={toasts()}>
384
+
385
+ {(t) => (
386
+
387
+ <ToastItemView
388
+
389
+ toast={t}
390
+
391
+ timers={timers}
392
+
393
+ onDismiss={() => dismiss(t.id)}
394
+
395
+ onPause={() => pauseTimer(t.id)}
396
+
397
+ onResume={() => resumeTimer(t.id)}
398
+
399
+ />
400
+
401
+ )}
402
+
403
+ </For>
404
+
405
+ </div>
406
+
407
+ </Portal>
408
+
409
+ </ToastContext.Provider>
410
+
411
+ )
412
+
413
+ }
414
+
415
+
416
+
417
+ const variantClasses: Record<ToastVariant, string> = {
418
+
419
+ default: 'bg-ink-800 text-white dark:bg-ink-200 dark:text-ink-900',
420
+
421
+ success: 'bg-success-600 text-white dark:bg-success-500',
422
+
423
+ error: 'bg-danger-600 text-white dark:bg-danger-500',
424
+
425
+ warning: 'bg-warning-600 text-white dark:bg-warning-500',
426
+
427
+ info: 'bg-primary-600 text-white dark:bg-primary-500',
428
+
429
+ }
430
+
431
+
432
+
433
+ function ToastItemView(props: { toast: ToastItem; onDismiss: () => void; onPause: () => void; onResume: () => void; timers: Map<string, TimerEntry> }) {
434
+
435
+ const [local, rest] = splitProps(props, ['toast', 'onDismiss', 'onPause', 'onResume'])
436
+
437
+
438
+
439
+ const t = () => local.toast
440
+
441
+ const variant = () => t().variant ?? 'default'
442
+
443
+ const isAlert = () => variant() === 'error' || variant() === 'warning'
444
+
445
+ const [progress, setProgress] = createSignal(100)
446
+
447
+
448
+
449
+ // Update progress based on timer - always running interval that checks pause state
450
+
451
+ createEffect(() => {
452
+
453
+ const id = t().id
454
+
455
+ const interval = setInterval(() => {
456
+
457
+ const timer = rest.timers.get(id)
458
+
459
+ if (!timer) {
460
+
461
+ setProgress(100)
462
+
463
+ return
464
+
465
+ }
466
+
467
+
468
+
469
+ if (timer.paused) {
470
+
471
+ return // Don't update progress when paused
472
+
473
+ }
474
+
475
+
476
+
477
+ const totalDuration = timer.remaining + (Date.now() - timer.startedAt)
478
+
479
+ if (totalDuration <= 0) {
480
+
481
+ setProgress(100)
482
+
483
+ return
484
+
485
+ }
486
+
487
+
488
+
489
+ const elapsed = Date.now() - timer.startedAt
490
+
491
+ const remaining = Math.max(0, timer.remaining - elapsed)
492
+
493
+ const percentage = (remaining / totalDuration) * 100
494
+
495
+ setProgress(percentage)
496
+
497
+ }, 50)
498
+
499
+
500
+
501
+ onCleanup(() => clearInterval(interval))
502
+
503
+ })
504
+
505
+ return (
506
+
507
+ <div
508
+
509
+ role={isAlert() ? 'alert' : 'status'}
510
+
511
+ aria-atomic="true"
512
+
513
+ tabIndex={0}
514
+
515
+ class={cn(
516
+
517
+ 'relative pointer-events-auto flex min-w-[280px] max-w-md items-center justify-between gap-3 rounded-lg px-4 py-3 text-sm shadow-lg',
518
+
519
+ variantClasses[variant()]
520
+
521
+ )}
522
+
523
+ onMouseEnter={local.onPause}
524
+
525
+ onMouseLeave={local.onResume}
526
+
527
+ onFocusIn={local.onPause}
528
+
529
+ onFocusOut={(e: FocusEvent) => {
530
+
531
+ const next = e.relatedTarget as Node | null
532
+
533
+ if (next && (e.currentTarget as Node).contains(next)) return
534
+
535
+ local.onResume()
536
+
537
+ }}
538
+
539
+ onKeyDown={(e: KeyboardEvent) => {
540
+
541
+ if (e.key === 'Escape') local.onDismiss()
542
+
543
+ }}
544
+
545
+ >
546
+
547
+ <div class="flex flex-1 flex-col gap-1">
548
+
549
+ <Show when={t().title}>
550
+
551
+ <div class="font-medium" role="heading" aria-level={3}>
552
+
553
+ {t().title}
554
+
555
+ </div>
556
+
557
+ </Show>
558
+
559
+ <Show when={t().description}>
560
+
561
+ <div class="text-sm opacity-90">
562
+
563
+ {t().description}
564
+
565
+ </div>
566
+
567
+ </Show>
568
+
569
+ <Show when={!t().title && !t().description}>
570
+
571
+ {/* Fallback for legacy single message */}
572
+
573
+ <div>{t().message}</div>
574
+
575
+ </Show>
576
+
577
+ </div>
578
+
579
+ <div class="flex shrink-0 items-center gap-2">
580
+
581
+ <Show when={t().actionLabel && t().onAction}>
582
+
583
+ <button
584
+
585
+ type="button"
586
+
587
+ onClick={() => { t().onAction?.(); local.onDismiss() }}
588
+
589
+ class="rounded font-medium underline underline-offset-2 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60"
590
+
591
+ >
592
+
593
+ {t().actionLabel}
594
+
595
+ </button>
596
+
597
+ </Show>
598
+
599
+ <button
600
+
601
+ type="button"
602
+
603
+ onClick={local.onDismiss}
604
+
605
+ class="rounded p-1 opacity-80 hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/60"
606
+
607
+ aria-label="Dismiss"
608
+
609
+ >
610
+
611
+ <X class="h-4 w-4" aria-hidden="true" />
612
+
613
+ </button>
614
+
615
+ </div>
616
+
617
+ <Show when={t().showProgress !== false && t().duration && t().duration! > 0}>
618
+
619
+ <div class="absolute bottom-0 left-0 h-1 w-full overflow-hidden rounded-b-lg">
620
+
621
+ <div
622
+
623
+ class="h-full bg-white/20 transition-all duration-75 ease-linear"
624
+
625
+ style={{ width: `${progress()}%` }}
626
+
627
+ role="progressbar"
628
+
629
+ aria-valuenow={progress()}
630
+
631
+ aria-valuemin={0}
632
+
633
+ aria-valuemax={100}
634
+
635
+ aria-label="Time remaining"
636
+
637
+ />
638
+
639
+ </div>
640
+
641
+ </Show>
642
+
643
+ </div>
644
+
645
+ )
646
+
647
+ }
648
+
@@ -0,0 +1,44 @@
1
+ export { Alert } from '../layout/Alert'
2
+ export type { AlertProps, AlertStatus, AlertAppearance } from '../layout/Alert'
3
+
4
+ export { AlertDialog } from '../overlays/AlertDialog'
5
+ export type { AlertDialogProps } from '../overlays/AlertDialog'
6
+
7
+ export { PasswordStrengthIndicator } from './password/PasswordStrengthIndicator'
8
+ export type { PasswordStrengthIndicatorProps } from './password/PasswordStrengthIndicator'
9
+ export { getPasswordAnalysis, getPasswordStrength, getPasswordRequirements, getPasswordSegmentScore } from './password/password-strength'
10
+ export type { PasswordStrength, PasswordAnalysis, PasswordRequirements } from './password/password-strength'
11
+ export { validatePassword, isPasswordWeak } from './password/password-validation'
12
+ export { Progress } from './Progress'
13
+ export type {
14
+ ProgressProps,
15
+ ProgressSize,
16
+ ProgressColor,
17
+ ProgressRadius,
18
+ ProgressClassNames,
19
+ } from './Progress'
20
+ export { Loading } from './Loading'
21
+ export type { LoadingProps, LoadingVariant } from './Loading'
22
+ export { Skeleton } from './Skeleton'
23
+ export type { SkeletonProps } from './Skeleton'
24
+ export {
25
+ SkeletonCard,
26
+ SkeletonTable,
27
+ SkeletonSection,
28
+ SkeletonHeading,
29
+ SkeletonForm,
30
+ SkeletonNavBlock,
31
+ } from './SkeletonBlocks'
32
+ export type {
33
+ SkeletonCardProps,
34
+ SkeletonTableProps,
35
+ SkeletonSectionProps,
36
+ SkeletonHeadingProps,
37
+ SkeletonFormProps,
38
+ SkeletonNavBlockProps,
39
+ } from './SkeletonBlocks'
40
+
41
+ export { ToastProvider, useToast } from './Toast'
42
+ export type { ToastContextValue, ToastItem, ToastVariant } from './Toast'
43
+
44
+ export type { PasswordValidationResult } from './password/password-validation'