polymorph-ui-components 0.1.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 (242) hide show
  1. package/README.md +354 -0
  2. package/dist/Accordion/Accordion.svelte +28 -0
  3. package/dist/Accordion/Accordion.svelte.d.ts +4 -0
  4. package/dist/Accordion/properties.d.ts +7 -0
  5. package/dist/Accordion/properties.js +1 -0
  6. package/dist/Animations/ModalAnimation.svelte +55 -0
  7. package/dist/Animations/ModalAnimation.svelte.d.ts +12 -0
  8. package/dist/Animations/OverlayAnimation.svelte +14 -0
  9. package/dist/Animations/OverlayAnimation.svelte.d.ts +7 -0
  10. package/dist/Avatar/Avatar.svelte +122 -0
  11. package/dist/Avatar/Avatar.svelte.d.ts +4 -0
  12. package/dist/Avatar/properties.d.ts +15 -0
  13. package/dist/Avatar/properties.js +1 -0
  14. package/dist/Badge/Badge.svelte +53 -0
  15. package/dist/Badge/Badge.svelte.d.ts +4 -0
  16. package/dist/Badge/properties.d.ts +6 -0
  17. package/dist/Badge/properties.js +1 -0
  18. package/dist/Banner/Banner.svelte +158 -0
  19. package/dist/Banner/Banner.svelte.d.ts +4 -0
  20. package/dist/Banner/properties.d.ts +19 -0
  21. package/dist/Banner/properties.js +1 -0
  22. package/dist/Book/Book.svelte +281 -0
  23. package/dist/Book/Book.svelte.d.ts +4 -0
  24. package/dist/Book/properties.d.ts +24 -0
  25. package/dist/Book/properties.js +1 -0
  26. package/dist/Browser/Browser.svelte +176 -0
  27. package/dist/Browser/Browser.svelte.d.ts +3 -0
  28. package/dist/Browser/properties.d.ts +14 -0
  29. package/dist/Browser/properties.js +1 -0
  30. package/dist/Button/Button.svelte +153 -0
  31. package/dist/Button/Button.svelte.d.ts +4 -0
  32. package/dist/Button/properties.d.ts +24 -0
  33. package/dist/Button/properties.js +1 -0
  34. package/dist/Calendar/Calendar.svelte +477 -0
  35. package/dist/Calendar/Calendar.svelte.d.ts +4 -0
  36. package/dist/Calendar/properties.d.ts +30 -0
  37. package/dist/Calendar/properties.js +1 -0
  38. package/dist/Carousel/Carousel.svelte +258 -0
  39. package/dist/Carousel/Carousel.svelte.d.ts +4 -0
  40. package/dist/Carousel/properties.d.ts +20 -0
  41. package/dist/Carousel/properties.js +1 -0
  42. package/dist/CheckListItem/CheckListItem.svelte +65 -0
  43. package/dist/CheckListItem/CheckListItem.svelte.d.ts +4 -0
  44. package/dist/CheckListItem/properties.d.ts +15 -0
  45. package/dist/CheckListItem/properties.js +1 -0
  46. package/dist/Checkbox/Checkbox.svelte +157 -0
  47. package/dist/Checkbox/Checkbox.svelte.d.ts +4 -0
  48. package/dist/Checkbox/properties.d.ts +17 -0
  49. package/dist/Checkbox/properties.js +1 -0
  50. package/dist/Choicebox/Choicebox.svelte +85 -0
  51. package/dist/Choicebox/Choicebox.svelte.d.ts +4 -0
  52. package/dist/Choicebox/properties.d.ts +14 -0
  53. package/dist/Choicebox/properties.js +1 -0
  54. package/dist/ColorPicker/ColorPicker.svelte +583 -0
  55. package/dist/ColorPicker/ColorPicker.svelte.d.ts +4 -0
  56. package/dist/ColorPicker/properties.d.ts +15 -0
  57. package/dist/ColorPicker/properties.js +1 -0
  58. package/dist/Combobox/Combobox.svelte +432 -0
  59. package/dist/Combobox/Combobox.svelte.d.ts +6 -0
  60. package/dist/Combobox/properties.d.ts +42 -0
  61. package/dist/Combobox/properties.js +1 -0
  62. package/dist/CommandMenu/CommandMenu.svelte +452 -0
  63. package/dist/CommandMenu/CommandMenu.svelte.d.ts +4 -0
  64. package/dist/CommandMenu/properties.d.ts +26 -0
  65. package/dist/CommandMenu/properties.js +1 -0
  66. package/dist/ContextMenu/ContextMenu.svelte +308 -0
  67. package/dist/ContextMenu/ContextMenu.svelte.d.ts +4 -0
  68. package/dist/ContextMenu/properties.d.ts +26 -0
  69. package/dist/ContextMenu/properties.js +1 -0
  70. package/dist/Gauge/Gauge.svelte +70 -0
  71. package/dist/Gauge/Gauge.svelte.d.ts +4 -0
  72. package/dist/Gauge/properties.d.ts +9 -0
  73. package/dist/Gauge/properties.js +1 -0
  74. package/dist/GridItem/GridItem.svelte +145 -0
  75. package/dist/GridItem/GridItem.svelte.d.ts +4 -0
  76. package/dist/GridItem/properties.d.ts +15 -0
  77. package/dist/GridItem/properties.js +1 -0
  78. package/dist/Icon/Icon.svelte +61 -0
  79. package/dist/Icon/Icon.svelte.d.ts +4 -0
  80. package/dist/Icon/properties.d.ts +12 -0
  81. package/dist/Icon/properties.js +1 -0
  82. package/dist/IconStack/IconStack.svelte +55 -0
  83. package/dist/IconStack/IconStack.svelte.d.ts +4 -0
  84. package/dist/IconStack/properties.d.ts +9 -0
  85. package/dist/IconStack/properties.js +1 -0
  86. package/dist/Img/Img.svelte +37 -0
  87. package/dist/Img/Img.svelte.d.ts +4 -0
  88. package/dist/Img/properties.d.ts +13 -0
  89. package/dist/Img/properties.js +1 -0
  90. package/dist/Input/Input.svelte +349 -0
  91. package/dist/Input/Input.svelte.d.ts +8 -0
  92. package/dist/Input/properties.d.ts +45 -0
  93. package/dist/Input/properties.js +1 -0
  94. package/dist/InputButton/InputButton.svelte +252 -0
  95. package/dist/InputButton/InputButton.svelte.d.ts +7 -0
  96. package/dist/InputButton/properties.d.ts +22 -0
  97. package/dist/InputButton/properties.js +1 -0
  98. package/dist/KeyboardInput/KeyboardInput.svelte +93 -0
  99. package/dist/KeyboardInput/KeyboardInput.svelte.d.ts +4 -0
  100. package/dist/KeyboardInput/properties.d.ts +12 -0
  101. package/dist/KeyboardInput/properties.js +1 -0
  102. package/dist/ListItem/ListItem.svelte +309 -0
  103. package/dist/ListItem/ListItem.svelte.d.ts +4 -0
  104. package/dist/ListItem/properties.d.ts +34 -0
  105. package/dist/ListItem/properties.js +1 -0
  106. package/dist/Loader/Loader.svelte +90 -0
  107. package/dist/Loader/Loader.svelte.d.ts +4 -0
  108. package/dist/Loader/properties.d.ts +4 -0
  109. package/dist/Loader/properties.js +1 -0
  110. package/dist/LoadingDots/LoadingDots.svelte +59 -0
  111. package/dist/LoadingDots/LoadingDots.svelte.d.ts +3 -0
  112. package/dist/LoadingDots/properties.d.ts +8 -0
  113. package/dist/LoadingDots/properties.js +1 -0
  114. package/dist/Menu/Menu.svelte +356 -0
  115. package/dist/Menu/Menu.svelte.d.ts +4 -0
  116. package/dist/Menu/properties.d.ts +28 -0
  117. package/dist/Menu/properties.js +1 -0
  118. package/dist/Modal/Modal.svelte +357 -0
  119. package/dist/Modal/Modal.svelte.d.ts +4 -0
  120. package/dist/Modal/properties.d.ts +39 -0
  121. package/dist/Modal/properties.js +1 -0
  122. package/dist/Pagination/Pagination.svelte +148 -0
  123. package/dist/Pagination/Pagination.svelte.d.ts +4 -0
  124. package/dist/Pagination/properties.d.ts +14 -0
  125. package/dist/Pagination/properties.js +1 -0
  126. package/dist/Phone/Phone.svelte +234 -0
  127. package/dist/Phone/Phone.svelte.d.ts +3 -0
  128. package/dist/Phone/properties.d.ts +11 -0
  129. package/dist/Phone/properties.js +1 -0
  130. package/dist/Pill/Pill.svelte +130 -0
  131. package/dist/Pill/Pill.svelte.d.ts +4 -0
  132. package/dist/Pill/properties.d.ts +16 -0
  133. package/dist/Pill/properties.js +1 -0
  134. package/dist/Progress/Progress.svelte +68 -0
  135. package/dist/Progress/Progress.svelte.d.ts +4 -0
  136. package/dist/Progress/properties.d.ts +10 -0
  137. package/dist/Progress/properties.js +1 -0
  138. package/dist/Radio/Radio.svelte +124 -0
  139. package/dist/Radio/Radio.svelte.d.ts +4 -0
  140. package/dist/Radio/properties.d.ts +15 -0
  141. package/dist/Radio/properties.js +1 -0
  142. package/dist/RelativeTime/RelativeTime.svelte +109 -0
  143. package/dist/RelativeTime/RelativeTime.svelte.d.ts +4 -0
  144. package/dist/RelativeTime/properties.d.ts +13 -0
  145. package/dist/RelativeTime/properties.js +1 -0
  146. package/dist/Scroller/Scroller.svelte +390 -0
  147. package/dist/Scroller/Scroller.svelte.d.ts +4 -0
  148. package/dist/Scroller/properties.d.ts +30 -0
  149. package/dist/Scroller/properties.js +1 -0
  150. package/dist/Select/Select.svelte +472 -0
  151. package/dist/Select/Select.svelte.d.ts +4 -0
  152. package/dist/Select/properties.d.ts +20 -0
  153. package/dist/Select/properties.js +1 -0
  154. package/dist/Sheet/Sheet.svelte +264 -0
  155. package/dist/Sheet/Sheet.svelte.d.ts +4 -0
  156. package/dist/Sheet/properties.d.ts +19 -0
  157. package/dist/Sheet/properties.js +1 -0
  158. package/dist/Shimmer/Shimmer.svelte +44 -0
  159. package/dist/Shimmer/Shimmer.svelte.d.ts +4 -0
  160. package/dist/Shimmer/properties.d.ts +4 -0
  161. package/dist/Shimmer/properties.js +1 -0
  162. package/dist/Slider/Slider.svelte +147 -0
  163. package/dist/Slider/Slider.svelte.d.ts +4 -0
  164. package/dist/Slider/properties.d.ts +17 -0
  165. package/dist/Slider/properties.js +1 -0
  166. package/dist/Snippet/Snippet.svelte +123 -0
  167. package/dist/Snippet/Snippet.svelte.d.ts +4 -0
  168. package/dist/Snippet/properties.d.ts +15 -0
  169. package/dist/Snippet/properties.js +1 -0
  170. package/dist/SplitButton/SplitButton.svelte +145 -0
  171. package/dist/SplitButton/SplitButton.svelte.d.ts +4 -0
  172. package/dist/SplitButton/properties.d.ts +17 -0
  173. package/dist/SplitButton/properties.js +1 -0
  174. package/dist/SplitInput/SplitInput.svelte +225 -0
  175. package/dist/SplitInput/SplitInput.svelte.d.ts +7 -0
  176. package/dist/SplitInput/properties.d.ts +20 -0
  177. package/dist/SplitInput/properties.js +1 -0
  178. package/dist/Stepper/Step.svelte +88 -0
  179. package/dist/Stepper/Step.svelte.d.ts +4 -0
  180. package/dist/Stepper/Stepper.svelte +64 -0
  181. package/dist/Stepper/Stepper.svelte.d.ts +4 -0
  182. package/dist/Stepper/properties.d.ts +27 -0
  183. package/dist/Stepper/properties.js +1 -0
  184. package/dist/Table/Table.svelte +357 -0
  185. package/dist/Table/Table.svelte.d.ts +4 -0
  186. package/dist/Table/properties.d.ts +26 -0
  187. package/dist/Table/properties.js +1 -0
  188. package/dist/Tabs/Tabs.svelte +303 -0
  189. package/dist/Tabs/Tabs.svelte.d.ts +4 -0
  190. package/dist/Tabs/properties.d.ts +30 -0
  191. package/dist/Tabs/properties.js +1 -0
  192. package/dist/ThemeSwitcher/ThemeSwitcher.svelte +249 -0
  193. package/dist/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +4 -0
  194. package/dist/ThemeSwitcher/properties.d.ts +19 -0
  195. package/dist/ThemeSwitcher/properties.js +1 -0
  196. package/dist/Toast/Toast.svelte +220 -0
  197. package/dist/Toast/Toast.svelte.d.ts +4 -0
  198. package/dist/Toast/properties.d.ts +24 -0
  199. package/dist/Toast/properties.js +1 -0
  200. package/dist/Toggle/Toggle.svelte +99 -0
  201. package/dist/Toggle/Toggle.svelte.d.ts +4 -0
  202. package/dist/Toggle/properties.d.ts +9 -0
  203. package/dist/Toggle/properties.js +1 -0
  204. package/dist/Toolbar/Toolbar.svelte +142 -0
  205. package/dist/Toolbar/Toolbar.svelte.d.ts +4 -0
  206. package/dist/Toolbar/properties.d.ts +16 -0
  207. package/dist/Toolbar/properties.js +1 -0
  208. package/dist/Tooltip/Tooltip.svelte +153 -0
  209. package/dist/Tooltip/Tooltip.svelte.d.ts +4 -0
  210. package/dist/Tooltip/properties.d.ts +13 -0
  211. package/dist/Tooltip/properties.js +1 -0
  212. package/dist/assets/back.svg +3 -0
  213. package/dist/assets/battery.svg +5 -0
  214. package/dist/assets/checkmark.svg +3 -0
  215. package/dist/assets/chevron-down-sm.svg +3 -0
  216. package/dist/assets/chevron-down.svg +3 -0
  217. package/dist/assets/chevron-left-lg.svg +3 -0
  218. package/dist/assets/chevron-left.svg +3 -0
  219. package/dist/assets/chevron-right-lg.svg +3 -0
  220. package/dist/assets/chevron-right.svg +3 -0
  221. package/dist/assets/chevron-up.svg +3 -0
  222. package/dist/assets/close.svg +4 -0
  223. package/dist/assets/copy.svg +4 -0
  224. package/dist/assets/error-circle.svg +5 -0
  225. package/dist/assets/lock.svg +3 -0
  226. package/dist/assets/minus.svg +3 -0
  227. package/dist/assets/monitor.svg +5 -0
  228. package/dist/assets/moon.svg +3 -0
  229. package/dist/assets/palette.svg +7 -0
  230. package/dist/assets/search.svg +4 -0
  231. package/dist/assets/signal.svg +6 -0
  232. package/dist/assets/sort-default.svg +4 -0
  233. package/dist/assets/sun.svg +11 -0
  234. package/dist/assets/swap-vertical.svg +6 -0
  235. package/dist/assets/wifi.svg +3 -0
  236. package/dist/index.d.ts +103 -0
  237. package/dist/index.js +55 -0
  238. package/dist/types.d.ts +42 -0
  239. package/dist/types.js +1 -0
  240. package/dist/utils.d.ts +28 -0
  241. package/dist/utils.js +294 -0
  242. package/package.json +91 -0
@@ -0,0 +1,472 @@
1
+ <script lang="ts">
2
+ import { onMount, tick } from 'svelte';
3
+ import type { SelectItem, SelectProperties } from './properties';
4
+ import Pill from '../Pill/Pill.svelte';
5
+ import chevronDownSvg from '../assets/chevron-down.svg?raw';
6
+
7
+ let {
8
+ items,
9
+ value = $bindable([]),
10
+ multiple = false,
11
+ searchable = false,
12
+ placeholder = '',
13
+ disabled = false,
14
+ testId,
15
+ onchange,
16
+ classes
17
+ }: SelectProperties = $props();
18
+
19
+ let isOpen = $state(false);
20
+ let query = $state('');
21
+ let highlightedIndex = $state(-1);
22
+ let containerEl: HTMLDivElement | null = $state(null);
23
+ let searchInputEl: HTMLInputElement | null = $state(null);
24
+ let triggerEl: HTMLDivElement | null = $state(null);
25
+
26
+ const listboxId = `select-listbox-${Math.random().toString(36).slice(2, 9)}`;
27
+
28
+ function getLabel(id: string): string {
29
+ const found = items.find((item) => item.id === id);
30
+ return typeof found === 'object' ? found.label : id;
31
+ }
32
+
33
+ let filteredItems: SelectItem[] = $derived(
34
+ searchable && query.length > 0
35
+ ? items.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()))
36
+ : items
37
+ );
38
+
39
+ let displayText = $derived.by(() => {
40
+ const firstId = value.at(0);
41
+ if (typeof firstId !== 'string') {
42
+ return '';
43
+ }
44
+ return getLabel(firstId);
45
+ });
46
+
47
+ let highlightedOptionId: string | null = $derived(
48
+ highlightedIndex >= 0 ? `${listboxId}-option-${highlightedIndex}` : null
49
+ );
50
+
51
+ let searchPlaceholder = $derived(isOpen && displayText.length > 0 ? displayText : placeholder);
52
+
53
+ async function open(): Promise<void> {
54
+ if (disabled || isOpen) {
55
+ return;
56
+ }
57
+ isOpen = true;
58
+ highlightedIndex = -1;
59
+ query = '';
60
+ if (searchable) {
61
+ await tick();
62
+ if (searchInputEl !== null) {
63
+ searchInputEl.focus();
64
+ }
65
+ }
66
+ }
67
+
68
+ function close(): void {
69
+ isOpen = false;
70
+ query = '';
71
+ highlightedIndex = -1;
72
+ }
73
+
74
+ function selectItem(id: string): void {
75
+ if (disabled) {
76
+ return;
77
+ }
78
+ if (multiple) {
79
+ value = value.includes(id) ? value.filter((v) => v !== id) : [...value, id];
80
+ } else {
81
+ value = [id];
82
+ close();
83
+ }
84
+ onchange?.(value);
85
+ }
86
+
87
+ function removeItem(id: string): void {
88
+ if (disabled) {
89
+ return;
90
+ }
91
+ value = value.filter((v) => v !== id);
92
+ onchange?.(value);
93
+ }
94
+
95
+ function selectHighlighted(): void {
96
+ if (highlightedIndex < 0 || highlightedIndex >= filteredItems.length) {
97
+ return;
98
+ }
99
+ const item = filteredItems.at(highlightedIndex);
100
+ if (typeof item === 'object' && item !== null) {
101
+ selectItem(item.id);
102
+ }
103
+ }
104
+
105
+ async function moveHighlight(delta: number): Promise<void> {
106
+ const next = highlightedIndex + delta;
107
+ if (next < 0 || next >= filteredItems.length) {
108
+ return;
109
+ }
110
+ highlightedIndex = next;
111
+ await tick();
112
+ if (containerEl !== null) {
113
+ const el = containerEl.querySelector('.select-option.highlighted');
114
+ if (el instanceof HTMLElement) {
115
+ el.scrollIntoView({ block: 'nearest' });
116
+ }
117
+ }
118
+ }
119
+
120
+ function handleTriggerClick(event: MouseEvent): void {
121
+ if (event.target instanceof HTMLInputElement) {
122
+ if (!isOpen) {
123
+ open();
124
+ }
125
+ return;
126
+ }
127
+ if (multiple && searchable) {
128
+ open();
129
+ } else if (isOpen) {
130
+ close();
131
+ } else {
132
+ open();
133
+ }
134
+ }
135
+
136
+ function handleKeydown(event: KeyboardEvent): void {
137
+ if (disabled) {
138
+ return;
139
+ }
140
+ switch (event.key) {
141
+ case 'Enter':
142
+ event.preventDefault();
143
+ if (isOpen) {
144
+ selectHighlighted();
145
+ } else {
146
+ open();
147
+ }
148
+ break;
149
+ case ' ':
150
+ if (!(event.target instanceof HTMLInputElement)) {
151
+ event.preventDefault();
152
+ if (isOpen) {
153
+ selectHighlighted();
154
+ } else {
155
+ open();
156
+ }
157
+ }
158
+ break;
159
+ case 'ArrowDown':
160
+ event.preventDefault();
161
+ if (isOpen) {
162
+ moveHighlight(1);
163
+ } else {
164
+ open();
165
+ }
166
+ break;
167
+ case 'ArrowUp':
168
+ event.preventDefault();
169
+ moveHighlight(-1);
170
+ break;
171
+ case 'Escape':
172
+ if (isOpen) {
173
+ close();
174
+ if (!searchable && triggerEl !== null) {
175
+ triggerEl.focus();
176
+ }
177
+ }
178
+ break;
179
+ case 'Backspace':
180
+ if (multiple && query === '' && value.length > 0) {
181
+ const lastId = value.at(-1);
182
+ if (typeof lastId === 'string') {
183
+ removeItem(lastId);
184
+ }
185
+ }
186
+ break;
187
+ case 'Tab':
188
+ if (isOpen) {
189
+ close();
190
+ }
191
+ break;
192
+ }
193
+ }
194
+
195
+ function handleSearchInput(event: Event): void {
196
+ if (!(event.target instanceof HTMLInputElement)) {
197
+ return;
198
+ }
199
+ query = event.target.value;
200
+ if (!isOpen) {
201
+ isOpen = true;
202
+ }
203
+ highlightedIndex = -1;
204
+ }
205
+
206
+ function handleSearchFocus(): void {
207
+ if (!isOpen) {
208
+ open();
209
+ }
210
+ }
211
+
212
+ function handleClickOutside(event: Event): void {
213
+ if (
214
+ event.target instanceof Node &&
215
+ containerEl !== null &&
216
+ !containerEl.contains(event.target)
217
+ ) {
218
+ close();
219
+ }
220
+ }
221
+
222
+ onMount(() => {
223
+ document.addEventListener('click', handleClickOutside);
224
+ return () => {
225
+ document.removeEventListener('click', handleClickOutside);
226
+ };
227
+ });
228
+ </script>
229
+
230
+ <div
231
+ class="select {classes ?? ''}"
232
+ class:open={isOpen}
233
+ class:disabled
234
+ bind:this={containerEl}
235
+ {...typeof testId === 'string' ? { 'data-pw': testId } : {}}
236
+ >
237
+ <div
238
+ class="select-trigger"
239
+ bind:this={triggerEl}
240
+ onclick={handleTriggerClick}
241
+ onkeydown={handleKeydown}
242
+ role="combobox"
243
+ aria-expanded={isOpen}
244
+ aria-haspopup="listbox"
245
+ aria-controls={listboxId}
246
+ {...highlightedOptionId !== null ? { 'aria-activedescendant': highlightedOptionId } : {}}
247
+ tabindex={disabled ? -1 : searchable ? -1 : 0}
248
+ >
249
+ {#if multiple}
250
+ {#each value as id (id)}
251
+ <Pill
252
+ text={getLabel(id)}
253
+ dismissible
254
+ {disabled}
255
+ ondismiss={() => removeItem(id)}
256
+ {...typeof testId === 'string' ? { testId: `${testId}-pill-${id}` } : {}}
257
+ />
258
+ {/each}
259
+ {#if searchable}
260
+ <input
261
+ class="select-search"
262
+ type="text"
263
+ value={query}
264
+ oninput={handleSearchInput}
265
+ onfocus={handleSearchFocus}
266
+ bind:this={searchInputEl}
267
+ placeholder={value.length === 0 ? placeholder : ''}
268
+ {disabled}
269
+ autocomplete="off"
270
+ tabindex={disabled ? -1 : 0}
271
+ />
272
+ {:else if value.length === 0}
273
+ <span class="select-placeholder">{placeholder}</span>
274
+ {/if}
275
+ {:else if searchable}
276
+ <input
277
+ class="select-search"
278
+ type="text"
279
+ value={isOpen ? query : displayText}
280
+ oninput={handleSearchInput}
281
+ onfocus={handleSearchFocus}
282
+ bind:this={searchInputEl}
283
+ placeholder={searchPlaceholder}
284
+ {disabled}
285
+ autocomplete="off"
286
+ tabindex={disabled ? -1 : 0}
287
+ />
288
+ {:else}
289
+ <span class={displayText.length > 0 ? 'select-value' : 'select-placeholder'}>
290
+ {displayText.length > 0 ? displayText : placeholder}
291
+ </span>
292
+ {/if}
293
+ <!-- eslint-disable svelte/no-at-html-tags -->
294
+ <span class="select-arrow">{@html chevronDownSvg}</span>
295
+ </div>
296
+
297
+ {#if isOpen && !disabled}
298
+ <div class="select-dropdown" role="listbox" id={listboxId} aria-multiselectable={multiple}>
299
+ {#if filteredItems.length === 0}
300
+ <div class="select-empty">No results</div>
301
+ {:else}
302
+ {#each filteredItems as item, index (item.id)}
303
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
304
+ <div
305
+ class="select-option"
306
+ class:selected={value.includes(item.id)}
307
+ class:highlighted={index === highlightedIndex}
308
+ role="option"
309
+ id={`${listboxId}-option-${index}`}
310
+ aria-selected={value.includes(item.id)}
311
+ tabindex="-1"
312
+ onclick={() => selectItem(item.id)}
313
+ onmouseenter={() => (highlightedIndex = index)}
314
+ >
315
+ {item.label}
316
+ </div>
317
+ {/each}
318
+ {/if}
319
+ </div>
320
+ {/if}
321
+ </div>
322
+
323
+ <style>
324
+ .select {
325
+ position: relative;
326
+ width: var(--select-width, 100%);
327
+ font-family: var(--select-font-family, inherit);
328
+ font-size: var(--select-font-size, 14px);
329
+ color: var(--select-color, currentColor);
330
+ }
331
+
332
+ .select.disabled {
333
+ opacity: var(--select-disabled-opacity, 0.5);
334
+ cursor: var(--select-disabled-cursor, not-allowed);
335
+ pointer-events: none;
336
+ }
337
+
338
+ .select-trigger {
339
+ display: flex;
340
+ flex-wrap: wrap;
341
+ align-items: center;
342
+ box-sizing: border-box;
343
+ gap: var(--select-trigger-gap, 4px);
344
+ min-height: var(--select-trigger-min-height, 38px);
345
+ padding: var(--select-trigger-padding, 6px 12px);
346
+ background: var(--select-trigger-background, #ffffff);
347
+ border: var(--select-trigger-border, 1px solid currentColor);
348
+ border-radius: var(--select-trigger-border-radius, 6px);
349
+ cursor: pointer;
350
+ outline: none;
351
+ -webkit-tap-highlight-color: transparent;
352
+ transition: var(--select-trigger-transition, border-color 0.15s, box-shadow 0.15s);
353
+ }
354
+
355
+ .select-trigger:hover:not(.disabled .select-trigger) {
356
+ border-color: var(--select-trigger-hover-border-color, currentColor);
357
+ }
358
+
359
+ .select-trigger:focus-within,
360
+ .select.open .select-trigger {
361
+ border-color: var(--select-trigger-focus-border-color, currentColor);
362
+ box-shadow: var(--select-trigger-focus-shadow, 0 0 0 2px currentColor);
363
+ }
364
+
365
+ .select-value {
366
+ flex: 1;
367
+ white-space: nowrap;
368
+ overflow: hidden;
369
+ text-overflow: ellipsis;
370
+ }
371
+
372
+ .select-placeholder {
373
+ flex: 1;
374
+ color: var(--select-placeholder-color, currentColor);
375
+ white-space: nowrap;
376
+ overflow: hidden;
377
+ text-overflow: ellipsis;
378
+ }
379
+
380
+ .select-search {
381
+ flex: 1;
382
+ min-width: 60px;
383
+ border: none;
384
+ outline: none;
385
+ background: transparent;
386
+ font-family: inherit;
387
+ font-size: inherit;
388
+ color: inherit;
389
+ padding: 0;
390
+ cursor: text;
391
+ }
392
+
393
+ .select-search::placeholder {
394
+ color: var(--select-placeholder-color, currentColor);
395
+ }
396
+
397
+ .select-arrow {
398
+ display: inline-flex;
399
+ align-items: center;
400
+ justify-content: center;
401
+ width: var(--select-arrow-size, 16px);
402
+ height: var(--select-arrow-size, 16px);
403
+ color: var(--select-arrow-color, currentColor);
404
+ flex-shrink: 0;
405
+ transition: transform 0.15s;
406
+ }
407
+
408
+ .select.open .select-arrow {
409
+ transform: rotate(180deg);
410
+ }
411
+
412
+ .select-arrow :global(svg) {
413
+ width: 100%;
414
+ height: 100%;
415
+ }
416
+
417
+ .select-dropdown {
418
+ position: absolute;
419
+ top: 100%;
420
+ left: 0;
421
+ right: 0;
422
+ margin-top: var(--select-dropdown-gap, 4px);
423
+ background: var(--select-dropdown-background, #ffffff);
424
+ border: var(--select-dropdown-border, 1px solid currentColor);
425
+ border-radius: var(--select-dropdown-border-radius, 8px);
426
+ box-shadow: var(--select-dropdown-shadow, 0 4px 12px rgba(0, 0, 0, 0.1));
427
+ max-height: var(--select-dropdown-max-height, 200px);
428
+ overflow-y: auto;
429
+ z-index: var(--select-dropdown-z-index, 10);
430
+ }
431
+
432
+ .select-option {
433
+ padding: var(--select-option-padding, 8px 12px);
434
+ color: var(--select-option-color, currentColor);
435
+ font-size: var(--select-option-font-size, inherit);
436
+ cursor: pointer;
437
+ transition: background 0.1s;
438
+ }
439
+
440
+ .select-option:hover,
441
+ .select-option.highlighted {
442
+ background: var(--select-option-hover-background, #f4f4f5);
443
+ color: var(--select-option-hover-color, var(--select-option-color, currentColor));
444
+ }
445
+
446
+ .select-option.selected {
447
+ background: var(--select-option-selected-background, #18181b);
448
+ color: var(--select-option-selected-color, #ffffff);
449
+ }
450
+
451
+ .select-option.selected.highlighted {
452
+ background: var(
453
+ --select-option-selected-hover-background,
454
+ var(--select-option-selected-background, #18181b)
455
+ );
456
+ }
457
+
458
+ .select-empty {
459
+ padding: var(--select-empty-padding, 8px 12px);
460
+ color: var(--select-empty-color, currentColor);
461
+ font-style: var(--select-empty-font-style, italic);
462
+ font-size: var(--select-empty-font-size, inherit);
463
+ }
464
+
465
+ .select-trigger :global(.pill) {
466
+ --pill-background: var(--select-pill-background, #18181b);
467
+ --pill-color: var(--select-pill-color, #ffffff);
468
+ --pill-border-radius: var(--select-pill-border-radius, 999px);
469
+ --pill-padding: var(--select-pill-padding, 2px 8px);
470
+ --pill-font-size: var(--select-pill-font-size, 14px);
471
+ }
472
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { SelectProperties } from './properties';
2
+ declare const Select: import("svelte").Component<SelectProperties, {}, "value">;
3
+ type Select = ReturnType<typeof Select>;
4
+ export default Select;
@@ -0,0 +1,20 @@
1
+ export type SelectProperties = MandatorySelectProperties & OptionalSelectProperties & SelectEventProperties;
2
+ export type SelectItem = {
3
+ id: string;
4
+ label: string;
5
+ };
6
+ export type MandatorySelectProperties = {
7
+ items: SelectItem[];
8
+ };
9
+ export type OptionalSelectProperties = {
10
+ value?: string[];
11
+ multiple?: boolean;
12
+ searchable?: boolean;
13
+ placeholder?: string;
14
+ disabled?: boolean;
15
+ testId?: string;
16
+ classes?: string;
17
+ };
18
+ export type SelectEventProperties = {
19
+ onchange?: (value: string[]) => void;
20
+ };
@@ -0,0 +1 @@
1
+ export {};