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,78 @@
1
+ export default FileUpload;
2
+ type FileUpload = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * FileUpload - A component for uploading files with drag and drop support.
8
+ * Provides consistent styling, accessibility features, and various display options.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <FileUpload
13
+ * onchange={handleFiles}
14
+ * accept="image/*"
15
+ * multiple
16
+ * />
17
+ *
18
+ * <FileUpload
19
+ * value={existingFiles}
20
+ * maxFiles={5}
21
+ * maxSize={5242880}
22
+ * onchange={handleFiles}
23
+ * onerror={handleError}
24
+ * >
25
+ * <div slot="dropzone">
26
+ * <p>Drag files here or click to browse</p>
27
+ * </div>
28
+ * </FileUpload>
29
+ * ```
30
+ */
31
+ declare const FileUpload: import("svelte").Component<{
32
+ class?: string;
33
+ id?: any;
34
+ name: any;
35
+ value?: any[];
36
+ accept: any;
37
+ multiple?: boolean;
38
+ disabled?: boolean;
39
+ maxFiles: any;
40
+ maxSize: any;
41
+ showPreviews?: boolean;
42
+ autoUpload?: boolean;
43
+ uploadUrl: any;
44
+ uploadHeaders: any;
45
+ browseLabel?: string;
46
+ dropzoneLabel?: string;
47
+ ariaLabel?: string;
48
+ onchange: any;
49
+ onerror: any;
50
+ onprogress: any;
51
+ onsuccess: any;
52
+ dropzone: any;
53
+ previews: any;
54
+ }, {}, "">;
55
+ type $$ComponentProps = {
56
+ class?: string;
57
+ id?: any;
58
+ name: any;
59
+ value?: any[];
60
+ accept: any;
61
+ multiple?: boolean;
62
+ disabled?: boolean;
63
+ maxFiles: any;
64
+ maxSize: any;
65
+ showPreviews?: boolean;
66
+ autoUpload?: boolean;
67
+ uploadUrl: any;
68
+ uploadHeaders: any;
69
+ browseLabel?: string;
70
+ dropzoneLabel?: string;
71
+ ariaLabel?: string;
72
+ onchange: any;
73
+ onerror: any;
74
+ onprogress: any;
75
+ onsuccess: any;
76
+ dropzone: any;
77
+ previews: any;
78
+ };
@@ -0,0 +1,245 @@
1
+ <!--
2
+ @component
3
+ FloatLabel - A component for creating form inputs with animated floating labels.
4
+ Provides a modern, space-efficient input with improved user experience.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <FloatLabel label="Username">
9
+ <TextInput name="username" />
10
+ </FloatLabel>
11
+
12
+ <FloatLabel label="Email" required>
13
+ <TextInput type="email" name="email" />
14
+ </FloatLabel>
15
+
16
+ <FloatLabel label="Message">
17
+ <Textarea name="message" rows={3} />
18
+ </FloatLabel>
19
+ ```
20
+ -->
21
+ <script>
22
+ import { onMount } from "svelte"
23
+
24
+ const {
25
+ /** @type {string} - Additional CSS classes */
26
+ class: className = "",
27
+
28
+ /** @type {string} - HTML id for accessibility */
29
+ id = crypto.randomUUID(),
30
+
31
+ /** @type {string} - Label text */
32
+ label,
33
+
34
+ /** @type {boolean} - Whether the input is required */
35
+ required = false,
36
+
37
+ /** @type {boolean} - Whether the input is disabled */
38
+ disabled = false,
39
+
40
+ /** @type {string} - Error message to display */
41
+ error,
42
+
43
+ /** @type {string} - Help text to display below the input */
44
+ helpText,
45
+
46
+ children,
47
+ } = $props()
48
+
49
+ // Component state
50
+ let inputElement
51
+ let isFocused = $state(false)
52
+ let hasValue = $state(false)
53
+ let isFloating = $state(false)
54
+
55
+ /**
56
+ * Checks if the input has a value
57
+ */
58
+ function checkValue() {
59
+ if (!inputElement) return
60
+
61
+ // Find the actual input element (could be nested)
62
+ const input = findInputElement(inputElement)
63
+
64
+ if (input) {
65
+ hasValue = !!input.value
66
+ }
67
+
68
+ // Update floating state
69
+ isFloating = isFocused || hasValue
70
+ }
71
+
72
+ /**
73
+ * Recursively finds an input element
74
+ * @param {HTMLElement} element - Element to search in
75
+ * @returns {HTMLElement|null} - Found input element or null
76
+ */
77
+ function findInputElement(element) {
78
+ // Check if this is an input, textarea, or select
79
+ if (
80
+ element.tagName === "INPUT" ||
81
+ element.tagName === "TEXTAREA" ||
82
+ element.tagName === "SELECT"
83
+ ) {
84
+ return element
85
+ }
86
+
87
+ // Check children
88
+ const inputs = element.querySelectorAll("input, textarea, select")
89
+ if (inputs.length > 0) {
90
+ return inputs[0]
91
+ }
92
+
93
+ return null
94
+ }
95
+
96
+ /**
97
+ * Handles focus event
98
+ */
99
+ function handleFocus() {
100
+ isFocused = true
101
+ isFloating = true
102
+ }
103
+
104
+ /**
105
+ * Handles blur event
106
+ */
107
+ function handleBlur() {
108
+ isFocused = false
109
+ checkValue()
110
+ }
111
+
112
+ /**
113
+ * Handles input event
114
+ */
115
+ function handleInput() {
116
+ checkValue()
117
+ }
118
+
119
+ // Initialize component
120
+ onMount(() => {
121
+ if (inputElement) {
122
+ // Find the actual input element
123
+ const input = findInputElement(inputElement)
124
+
125
+ if (input) {
126
+ // Add event listeners
127
+ input.addEventListener("focus", handleFocus)
128
+ input.addEventListener("blur", handleBlur)
129
+ input.addEventListener("input", handleInput)
130
+
131
+ // Initial check
132
+ checkValue()
133
+
134
+ // Clean up
135
+ return () => {
136
+ input.removeEventListener("focus", handleFocus)
137
+ input.removeEventListener("blur", handleBlur)
138
+ input.removeEventListener("input", handleInput)
139
+ }
140
+ }
141
+ }
142
+ })
143
+ </script>
144
+
145
+ <div
146
+ class="
147
+ float-label-wrapper
148
+ {isFocused ? 'is-focused' : ''}
149
+ {isFloating ? 'is-floating' : ''}
150
+ {hasValue ? 'has-value' : ''}
151
+ {error ? 'has-error' : ''}
152
+ {disabled ? 'is-disabled' : ''}
153
+ {className}
154
+ "
155
+ >
156
+ <div class="float-label-container">
157
+ {#if label}
158
+ <label
159
+ for={id}
160
+ class="float-label"
161
+ >
162
+ {label}
163
+ {#if required}
164
+ <span class="required-indicator" aria-hidden="true">*</span>
165
+ <span class="sr-only">required</span>
166
+ {/if}
167
+ </label>
168
+ {/if}
169
+
170
+ <div class="float-label-input" bind:this={inputElement}>
171
+ {@render children?.()}
172
+ </div>
173
+ </div>
174
+
175
+ {#if error}
176
+ <div class="float-label-error" role="alert">
177
+ {error}
178
+ </div>
179
+ {/if}
180
+
181
+ {#if helpText && !error}
182
+ <div class="float-label-help">
183
+ {helpText}
184
+ </div>
185
+ {/if}
186
+ </div>
187
+
188
+ <style>
189
+ @reference "../../twintrinsic.css";
190
+
191
+ .float-label-wrapper {
192
+ @apply w-full;
193
+ }
194
+
195
+ .float-label-container {
196
+ @apply relative;
197
+ }
198
+
199
+ .float-label {
200
+ @apply absolute left-3 top-1/2 -translate-y-1/2;
201
+ @apply text-muted dark:text-muted;
202
+ @apply pointer-events-none transition-all duration-200;
203
+ @apply text-base;
204
+ }
205
+
206
+ .is-floating .float-label {
207
+ @apply text-xs top-0 -translate-y-1/2;
208
+ @apply bg-background dark:bg-background px-1;
209
+ }
210
+
211
+ .is-focused .float-label {
212
+ @apply text-primary-500 dark:text-primary-400;
213
+ }
214
+
215
+ .has-error .float-label {
216
+ @apply text-error-500 dark:text-error-400;
217
+ }
218
+
219
+ .float-label-input {
220
+ @apply w-full;
221
+ }
222
+
223
+ /* Style child inputs */
224
+ .float-label-input :global(input),
225
+ .float-label-input :global(textarea),
226
+ .float-label-input :global(select) {
227
+ @apply pt-4 pb-2;
228
+ }
229
+
230
+ .required-indicator {
231
+ @apply ml-1 text-error-500 dark:text-error-400;
232
+ }
233
+
234
+ .float-label-error {
235
+ @apply mt-1 text-xs text-error-600 dark:text-error-400;
236
+ }
237
+
238
+ .float-label-help {
239
+ @apply mt-1 text-xs text-muted dark:text-muted;
240
+ }
241
+
242
+ .is-disabled {
243
+ @apply opacity-60 pointer-events-none;
244
+ }
245
+ </style>
@@ -0,0 +1,44 @@
1
+ export default FloatLabel;
2
+ type FloatLabel = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * FloatLabel - A component for creating form inputs with animated floating labels.
8
+ * Provides a modern, space-efficient input with improved user experience.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <FloatLabel label="Username">
13
+ * <TextInput name="username" />
14
+ * </FloatLabel>
15
+ *
16
+ * <FloatLabel label="Email" required>
17
+ * <TextInput type="email" name="email" />
18
+ * </FloatLabel>
19
+ *
20
+ * <FloatLabel label="Message">
21
+ * <Textarea name="message" rows={3} />
22
+ * </FloatLabel>
23
+ * ```
24
+ */
25
+ declare const FloatLabel: import("svelte").Component<{
26
+ class?: string;
27
+ id?: any;
28
+ label: any;
29
+ required?: boolean;
30
+ disabled?: boolean;
31
+ error: any;
32
+ helpText: any;
33
+ children: any;
34
+ }, {}, "">;
35
+ type $$ComponentProps = {
36
+ class?: string;
37
+ id?: any;
38
+ label: any;
39
+ required?: boolean;
40
+ disabled?: boolean;
41
+ error: any;
42
+ helpText: any;
43
+ children: any;
44
+ };
@@ -0,0 +1,281 @@
1
+ <!--
2
+ @component
3
+ Form - A component for creating accessible, styled forms with validation support.
4
+ Handles form submission, validation, and provides context for form controls.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Form onsubmit={handleSubmit}>
9
+ <FormField label="Username" name="username" required>
10
+ <TextInput />
11
+ </FormField>
12
+
13
+ <FormField label="Email" name="email" required type="email">
14
+ <TextInput type="email" />
15
+ </FormField>
16
+
17
+ <Button type="submit">Submit</Button>
18
+ </Form>
19
+ ```
20
+ -->
21
+ <script>
22
+ import { setContext } from "svelte"
23
+
24
+ const {
25
+ /** @type {string} - Additional CSS classes */
26
+ class: className = "",
27
+
28
+ /** @type {string} - HTML id for accessibility */
29
+ id = crypto.randomUUID(),
30
+
31
+ /** @type {string} - Form method (get or post) */
32
+ method = "post",
33
+
34
+ /** @type {string} - Form action URL */
35
+ action = "",
36
+
37
+ /** @type {boolean} - Whether to validate the form on submission */
38
+ validate = true,
39
+
40
+ /** @type {boolean} - Whether to use the browser's built-in validation UI */
41
+ useNativeValidation = true,
42
+
43
+ /** @type {string} - Layout direction (vertical or horizontal) */
44
+ layout = "vertical",
45
+
46
+ /** @type {boolean} - Whether to disable all form controls */
47
+ disabled = false,
48
+
49
+ /** @type {boolean} - Whether the form is in a loading state */
50
+ loading = false,
51
+
52
+ /** @type {(event: CustomEvent) => void} - Submit event handler */
53
+ onsubmit,
54
+ /** @type {(event: CustomEvent) => void} - Change event handler */
55
+ onchange,
56
+ /** @type {(event: CustomEvent) => void} - Error event handler */
57
+ onerror,
58
+
59
+ children,
60
+ } = $props()
61
+
62
+ // Form state
63
+ let formElement
64
+ let formData = $state({})
65
+ let errors = $state({})
66
+ let touched = $state({})
67
+ let isSubmitting = $state(false)
68
+ let isValid = $state(true)
69
+
70
+ /**
71
+ * Updates a field's value in the form data
72
+ * @param {string} name - Field name
73
+ * @param {any} value - Field value
74
+ */
75
+ function updateField(name, value) {
76
+ formData[name] = value
77
+ touched[name] = true
78
+
79
+ // Validate the field if needed
80
+ if (validate) {
81
+ validateField(name, value)
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Validates a single field
87
+ * @param {string} name - Field name
88
+ * @param {any} value - Field value
89
+ * @returns {boolean} - Whether the field is valid
90
+ */
91
+ function validateField(name, value) {
92
+ const field = formElement?.elements[name]
93
+
94
+ if (!field) return true
95
+
96
+ // Clear existing errors for this field
97
+ delete errors[name]
98
+
99
+ // Use HTML5 validation API
100
+ if (field.validity) {
101
+ if (!field.validity.valid) {
102
+ errors[name] = field.validationMessage
103
+ return false
104
+ }
105
+ }
106
+
107
+ return true
108
+ }
109
+
110
+ /**
111
+ * Validates the entire form
112
+ * @returns {boolean} - Whether the form is valid
113
+ */
114
+ function validateForm() {
115
+ // Reset errors
116
+ errors = {}
117
+
118
+ // Check all fields
119
+ let valid = true
120
+
121
+ if (formElement) {
122
+ const formControls = Array.from(formElement.elements)
123
+
124
+ formControls.forEach((field) => {
125
+ if (field.name) {
126
+ const fieldValid = validateField(field.name, field.value)
127
+ if (!fieldValid) {
128
+ valid = false
129
+ }
130
+ }
131
+ })
132
+ }
133
+
134
+ isValid = valid
135
+ return valid
136
+ }
137
+
138
+ /**
139
+ * Handles form submission
140
+ * @param {Event} event - Submit event
141
+ */
142
+ function handleSubmit(event) {
143
+ // Prevent default form submission
144
+ event.preventDefault()
145
+
146
+ // Mark all fields as touched
147
+ if (formElement) {
148
+ const formControls = Array.from(formElement.elements)
149
+ formControls.forEach((field) => {
150
+ if (field.name) {
151
+ touched[field.name] = true
152
+ }
153
+ })
154
+ }
155
+
156
+ // Validate if needed
157
+ if (validate) {
158
+ if (!validateForm()) {
159
+ // If validation fails, don't submit
160
+ onerror?.(new CustomEvent("invalid", { detail: { errors } }))
161
+ return
162
+ }
163
+ }
164
+
165
+ // Set submitting state
166
+ isSubmitting = true
167
+
168
+ // Get form data
169
+ const formDataObj = new FormData(formElement)
170
+ const dataObj = {}
171
+
172
+ for (const [key, value] of formDataObj.entries()) {
173
+ dataObj[key] = value
174
+ }
175
+
176
+ // Dispatch submit event with form data
177
+ onsubmit?.(new CustomEvent("submit", { detail: {
178
+ data: dataObj,
179
+ formData: formDataObj,
180
+ form: formElement,
181
+ } }))
182
+
183
+ // Reset submitting state after a short delay
184
+ setTimeout(() => {
185
+ isSubmitting = false
186
+ }, 100)
187
+ }
188
+
189
+ /**
190
+ * Resets the form to its initial state
191
+ */
192
+ function resetForm() {
193
+ if (formElement) {
194
+ formElement.reset()
195
+ formData = {}
196
+ errors = {}
197
+ touched = {}
198
+ isValid = true
199
+ }
200
+ }
201
+
202
+ // Provide form context to child components
203
+ $effect(() => {
204
+ setContext("form", {
205
+ registerField: (name, initialValue) => {
206
+ if (initialValue !== undefined && formData[name] === undefined) {
207
+ formData[name] = initialValue
208
+ }
209
+
210
+ return {
211
+ getValue: () => formData[name],
212
+ setValue: (value) => updateField(name, value),
213
+ getError: () => errors[name],
214
+ isTouched: () => !!touched[name],
215
+ isDisabled: () => disabled || loading || isSubmitting,
216
+ }
217
+ },
218
+ layout,
219
+ disabled: () => disabled || loading || isSubmitting,
220
+ })
221
+ })
222
+
223
+ // Expose form API to parent components
224
+ const formApi = {
225
+ reset: resetForm,
226
+ validate: validateForm,
227
+ setValues: (values) => {
228
+ formData = { ...formData, ...values }
229
+ },
230
+ getValues: () => ({ ...formData }),
231
+ setErrors: (newErrors) => {
232
+ errors = { ...errors, ...newErrors }
233
+ isValid = Object.keys(errors).length === 0
234
+ },
235
+ clearErrors: () => {
236
+ errors = {}
237
+ isValid = true
238
+ },
239
+ }
240
+
241
+ // Expose form API to parent
242
+ dispatch("ready", { form: formApi })
243
+ </script>
244
+
245
+ <form
246
+ {id}
247
+ class="form {layout === 'horizontal' ? 'form-horizontal' : 'form-vertical'} {className}"
248
+ class:disabled
249
+ class:loading={loading || isSubmitting}
250
+ {method}
251
+ {action}
252
+ novalidate={!useNativeValidation}
253
+ onsubmit={handleSubmit}
254
+ bind:this={formElement}
255
+ >
256
+ {@render children?.()}
257
+ </form>
258
+
259
+ <style>
260
+ @reference "../../twintrinsic.css";
261
+
262
+ .form {
263
+ @apply w-full;
264
+ }
265
+
266
+ .form-vertical {
267
+ @apply space-y-4;
268
+ }
269
+
270
+ .form-horizontal {
271
+ @apply grid gap-4;
272
+ }
273
+
274
+ .form.disabled {
275
+ @apply opacity-70 pointer-events-none;
276
+ }
277
+
278
+ .form.loading {
279
+ @apply opacity-70;
280
+ }
281
+ </style>
@@ -0,0 +1,54 @@
1
+ export default Form;
2
+ type Form = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Form - A component for creating accessible, styled forms with validation support.
8
+ * Handles form submission, validation, and provides context for form controls.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Form onsubmit={handleSubmit}>
13
+ * <FormField label="Username" name="username" required>
14
+ * <TextInput />
15
+ * </FormField>
16
+ *
17
+ * <FormField label="Email" name="email" required type="email">
18
+ * <TextInput type="email" />
19
+ * </FormField>
20
+ *
21
+ * <Button type="submit">Submit</Button>
22
+ * </Form>
23
+ * ```
24
+ */
25
+ declare const Form: import("svelte").Component<{
26
+ class?: string;
27
+ id?: any;
28
+ method?: string;
29
+ action?: string;
30
+ validate?: boolean;
31
+ useNativeValidation?: boolean;
32
+ layout?: string;
33
+ disabled?: boolean;
34
+ loading?: boolean;
35
+ onsubmit: any;
36
+ onchange: any;
37
+ onerror: any;
38
+ children: any;
39
+ }, {}, "">;
40
+ type $$ComponentProps = {
41
+ class?: string;
42
+ id?: any;
43
+ method?: string;
44
+ action?: string;
45
+ validate?: boolean;
46
+ useNativeValidation?: boolean;
47
+ layout?: string;
48
+ disabled?: boolean;
49
+ loading?: boolean;
50
+ onsubmit: any;
51
+ onchange: any;
52
+ onerror: any;
53
+ children: any;
54
+ };