sv5ui 1.1.3 → 1.3.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 (187) hide show
  1. package/README.md +6 -0
  2. package/dist/Alert/Alert.svelte +33 -22
  3. package/dist/Alert/Alert.svelte.d.ts +1 -1
  4. package/dist/Alert/alert.types.d.ts +4 -0
  5. package/dist/Avatar/Avatar.svelte +72 -46
  6. package/dist/Avatar/avatar.types.d.ts +36 -3
  7. package/dist/Avatar/avatar.variants.d.ts +138 -0
  8. package/dist/Avatar/avatar.variants.js +23 -12
  9. package/dist/Avatar/index.d.ts +1 -1
  10. package/dist/AvatarGroup/AvatarGroup.svelte +11 -6
  11. package/dist/AvatarGroup/AvatarGroup.svelte.d.ts +1 -1
  12. package/dist/AvatarGroup/avatar-group.types.d.ts +18 -3
  13. package/dist/AvatarGroup/avatar-group.variants.d.ts +85 -0
  14. package/dist/AvatarGroup/avatar-group.variants.js +19 -29
  15. package/dist/Badge/Badge.svelte +4 -3
  16. package/dist/Badge/Badge.svelte.d.ts +1 -1
  17. package/dist/Badge/badge.types.d.ts +9 -0
  18. package/dist/Breadcrumb/Breadcrumb.svelte +20 -7
  19. package/dist/Breadcrumb/Breadcrumb.svelte.d.ts +1 -1
  20. package/dist/Breadcrumb/breadcrumb.types.d.ts +5 -1
  21. package/dist/Breadcrumb/breadcrumb.variants.d.ts +15 -5
  22. package/dist/Breadcrumb/breadcrumb.variants.js +7 -3
  23. package/dist/Button/Button.svelte +71 -16
  24. package/dist/Button/Button.svelte.d.ts +0 -1
  25. package/dist/Button/button.types.d.ts +61 -2
  26. package/dist/Calendar/Calendar.svelte +4 -0
  27. package/dist/Calendar/Calendar.svelte.d.ts +1 -1
  28. package/dist/Calendar/calendar.types.d.ts +4 -0
  29. package/dist/Card/Card.svelte +5 -4
  30. package/dist/Card/Card.svelte.d.ts +1 -1
  31. package/dist/Card/card.types.d.ts +5 -1
  32. package/dist/Checkbox/Checkbox.svelte +37 -11
  33. package/dist/Checkbox/Checkbox.svelte.d.ts +1 -1
  34. package/dist/Checkbox/checkbox.types.d.ts +16 -1
  35. package/dist/Checkbox/checkbox.variants.d.ts +90 -0
  36. package/dist/Checkbox/checkbox.variants.js +73 -4
  37. package/dist/CheckboxGroup/CheckboxGroup.svelte +215 -0
  38. package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +5 -0
  39. package/dist/CheckboxGroup/checkbox-group.types.d.ts +130 -0
  40. package/dist/CheckboxGroup/checkbox-group.types.js +1 -0
  41. package/dist/CheckboxGroup/checkbox-group.variants.d.ts +553 -0
  42. package/dist/CheckboxGroup/checkbox-group.variants.js +231 -0
  43. package/dist/CheckboxGroup/index.d.ts +2 -0
  44. package/dist/CheckboxGroup/index.js +1 -0
  45. package/dist/Chip/Chip.svelte +3 -2
  46. package/dist/Chip/Chip.svelte.d.ts +1 -1
  47. package/dist/Chip/chip.types.d.ts +5 -1
  48. package/dist/Chip/chip.variants.d.ts +135 -45
  49. package/dist/Chip/chip.variants.js +9 -9
  50. package/dist/ContextMenu/ContextMenu.svelte +87 -77
  51. package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
  52. package/dist/ContextMenu/context-menu.types.d.ts +9 -3
  53. package/dist/ContextMenu/context-menu.types.js +1 -1
  54. package/dist/ContextMenu/context-menu.variants.d.ts +74 -160
  55. package/dist/ContextMenu/context-menu.variants.js +63 -95
  56. package/dist/DropdownMenu/DropdownMenu.svelte +37 -43
  57. package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
  58. package/dist/DropdownMenu/dropdown-menu.types.d.ts +9 -3
  59. package/dist/DropdownMenu/dropdown-menu.types.js +1 -1
  60. package/dist/DropdownMenu/dropdown-menu.variants.d.ts +79 -230
  61. package/dist/DropdownMenu/dropdown-menu.variants.js +68 -111
  62. package/dist/DropdownMenu/index.d.ts +1 -1
  63. package/dist/Empty/Empty.svelte +68 -33
  64. package/dist/Empty/Empty.svelte.d.ts +1 -1
  65. package/dist/Empty/empty.types.d.ts +26 -9
  66. package/dist/Empty/empty.variants.d.ts +150 -130
  67. package/dist/Empty/empty.variants.js +33 -324
  68. package/dist/FieldGroup/FieldGroup.svelte +11 -6
  69. package/dist/FieldGroup/FieldGroup.svelte.d.ts +1 -1
  70. package/dist/FieldGroup/field-group.types.d.ts +4 -0
  71. package/dist/FileUpload/FileUpload.svelte +561 -0
  72. package/dist/FileUpload/FileUpload.svelte.d.ts +8 -0
  73. package/dist/FileUpload/file-upload.types.d.ts +164 -0
  74. package/dist/FileUpload/file-upload.types.js +1 -0
  75. package/dist/FileUpload/file-upload.variants.d.ts +397 -0
  76. package/dist/FileUpload/file-upload.variants.js +224 -0
  77. package/dist/FileUpload/index.d.ts +2 -0
  78. package/dist/FileUpload/index.js +1 -0
  79. package/dist/FormField/FormField.svelte +17 -18
  80. package/dist/FormField/FormField.svelte.d.ts +1 -1
  81. package/dist/FormField/form-field.types.d.ts +4 -0
  82. package/dist/Icon/Icon.svelte +13 -7
  83. package/dist/Icon/icon.types.d.ts +18 -9
  84. package/dist/Input/Input.svelte +30 -29
  85. package/dist/Kbd/Kbd.svelte +13 -3
  86. package/dist/Kbd/Kbd.svelte.d.ts +1 -1
  87. package/dist/Kbd/index.d.ts +1 -1
  88. package/dist/Kbd/kbd.types.d.ts +15 -1
  89. package/dist/Kbd/kbd.variants.d.ts +92 -30
  90. package/dist/Kbd/kbd.variants.js +55 -35
  91. package/dist/Kbd/useKbd.svelte.d.ts +2 -2
  92. package/dist/Kbd/useKbd.svelte.js +34 -41
  93. package/dist/Link/Link.svelte +69 -24
  94. package/dist/Link/Link.svelte.d.ts +1 -1
  95. package/dist/Link/link.types.d.ts +26 -8
  96. package/dist/Link/link.variants.d.ts +35 -60
  97. package/dist/Link/link.variants.js +8 -110
  98. package/dist/Modal/Modal.svelte +9 -1
  99. package/dist/Modal/modal.types.d.ts +5 -0
  100. package/dist/Modal/modal.variants.d.ts +5 -0
  101. package/dist/Modal/modal.variants.js +1 -0
  102. package/dist/Pagination/Pagination.svelte +143 -94
  103. package/dist/Pagination/Pagination.svelte.d.ts +1 -1
  104. package/dist/Pagination/index.d.ts +1 -1
  105. package/dist/Pagination/pagination.types.d.ts +21 -2
  106. package/dist/Pagination/pagination.variants.d.ts +21 -387
  107. package/dist/Pagination/pagination.variants.js +63 -59
  108. package/dist/PinInput/PinInput.svelte +150 -0
  109. package/dist/PinInput/PinInput.svelte.d.ts +6 -0
  110. package/dist/PinInput/index.d.ts +2 -0
  111. package/dist/PinInput/index.js +1 -0
  112. package/dist/PinInput/pin-input.types.d.ts +99 -0
  113. package/dist/PinInput/pin-input.types.js +1 -0
  114. package/dist/PinInput/pin-input.variants.d.ts +303 -0
  115. package/dist/PinInput/pin-input.variants.js +196 -0
  116. package/dist/Popover/Popover.svelte +9 -12
  117. package/dist/Popover/Popover.svelte.d.ts +1 -1
  118. package/dist/Popover/popover.types.d.ts +4 -0
  119. package/dist/Popover/popover.variants.d.ts +5 -75
  120. package/dist/Popover/popover.variants.js +6 -16
  121. package/dist/Progress/Progress.svelte +58 -30
  122. package/dist/Progress/progress.types.d.ts +9 -1
  123. package/dist/Progress/progress.variants.d.ts +55 -25
  124. package/dist/Progress/progress.variants.js +34 -28
  125. package/dist/RadioGroup/RadioGroup.svelte +105 -61
  126. package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
  127. package/dist/RadioGroup/radio-group.types.d.ts +16 -1
  128. package/dist/RadioGroup/radio-group.variants.d.ts +90 -0
  129. package/dist/RadioGroup/radio-group.variants.js +73 -4
  130. package/dist/Select/Select.svelte +9 -6
  131. package/dist/Select/Select.svelte.d.ts +1 -1
  132. package/dist/Select/select.types.d.ts +4 -0
  133. package/dist/SelectMenu/SelectMenu.svelte +436 -0
  134. package/dist/SelectMenu/SelectMenu.svelte.d.ts +5 -0
  135. package/dist/SelectMenu/index.d.ts +2 -0
  136. package/dist/SelectMenu/index.js +1 -0
  137. package/dist/SelectMenu/select-menu.types.d.ts +262 -0
  138. package/dist/SelectMenu/select-menu.types.js +1 -0
  139. package/dist/SelectMenu/select-menu.variants.d.ts +759 -0
  140. package/dist/SelectMenu/select-menu.variants.js +33 -0
  141. package/dist/Separator/Separator.svelte +1 -2
  142. package/dist/Separator/separator.variants.d.ts +1 -5
  143. package/dist/Separator/separator.variants.js +2 -2
  144. package/dist/Skeleton/Skeleton.svelte +18 -2
  145. package/dist/Skeleton/Skeleton.svelte.d.ts +1 -1
  146. package/dist/Skeleton/skeleton.types.d.ts +10 -1
  147. package/dist/Slideover/Slideover.svelte +9 -1
  148. package/dist/Slideover/slideover.types.d.ts +5 -0
  149. package/dist/Slideover/slideover.variants.d.ts +20 -5
  150. package/dist/Slideover/slideover.variants.js +4 -29
  151. package/dist/Slider/Slider.svelte +135 -0
  152. package/dist/Slider/Slider.svelte.d.ts +6 -0
  153. package/dist/Slider/index.d.ts +2 -0
  154. package/dist/Slider/index.js +1 -0
  155. package/dist/Slider/slider.types.d.ts +55 -0
  156. package/dist/Slider/slider.types.js +1 -0
  157. package/dist/Slider/slider.variants.d.ts +383 -0
  158. package/dist/Slider/slider.variants.js +102 -0
  159. package/dist/Switch/Switch.svelte +32 -31
  160. package/dist/Switch/Switch.svelte.d.ts +1 -1
  161. package/dist/Switch/switch.types.d.ts +6 -1
  162. package/dist/Switch/switch.variants.js +6 -6
  163. package/dist/Tabs/Tabs.svelte +6 -9
  164. package/dist/Tabs/Tabs.svelte.d.ts +1 -1
  165. package/dist/Tabs/tabs.types.d.ts +4 -0
  166. package/dist/Tabs/tabs.variants.js +2 -0
  167. package/dist/Textarea/Textarea.svelte +26 -25
  168. package/dist/ThemeModeButton/theme-mode-button.types.d.ts +7 -2
  169. package/dist/Timeline/Timeline.svelte +62 -19
  170. package/dist/Timeline/Timeline.svelte.d.ts +1 -1
  171. package/dist/Timeline/index.d.ts +1 -1
  172. package/dist/Timeline/timeline.types.d.ts +8 -0
  173. package/dist/Tooltip/Tooltip.svelte +12 -10
  174. package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
  175. package/dist/Tooltip/tooltip.types.d.ts +8 -4
  176. package/dist/Tooltip/tooltip.variants.d.ts +10 -75
  177. package/dist/Tooltip/tooltip.variants.js +8 -17
  178. package/dist/User/User.svelte +13 -9
  179. package/dist/User/User.svelte.d.ts +1 -1
  180. package/dist/User/user.types.d.ts +4 -0
  181. package/dist/User/user.variants.d.ts +60 -0
  182. package/dist/User/user.variants.js +13 -1
  183. package/dist/config.d.ts +8 -0
  184. package/dist/config.js +9 -1
  185. package/dist/index.d.ts +5 -0
  186. package/dist/index.js +5 -0
  187. package/package.json +2 -2
@@ -1,12 +1,57 @@
1
1
  import { tv } from 'tailwind-variants';
2
- const navButton = [
3
- 'inline-flex items-center justify-center rounded-md',
4
- 'cursor-pointer select-none transition-colors',
5
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary',
6
- 'disabled:cursor-not-allowed disabled:opacity-50',
7
- 'hover:bg-surface-container-high text-on-surface-variant'
8
- ];
9
2
  const navIcon = 'shrink-0';
3
+ export const activeVariantColorClasses = {
4
+ solid: {
5
+ primary: 'data-[selected]:bg-primary data-[selected]:text-on-primary data-[selected]:hover:bg-primary/90',
6
+ secondary: 'data-[selected]:bg-secondary data-[selected]:text-on-secondary data-[selected]:hover:bg-secondary/90',
7
+ tertiary: 'data-[selected]:bg-tertiary data-[selected]:text-on-tertiary data-[selected]:hover:bg-tertiary/90',
8
+ success: 'data-[selected]:bg-success data-[selected]:text-on-success data-[selected]:hover:bg-success/90',
9
+ warning: 'data-[selected]:bg-warning data-[selected]:text-on-warning data-[selected]:hover:bg-warning/90',
10
+ error: 'data-[selected]:bg-error data-[selected]:text-on-error data-[selected]:hover:bg-error/90',
11
+ info: 'data-[selected]:bg-info data-[selected]:text-on-info data-[selected]:hover:bg-info/90',
12
+ surface: 'data-[selected]:bg-surface-container-highest data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest/90'
13
+ },
14
+ outline: {
15
+ primary: 'data-[selected]:ring-2 data-[selected]:ring-primary data-[selected]:text-primary data-[selected]:hover:bg-primary/10',
16
+ secondary: 'data-[selected]:ring-2 data-[selected]:ring-secondary data-[selected]:text-secondary data-[selected]:hover:bg-secondary/10',
17
+ tertiary: 'data-[selected]:ring-2 data-[selected]:ring-tertiary data-[selected]:text-tertiary data-[selected]:hover:bg-tertiary/10',
18
+ success: 'data-[selected]:ring-2 data-[selected]:ring-success data-[selected]:text-success data-[selected]:hover:bg-success/10',
19
+ warning: 'data-[selected]:ring-2 data-[selected]:ring-warning data-[selected]:text-warning data-[selected]:hover:bg-warning/10',
20
+ error: 'data-[selected]:ring-2 data-[selected]:ring-error data-[selected]:text-error data-[selected]:hover:bg-error/10',
21
+ info: 'data-[selected]:ring-2 data-[selected]:ring-info data-[selected]:text-info data-[selected]:hover:bg-info/10',
22
+ surface: 'data-[selected]:ring-2 data-[selected]:ring-outline-variant data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest'
23
+ },
24
+ soft: {
25
+ primary: 'data-[selected]:bg-primary-container data-[selected]:text-on-primary-container data-[selected]:hover:bg-primary-container/90',
26
+ secondary: 'data-[selected]:bg-secondary-container data-[selected]:text-on-secondary-container data-[selected]:hover:bg-secondary-container/90',
27
+ tertiary: 'data-[selected]:bg-tertiary-container data-[selected]:text-on-tertiary-container data-[selected]:hover:bg-tertiary-container/90',
28
+ success: 'data-[selected]:bg-success-container data-[selected]:text-on-success-container data-[selected]:hover:bg-success-container/90',
29
+ warning: 'data-[selected]:bg-warning-container data-[selected]:text-on-warning-container data-[selected]:hover:bg-warning-container/90',
30
+ error: 'data-[selected]:bg-error-container data-[selected]:text-on-error-container data-[selected]:hover:bg-error-container/90',
31
+ info: 'data-[selected]:bg-info-container data-[selected]:text-on-info-container data-[selected]:hover:bg-info-container/90',
32
+ surface: 'data-[selected]:bg-surface-container-highest data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest/90'
33
+ },
34
+ subtle: {
35
+ primary: 'data-[selected]:bg-primary-container/50 data-[selected]:text-primary data-[selected]:hover:bg-primary-container/70',
36
+ secondary: 'data-[selected]:bg-secondary-container/50 data-[selected]:text-secondary data-[selected]:hover:bg-secondary-container/70',
37
+ tertiary: 'data-[selected]:bg-tertiary-container/50 data-[selected]:text-tertiary data-[selected]:hover:bg-tertiary-container/70',
38
+ success: 'data-[selected]:bg-success-container/50 data-[selected]:text-success data-[selected]:hover:bg-success-container/70',
39
+ warning: 'data-[selected]:bg-warning-container/50 data-[selected]:text-warning data-[selected]:hover:bg-warning-container/70',
40
+ error: 'data-[selected]:bg-error-container/50 data-[selected]:text-error data-[selected]:hover:bg-error-container/70',
41
+ info: 'data-[selected]:bg-info-container/50 data-[selected]:text-info data-[selected]:hover:bg-info-container/70',
42
+ surface: 'data-[selected]:bg-surface-container-highest/50 data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest/70'
43
+ },
44
+ ghost: {
45
+ primary: 'data-[selected]:text-primary data-[selected]:hover:bg-primary/10',
46
+ secondary: 'data-[selected]:text-secondary data-[selected]:hover:bg-secondary/10',
47
+ tertiary: 'data-[selected]:text-tertiary data-[selected]:hover:bg-tertiary/10',
48
+ success: 'data-[selected]:text-success data-[selected]:hover:bg-success/10',
49
+ warning: 'data-[selected]:text-warning data-[selected]:hover:bg-warning/10',
50
+ error: 'data-[selected]:text-error data-[selected]:hover:bg-error/10',
51
+ info: 'data-[selected]:text-info data-[selected]:hover:bg-info/10',
52
+ surface: 'data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest'
53
+ }
54
+ };
10
55
  export const paginationVariants = tv({
11
56
  slots: {
12
57
  root: '',
@@ -19,10 +64,10 @@ export const paginationVariants = tv({
19
64
  'hover:bg-surface-container-high text-on-surface'
20
65
  ],
21
66
  ellipsis: 'inline-flex items-center justify-center pointer-events-none text-on-surface-variant',
22
- first: navButton,
23
- prev: navButton,
24
- next: navButton,
25
- last: navButton,
67
+ first: '',
68
+ prev: '',
69
+ next: '',
70
+ last: '',
26
71
  ellipsisIcon: navIcon,
27
72
  firstIcon: navIcon,
28
73
  prevIcon: navIcon,
@@ -30,41 +75,11 @@ export const paginationVariants = tv({
30
75
  lastIcon: navIcon
31
76
  },
32
77
  variants: {
33
- activeColor: {
34
- primary: {
35
- item: 'data-[selected]:bg-primary data-[selected]:text-on-primary data-[selected]:hover:bg-primary/90'
36
- },
37
- secondary: {
38
- item: 'data-[selected]:bg-secondary data-[selected]:text-on-secondary data-[selected]:hover:bg-secondary/90'
39
- },
40
- tertiary: {
41
- item: 'data-[selected]:bg-tertiary data-[selected]:text-on-tertiary data-[selected]:hover:bg-tertiary/90'
42
- },
43
- success: {
44
- item: 'data-[selected]:bg-success data-[selected]:text-on-success data-[selected]:hover:bg-success/90'
45
- },
46
- warning: {
47
- item: 'data-[selected]:bg-warning data-[selected]:text-on-warning data-[selected]:hover:bg-warning/90'
48
- },
49
- error: {
50
- item: 'data-[selected]:bg-error data-[selected]:text-on-error data-[selected]:hover:bg-error/90'
51
- },
52
- info: {
53
- item: 'data-[selected]:bg-info data-[selected]:text-on-info data-[selected]:hover:bg-info/90'
54
- },
55
- surface: {
56
- item: 'data-[selected]:bg-surface-container-highest data-[selected]:text-on-surface data-[selected]:hover:bg-surface-container-highest/90'
57
- }
58
- },
59
78
  size: {
60
79
  xs: {
61
80
  list: 'gap-0.5',
62
81
  item: 'size-7 text-xs',
63
82
  ellipsis: 'size-7 text-xs',
64
- first: 'size-7',
65
- prev: 'size-7',
66
- next: 'size-7',
67
- last: 'size-7',
68
83
  ellipsisIcon: 'size-3',
69
84
  firstIcon: 'size-3',
70
85
  prevIcon: 'size-3',
@@ -75,10 +90,6 @@ export const paginationVariants = tv({
75
90
  list: 'gap-0.5',
76
91
  item: 'size-8 text-xs',
77
92
  ellipsis: 'size-8 text-xs',
78
- first: 'size-8',
79
- prev: 'size-8',
80
- next: 'size-8',
81
- last: 'size-8',
82
93
  ellipsisIcon: 'size-3.5',
83
94
  firstIcon: 'size-3.5',
84
95
  prevIcon: 'size-3.5',
@@ -89,10 +100,6 @@ export const paginationVariants = tv({
89
100
  list: 'gap-1',
90
101
  item: 'size-9 text-sm',
91
102
  ellipsis: 'size-9 text-sm',
92
- first: 'size-9',
93
- prev: 'size-9',
94
- next: 'size-9',
95
- last: 'size-9',
96
103
  ellipsisIcon: 'size-4',
97
104
  firstIcon: 'size-4',
98
105
  prevIcon: 'size-4',
@@ -103,10 +110,6 @@ export const paginationVariants = tv({
103
110
  list: 'gap-1',
104
111
  item: 'size-10 text-sm',
105
112
  ellipsis: 'size-10 text-sm',
106
- first: 'size-10',
107
- prev: 'size-10',
108
- next: 'size-10',
109
- last: 'size-10',
110
113
  ellipsisIcon: 'size-5',
111
114
  firstIcon: 'size-5',
112
115
  prevIcon: 'size-5',
@@ -117,10 +120,6 @@ export const paginationVariants = tv({
117
120
  list: 'gap-1.5',
118
121
  item: 'size-11 text-base',
119
122
  ellipsis: 'size-11 text-base',
120
- first: 'size-11',
121
- prev: 'size-11',
122
- next: 'size-11',
123
- last: 'size-11',
124
123
  ellipsisIcon: 'size-5',
125
124
  firstIcon: 'size-5',
126
125
  prevIcon: 'size-5',
@@ -135,11 +134,16 @@ export const paginationVariants = tv({
135
134
  }
136
135
  },
137
136
  defaultVariants: {
138
- activeColor: 'primary',
139
137
  size: 'md'
140
138
  }
141
139
  });
142
140
  export const paginationDefaults = {
143
- defaultVariants: paginationVariants.defaultVariants,
141
+ defaultVariants: {
142
+ ...paginationVariants.defaultVariants,
143
+ variant: 'ghost',
144
+ color: 'surface',
145
+ activeColor: 'primary',
146
+ activeVariant: 'solid'
147
+ },
144
148
  slots: {}
145
149
  };
@@ -0,0 +1,150 @@
1
+ <script lang="ts" module>
2
+ import type { PinInputProps } from './pin-input.types.js'
3
+
4
+ export type Props = PinInputProps
5
+ </script>
6
+
7
+ <script lang="ts">
8
+ import { PinInput, useId } from 'bits-ui'
9
+ import { getContext } from 'svelte'
10
+ import { pinInputVariants, pinInputDefaults } from './pin-input.variants.js'
11
+ import { getComponentConfig } from '../config.js'
12
+ import type { FormFieldProps } from '../FormField/form-field.types.js'
13
+
14
+ const config = getComponentConfig('pinInput', pinInputDefaults)
15
+
16
+ let {
17
+ ref = $bindable(null),
18
+ defaultValue = '',
19
+ value = $bindable(defaultValue),
20
+ onValueChange,
21
+ onComplete,
22
+ length = 5,
23
+ type = 'text',
24
+ mask = false,
25
+ otp = false,
26
+ disabled = false,
27
+ required,
28
+ textalign,
29
+ pasteTransformer,
30
+ pushPasswordManagerStrategy,
31
+ inputId,
32
+ name,
33
+ placeholder = '○',
34
+ autofocus = false,
35
+ autofocusDelay = 0,
36
+ highlight = false,
37
+ fixed = false,
38
+ color = config.defaultVariants.color,
39
+ size,
40
+ variant = config.defaultVariants.variant,
41
+ class: className,
42
+ ui,
43
+ ...restProps
44
+ }: Props = $props()
45
+
46
+ const formFieldContext = getContext<
47
+ | {
48
+ name?: string
49
+ size: NonNullable<FormFieldProps['size']>
50
+ error?: string | boolean
51
+ ariaId: string
52
+ }
53
+ | undefined
54
+ >('formField')
55
+
56
+ const autoInputId = useId()
57
+ const hasError = $derived(
58
+ formFieldContext?.error !== undefined && formFieldContext?.error !== false
59
+ )
60
+ const resolvedInputId = $derived(inputId ?? formFieldContext?.ariaId ?? autoInputId)
61
+ const resolvedName = $derived(name ?? formFieldContext?.name)
62
+ const resolvedSize = $derived(size ?? formFieldContext?.size ?? config.defaultVariants.size)
63
+ const resolvedColor = $derived(hasError ? 'error' : color)
64
+ const resolvedHighlight = $derived(hasError || highlight)
65
+ const ariaDescribedBy = $derived(
66
+ !formFieldContext
67
+ ? undefined
68
+ : hasError
69
+ ? `${formFieldContext.ariaId}-error`
70
+ : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`
71
+ )
72
+
73
+ const resolvedPasteTransformer = $derived(
74
+ pasteTransformer ??
75
+ (type === 'number' ? (text: string) => text.replace(/\D/g, '') : undefined)
76
+ )
77
+
78
+ function handleValueChange(v: string) {
79
+ const filtered = type === 'number' ? v.replace(/\D/g, '') : v
80
+ value = filtered
81
+ onValueChange?.(filtered)
82
+ }
83
+
84
+ const slots = $derived(
85
+ pinInputVariants({
86
+ variant,
87
+ color: resolvedColor,
88
+ size: resolvedSize,
89
+ highlight: resolvedHighlight,
90
+ fixed,
91
+ disabled
92
+ })
93
+ )
94
+
95
+ const classes = $derived.by(() => {
96
+ const u = ui ?? {}
97
+ return {
98
+ root: slots.root({ class: [config.slots.root, className, u.root] }),
99
+ base: slots.base({ class: [config.slots.base, u.base] })
100
+ }
101
+ })
102
+
103
+ $effect(() => {
104
+ if (!autofocus) return
105
+ const input = ref?.querySelector('[data-pin-input-input]') as HTMLInputElement | null
106
+ if (!input) return
107
+ const timer = setTimeout(() => input.focus(), autofocusDelay)
108
+ return () => clearTimeout(timer)
109
+ })
110
+ </script>
111
+
112
+ <div class="contents" {...restProps}>
113
+ {#if resolvedName}
114
+ <input type="hidden" name={resolvedName} {value} />
115
+ {/if}
116
+ <PinInput.Root
117
+ bind:ref
118
+ {value}
119
+ maxlength={length}
120
+ {disabled}
121
+ {textalign}
122
+ {onComplete}
123
+ pasteTransformer={resolvedPasteTransformer}
124
+ {pushPasswordManagerStrategy}
125
+ inputId={resolvedInputId}
126
+ autocomplete={otp ? 'one-time-code' : undefined}
127
+ inputmode={type === 'number' ? 'numeric' : 'text'}
128
+ {required}
129
+ aria-describedby={ariaDescribedBy}
130
+ onValueChange={handleValueChange}
131
+ class={classes.root}
132
+ >
133
+ {#snippet children({ cells })}
134
+ {#each cells as cell, i (i)}
135
+ <PinInput.Cell {cell} class={classes.base}>
136
+ {#if mask && cell.char}
137
+ <span class="block size-2 rounded-full bg-current"></span>
138
+ {:else if cell.char}
139
+ {cell.char}
140
+ {:else if cell.hasFakeCaret}
141
+ <span class="pointer-events-none absolute animate-pulse select-none">|</span
142
+ >
143
+ {:else}
144
+ <span class="text-on-surface/30">{placeholder}</span>
145
+ {/if}
146
+ </PinInput.Cell>
147
+ {/each}
148
+ {/snippet}
149
+ </PinInput.Root>
150
+ </div>
@@ -0,0 +1,6 @@
1
+ import type { PinInputProps } from './pin-input.types.js';
2
+ export type Props = PinInputProps;
3
+ import { PinInput } from 'bits-ui';
4
+ declare const PinInput: import("svelte").Component<PinInputProps, {}, "ref" | "value">;
5
+ type PinInput = ReturnType<typeof PinInput>;
6
+ export default PinInput;
@@ -0,0 +1,2 @@
1
+ export { default as PinInput } from './PinInput.svelte';
2
+ export type { PinInputProps } from './pin-input.types.js';
@@ -0,0 +1 @@
1
+ export { default as PinInput } from './PinInput.svelte';
@@ -0,0 +1,99 @@
1
+ import type { PinInput as PinInputPrimitive } from 'bits-ui';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ClassNameValue } from 'tailwind-merge';
4
+ import type { PinInputVariantProps, PinInputSlots } from './pin-input.variants.js';
5
+ export type PinInputProps = Pick<PinInputPrimitive.RootProps, 'disabled' | 'textalign' | 'onComplete' | 'pasteTransformer' | 'pushPasswordManagerStrategy' | 'inputId'> & Omit<HTMLAttributes<HTMLElement>, 'class' | 'children'> & {
6
+ /**
7
+ * Bindable reference to the root DOM element.
8
+ */
9
+ ref?: HTMLElement | null;
10
+ /**
11
+ * The current value. Supports two-way binding with `bind:value`.
12
+ * @default ''
13
+ */
14
+ value?: string;
15
+ /**
16
+ * The initial value when uncontrolled.
17
+ */
18
+ defaultValue?: string;
19
+ /**
20
+ * Callback fired when the value changes.
21
+ */
22
+ onValueChange?: (value: string) => void;
23
+ /**
24
+ * The name attribute for the hidden input (used in form submission).
25
+ */
26
+ name?: string;
27
+ /**
28
+ * Whether the field is required.
29
+ */
30
+ required?: boolean;
31
+ /**
32
+ * Number of cells (characters).
33
+ * @default 5
34
+ */
35
+ length?: number;
36
+ /**
37
+ * Input type. Use 'number' to restrict to digits only.
38
+ * @default 'text'
39
+ */
40
+ type?: 'text' | 'number';
41
+ /**
42
+ * Mask the input, showing ● instead of typed characters.
43
+ * @default false
44
+ */
45
+ mask?: boolean;
46
+ /**
47
+ * Enable OTP mode (sets autocomplete="one-time-code").
48
+ * @default false
49
+ */
50
+ otp?: boolean;
51
+ /**
52
+ * Placeholder character displayed in each empty cell.
53
+ * @default '○'
54
+ */
55
+ placeholder?: string;
56
+ /**
57
+ * Automatically focus the input on mount.
58
+ * @default false
59
+ */
60
+ autofocus?: boolean;
61
+ /**
62
+ * Delay in milliseconds before autofocusing.
63
+ * @default 0
64
+ */
65
+ autofocusDelay?: number;
66
+ /**
67
+ * Highlight all cells with the active color ring (e.g. for error state).
68
+ * @default false
69
+ */
70
+ highlight?: boolean;
71
+ /**
72
+ * Prevent responsive text size changes on mobile.
73
+ * @default false
74
+ */
75
+ fixed?: boolean;
76
+ /**
77
+ * Color scheme of the input cells.
78
+ * @default 'primary'
79
+ */
80
+ color?: NonNullable<PinInputVariantProps['color']>;
81
+ /**
82
+ * Size of each cell.
83
+ * @default 'md'
84
+ */
85
+ size?: NonNullable<PinInputVariantProps['size']>;
86
+ /**
87
+ * Visual style of the input cells.
88
+ * @default 'outline'
89
+ */
90
+ variant?: NonNullable<PinInputVariantProps['variant']>;
91
+ /**
92
+ * Additional CSS classes for the root element.
93
+ */
94
+ class?: ClassNameValue;
95
+ /**
96
+ * Override styles for specific slots.
97
+ */
98
+ ui?: Partial<Record<PinInputSlots, ClassNameValue>>;
99
+ };
@@ -0,0 +1 @@
1
+ export {};