twintrinsic 0.0.1

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 (212) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +150 -0
  3. package/dist/App/App.svelte +54 -0
  4. package/dist/App/App.svelte.d.ts +65 -0
  5. package/dist/Section.svelte +25 -0
  6. package/dist/Section.svelte.d.ts +34 -0
  7. package/dist/actions/clickOutside.d.ts +9 -0
  8. package/dist/actions/clickOutside.js +19 -0
  9. package/dist/actions/index.d.ts +1 -0
  10. package/dist/actions/index.js +1 -0
  11. package/dist/components/Accordion/Accordion.svelte +75 -0
  12. package/dist/components/Accordion/Accordion.svelte.d.ts +39 -0
  13. package/dist/components/Accordion/AccordionItem.svelte +150 -0
  14. package/dist/components/Accordion/AccordionItem.svelte.d.ts +30 -0
  15. package/dist/components/App/App.story.md +8 -0
  16. package/dist/components/App/App.story.svelte +170 -0
  17. package/dist/components/App/App.story.svelte.d.ts +22 -0
  18. package/dist/components/App/App.svelte +77 -0
  19. package/dist/components/App/App.svelte.d.ts +66 -0
  20. package/dist/components/App/Split.svelte +346 -0
  21. package/dist/components/App/Split.svelte.d.ts +54 -0
  22. package/dist/components/App/index.d.ts +2 -0
  23. package/dist/components/App/index.js +3 -0
  24. package/dist/components/AppHeader/AppHeader.svelte +439 -0
  25. package/dist/components/AppHeader/AppHeader.svelte.d.ts +24 -0
  26. package/dist/components/Avatar/Avatar.svelte +300 -0
  27. package/dist/components/Avatar/Avatar.svelte.d.ts +48 -0
  28. package/dist/components/Avatar/AvatarGroup.svelte +185 -0
  29. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +46 -0
  30. package/dist/components/Badge/Badge.svelte +186 -0
  31. package/dist/components/Badge/Badge.svelte.d.ts +51 -0
  32. package/dist/components/BottomBar/BottomBar.svelte +146 -0
  33. package/dist/components/BottomBar/BottomBar.svelte.d.ts +38 -0
  34. package/dist/components/Breadcrumb/Breadcrumb.svelte +77 -0
  35. package/dist/components/Breadcrumb/Breadcrumb.svelte.d.ts +42 -0
  36. package/dist/components/Breadcrumb/BreadcrumbItem.svelte +171 -0
  37. package/dist/components/Breadcrumb/BreadcrumbItem.svelte.d.ts +38 -0
  38. package/dist/components/Button/Button.svelte +252 -0
  39. package/dist/components/Button/Button.svelte.d.ts +80 -0
  40. package/dist/components/Button/ButtonGroup.svelte +127 -0
  41. package/dist/components/Button/ButtonGroup.svelte.d.ts +44 -0
  42. package/dist/components/Card/Card.svelte +152 -0
  43. package/dist/components/Card/Card.svelte.d.ts +55 -0
  44. package/dist/components/Carousel/Carousel.svelte +461 -0
  45. package/dist/components/Carousel/Carousel.svelte.d.ts +79 -0
  46. package/dist/components/Carousel/CarouselItem.svelte +149 -0
  47. package/dist/components/Carousel/CarouselItem.svelte.d.ts +35 -0
  48. package/dist/components/Chip/Chip.svelte +288 -0
  49. package/dist/components/Chip/Chip.svelte.d.ts +71 -0
  50. package/dist/components/Chip/ChipGroup.svelte +190 -0
  51. package/dist/components/Chip/ChipGroup.svelte.d.ts +71 -0
  52. package/dist/components/CodeBlock/CodeBlock.svelte +356 -0
  53. package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +44 -0
  54. package/dist/components/CodeBlock/index.d.ts +1 -0
  55. package/dist/components/CodeBlock/index.js +1 -0
  56. package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte +145 -0
  57. package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte.d.ts +44 -0
  58. package/dist/components/CodeEditor/CodeEditor.svelte +229 -0
  59. package/dist/components/CodeEditor/CodeEditor.svelte.d.ts +23 -0
  60. package/dist/components/Combobox/Combobox.svelte +279 -0
  61. package/dist/components/Combobox/Combobox.svelte.d.ts +34 -0
  62. package/dist/components/Container/Container.svelte +45 -0
  63. package/dist/components/Container/Container.svelte.d.ts +36 -0
  64. package/dist/components/DataTable/DataTable.svelte +879 -0
  65. package/dist/components/DataTable/DataTable.svelte.d.ts +102 -0
  66. package/dist/components/Form/AutoComplete.svelte +357 -0
  67. package/dist/components/Form/AutoComplete.svelte.d.ts +73 -0
  68. package/dist/components/Form/Calendar.svelte +429 -0
  69. package/dist/components/Form/Calendar.svelte.d.ts +53 -0
  70. package/dist/components/Form/Checkbox.svelte +196 -0
  71. package/dist/components/Form/Checkbox.svelte.d.ts +50 -0
  72. package/dist/components/Form/ColorPicker.svelte +396 -0
  73. package/dist/components/Form/ColorPicker.svelte.d.ts +43 -0
  74. package/dist/components/Form/Combobox.svelte +645 -0
  75. package/dist/components/Form/Combobox.svelte.d.ts +93 -0
  76. package/dist/components/Form/Dropdown.svelte +773 -0
  77. package/dist/components/Form/Dropdown.svelte.d.ts +81 -0
  78. package/dist/components/Form/FileUpload.svelte +796 -0
  79. package/dist/components/Form/FileUpload.svelte.d.ts +78 -0
  80. package/dist/components/Form/FloatLabel.svelte +245 -0
  81. package/dist/components/Form/FloatLabel.svelte.d.ts +44 -0
  82. package/dist/components/Form/Form.svelte +281 -0
  83. package/dist/components/Form/Form.svelte.d.ts +54 -0
  84. package/dist/components/Form/FormField.svelte +218 -0
  85. package/dist/components/Form/FormField.svelte.d.ts +47 -0
  86. package/dist/components/Form/Input.svelte +340 -0
  87. package/dist/components/Form/Input.svelte.d.ts +79 -0
  88. package/dist/components/Form/InputSwitch.svelte +189 -0
  89. package/dist/components/Form/InputSwitch.svelte.d.ts +46 -0
  90. package/dist/components/Form/InvalidState.svelte +97 -0
  91. package/dist/components/Form/InvalidState.svelte.d.ts +37 -0
  92. package/dist/components/Form/Knob.svelte +537 -0
  93. package/dist/components/Form/Knob.svelte.d.ts +78 -0
  94. package/dist/components/Form/ListInput.svelte +469 -0
  95. package/dist/components/Form/ListInput.svelte.d.ts +70 -0
  96. package/dist/components/Form/Listbox.svelte +513 -0
  97. package/dist/components/Form/Listbox.svelte.d.ts +74 -0
  98. package/dist/components/Form/NumberInput.svelte +452 -0
  99. package/dist/components/Form/NumberInput.svelte.d.ts +82 -0
  100. package/dist/components/Form/Radio.svelte +192 -0
  101. package/dist/components/Form/Radio.svelte.d.ts +53 -0
  102. package/dist/components/Form/RadioGroup.svelte +155 -0
  103. package/dist/components/Form/RadioGroup.svelte.d.ts +48 -0
  104. package/dist/components/Form/Rating.svelte +380 -0
  105. package/dist/components/Form/Rating.svelte.d.ts +64 -0
  106. package/dist/components/Form/Select.svelte +436 -0
  107. package/dist/components/Form/Select.svelte.d.ts +49 -0
  108. package/dist/components/Form/SelectGroup.svelte +34 -0
  109. package/dist/components/Form/SelectGroup.svelte.d.ts +33 -0
  110. package/dist/components/Form/Slider.svelte +622 -0
  111. package/dist/components/Form/Slider.svelte.d.ts +73 -0
  112. package/dist/components/Form/Switch.svelte +192 -0
  113. package/dist/components/Form/Switch.svelte.d.ts +46 -0
  114. package/dist/components/Form/TextInput.svelte +274 -0
  115. package/dist/components/Form/TextInput.svelte.d.ts +74 -0
  116. package/dist/components/Form/Textarea.svelte +207 -0
  117. package/dist/components/Form/Textarea.svelte.d.ts +62 -0
  118. package/dist/components/Icon/Icon.svelte +140 -0
  119. package/dist/components/Icon/Icon.svelte.d.ts +25 -0
  120. package/dist/components/Icon/index.d.ts +1 -0
  121. package/dist/components/Icon/index.js +1 -0
  122. package/dist/components/Lazy/Lazy.svelte +158 -0
  123. package/dist/components/Lazy/Lazy.svelte.d.ts +42 -0
  124. package/dist/components/Masonry/Masonry.svelte +299 -0
  125. package/dist/components/Masonry/Masonry.svelte.d.ts +55 -0
  126. package/dist/components/Menu/Menu/Menu.svelte +65 -0
  127. package/dist/components/Menu/Menu/Menu.svelte.d.ts +17 -0
  128. package/dist/components/Menu/Menu/MenuItem.svelte +90 -0
  129. package/dist/components/Menu/Menu/MenuItem.svelte.d.ts +27 -0
  130. package/dist/components/Modal/Modal.svelte +334 -0
  131. package/dist/components/Modal/Modal.svelte.d.ts +55 -0
  132. package/dist/components/Panel/Card.svelte +141 -0
  133. package/dist/components/Panel/Card.svelte.d.ts +52 -0
  134. package/dist/components/Panel/Hero/Hero.story.md +9 -0
  135. package/dist/components/Panel/Hero/Hero.story.svelte +49 -0
  136. package/dist/components/Panel/Hero/Hero.story.svelte.d.ts +21 -0
  137. package/dist/components/Panel/Hero/Hero.svelte +24 -0
  138. package/dist/components/Panel/Hero/Hero.svelte.d.ts +32 -0
  139. package/dist/components/Panel/LazyPanel.svelte +110 -0
  140. package/dist/components/Panel/LazyPanel.svelte.d.ts +46 -0
  141. package/dist/components/Panel/Panel.svelte +205 -0
  142. package/dist/components/Panel/Panel.svelte.d.ts +23 -0
  143. package/dist/components/Progress/Progress.svelte +220 -0
  144. package/dist/components/Progress/Progress.svelte.d.ts +61 -0
  145. package/dist/components/Separator/Separator.svelte +109 -0
  146. package/dist/components/Separator/Separator.svelte.d.ts +35 -0
  147. package/dist/components/Sidebar/Sidebar.svelte +213 -0
  148. package/dist/components/Sidebar/Sidebar.svelte.d.ts +60 -0
  149. package/dist/components/Skeleton/Skeleton.svelte +170 -0
  150. package/dist/components/Skeleton/Skeleton.svelte.d.ts +48 -0
  151. package/dist/components/Stepper/Stepper.svelte +111 -0
  152. package/dist/components/Stepper/Stepper.svelte.d.ts +54 -0
  153. package/dist/components/Stepper/StepperStep.svelte +369 -0
  154. package/dist/components/Stepper/StepperStep.svelte.d.ts +63 -0
  155. package/dist/components/Table/Table.svelte +167 -0
  156. package/dist/components/Table/Table.svelte.d.ts +56 -0
  157. package/dist/components/Table/TableBody.svelte +41 -0
  158. package/dist/components/Table/TableBody.svelte.d.ts +33 -0
  159. package/dist/components/Table/TableCell.svelte +76 -0
  160. package/dist/components/Table/TableCell.svelte.d.ts +36 -0
  161. package/dist/components/Table/TableHead.svelte +41 -0
  162. package/dist/components/Table/TableHead.svelte.d.ts +32 -0
  163. package/dist/components/Table/TableHeader.svelte +148 -0
  164. package/dist/components/Table/TableHeader.svelte.d.ts +42 -0
  165. package/dist/components/Table/TableRow.svelte +99 -0
  166. package/dist/components/Table/TableRow.svelte.d.ts +40 -0
  167. package/dist/components/Tabs/Tab.svelte +145 -0
  168. package/dist/components/Tabs/Tab.svelte.d.ts +36 -0
  169. package/dist/components/Tabs/TabList.svelte +60 -0
  170. package/dist/components/Tabs/TabList.svelte.d.ts +32 -0
  171. package/dist/components/Tabs/TabPanel.svelte +118 -0
  172. package/dist/components/Tabs/TabPanel.svelte.d.ts +38 -0
  173. package/dist/components/Tabs/Tabs.svelte +287 -0
  174. package/dist/components/Tabs/Tabs.svelte.d.ts +50 -0
  175. package/dist/components/Tag/Tag.svelte +260 -0
  176. package/dist/components/Tag/Tag.svelte.d.ts +54 -0
  177. package/dist/components/Tag/TagGroup.svelte +147 -0
  178. package/dist/components/Tag/TagGroup.svelte.d.ts +62 -0
  179. package/dist/components/ThemeToggle/ThemeToggle.svelte +93 -0
  180. package/dist/components/ThemeToggle/ThemeToggle.svelte.d.ts +12 -0
  181. package/dist/components/Timeline/Timeline.svelte +144 -0
  182. package/dist/components/Timeline/Timeline.svelte.d.ts +48 -0
  183. package/dist/components/Timeline/TimelineItem.svelte +391 -0
  184. package/dist/components/Timeline/TimelineItem.svelte.d.ts +63 -0
  185. package/dist/components/Toast/Toast.svelte +313 -0
  186. package/dist/components/Toast/Toast.svelte.d.ts +44 -0
  187. package/dist/components/Toast/toastStore.d.ts +40 -0
  188. package/dist/components/Toast/toastStore.js +293 -0
  189. package/dist/components/Tooltip/Tooltip.svelte +282 -0
  190. package/dist/components/Tooltip/Tooltip.svelte.d.ts +55 -0
  191. package/dist/components/Tree/Tree.svelte +129 -0
  192. package/dist/components/Tree/Tree.svelte.d.ts +61 -0
  193. package/dist/components/Tree/TreeNode.svelte +332 -0
  194. package/dist/components/Tree/TreeNode.svelte.d.ts +55 -0
  195. package/dist/components/icons/TwintrinsicLogo.svelte +73 -0
  196. package/dist/components/icons/TwintrinsicLogo.svelte.d.ts +17 -0
  197. package/dist/components/icons/twintrinsic-source.svg +73 -0
  198. package/dist/components/icons/twintrinsic.svg +38 -0
  199. package/dist/docs/EventsTable.svelte +86 -0
  200. package/dist/docs/EventsTable.svelte.d.ts +27 -0
  201. package/dist/docs/PropsTable.svelte +103 -0
  202. package/dist/docs/PropsTable.svelte.d.ts +28 -0
  203. package/dist/docs/index.d.ts +2 -0
  204. package/dist/docs/index.js +2 -0
  205. package/dist/helpers/detectLanguage.d.ts +6 -0
  206. package/dist/helpers/detectLanguage.js +60 -0
  207. package/dist/helpers/index.d.ts +1 -0
  208. package/dist/helpers/index.js +1 -0
  209. package/dist/index.d.ts +86 -0
  210. package/dist/index.js +94 -0
  211. package/dist/twintrinsic.css +347 -0
  212. package/package.json +98 -0
@@ -0,0 +1,436 @@
1
+ <!--
2
+ @component
3
+ Select - A form component for selecting options from a dropdown list.
4
+ Supports single and multiple selection, option groups, and custom option templates.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Select
9
+ label="Country"
10
+ options={countries}
11
+ onchange={handleChange}
12
+ />
13
+
14
+ <Select
15
+ label="Skills"
16
+ options={skills}
17
+ multiple={true}
18
+ placeholder="Select skills..."
19
+ />
20
+ ```
21
+ -->
22
+ <script>
23
+ import { slide } from "svelte/transition"
24
+ import { clickOutside } from "../../actions/index.js"
25
+
26
+ const {
27
+ /** @type {string} - Input label */
28
+ label = "",
29
+ /** @type {Array<{ value: string, label: string, group?: string }>} - Options to display */
30
+ options = [],
31
+ /** @type {string | string[]} - Selected value(s) */
32
+ value = "",
33
+ /** @type {boolean} - Whether multiple selection is allowed */
34
+ multiple = false,
35
+ /** @type {string} - Placeholder text */
36
+ placeholder = "Select...",
37
+ /** @type {boolean} - Whether the select is disabled */
38
+ disabled = false,
39
+ /** @type {string} - Error message */
40
+ error = "",
41
+ /** @type {boolean} - Whether the field is required */
42
+ required = false,
43
+ /** @type {string} - Additional CSS classes */
44
+ class: className = "",
45
+ /** @type {(event: CustomEvent) => void} - Change event handler */
46
+ onchange,
47
+ } = $props()
48
+
49
+ let showDropdown = $state(false)
50
+ let searchValue = $state("")
51
+ let selectedValues = $state([])
52
+ let focusedIndex = $state(-1)
53
+ let dropdownRef = $state()
54
+
55
+ // Initialize selected values
56
+ $effect(() => {
57
+ selectedValues = Array.isArray(value) ? value : value ? [value] : []
58
+ })
59
+
60
+ // Filter options based on search
61
+ const filteredOptions = $derived(() => {
62
+ const search = searchValue.toLowerCase()
63
+ return options.filter((option) => option.label.toLowerCase().includes(search))
64
+ })
65
+
66
+ // Group options by their group property
67
+ const groupedOptions = $derived(() => {
68
+ const groups = new Map()
69
+
70
+ for (const option of filteredOptions) {
71
+ const group = option.group || ""
72
+ if (!groups.has(group)) {
73
+ groups.set(group, [])
74
+ }
75
+ groups.get(group).push(option)
76
+ }
77
+
78
+ return groups
79
+ })
80
+
81
+ // Handle option selection
82
+ function selectOption(option) {
83
+ if (disabled) return
84
+
85
+ const value = option.value
86
+ let newValues
87
+
88
+ if (multiple) {
89
+ newValues = selectedValues.includes(value)
90
+ ? selectedValues.filter((v) => v !== value)
91
+ : [...selectedValues, value]
92
+ } else {
93
+ newValues = [value]
94
+ showDropdown = false
95
+ }
96
+
97
+ selectedValues = newValues
98
+ onchange?.(new CustomEvent("change", {
99
+ detail: {
100
+ value: multiple ? newValues : newValues[0],
101
+ }
102
+ }))
103
+ }
104
+
105
+ // Handle keyboard navigation
106
+ function handleKeydown(event) {
107
+ if (disabled) return
108
+
109
+ switch (event.key) {
110
+ case "Enter":
111
+ case " ":
112
+ if (!showDropdown) {
113
+ event.preventDefault()
114
+ showDropdown = true
115
+ } else if (focusedIndex >= 0) {
116
+ event.preventDefault()
117
+ selectOption(filteredOptions[focusedIndex])
118
+ }
119
+ break
120
+
121
+ case "ArrowDown":
122
+ event.preventDefault()
123
+ if (!showDropdown) {
124
+ showDropdown = true
125
+ } else {
126
+ focusedIndex = Math.min(focusedIndex + 1, filteredOptions.length - 1)
127
+ scrollToOption(focusedIndex)
128
+ }
129
+ break
130
+
131
+ case "ArrowUp":
132
+ event.preventDefault()
133
+ if (showDropdown) {
134
+ focusedIndex = Math.max(focusedIndex - 1, 0)
135
+ scrollToOption(focusedIndex)
136
+ }
137
+ break
138
+
139
+ case "Escape":
140
+ showDropdown = false
141
+ break
142
+
143
+ case "Tab":
144
+ showDropdown = false
145
+ break
146
+ }
147
+ }
148
+
149
+ // Scroll focused option into view
150
+ function scrollToOption(index) {
151
+ if (!dropdownRef) return
152
+
153
+ const options = dropdownRef.querySelectorAll(".select-option")
154
+ if (options[index]) {
155
+ options[index].scrollIntoView({
156
+ block: "nearest",
157
+ })
158
+ }
159
+ }
160
+
161
+ // Clear selection
162
+ function clearSelection(event) {
163
+ event.stopPropagation()
164
+ if (disabled) return
165
+ selectedValues = []
166
+ dispatch("change", { value: multiple ? [] : "" })
167
+ }
168
+
169
+ // Get display value
170
+ const displayValue = $derived(() => {
171
+ if (!selectedValues.length) return ""
172
+
173
+ const selected = options.filter((option) => selectedValues.includes(option.value))
174
+
175
+ if (multiple) {
176
+ return selected.length === 1 ? selected[0].label : `${selected.length} items selected`
177
+ }
178
+
179
+ return selected[0]?.label || ""
180
+ })
181
+ </script>
182
+
183
+ <div
184
+ class="select {className}"
185
+ class:select-error={!!error}
186
+ class:select-disabled={disabled}
187
+ use:clickOutside
188
+ onclickOutside={() => showDropdown = false}
189
+ >
190
+ <label class="select-label">
191
+ {#if label}
192
+ <span class="select-label-text">
193
+ {label}
194
+ {#if required}
195
+ <span class="select-required" aria-hidden="true">*</span>
196
+ {/if}
197
+ </span>
198
+ {/if}
199
+
200
+ <div
201
+ class="select-control"
202
+ role="combobox"
203
+ aria-expanded={showDropdown}
204
+ aria-haspopup="listbox"
205
+ aria-controls="select-options"
206
+ aria-label={label}
207
+ aria-required={required}
208
+ aria-invalid={!!error}
209
+ aria-describedby={error ? 'select-error' : undefined}
210
+ tabindex={disabled ? -1 : 0}
211
+ onclick={() => !disabled && (showDropdown = !showDropdown)}
212
+ onkeydown={handleKeydown}
213
+ >
214
+ <div class="select-value">
215
+ {#if selectedValues.length}
216
+ <span class="select-text">{displayValue}</span>
217
+ {#if !disabled}
218
+ <button
219
+ type="button"
220
+ class="select-clear"
221
+ aria-label="Clear selection"
222
+ onclick={clearSelection}
223
+ >
224
+ ×
225
+ </button>
226
+ {/if}
227
+ {:else}
228
+ <span class="select-placeholder">{placeholder}</span>
229
+ {/if}
230
+ </div>
231
+
232
+ <div class="select-indicator">
233
+ <svg
234
+ class="select-arrow"
235
+ class:select-arrow-open={showDropdown}
236
+ viewBox="0 0 24 24"
237
+ width="16"
238
+ height="16"
239
+ >
240
+ <path
241
+ fill="currentColor"
242
+ d="M7 10l5 5 5-5z"
243
+ />
244
+ </svg>
245
+ </div>
246
+ </div>
247
+ </label>
248
+
249
+ {#if error}
250
+ <div
251
+ id="select-error"
252
+ class="select-error-text"
253
+ aria-live="polite"
254
+ >
255
+ {error}
256
+ </div>
257
+ {/if}
258
+
259
+ {#if showDropdown}
260
+ <div
261
+ class="select-dropdown"
262
+ id="select-options"
263
+ role="listbox"
264
+ aria-multiselectable={multiple}
265
+ bind:this={dropdownRef}
266
+ transition:slide={{ duration: 150 }}
267
+ >
268
+ {#if options.length > 10}
269
+ <div class="select-search">
270
+ <input
271
+ type="text"
272
+ placeholder="Search..."
273
+ bind:value={searchValue}
274
+ onclick={event => event.stopPropagation()}
275
+ />
276
+ </div>
277
+ {/if}
278
+
279
+ <div class="select-options">
280
+ {#each [...groupedOptions.entries()] as [group, options]}
281
+ {#if group}
282
+ <div class="select-group">
283
+ <div class="select-group-label">{group}</div>
284
+ {#each options as option, index}
285
+ <div
286
+ class="select-option"
287
+ class:select-option-selected={selectedValues.includes(option.value)}
288
+ class:select-option-focused={focusedIndex === index}
289
+ role="option"
290
+ aria-selected={selectedValues.includes(option.value)}
291
+ onclick={() => selectOption(option)}
292
+ >
293
+ {option.label}
294
+ </div>
295
+ {/each}
296
+ </div>
297
+ {:else}
298
+ {#each options as option, index}
299
+ <div
300
+ class="select-option"
301
+ class:select-option-selected={selectedValues.includes(option.value)}
302
+ class:select-option-focused={focusedIndex === index}
303
+ role="option"
304
+ aria-selected={selectedValues.includes(option.value)}
305
+ onclick={() => selectOption(option)}
306
+ >
307
+ {option.label}
308
+ </div>
309
+ {/each}
310
+ {/if}
311
+ {/each}
312
+
313
+ {#if filteredOptions.length === 0}
314
+ <div class="select-no-results">
315
+ No options found
316
+ </div>
317
+ {/if}
318
+ </div>
319
+ </div>
320
+ {/if}
321
+ </div>
322
+
323
+ <style>
324
+ @reference '../../twintrinsic.css';
325
+
326
+ .select {
327
+ @apply relative inline-block w-full;
328
+ }
329
+
330
+ .select-label {
331
+ @apply block;
332
+ }
333
+
334
+ .select-label-text {
335
+ @apply block mb-1 text-sm font-medium;
336
+ }
337
+
338
+ .select-required {
339
+ @apply ml-1 text-error;
340
+ }
341
+
342
+ .select-control {
343
+ @apply relative flex items-center w-full px-3 py-2;
344
+ @apply bg-surface border border-border rounded-md;
345
+ @apply text-sm cursor-pointer;
346
+ @apply transition-colors duration-150;
347
+ @apply focus:outline-none focus:ring-2 focus:ring-primary/50;
348
+ }
349
+
350
+ .select-disabled .select-control {
351
+ @apply bg-surface/50 cursor-not-allowed;
352
+ }
353
+
354
+ .select-error .select-control {
355
+ @apply border-error;
356
+ }
357
+
358
+ .select-value {
359
+ @apply flex-1 flex items-center min-w-0;
360
+ }
361
+
362
+ .select-text {
363
+ @apply truncate;
364
+ }
365
+
366
+ .select-placeholder {
367
+ @apply text-muted;
368
+ }
369
+
370
+ .select-clear {
371
+ @apply ml-2 text-lg text-muted hover:text-primary-text;
372
+ @apply focus:outline-none focus:text-primary-text;
373
+ }
374
+
375
+ .select-indicator {
376
+ @apply ml-2 flex-none;
377
+ }
378
+
379
+ .select-arrow {
380
+ @apply transition-transform duration-150;
381
+ }
382
+
383
+ .select-arrow-open {
384
+ @apply rotate-180;
385
+ }
386
+
387
+ .select-dropdown {
388
+ @apply absolute z-50 w-full mt-1;
389
+ @apply bg-surface border border-border rounded-md shadow-lg;
390
+ @apply max-h-60 overflow-auto;
391
+ }
392
+
393
+ .select-search {
394
+ @apply sticky top-0 p-2 border-b border-border bg-surface;
395
+ }
396
+
397
+ .select-search input {
398
+ @apply w-full px-2 py-1 text-sm;
399
+ @apply bg-surface border border-border rounded;
400
+ @apply focus:outline-none focus:ring-2 focus:ring-primary/50;
401
+ }
402
+
403
+ .select-options {
404
+ @apply py-1;
405
+ }
406
+
407
+ .select-group {
408
+ @apply py-1;
409
+ }
410
+
411
+ .select-group-label {
412
+ @apply px-3 py-1 text-xs font-medium text-muted;
413
+ }
414
+
415
+ .select-option {
416
+ @apply px-3 py-2 text-sm cursor-pointer;
417
+ @apply hover:bg-hover focus:bg-hover;
418
+ @apply transition-colors duration-150;
419
+ }
420
+
421
+ .select-option-selected {
422
+ @apply bg-primary/10 text-primary;
423
+ }
424
+
425
+ .select-option-focused {
426
+ @apply bg-hover;
427
+ }
428
+
429
+ .select-no-results {
430
+ @apply px-3 py-2 text-sm text-muted;
431
+ }
432
+
433
+ .select-error-text {
434
+ @apply mt-1 text-sm text-error;
435
+ }
436
+ </style>
@@ -0,0 +1,49 @@
1
+ export default Select;
2
+ type Select = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Select - A form component for selecting options from a dropdown list.
8
+ * Supports single and multiple selection, option groups, and custom option templates.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Select
13
+ * label="Country"
14
+ * options={countries}
15
+ * onchange={handleChange}
16
+ * />
17
+ *
18
+ * <Select
19
+ * label="Skills"
20
+ * options={skills}
21
+ * multiple={true}
22
+ * placeholder="Select skills..."
23
+ * />
24
+ * ```
25
+ */
26
+ declare const Select: import("svelte").Component<{
27
+ label?: string;
28
+ options?: any[];
29
+ value?: string;
30
+ multiple?: boolean;
31
+ placeholder?: string;
32
+ disabled?: boolean;
33
+ error?: string;
34
+ required?: boolean;
35
+ class?: string;
36
+ onchange: any;
37
+ }, {}, "">;
38
+ type $$ComponentProps = {
39
+ label?: string;
40
+ options?: any[];
41
+ value?: string;
42
+ multiple?: boolean;
43
+ placeholder?: string;
44
+ disabled?: boolean;
45
+ error?: string;
46
+ required?: boolean;
47
+ class?: string;
48
+ onchange: any;
49
+ };
@@ -0,0 +1,34 @@
1
+ <!--
2
+ @component
3
+ SelectGroup - A component for grouping related options in a Select component.
4
+ Provides semantic grouping with optional labels.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Select name="country">
9
+ <SelectGroup label="Europe">
10
+ <option value="fr">France</option>
11
+ <option value="de">Germany</option>
12
+ </SelectGroup>
13
+ <SelectGroup label="North America">
14
+ <option value="us">United States</option>
15
+ <option value="ca">Canada</option>
16
+ </SelectGroup>
17
+ </Select>
18
+ ```
19
+ -->
20
+ <script>
21
+ const {
22
+ /** @type {string} - Group label */
23
+ label,
24
+
25
+ /** @type {boolean} - Whether the group is disabled */
26
+ disabled = false,
27
+
28
+ children,
29
+ } = $props()
30
+ </script>
31
+
32
+ <optgroup {label} {disabled}>
33
+ {@render children?.()}
34
+ </optgroup>
@@ -0,0 +1,33 @@
1
+ export default SelectGroup;
2
+ type SelectGroup = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * SelectGroup - A component for grouping related options in a Select component.
8
+ * Provides semantic grouping with optional labels.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Select name="country">
13
+ * <SelectGroup label="Europe">
14
+ * <option value="fr">France</option>
15
+ * <option value="de">Germany</option>
16
+ * </SelectGroup>
17
+ * <SelectGroup label="North America">
18
+ * <option value="us">United States</option>
19
+ * <option value="ca">Canada</option>
20
+ * </SelectGroup>
21
+ * </Select>
22
+ * ```
23
+ */
24
+ declare const SelectGroup: import("svelte").Component<{
25
+ label: any;
26
+ disabled?: boolean;
27
+ children: any;
28
+ }, {}, "">;
29
+ type $$ComponentProps = {
30
+ label: any;
31
+ disabled?: boolean;
32
+ children: any;
33
+ };