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.
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/adapters/notify.d.ts +29 -0
- package/dist/adapters/notify.js +88 -0
- package/dist/compat.d.ts +6 -0
- package/dist/compat.js +6 -0
- package/dist/components/BentoGrid/BentoCard.svelte +45 -0
- package/dist/components/BentoGrid/BentoCard.svelte.d.ts +4 -0
- package/dist/components/BentoGrid/BentoGrid.svelte +9 -0
- package/dist/components/BentoGrid/BentoGrid.svelte.d.ts +4 -0
- package/dist/components/BentoGrid/bento-grid.types.d.ts +47 -0
- package/dist/components/BentoGrid/bento-grid.types.js +1 -0
- package/dist/components/BentoGrid/bento-grid.variants.d.ts +30 -0
- package/dist/components/BentoGrid/bento-grid.variants.js +16 -0
- package/dist/components/BentoGrid/index.d.ts +5 -0
- package/dist/components/BentoGrid/index.js +5 -0
- package/dist/components/Chart/Chart.svelte +62 -0
- package/dist/components/Chart/Chart.svelte.d.ts +4 -0
- package/dist/components/Chart/chart.types.d.ts +16 -0
- package/dist/components/Chart/chart.types.js +1 -0
- package/dist/components/Chart/index.d.ts +2 -0
- package/dist/components/Chart/index.js +2 -0
- package/dist/components/Chat/ChatBubble.svelte +30 -0
- package/dist/components/Chat/ChatBubble.svelte.d.ts +4 -0
- package/dist/components/Chat/ChatInput.svelte +50 -0
- package/dist/components/Chat/ChatInput.svelte.d.ts +4 -0
- package/dist/components/Chat/ChatMessage.svelte +15 -0
- package/dist/components/Chat/ChatMessage.svelte.d.ts +4 -0
- package/dist/components/Chat/chat.types.d.ts +63 -0
- package/dist/components/Chat/chat.types.js +1 -0
- package/dist/components/Chat/chat.variants.d.ts +117 -0
- package/dist/components/Chat/chat.variants.js +47 -0
- package/dist/components/Chat/index.d.ts +6 -0
- package/dist/components/Chat/index.js +6 -0
- package/dist/components/CodeBlock/CodeBlock.svelte +66 -0
- package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +5 -0
- package/dist/components/CodeBlock/code-block.types.d.ts +15 -0
- package/dist/components/CodeBlock/code-block.types.js +1 -0
- package/dist/components/CodeBlock/code-block.variants.d.ts +288 -0
- package/dist/components/CodeBlock/code-block.variants.js +69 -0
- package/dist/components/CodeBlock/index.d.ts +2 -0
- package/dist/components/CodeBlock/index.js +1 -0
- package/dist/components/ColorPicker/ColorPicker.svelte +109 -0
- package/dist/components/ColorPicker/ColorPicker.svelte.d.ts +4 -0
- package/dist/components/ColorPicker/color-picker.types.d.ts +26 -0
- package/dist/components/ColorPicker/color-picker.types.js +1 -0
- package/dist/components/ColorPicker/color-picker.variants.d.ts +69 -0
- package/dist/components/ColorPicker/color-picker.variants.js +13 -0
- package/dist/components/ColorPicker/index.d.ts +4 -0
- package/dist/components/ColorPicker/index.js +4 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.svelte +175 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.svelte.d.ts +10 -0
- package/dist/components/ConfirmDialog/confirm.d.ts +9 -0
- package/dist/components/ConfirmDialog/confirm.js +24 -0
- package/dist/components/ConfirmDialog/confirm.types.d.ts +21 -0
- package/dist/components/ConfirmDialog/confirm.types.js +1 -0
- package/dist/components/ConfirmDialog/index.d.ts +4 -0
- package/dist/components/ConfirmDialog/index.js +2 -0
- package/dist/components/Fonts/Fonts.svelte +32 -0
- package/dist/components/Fonts/Fonts.svelte.d.ts +5 -0
- package/dist/components/Fonts/fonts.d.ts +12 -0
- package/dist/components/Fonts/fonts.js +126 -0
- package/dist/components/Fonts/fonts.types.d.ts +40 -0
- package/dist/components/Fonts/fonts.types.js +1 -0
- package/dist/components/Fonts/index.d.ts +3 -0
- package/dist/components/Fonts/index.js +2 -0
- package/dist/components/List/List.svelte +14 -0
- package/dist/components/List/List.svelte.d.ts +4 -0
- package/dist/components/List/ListItem.svelte +64 -0
- package/dist/components/List/ListItem.svelte.d.ts +4 -0
- package/dist/components/List/index.d.ts +5 -0
- package/dist/components/List/index.js +5 -0
- package/dist/components/List/list.types.d.ts +62 -0
- package/dist/components/List/list.types.js +1 -0
- package/dist/components/List/list.variants.d.ts +99 -0
- package/dist/components/List/list.variants.js +42 -0
- package/dist/components/LocaleButton/LocaleButton.svelte +181 -0
- package/dist/components/LocaleButton/LocaleButton.svelte.d.ts +5 -0
- package/dist/components/LocaleButton/index.d.ts +2 -0
- package/dist/components/LocaleButton/index.js +1 -0
- package/dist/components/LocaleButton/locale-button.types.d.ts +208 -0
- package/dist/components/LocaleButton/locale-button.types.js +1 -0
- package/dist/components/LocaleButton/locale-button.variants.d.ts +245 -0
- package/dist/components/LocaleButton/locale-button.variants.js +98 -0
- package/dist/components/Marquee/Marquee.svelte +50 -0
- package/dist/components/Marquee/Marquee.svelte.d.ts +4 -0
- package/dist/components/Marquee/index.d.ts +4 -0
- package/dist/components/Marquee/index.js +4 -0
- package/dist/components/Marquee/marquee.types.d.ts +38 -0
- package/dist/components/Marquee/marquee.types.js +1 -0
- package/dist/components/Marquee/marquee.variants.d.ts +78 -0
- package/dist/components/Marquee/marquee.variants.js +28 -0
- package/dist/components/NavigationMenu/NavigationMenu.svelte +623 -0
- package/dist/components/NavigationMenu/NavigationMenu.svelte.d.ts +5 -0
- package/dist/components/NavigationMenu/index.d.ts +2 -0
- package/dist/components/NavigationMenu/index.js +1 -0
- package/dist/components/NavigationMenu/navigation-menu.types.d.ts +245 -0
- package/dist/components/NavigationMenu/navigation-menu.types.js +1 -0
- package/dist/components/NavigationMenu/navigation-menu.variants.d.ts +543 -0
- package/dist/components/NavigationMenu/navigation-menu.variants.js +287 -0
- package/dist/components/NumberTicker/NumberTicker.svelte +59 -0
- package/dist/components/NumberTicker/NumberTicker.svelte.d.ts +4 -0
- package/dist/components/NumberTicker/index.d.ts +4 -0
- package/dist/components/NumberTicker/index.js +4 -0
- package/dist/components/NumberTicker/number-ticker.types.d.ts +26 -0
- package/dist/components/NumberTicker/number-ticker.types.js +1 -0
- package/dist/components/NumberTicker/number-ticker.variants.d.ts +27 -0
- package/dist/components/NumberTicker/number-ticker.variants.js +6 -0
- package/dist/components/PasswordInput/PasswordInput.svelte +182 -0
- package/dist/components/PasswordInput/PasswordInput.svelte.d.ts +5 -0
- package/dist/components/PasswordInput/index.d.ts +2 -0
- package/dist/components/PasswordInput/index.js +1 -0
- package/dist/components/PasswordInput/password-input.types.d.ts +111 -0
- package/dist/components/PasswordInput/password-input.types.js +1 -0
- package/dist/components/PasswordInput/password-input.variants.d.ts +273 -0
- package/dist/components/PasswordInput/password-input.variants.js +105 -0
- package/dist/components/Prose/Prose.svelte +13 -0
- package/dist/components/Prose/Prose.svelte.d.ts +4 -0
- package/dist/components/Prose/index.d.ts +4 -0
- package/dist/components/Prose/index.js +4 -0
- package/dist/components/Prose/prose.types.d.ts +22 -0
- package/dist/components/Prose/prose.types.js +1 -0
- package/dist/components/Prose/prose.variants.d.ts +45 -0
- package/dist/components/Prose/prose.variants.js +45 -0
- package/dist/components/Resizable/Resizable.svelte +9 -0
- package/dist/components/Resizable/Resizable.svelte.d.ts +4 -0
- package/dist/components/Resizable/index.d.ts +4 -0
- package/dist/components/Resizable/index.js +4 -0
- package/dist/components/Resizable/resizable.types.d.ts +18 -0
- package/dist/components/Resizable/resizable.types.js +1 -0
- package/dist/components/Resizable/resizable.variants.d.ts +48 -0
- package/dist/components/Resizable/resizable.variants.js +17 -0
- package/dist/components/ScrollArea/ScrollArea.svelte +54 -0
- package/dist/components/ScrollArea/ScrollArea.svelte.d.ts +4 -0
- package/dist/components/ScrollArea/index.d.ts +4 -0
- package/dist/components/ScrollArea/index.js +4 -0
- package/dist/components/ScrollArea/scroll-area.types.d.ts +27 -0
- package/dist/components/ScrollArea/scroll-area.types.js +1 -0
- package/dist/components/ScrollArea/scroll-area.variants.d.ts +45 -0
- package/dist/components/ScrollArea/scroll-area.variants.js +27 -0
- package/dist/components/Search/Search.svelte +94 -0
- package/dist/components/Search/Search.svelte.d.ts +4 -0
- package/dist/components/Search/index.d.ts +2 -0
- package/dist/components/Search/index.js +1 -0
- package/dist/components/Search/search.types.d.ts +40 -0
- package/dist/components/Search/search.types.js +1 -0
- package/dist/components/SortableGroup/SortableGroup.svelte +53 -0
- package/dist/components/SortableGroup/SortableGroup.svelte.d.ts +13 -0
- package/dist/components/SortableGroup/index.d.ts +1 -0
- package/dist/components/SortableGroup/index.js +1 -0
- package/dist/components/SortableList/SortableList.svelte +81 -0
- package/dist/components/SortableList/SortableList.svelte.d.ts +26 -0
- package/dist/components/SortableList/index.d.ts +2 -0
- package/dist/components/SortableList/index.js +1 -0
- package/dist/components/SortableList/sortable-list.types.d.ts +21 -0
- package/dist/components/SortableList/sortable-list.types.js +1 -0
- package/dist/components/Spotlight/Spotlight.svelte +31 -0
- package/dist/components/Spotlight/Spotlight.svelte.d.ts +4 -0
- package/dist/components/Spotlight/index.d.ts +4 -0
- package/dist/components/Spotlight/index.js +4 -0
- package/dist/components/Spotlight/spotlight.types.d.ts +22 -0
- package/dist/components/Spotlight/spotlight.types.js +1 -0
- package/dist/components/Spotlight/spotlight.variants.d.ts +39 -0
- package/dist/components/Spotlight/spotlight.variants.js +8 -0
- package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte +38 -0
- package/dist/components/TableBulkActionBar/TableBulkActionBar.svelte.d.ts +5 -0
- package/dist/components/TableBulkActionBar/index.d.ts +2 -0
- package/dist/components/TableBulkActionBar/index.js +1 -0
- package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.d.ts +31 -0
- package/dist/components/TableBulkActionBar/table-bulk-action-bar.types.js +1 -0
- package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.d.ts +52 -0
- package/dist/components/TableBulkActionBar/table-bulk-action-bar.variants.js +10 -0
- package/dist/components/TreeView/TreeView.svelte +95 -0
- package/dist/components/TreeView/TreeView.svelte.d.ts +4 -0
- package/dist/components/TreeView/index.d.ts +4 -0
- package/dist/components/TreeView/index.js +3 -0
- package/dist/components/TreeView/tree-view.types.d.ts +68 -0
- package/dist/components/TreeView/tree-view.types.js +1 -0
- package/dist/components/TreeView/tree-view.variants.d.ts +69 -0
- package/dist/components/TreeView/tree-view.variants.js +30 -0
- package/dist/config.d.ts +91 -0
- package/dist/config.js +124 -0
- package/dist/editor.d.ts +2 -0
- package/dist/editor.js +2 -0
- package/dist/form/resolve-form-field-name.d.ts +5 -0
- package/dist/form/resolve-form-field-name.js +11 -0
- package/dist/hooks/internal/DragDropProviderScope.svelte +29 -0
- package/dist/hooks/internal/DragDropProviderScope.svelte.d.ts +7 -0
- package/dist/hooks/internal/SortableProvider.svelte +68 -0
- package/dist/hooks/internal/SortableProvider.svelte.d.ts +30 -0
- package/dist/hooks/internal/drag-drop-context.d.ts +12 -0
- package/dist/hooks/internal/drag-drop-context.js +1 -0
- package/dist/hooks/internal/sortable-context.d.ts +26 -0
- package/dist/hooks/internal/sortable-context.js +2 -0
- package/dist/hooks/useDragDrop/index.d.ts +1 -0
- package/dist/hooks/useDragDrop/index.js +1 -0
- package/dist/hooks/useDragDrop/useDragDrop.svelte.d.ts +40 -0
- package/dist/hooks/useDragDrop/useDragDrop.svelte.js +128 -0
- package/dist/hooks/useSortable/index.d.ts +2 -0
- package/dist/hooks/useSortable/index.js +2 -0
- package/dist/hooks/useSortable/sortable-utils.d.ts +1 -0
- package/dist/hooks/useSortable/sortable-utils.js +13 -0
- package/dist/hooks/useSortable/useSortable.svelte.d.ts +60 -0
- package/dist/hooks/useSortable/useSortable.svelte.js +151 -0
- package/dist/hooks/utils.d.ts +1 -0
- package/dist/hooks/utils.js +3 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +30 -0
- package/dist/mcp/cursor.mcp.json +12 -0
- package/dist/mcp/install-template.mjs +55 -0
- package/dist/mcp/server.mjs +338 -0
- package/dist/mcp/sv5ui-plus-docs.data.json +17 -0
- package/dist/theme.css +64 -0
- 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,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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,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 @@
|
|
|
1
|
+
export { default as PasswordInput } from './PasswordInput.svelte';
|