sv5ui-plus 4.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 (214) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/adapters/notify.d.ts +29 -0
  4. package/dist/adapters/notify.js +88 -0
  5. package/dist/compat.d.ts +6 -0
  6. package/dist/compat.js +6 -0
  7. package/dist/components/BentoGrid/BentoCard.svelte +45 -0
  8. package/dist/components/BentoGrid/BentoCard.svelte.d.ts +4 -0
  9. package/dist/components/BentoGrid/BentoGrid.svelte +9 -0
  10. package/dist/components/BentoGrid/BentoGrid.svelte.d.ts +4 -0
  11. package/dist/components/BentoGrid/bento-grid.types.d.ts +47 -0
  12. package/dist/components/BentoGrid/bento-grid.types.js +1 -0
  13. package/dist/components/BentoGrid/bento-grid.variants.d.ts +30 -0
  14. package/dist/components/BentoGrid/bento-grid.variants.js +16 -0
  15. package/dist/components/BentoGrid/index.d.ts +5 -0
  16. package/dist/components/BentoGrid/index.js +5 -0
  17. package/dist/components/Chart/Chart.svelte +62 -0
  18. package/dist/components/Chart/Chart.svelte.d.ts +4 -0
  19. package/dist/components/Chart/chart.types.d.ts +16 -0
  20. package/dist/components/Chart/chart.types.js +1 -0
  21. package/dist/components/Chart/index.d.ts +2 -0
  22. package/dist/components/Chart/index.js +2 -0
  23. package/dist/components/Chat/ChatBubble.svelte +30 -0
  24. package/dist/components/Chat/ChatBubble.svelte.d.ts +4 -0
  25. package/dist/components/Chat/ChatInput.svelte +50 -0
  26. package/dist/components/Chat/ChatInput.svelte.d.ts +4 -0
  27. package/dist/components/Chat/ChatMessage.svelte +15 -0
  28. package/dist/components/Chat/ChatMessage.svelte.d.ts +4 -0
  29. package/dist/components/Chat/chat.types.d.ts +63 -0
  30. package/dist/components/Chat/chat.types.js +1 -0
  31. package/dist/components/Chat/chat.variants.d.ts +117 -0
  32. package/dist/components/Chat/chat.variants.js +47 -0
  33. package/dist/components/Chat/index.d.ts +6 -0
  34. package/dist/components/Chat/index.js +6 -0
  35. package/dist/components/CodeBlock/CodeBlock.svelte +66 -0
  36. package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +5 -0
  37. package/dist/components/CodeBlock/code-block.types.d.ts +15 -0
  38. package/dist/components/CodeBlock/code-block.types.js +1 -0
  39. package/dist/components/CodeBlock/code-block.variants.d.ts +288 -0
  40. package/dist/components/CodeBlock/code-block.variants.js +69 -0
  41. package/dist/components/CodeBlock/index.d.ts +2 -0
  42. package/dist/components/CodeBlock/index.js +1 -0
  43. package/dist/components/ColorPicker/ColorPicker.svelte +109 -0
  44. package/dist/components/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  45. package/dist/components/ColorPicker/color-picker.types.d.ts +26 -0
  46. package/dist/components/ColorPicker/color-picker.types.js +1 -0
  47. package/dist/components/ColorPicker/color-picker.variants.d.ts +69 -0
  48. package/dist/components/ColorPicker/color-picker.variants.js +13 -0
  49. package/dist/components/ColorPicker/index.d.ts +4 -0
  50. package/dist/components/ColorPicker/index.js +4 -0
  51. package/dist/components/ConfirmDialog/ConfirmDialog.svelte +175 -0
  52. package/dist/components/ConfirmDialog/ConfirmDialog.svelte.d.ts +10 -0
  53. package/dist/components/ConfirmDialog/confirm.d.ts +9 -0
  54. package/dist/components/ConfirmDialog/confirm.js +24 -0
  55. package/dist/components/ConfirmDialog/confirm.types.d.ts +21 -0
  56. package/dist/components/ConfirmDialog/confirm.types.js +1 -0
  57. package/dist/components/ConfirmDialog/index.d.ts +4 -0
  58. package/dist/components/ConfirmDialog/index.js +2 -0
  59. package/dist/components/Fonts/Fonts.svelte +32 -0
  60. package/dist/components/Fonts/Fonts.svelte.d.ts +5 -0
  61. package/dist/components/Fonts/fonts.d.ts +12 -0
  62. package/dist/components/Fonts/fonts.js +126 -0
  63. package/dist/components/Fonts/fonts.types.d.ts +40 -0
  64. package/dist/components/Fonts/fonts.types.js +1 -0
  65. package/dist/components/Fonts/index.d.ts +3 -0
  66. package/dist/components/Fonts/index.js +2 -0
  67. package/dist/components/List/List.svelte +14 -0
  68. package/dist/components/List/List.svelte.d.ts +4 -0
  69. package/dist/components/List/ListItem.svelte +64 -0
  70. package/dist/components/List/ListItem.svelte.d.ts +4 -0
  71. package/dist/components/List/index.d.ts +5 -0
  72. package/dist/components/List/index.js +5 -0
  73. package/dist/components/List/list.types.d.ts +62 -0
  74. package/dist/components/List/list.types.js +1 -0
  75. package/dist/components/List/list.variants.d.ts +99 -0
  76. package/dist/components/List/list.variants.js +42 -0
  77. package/dist/components/LocaleButton/LocaleButton.svelte +181 -0
  78. package/dist/components/LocaleButton/LocaleButton.svelte.d.ts +5 -0
  79. package/dist/components/LocaleButton/index.d.ts +2 -0
  80. package/dist/components/LocaleButton/index.js +1 -0
  81. package/dist/components/LocaleButton/locale-button.types.d.ts +208 -0
  82. package/dist/components/LocaleButton/locale-button.types.js +1 -0
  83. package/dist/components/LocaleButton/locale-button.variants.d.ts +245 -0
  84. package/dist/components/LocaleButton/locale-button.variants.js +98 -0
  85. package/dist/components/Marquee/Marquee.svelte +50 -0
  86. package/dist/components/Marquee/Marquee.svelte.d.ts +4 -0
  87. package/dist/components/Marquee/index.d.ts +4 -0
  88. package/dist/components/Marquee/index.js +4 -0
  89. package/dist/components/Marquee/marquee.types.d.ts +38 -0
  90. package/dist/components/Marquee/marquee.types.js +1 -0
  91. package/dist/components/Marquee/marquee.variants.d.ts +78 -0
  92. package/dist/components/Marquee/marquee.variants.js +28 -0
  93. package/dist/components/NavigationMenu/NavigationMenu.svelte +623 -0
  94. package/dist/components/NavigationMenu/NavigationMenu.svelte.d.ts +5 -0
  95. package/dist/components/NavigationMenu/index.d.ts +2 -0
  96. package/dist/components/NavigationMenu/index.js +1 -0
  97. package/dist/components/NavigationMenu/navigation-menu.types.d.ts +245 -0
  98. package/dist/components/NavigationMenu/navigation-menu.types.js +1 -0
  99. package/dist/components/NavigationMenu/navigation-menu.variants.d.ts +543 -0
  100. package/dist/components/NavigationMenu/navigation-menu.variants.js +287 -0
  101. package/dist/components/NumberTicker/NumberTicker.svelte +59 -0
  102. package/dist/components/NumberTicker/NumberTicker.svelte.d.ts +4 -0
  103. package/dist/components/NumberTicker/index.d.ts +4 -0
  104. package/dist/components/NumberTicker/index.js +4 -0
  105. package/dist/components/NumberTicker/number-ticker.types.d.ts +26 -0
  106. package/dist/components/NumberTicker/number-ticker.types.js +1 -0
  107. package/dist/components/NumberTicker/number-ticker.variants.d.ts +27 -0
  108. package/dist/components/NumberTicker/number-ticker.variants.js +6 -0
  109. package/dist/components/PasswordInput/PasswordInput.svelte +182 -0
  110. package/dist/components/PasswordInput/PasswordInput.svelte.d.ts +5 -0
  111. package/dist/components/PasswordInput/index.d.ts +2 -0
  112. package/dist/components/PasswordInput/index.js +1 -0
  113. package/dist/components/PasswordInput/password-input.types.d.ts +111 -0
  114. package/dist/components/PasswordInput/password-input.types.js +1 -0
  115. package/dist/components/PasswordInput/password-input.variants.d.ts +273 -0
  116. package/dist/components/PasswordInput/password-input.variants.js +105 -0
  117. package/dist/components/Prose/Prose.svelte +13 -0
  118. package/dist/components/Prose/Prose.svelte.d.ts +4 -0
  119. package/dist/components/Prose/index.d.ts +4 -0
  120. package/dist/components/Prose/index.js +4 -0
  121. package/dist/components/Prose/prose.types.d.ts +22 -0
  122. package/dist/components/Prose/prose.types.js +1 -0
  123. package/dist/components/Prose/prose.variants.d.ts +45 -0
  124. package/dist/components/Prose/prose.variants.js +45 -0
  125. package/dist/components/Resizable/Resizable.svelte +9 -0
  126. package/dist/components/Resizable/Resizable.svelte.d.ts +4 -0
  127. package/dist/components/Resizable/index.d.ts +4 -0
  128. package/dist/components/Resizable/index.js +4 -0
  129. package/dist/components/Resizable/resizable.types.d.ts +18 -0
  130. package/dist/components/Resizable/resizable.types.js +1 -0
  131. package/dist/components/Resizable/resizable.variants.d.ts +48 -0
  132. package/dist/components/Resizable/resizable.variants.js +17 -0
  133. package/dist/components/ScrollArea/ScrollArea.svelte +54 -0
  134. package/dist/components/ScrollArea/ScrollArea.svelte.d.ts +4 -0
  135. package/dist/components/ScrollArea/index.d.ts +4 -0
  136. package/dist/components/ScrollArea/index.js +4 -0
  137. package/dist/components/ScrollArea/scroll-area.types.d.ts +27 -0
  138. package/dist/components/ScrollArea/scroll-area.types.js +1 -0
  139. package/dist/components/ScrollArea/scroll-area.variants.d.ts +45 -0
  140. package/dist/components/ScrollArea/scroll-area.variants.js +27 -0
  141. package/dist/components/Search/Search.svelte +94 -0
  142. package/dist/components/Search/Search.svelte.d.ts +4 -0
  143. package/dist/components/Search/index.d.ts +2 -0
  144. package/dist/components/Search/index.js +1 -0
  145. package/dist/components/Search/search.types.d.ts +40 -0
  146. package/dist/components/Search/search.types.js +1 -0
  147. package/dist/components/SortableGroup/SortableGroup.svelte +53 -0
  148. package/dist/components/SortableGroup/SortableGroup.svelte.d.ts +13 -0
  149. package/dist/components/SortableGroup/index.d.ts +1 -0
  150. package/dist/components/SortableGroup/index.js +1 -0
  151. package/dist/components/SortableList/SortableList.svelte +81 -0
  152. package/dist/components/SortableList/SortableList.svelte.d.ts +26 -0
  153. package/dist/components/SortableList/index.d.ts +2 -0
  154. package/dist/components/SortableList/index.js +1 -0
  155. package/dist/components/SortableList/sortable-list.types.d.ts +21 -0
  156. package/dist/components/SortableList/sortable-list.types.js +1 -0
  157. package/dist/components/Spotlight/Spotlight.svelte +31 -0
  158. package/dist/components/Spotlight/Spotlight.svelte.d.ts +4 -0
  159. package/dist/components/Spotlight/index.d.ts +4 -0
  160. package/dist/components/Spotlight/index.js +4 -0
  161. package/dist/components/Spotlight/spotlight.types.d.ts +22 -0
  162. package/dist/components/Spotlight/spotlight.types.js +1 -0
  163. package/dist/components/Spotlight/spotlight.variants.d.ts +39 -0
  164. package/dist/components/Spotlight/spotlight.variants.js +8 -0
  165. package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte +38 -0
  166. package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte.d.ts +5 -0
  167. package/dist/components/TableBulkActionBar/index.d.ts +2 -0
  168. package/dist/components/TableBulkActionBar/index.js +1 -0
  169. package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.d.ts +31 -0
  170. package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.js +1 -0
  171. package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.d.ts +52 -0
  172. package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.js +10 -0
  173. package/dist/components/TreeView/TreeView.svelte +95 -0
  174. package/dist/components/TreeView/TreeView.svelte.d.ts +4 -0
  175. package/dist/components/TreeView/index.d.ts +4 -0
  176. package/dist/components/TreeView/index.js +3 -0
  177. package/dist/components/TreeView/tree-view.types.d.ts +68 -0
  178. package/dist/components/TreeView/tree-view.types.js +1 -0
  179. package/dist/components/TreeView/tree-view.variants.d.ts +69 -0
  180. package/dist/components/TreeView/tree-view.variants.js +30 -0
  181. package/dist/config.d.ts +91 -0
  182. package/dist/config.js +124 -0
  183. package/dist/editor.d.ts +2 -0
  184. package/dist/editor.js +2 -0
  185. package/dist/form/resolve-form-field-name.d.ts +5 -0
  186. package/dist/form/resolve-form-field-name.js +11 -0
  187. package/dist/hooks/internal/DragDropProviderScope.svelte +29 -0
  188. package/dist/hooks/internal/DragDropProviderScope.svelte.d.ts +7 -0
  189. package/dist/hooks/internal/SortableProvider.svelte +68 -0
  190. package/dist/hooks/internal/SortableProvider.svelte.d.ts +30 -0
  191. package/dist/hooks/internal/drag-drop-context.d.ts +12 -0
  192. package/dist/hooks/internal/drag-drop-context.js +1 -0
  193. package/dist/hooks/internal/sortable-context.d.ts +26 -0
  194. package/dist/hooks/internal/sortable-context.js +2 -0
  195. package/dist/hooks/useDragDrop/index.d.ts +1 -0
  196. package/dist/hooks/useDragDrop/index.js +1 -0
  197. package/dist/hooks/useDragDrop/useDragDrop.svelte.d.ts +40 -0
  198. package/dist/hooks/useDragDrop/useDragDrop.svelte.js +128 -0
  199. package/dist/hooks/useSortable/index.d.ts +2 -0
  200. package/dist/hooks/useSortable/index.js +2 -0
  201. package/dist/hooks/useSortable/sortable-utils.d.ts +1 -0
  202. package/dist/hooks/useSortable/sortable-utils.js +13 -0
  203. package/dist/hooks/useSortable/useSortable.svelte.d.ts +60 -0
  204. package/dist/hooks/useSortable/useSortable.svelte.js +151 -0
  205. package/dist/hooks/utils.d.ts +1 -0
  206. package/dist/hooks/utils.js +3 -0
  207. package/dist/index.d.ts +27 -0
  208. package/dist/index.js +30 -0
  209. package/dist/mcp/cursor.mcp.json +12 -0
  210. package/dist/mcp/install-template.mjs +55 -0
  211. package/dist/mcp/server.mjs +338 -0
  212. package/dist/mcp/sv5ui-plus-docs.data.json +17 -0
  213. package/dist/theme.css +64 -0
  214. package/package.json +176 -0
@@ -0,0 +1,287 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const navigationMenuVariants = tv({
3
+ slots: {
4
+ root: 'relative',
5
+ list: 'relative isolate min-w-0',
6
+ highlight: 'absolute z-0 rounded-full transition-all duration-200',
7
+ item: 'min-w-0',
8
+ label: 'w-full flex items-center gap-1.5 px-2.5 pt-3 pb-1 font-semibold text-sm text-on-surface-variant',
9
+ separator: 'shrink-0 bg-outline-variant',
10
+ link: [
11
+ 'group relative w-full flex items-center gap-1.5 font-medium text-sm rounded-md',
12
+ 'text-on-surface-variant',
13
+ 'transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset',
14
+ 'data-disabled:cursor-not-allowed data-disabled:opacity-60'
15
+ ],
16
+ linkLeadingIcon: 'shrink-0',
17
+ linkLeadingAvatar: 'shrink-0',
18
+ linkLabel: 'truncate',
19
+ linkLabelExternalIcon: 'size-3.5 shrink-0 text-on-surface-variant/70',
20
+ linkTrailing: 'ms-auto inline-flex items-center gap-1.5',
21
+ linkTrailingBadge: 'shrink-0',
22
+ linkTrailingIcon: 'size-5 shrink-0 transform transition-transform duration-200',
23
+ childList: 'grid gap-0.5 p-2',
24
+ childLabel: 'font-semibold text-sm text-on-surface-variant px-2 py-1.5',
25
+ childItem: 'min-w-0',
26
+ childLink: [
27
+ 'group relative w-full flex items-start gap-2.5 px-2.5 py-2 rounded-lg',
28
+ 'text-sm text-on-surface-variant',
29
+ 'transition-colors hover:bg-surface-container-high hover:text-on-surface',
30
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary',
31
+ 'data-[active]:bg-surface-container-high data-[active]:text-on-surface'
32
+ ],
33
+ childLinkWrapper: 'min-w-0 flex flex-col gap-0.5',
34
+ childLinkIcon: 'size-5 shrink-0 mt-0.5 text-on-surface-variant group-hover:text-primary',
35
+ childLinkLabel: 'font-medium text-on-surface truncate',
36
+ childLinkDescription: 'text-xs text-on-surface-variant/80 line-clamp-2',
37
+ childGroup: 'min-w-0',
38
+ childGroupLabel: 'px-2.5 pt-1 pb-1.5 font-semibold text-sm text-on-surface-variant',
39
+ childGroupList: 'grid gap-0.5',
40
+ linkBadgeDot: 'absolute top-1 end-1 size-2 rounded-full bg-error ring-2 ring-surface',
41
+ itemActions: 'absolute end-1.5 top-1/2 z-10 -translate-y-1/2 inline-flex items-center opacity-0 transition-opacity focus-within:opacity-100 group-hover/nav-row:opacity-100 has-[[data-state=open]]:opacity-100',
42
+ labelActions: 'ms-auto inline-flex items-center',
43
+ content: [
44
+ 'top-0 left-0 w-full sm:absolute sm:w-auto',
45
+ 'data-[motion=from-start]:animate-[nav-from-start_250ms_ease]',
46
+ 'data-[motion=from-end]:animate-[nav-from-end_250ms_ease]',
47
+ 'data-[motion=to-start]:animate-[nav-to-start_250ms_ease]',
48
+ 'data-[motion=to-end]:animate-[nav-to-end_250ms_ease]'
49
+ ],
50
+ viewportWrapper: 'absolute top-full left-0 z-50 flex w-full justify-start pt-1.5 [perspective:2000px]',
51
+ viewport: [
52
+ 'relative h-(--bits-navigation-menu-viewport-height) w-full origin-[top_center] overflow-hidden sm:w-(--bits-navigation-menu-viewport-width)',
53
+ 'rounded-xl border border-outline-variant bg-surface-container-low shadow-lg',
54
+ 'transition-[width,height] duration-200',
55
+ 'data-[state=open]:animate-[nav-scale-in_200ms_ease]',
56
+ 'data-[state=closed]:animate-[nav-scale-out_200ms_ease]'
57
+ ],
58
+ indicator: [
59
+ 'top-full z-50 flex h-2 items-end justify-center overflow-hidden',
60
+ 'data-[state=visible]:animate-[fade-in_150ms_ease]',
61
+ 'data-[state=hidden]:animate-[fade-out_150ms_ease]'
62
+ ],
63
+ arrow: 'relative top-[60%] size-2 rotate-45 rounded-tl-sm border-t border-l border-outline-variant bg-surface-container-low',
64
+ toggle: '',
65
+ childTrigger: 'group ms-auto inline-flex items-center justify-center transition-transform duration-200'
66
+ },
67
+ variants: {
68
+ variant: {
69
+ pill: '',
70
+ link: ''
71
+ },
72
+ color: {
73
+ primary: { highlight: 'bg-primary' },
74
+ secondary: { highlight: 'bg-secondary' },
75
+ tertiary: { highlight: 'bg-tertiary' },
76
+ success: { highlight: 'bg-success' },
77
+ warning: { highlight: 'bg-warning' },
78
+ error: { highlight: 'bg-error' },
79
+ info: { highlight: 'bg-info' },
80
+ surface: { highlight: 'bg-on-surface-variant' }
81
+ },
82
+ orientation: {
83
+ horizontal: {
84
+ root: 'w-full',
85
+ list: 'flex items-center gap-1 overflow-x-auto scrollbar-thin',
86
+ separator: 'mx-1 h-5 w-px self-center',
87
+ highlight: 'bottom-0 h-0.5'
88
+ },
89
+ vertical: {
90
+ root: 'w-full',
91
+ list: 'flex flex-col gap-0.5',
92
+ item: 'flex flex-col',
93
+ separator: 'my-1 h-px w-full',
94
+ childList: 'ms-3.5 mt-0.5 gap-0.5 border-s border-outline-variant p-0 ps-2',
95
+ highlight: 'start-0 w-0.5'
96
+ }
97
+ },
98
+ highlight: {
99
+ true: '',
100
+ false: ''
101
+ },
102
+ collapsed: {
103
+ true: {
104
+ link: 'justify-center',
105
+ linkLabel: 'sr-only',
106
+ linkTrailing: 'hidden'
107
+ },
108
+ false: ''
109
+ },
110
+ stacked: {
111
+ true: '',
112
+ false: ''
113
+ },
114
+ contentOrientation: {
115
+ horizontal: {},
116
+ vertical: {}
117
+ },
118
+ disabled: {
119
+ true: '',
120
+ false: ''
121
+ }
122
+ },
123
+ compoundVariants: [
124
+ {
125
+ orientation: 'horizontal',
126
+ class: {
127
+ item: 'shrink-0',
128
+ link: 'w-auto px-2.5 py-1.5',
129
+ label: 'w-auto shrink-0 whitespace-nowrap',
130
+ childList: 'min-w-60'
131
+ }
132
+ },
133
+ {
134
+ orientation: 'horizontal',
135
+ contentOrientation: 'horizontal',
136
+ class: { childList: 'sm:w-128 sm:grid-cols-2' }
137
+ },
138
+ {
139
+ orientation: 'vertical',
140
+ class: { link: 'px-2.5 py-1.5' }
141
+ },
142
+ {
143
+ stacked: true,
144
+ class: {
145
+ link: 'flex-col justify-center gap-1 py-2',
146
+ linkLabel: 'text-xs leading-tight',
147
+ linkTrailing: 'hidden'
148
+ }
149
+ },
150
+ {
151
+ orientation: 'horizontal',
152
+ stacked: true,
153
+ class: {
154
+ list: 'justify-around overflow-visible',
155
+ item: 'flex-1',
156
+ link: 'w-full'
157
+ }
158
+ },
159
+ {
160
+ collapsed: true,
161
+ stacked: true,
162
+ class: { linkLabel: 'not-sr-only text-xs leading-tight' }
163
+ },
164
+ {
165
+ variant: 'pill',
166
+ class: {
167
+ link: 'hover:bg-surface-container-high hover:text-on-surface data-[state=open]:bg-surface-container-high'
168
+ }
169
+ },
170
+ {
171
+ variant: 'link',
172
+ class: {
173
+ link: 'hover:text-on-surface data-[state=open]:text-on-surface'
174
+ }
175
+ },
176
+ {
177
+ variant: 'pill',
178
+ color: 'primary',
179
+ class: {
180
+ link: 'data-[active]:bg-primary-container data-[active]:text-on-primary-container focus-visible:ring-primary'
181
+ }
182
+ },
183
+ {
184
+ variant: 'pill',
185
+ color: 'secondary',
186
+ class: {
187
+ link: 'data-[active]:bg-secondary-container data-[active]:text-on-secondary-container focus-visible:ring-secondary'
188
+ }
189
+ },
190
+ {
191
+ variant: 'pill',
192
+ color: 'tertiary',
193
+ class: {
194
+ link: 'data-[active]:bg-tertiary-container data-[active]:text-on-tertiary-container focus-visible:ring-tertiary'
195
+ }
196
+ },
197
+ {
198
+ variant: 'pill',
199
+ color: 'success',
200
+ class: {
201
+ link: 'data-[active]:bg-success-container data-[active]:text-on-success-container focus-visible:ring-success'
202
+ }
203
+ },
204
+ {
205
+ variant: 'pill',
206
+ color: 'warning',
207
+ class: {
208
+ link: 'data-[active]:bg-warning-container data-[active]:text-on-warning-container focus-visible:ring-warning'
209
+ }
210
+ },
211
+ {
212
+ variant: 'pill',
213
+ color: 'error',
214
+ class: {
215
+ link: 'data-[active]:bg-error-container data-[active]:text-on-error-container focus-visible:ring-error'
216
+ }
217
+ },
218
+ {
219
+ variant: 'pill',
220
+ color: 'info',
221
+ class: {
222
+ link: 'data-[active]:bg-info-container data-[active]:text-on-info-container focus-visible:ring-info'
223
+ }
224
+ },
225
+ {
226
+ variant: 'pill',
227
+ color: 'surface',
228
+ class: {
229
+ link: 'data-[active]:bg-surface-container-high data-[active]:text-on-surface focus-visible:ring-outline'
230
+ }
231
+ },
232
+ {
233
+ variant: 'link',
234
+ color: 'primary',
235
+ class: { link: 'data-[active]:text-primary focus-visible:ring-primary' }
236
+ },
237
+ {
238
+ variant: 'link',
239
+ color: 'secondary',
240
+ class: { link: 'data-[active]:text-secondary focus-visible:ring-secondary' }
241
+ },
242
+ {
243
+ variant: 'link',
244
+ color: 'tertiary',
245
+ class: { link: 'data-[active]:text-tertiary focus-visible:ring-tertiary' }
246
+ },
247
+ {
248
+ variant: 'link',
249
+ color: 'success',
250
+ class: { link: 'data-[active]:text-success focus-visible:ring-success' }
251
+ },
252
+ {
253
+ variant: 'link',
254
+ color: 'warning',
255
+ class: { link: 'data-[active]:text-warning focus-visible:ring-warning' }
256
+ },
257
+ {
258
+ variant: 'link',
259
+ color: 'error',
260
+ class: { link: 'data-[active]:text-error focus-visible:ring-error' }
261
+ },
262
+ {
263
+ variant: 'link',
264
+ color: 'info',
265
+ class: { link: 'data-[active]:text-info focus-visible:ring-info' }
266
+ },
267
+ {
268
+ variant: 'link',
269
+ color: 'surface',
270
+ class: { link: 'data-[active]:text-on-surface focus-visible:ring-outline' }
271
+ }
272
+ ],
273
+ defaultVariants: {
274
+ variant: 'pill',
275
+ color: 'primary',
276
+ orientation: 'horizontal',
277
+ highlight: false,
278
+ collapsed: false,
279
+ stacked: false,
280
+ contentOrientation: 'horizontal',
281
+ disabled: false
282
+ }
283
+ });
284
+ export const navigationMenuDefaults = {
285
+ defaultVariants: navigationMenuVariants.defaultVariants,
286
+ slots: {}
287
+ };
@@ -0,0 +1,59 @@
1
+ <script lang="ts">import { twMerge } from "tailwind-merge";
2
+ import { onMount } from "svelte";
3
+ import { numberTickerVariants } from "./number-ticker.variants.js";
4
+ let { value, duration = 2e3, decimals = 0, delay = 0, class: className, ...restProps } = $props();
5
+ let styles = $derived(numberTickerVariants());
6
+ let displayValue = $state(0);
7
+ let isVisible = $state(false);
8
+ let nodeRef = $state(null);
9
+ // Easing function (easeOutExpo)
10
+ const easeOutExpo = (x) => {
11
+ return x === 1 ? 1 : 1 - 2 ** (-10 * x);
12
+ };
13
+ onMount(() => {
14
+ if (!nodeRef) return;
15
+ let startTime = null;
16
+ let animationFrame;
17
+ const animate = (timestamp) => {
18
+ if (!startTime) startTime = timestamp;
19
+ const progress = timestamp - startTime;
20
+ if (progress < duration) {
21
+ const percentage = progress / duration;
22
+ const easedProgress = easeOutExpo(percentage);
23
+ displayValue = value * easedProgress;
24
+ animationFrame = requestAnimationFrame(animate);
25
+ } else {
26
+ displayValue = value;
27
+ }
28
+ };
29
+ const observer = new IntersectionObserver((entries) => {
30
+ if (entries[0].isIntersecting && !isVisible) {
31
+ isVisible = true;
32
+ setTimeout(() => {
33
+ animationFrame = requestAnimationFrame(animate);
34
+ }, delay);
35
+ }
36
+ }, { threshold: .1 });
37
+ observer.observe(nodeRef);
38
+ return () => {
39
+ observer.disconnect();
40
+ if (animationFrame) cancelAnimationFrame(animationFrame);
41
+ };
42
+ });
43
+ // Re-animate if value changes significantly (optional)
44
+ $effect(() => {
45
+ if (isVisible && value !== undefined) {}
46
+ });
47
+ let formattedValue = $derived(new Intl.NumberFormat("en-US", {
48
+ minimumFractionDigits: decimals,
49
+ maximumFractionDigits: decimals
50
+ }).format(displayValue));
51
+ </script>
52
+
53
+ <span
54
+ bind:this={nodeRef}
55
+ class={twMerge(styles.base() as string, className)}
56
+ {...restProps}
57
+ >
58
+ {formattedValue}
59
+ </span>
@@ -0,0 +1,4 @@
1
+ import type { NumberTickerProps } from './number-ticker.types.js';
2
+ declare const NumberTicker: import("svelte").Component<NumberTickerProps, {}, "">;
3
+ type NumberTicker = ReturnType<typeof NumberTicker>;
4
+ export default NumberTicker;
@@ -0,0 +1,4 @@
1
+ import NumberTicker from './NumberTicker.svelte';
2
+ export { NumberTicker };
3
+ export * from './number-ticker.types.js';
4
+ export * from './number-ticker.variants.js';
@@ -0,0 +1,4 @@
1
+ import NumberTicker from './NumberTicker.svelte';
2
+ export { NumberTicker };
3
+ export * from './number-ticker.types.js';
4
+ export * from './number-ticker.variants.js';
@@ -0,0 +1,26 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ export interface NumberTickerProps extends HTMLAttributes<HTMLSpanElement> {
3
+ /**
4
+ * The target number to animate to.
5
+ */
6
+ value: number;
7
+ /**
8
+ * Duration of the animation in milliseconds.
9
+ * @default 2000
10
+ */
11
+ duration?: number;
12
+ /**
13
+ * Whether to show decimal places.
14
+ * @default 0
15
+ */
16
+ decimals?: number;
17
+ /**
18
+ * Start delay in milliseconds.
19
+ * @default 0
20
+ */
21
+ delay?: number;
22
+ /**
23
+ * Additional CSS classes.
24
+ */
25
+ class?: string;
26
+ }
@@ -0,0 +1,27 @@
1
+ import { type VariantProps } from 'tailwind-variants';
2
+ export declare const numberTickerVariants: import("tailwind-variants").TVReturnType<{
3
+ [key: string]: {
4
+ [key: string]: import("tailwind-variants").ClassValue | {
5
+ base?: import("tailwind-variants").ClassValue;
6
+ };
7
+ };
8
+ } | {
9
+ [x: string]: {
10
+ [x: string]: import("tailwind-variants").ClassValue | {
11
+ base?: import("tailwind-variants").ClassValue;
12
+ };
13
+ };
14
+ } | {}, {
15
+ base: string;
16
+ }, undefined, {
17
+ [key: string]: {
18
+ [key: string]: import("tailwind-variants").ClassValue | {
19
+ base?: import("tailwind-variants").ClassValue;
20
+ };
21
+ };
22
+ } | {}, {
23
+ base: string;
24
+ }, import("tailwind-variants").TVReturnTypeLike<unknown, {
25
+ base: string;
26
+ }>>;
27
+ export type NumberTickerVariantProps = VariantProps<typeof numberTickerVariants>;
@@ -0,0 +1,6 @@
1
+ import { tv } from 'tailwind-variants';
2
+ export const numberTickerVariants = tv({
3
+ slots: {
4
+ base: 'inline-block font-mono tracking-wider tabular-nums text-surface-900 dark:text-surface-50'
5
+ }
6
+ });
@@ -0,0 +1,182 @@
1
+ <script lang="ts" module>export {};
2
+ </script>
3
+
4
+ <script lang="ts">import { getComponentConfig } from "../../config.js";
5
+ import { Icon } from "sv5ui";
6
+ import { Input } from "sv5ui";
7
+ import { passwordInputVariants, passwordInputDefaults } from "./password-input.variants.js";
8
+ const config = getComponentConfig("passwordInput", passwordInputDefaults);
9
+ let { ref = $bindable(null), value = $bindable(""), showStrength = false, strengthFn, strengthLabels = [
10
+ "Very Weak",
11
+ "Weak",
12
+ "Fair",
13
+ "Good",
14
+ "Strong"
15
+ ], segmentIcon, maskChar, hideIcon = "lucide:eye-off", showIcon = "lucide:eye", hideLabel = "Hide password", showLabel = "Show password", size = config.defaultVariants.size ?? "md", color = config.defaultVariants.color ?? "primary", variant = config.defaultVariants.variant ?? "outline", class: className, ui, name, oninput, ...restProps } = $props();
16
+ let isVisible = $state(false);
17
+ function toggleVisibility() {
18
+ isVisible = !isVisible;
19
+ }
20
+ const useMaskChar = $derived(!!maskChar && maskChar !== "•" && !isVisible);
21
+ const displayValue = $derived(useMaskChar ? (maskChar ?? "✦").repeat(String(value ?? "").length) : String(value ?? ""));
22
+ function handleInput(e) {
23
+ if (useMaskChar) {
24
+ const input = e.currentTarget;
25
+ const newStr = input.value;
26
+ const oldVal = String(value ?? "");
27
+ const char = maskChar ?? "✦";
28
+ let prefixCount = 0;
29
+ let suffixCount = 0;
30
+ let inserted = "";
31
+ // Check if user inserted non-mask text (typing or pasting)
32
+ const firstNonMask = newStr.indexOf(char === "" ? "✦" : char);
33
+ const hasMaskChars = firstNonMask !== -1;
34
+ if (!hasMaskChars) {
35
+ // All mask chars were replaced/deleted
36
+ inserted = newStr;
37
+ prefixCount = 0;
38
+ suffixCount = 0;
39
+ } else {
40
+ // Count leading mask chars
41
+ while (prefixCount < newStr.length && newStr[prefixCount] === char) {
42
+ prefixCount++;
43
+ }
44
+ // Count trailing mask chars
45
+ while (suffixCount < newStr.length - prefixCount && newStr[newStr.length - 1 - suffixCount] === char) {
46
+ suffixCount++;
47
+ }
48
+ // Extract inserted text between prefix and suffix mask chars
49
+ inserted = newStr.slice(prefixCount, newStr.length - suffixCount);
50
+ // Deletion only case (no inserted text)
51
+ if (inserted === "" && newStr.length < oldVal.length) {
52
+ const cursorPos = input.selectionStart ?? prefixCount;
53
+ prefixCount = cursorPos;
54
+ suffixCount = newStr.length - cursorPos;
55
+ }
56
+ }
57
+ const head = oldVal.slice(0, prefixCount);
58
+ const tail = oldVal.slice(Math.max(prefixCount, oldVal.length - suffixCount));
59
+ value = head + inserted + tail;
60
+ const updatedVal = String(value ?? "");
61
+ input.value = char.repeat(updatedVal.length);
62
+ const newCursorPos = prefixCount + inserted.length;
63
+ try {
64
+ input.setSelectionRange(newCursorPos, newCursorPos);
65
+ } catch {}
66
+ } else {
67
+ value = e.currentTarget.value;
68
+ }
69
+ oninput?.(e);
70
+ }
71
+ // Built-in strength heuristic: returns -1 when empty, 0–4 otherwise.
72
+ function calculateStrength(pwd) {
73
+ if (!pwd) return -1;
74
+ let score = 0;
75
+ if (pwd.length >= 8) score += 1;
76
+ if (/[A-Z]/.test(pwd) && /[a-z]/.test(pwd)) score += 1;
77
+ if (/[0-9]/.test(pwd)) score += 1;
78
+ if (/[^A-Za-z0-9]/.test(pwd)) score += 1;
79
+ return score;
80
+ }
81
+ const strength = $derived(strengthFn ? strengthFn(String(value ?? "")) : calculateStrength(String(value ?? "")));
82
+ function getSegmentBgColor(index, currentStrength) {
83
+ if (currentStrength <= 0 || index >= currentStrength) {
84
+ return "bg-surface-200 dark:bg-surface-700";
85
+ }
86
+ if (currentStrength === 1) return "bg-error-500";
87
+ if (currentStrength === 2) return "bg-warning-500";
88
+ if (currentStrength === 3) return "bg-success-400";
89
+ return "bg-success-500";
90
+ }
91
+ function getSegmentTextColor(index, currentStrength) {
92
+ if (currentStrength <= 0 || index >= currentStrength) {
93
+ return "text-surface-200 dark:text-surface-700";
94
+ }
95
+ if (currentStrength === 1) return "text-error-500";
96
+ if (currentStrength === 2) return "text-warning-500";
97
+ if (currentStrength === 3) return "text-success-400";
98
+ return "text-success-500";
99
+ }
100
+ const variantSlots = $derived(passwordInputVariants({
101
+ size,
102
+ color,
103
+ variant
104
+ }));
105
+ const classes = $derived({
106
+ root: variantSlots.root({ class: [
107
+ config.slots.root,
108
+ className,
109
+ ui?.root
110
+ ] }),
111
+ inputWrapper: variantSlots.inputWrapper({ class: [config.slots.inputWrapper, ui?.inputWrapper] }),
112
+ toggleBtn: variantSlots.toggleBtn({ class: [config.slots.toggleBtn, ui?.toggleBtn] }),
113
+ toggleIcon: variantSlots.toggleIcon({ class: [config.slots.toggleIcon, ui?.toggleIcon] }),
114
+ meterWrapper: variantSlots.meterWrapper({ class: [config.slots.meterWrapper, ui?.meterWrapper] }),
115
+ meterSegment: variantSlots.meterSegment({ class: [config.slots.meterSegment, ui?.meterSegment] }),
116
+ meterIcon: variantSlots.meterIcon({ class: [config.slots.meterIcon, ui?.meterIcon] }),
117
+ strengthText: variantSlots.strengthText({ class: [config.slots.strengthText, ui?.strengthText] })
118
+ });
119
+ </script>
120
+
121
+ <div class={classes.root}>
122
+ {#if useMaskChar && name}
123
+ <input type="hidden" {name} value={value ?? ''} />
124
+ {/if}
125
+ <div class={classes.inputWrapper}>
126
+ <Input
127
+ {...restProps}
128
+ bind:ref
129
+ name={useMaskChar ? undefined : name}
130
+ value={useMaskChar ? displayValue : value}
131
+ {size}
132
+ {color}
133
+ {variant}
134
+ type={useMaskChar || isVisible ? 'text' : 'password'}
135
+ class="w-full"
136
+ oninput={handleInput}
137
+ ui={{
138
+ base: ui?.base,
139
+ root: ui?.inputRoot,
140
+ leading: ui?.leading,
141
+ leadingIcon: ui?.leadingIcon,
142
+ trailing: ui?.trailing,
143
+ trailingIcon: ui?.trailingIcon
144
+ }}
145
+ trailing
146
+ />
147
+
148
+ <button
149
+ type="button"
150
+ class={classes.toggleBtn}
151
+ onclick={toggleVisibility}
152
+ aria-label={isVisible ? hideLabel : showLabel}
153
+ aria-pressed={isVisible}
154
+ >
155
+ {#if isVisible}
156
+ <Icon name={hideIcon} class={classes.toggleIcon} />
157
+ {:else}
158
+ <Icon name={showIcon} class={classes.toggleIcon} />
159
+ {/if}
160
+ </button>
161
+ </div>
162
+
163
+ {#if showStrength && String(value ?? '').length > 0}
164
+ <div>
165
+ <div class={classes.meterWrapper}>
166
+ {#each { length: 4 } as _, i (i)}
167
+ {#if segmentIcon}
168
+ <Icon
169
+ name={segmentIcon}
170
+ class="{classes.meterIcon} {getSegmentTextColor(i, strength)}"
171
+ />
172
+ {:else}
173
+ <div class="{classes.meterSegment} {getSegmentBgColor(i, strength)}"></div>
174
+ {/if}
175
+ {/each}
176
+ </div>
177
+ <p class={classes.strengthText}>
178
+ {strengthLabels[Math.max(0, strength)]}
179
+ </p>
180
+ </div>
181
+ {/if}
182
+ </div>
@@ -0,0 +1,5 @@
1
+ import type { PasswordInputProps } from './password-input.types.js';
2
+ export type Props = PasswordInputProps;
3
+ declare const PasswordInput: import("svelte").Component<PasswordInputProps, {}, "value" | "ref">;
4
+ type PasswordInput = ReturnType<typeof PasswordInput>;
5
+ export default PasswordInput;
@@ -0,0 +1,2 @@
1
+ export { default as PasswordInput } from './PasswordInput.svelte';
2
+ export type { PasswordInputProps } from './password-input.types.js';
@@ -0,0 +1 @@
1
+ export { default as PasswordInput } from './PasswordInput.svelte';