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,218 @@
1
+ <!--
2
+ @component
3
+ FormField - A component for creating form field containers with labels, validation, and help text.
4
+ Provides consistent styling and accessibility features for form inputs.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <FormField
9
+ label="Username"
10
+ name="username"
11
+ required
12
+ helpText="Enter your username"
13
+ >
14
+ <TextInput />
15
+ </FormField>
16
+ ```
17
+ -->
18
+ <script>
19
+ import { getContext } from "svelte"
20
+
21
+ const {
22
+ /** @type {string} - Additional CSS classes */
23
+ class: className = "",
24
+
25
+ /** @type {string} - HTML id for accessibility */
26
+ id = crypto.randomUUID(),
27
+
28
+ /** @type {string} - Field name (used for form data) */
29
+ name,
30
+
31
+ /** @type {string} - Field label */
32
+ label,
33
+
34
+ /** @type {string} - Help text displayed below the field */
35
+ helpText,
36
+
37
+ /** @type {string} - Error message to display */
38
+ error,
39
+
40
+ /** @type {boolean} - Whether the field is required */
41
+ required = false,
42
+
43
+ /** @type {boolean} - Whether the field is disabled */
44
+ disabled = false,
45
+
46
+ /** @type {boolean} - Whether to hide the label visually (still accessible to screen readers) */
47
+ hideLabel = false,
48
+
49
+ /** @type {string} - Layout direction (vertical or horizontal) */
50
+ layout,
51
+
52
+ children,
53
+ } = $props()
54
+
55
+ // Get form context if available
56
+ const formContext = getContext("form")
57
+
58
+ // Use layout from form context if not specified
59
+ const fieldLayout = $derived(layout || (formContext ? formContext.layout : "vertical"))
60
+
61
+ // Generate unique ID for the field
62
+ const fieldId = $derived(`${id}-field`)
63
+ const errorId = $derived(`${id}-error`)
64
+ const helpId = $derived(`${id}-help`)
65
+
66
+ // Track field state
67
+ let fieldError = $state("")
68
+ let touched = $state(false)
69
+ let fieldDisabled = $state(false)
70
+ let fieldApi = $state()
71
+
72
+ // Register with form if available
73
+ $effect(() => {
74
+ if (formContext && name) {
75
+ fieldApi = formContext.registerField(name)
76
+ }
77
+ })
78
+
79
+ // Update field error when form validation runs
80
+ $effect(() => {
81
+ if (fieldApi) {
82
+ const formError = fieldApi.getError()
83
+ if (formError) {
84
+ fieldError = formError
85
+ }
86
+ } else {
87
+ fieldError = error || ""
88
+ }
89
+ })
90
+
91
+ // Update touched state
92
+ $effect(() => {
93
+ if (fieldApi) {
94
+ touched = fieldApi.isTouched()
95
+ }
96
+ })
97
+
98
+ // Update disabled state
99
+ $effect(() => {
100
+ if (fieldApi) {
101
+ const formDisabled = formContext.disabled()
102
+ fieldDisabled = disabled || formDisabled
103
+ } else {
104
+ fieldDisabled = disabled
105
+ }
106
+ })
107
+
108
+ // Determine if we should show an error
109
+ const showError = $derived(!!fieldError && touched)
110
+
111
+ // Determine the aria-describedby attribute value
112
+ const describedBy = $derived(
113
+ [helpText ? helpId : null, showError ? errorId : null].filter(Boolean).join(" ")
114
+ )
115
+ </script>
116
+
117
+ <div
118
+ class="
119
+ form-field
120
+ {fieldLayout === 'horizontal' ? 'form-field-horizontal' : 'form-field-vertical'}
121
+ {showError ? 'has-error' : ''}
122
+ {className}
123
+ "
124
+ >
125
+ {#if label}
126
+ <label
127
+ for={fieldId}
128
+ class="form-label {hideLabel ? 'sr-only' : ''}"
129
+ >
130
+ {label}
131
+ {#if required}
132
+ <span class="required-indicator" aria-hidden="true">*</span>
133
+ <span class="sr-only">required</span>
134
+ {/if}
135
+ </label>
136
+ {/if}
137
+
138
+ <div class="form-control-container">
139
+ <div class="form-control">
140
+ <!-- Slot for the actual form control -->
141
+ {@render children({
142
+ name: fieldName,
143
+ id: fieldId,
144
+ disabled: fieldDisabled,
145
+ 'aria-invalid': showError ? 'true' : undefined,
146
+ 'aria-describedby': describedBy || undefined,
147
+ 'aria-required': required ? 'true' : undefined,
148
+ required
149
+ })}
150
+ </div>
151
+
152
+ {#if helpText && !showError}
153
+ <div class="form-help-text" id={helpId}>
154
+ {helpText}
155
+ </div>
156
+ {/if}
157
+
158
+ {#if showError}
159
+ <div class="form-error" id={errorId} role="alert">
160
+ {fieldError}
161
+ </div>
162
+ {/if}
163
+ </div>
164
+ </div>
165
+
166
+ <style>
167
+ @reference "../../twintrinsic.css";
168
+
169
+ .form-field {
170
+ @apply w-full;
171
+ }
172
+
173
+ .form-field-vertical {
174
+ @apply flex flex-col gap-1.5;
175
+ }
176
+
177
+ .form-field-horizontal {
178
+ @apply grid grid-cols-12 gap-4 items-start;
179
+ }
180
+
181
+ .form-field-horizontal .form-label {
182
+ @apply col-span-3 pt-2 text-right;
183
+ }
184
+
185
+ .form-field-horizontal .form-control-container {
186
+ @apply col-span-9;
187
+ }
188
+
189
+ .form-label {
190
+ @apply block text-sm font-medium text-text dark:text-text;
191
+ }
192
+
193
+ .required-indicator {
194
+ @apply ml-1 text-error-500 dark:text-error-400;
195
+ }
196
+
197
+ .form-control-container {
198
+ @apply w-full;
199
+ }
200
+
201
+ .form-control {
202
+ @apply w-full;
203
+ }
204
+
205
+ .form-help-text {
206
+ @apply mt-1 text-xs text-muted dark:text-muted;
207
+ }
208
+
209
+ .form-error {
210
+ @apply mt-1 text-xs text-error-600 dark:text-error-400;
211
+ }
212
+
213
+ .has-error :global(input),
214
+ .has-error :global(select),
215
+ .has-error :global(textarea) {
216
+ @apply border-error-500 dark:border-error-400 focus:ring-error-500 dark:focus:ring-error-400 focus:border-error-500 dark:focus:border-error-400;
217
+ }
218
+ </style>
@@ -0,0 +1,47 @@
1
+ export default FormField;
2
+ type FormField = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * FormField - A component for creating form field containers with labels, validation, and help text.
8
+ * Provides consistent styling and accessibility features for form inputs.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <FormField
13
+ * label="Username"
14
+ * name="username"
15
+ * required
16
+ * helpText="Enter your username"
17
+ * >
18
+ * <TextInput />
19
+ * </FormField>
20
+ * ```
21
+ */
22
+ declare const FormField: import("svelte").Component<{
23
+ class?: string;
24
+ id?: any;
25
+ name: any;
26
+ label: any;
27
+ helpText: any;
28
+ error: any;
29
+ required?: boolean;
30
+ disabled?: boolean;
31
+ hideLabel?: boolean;
32
+ layout: any;
33
+ children: any;
34
+ }, {}, "">;
35
+ type $$ComponentProps = {
36
+ class?: string;
37
+ id?: any;
38
+ name: any;
39
+ label: any;
40
+ helpText: any;
41
+ error: any;
42
+ required?: boolean;
43
+ disabled?: boolean;
44
+ hideLabel?: boolean;
45
+ layout: any;
46
+ children: any;
47
+ };
@@ -0,0 +1,340 @@
1
+ <!--
2
+ @component
3
+ Input - Base component for form inputs with validation, floating labels, and input groups.
4
+ Built with accessibility and customization in mind.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Input label="Username" />
9
+
10
+ <Input
11
+ label="Email"
12
+ type="email"
13
+ value="user@example.com"
14
+ floating={true}
15
+ required
16
+ error="Please enter a valid email"
17
+ />
18
+
19
+ <Input
20
+ label="Password"
21
+ type="password"
22
+ leftIcon="lock"
23
+ rightIcon="eye"
24
+ onrightIconClick={togglePassword}
25
+ />
26
+ ```
27
+ -->
28
+ <script>
29
+ import { slide } from "svelte/transition"
30
+ import Icon from "../Icon/Icon.svelte"
31
+
32
+ const {
33
+ /** @type {string} - Input label text */
34
+ label,
35
+ /** @type {string} - Input type (text, email, password, etc.) */
36
+ type = "text",
37
+ /** @type {string} - Input value */
38
+ value = "",
39
+ /** @type {string} - Placeholder text */
40
+ placeholder = "",
41
+ /** @type {string} - Name attribute */
42
+ name = "",
43
+ /** @type {string} - Id attribute */
44
+ id = crypto.randomUUID(),
45
+ /** @type {boolean} - Whether the input is disabled */
46
+ disabled = false,
47
+ /** @type {boolean} - Whether the input is required */
48
+ required = false,
49
+ /** @type {boolean} - Whether to use floating labels */
50
+ floating = false,
51
+ /** @type {boolean} - Whether the input is readonly */
52
+ readonly = false,
53
+ /** @type {string} - Error message to display */
54
+ error = "",
55
+ /** @type {string} - Help text to display below input */
56
+ helpText = "",
57
+ /** @type {string} - Left icon name */
58
+ leftIcon = "",
59
+ /** @type {string} - Right icon name */
60
+ rightIcon = "",
61
+ /** @type {string} - Additional CSS classes */
62
+ class: className = "",
63
+ /** @type {string} - Input mask pattern */
64
+ mask = "",
65
+ /** @type {string} - ARIA description */
66
+ ariaDescription = "",
67
+ /** @type {(event: Event) => void} - Focus event handler */
68
+ onfocus,
69
+ /** @type {(event: Event) => void} - Blur event handler */
70
+ onblur,
71
+ /** @type {(event: CustomEvent) => void} - Input event handler */
72
+ oninput,
73
+ /** @type {() => void} - Left icon click handler */
74
+ onleftIconClick,
75
+ /** @type {() => void} - Right icon click handler */
76
+ onrightIconClick,
77
+ } = $props()
78
+
79
+ let inputValue = $state(value)
80
+ let focused = $state(false)
81
+ let touched = $state(false)
82
+
83
+ // Sync input value when prop changes
84
+ $effect(() => {
85
+ inputValue = value
86
+ })
87
+
88
+ // Handle input focus
89
+ function handleFocus(event) {
90
+ focused = true
91
+ onfocus?.(event)
92
+ }
93
+
94
+ // Handle input blur
95
+ function handleBlur(event) {
96
+ focused = false
97
+ touched = true
98
+ onblur?.(event)
99
+ }
100
+
101
+ // Handle input change
102
+ function handleInput(event) {
103
+ const newValue = event.target.value
104
+
105
+ // Apply mask if provided
106
+ if (mask) {
107
+ inputValue = applyMask(newValue, mask)
108
+ } else {
109
+ inputValue = newValue
110
+ }
111
+
112
+ oninput?.(new CustomEvent("input", { detail: { value: inputValue } }))
113
+ }
114
+
115
+ // Handle icon clicks
116
+ function handleLeftIconClick() {
117
+ onleftIconClick?.()
118
+ }
119
+
120
+ function handleRightIconClick() {
121
+ onrightIconClick?.()
122
+ }
123
+
124
+ // Apply input mask
125
+ function applyMask(value, pattern) {
126
+ let result = ""
127
+ let valueIndex = 0
128
+
129
+ for (let i = 0; i < pattern.length && valueIndex < value.length; i++) {
130
+ const maskChar = pattern[i]
131
+ const valueChar = value[valueIndex]
132
+
133
+ if (maskChar === "#") {
134
+ if (/\d/.test(valueChar)) {
135
+ result += valueChar
136
+ valueIndex++
137
+ }
138
+ } else if (maskChar === "A") {
139
+ if (/[a-zA-Z]/.test(valueChar)) {
140
+ result += valueChar
141
+ valueIndex++
142
+ }
143
+ } else if (maskChar === "*") {
144
+ result += valueChar
145
+ valueIndex++
146
+ } else {
147
+ result += maskChar
148
+ if (valueChar === maskChar) {
149
+ valueIndex++
150
+ }
151
+ }
152
+ }
153
+
154
+ return result
155
+ }
156
+
157
+ // Compute classes
158
+ const containerClasses = $derived(`
159
+ form-input-container
160
+ ${floating ? "form-input-floating" : ""}
161
+ ${error ? "form-input-error" : ""}
162
+ ${disabled ? "form-input-disabled" : ""}
163
+ ${className}
164
+ `)
165
+
166
+ const labelClasses = $derived(`
167
+ form-input-label
168
+ ${floating && (focused || inputValue) ? "form-input-label-float" : ""}
169
+ ${error ? "form-input-label-error" : ""}
170
+ ${disabled ? "form-input-label-disabled" : ""}
171
+ `)
172
+
173
+ const inputClasses = $derived(`
174
+ form-input
175
+ ${leftIcon ? "form-input-left-icon" : ""}
176
+ ${rightIcon ? "form-input-right-icon" : ""}
177
+ ${error ? "form-input-field-error" : ""}
178
+ `)
179
+ </script>
180
+
181
+ <div class={containerClasses}>
182
+ {#if label}
183
+ <label for={id} class={labelClasses}>
184
+ {label}
185
+ {#if required}
186
+ <span class="form-input-required">*</span>
187
+ {/if}
188
+ </label>
189
+ {/if}
190
+
191
+ <div class="form-input-wrapper">
192
+ {#if leftIcon}
193
+ <button
194
+ type="button"
195
+ class="form-input-icon form-input-icon-left"
196
+ onclick={handleLeftIconClick}
197
+ tabindex="-1"
198
+ aria-hidden="true"
199
+ >
200
+ <Icon name={leftIcon} />
201
+ </button>
202
+ {/if}
203
+
204
+ <input
205
+ {type}
206
+ {id}
207
+ {name}
208
+ class={inputClasses}
209
+ value={inputValue}
210
+ placeholder={floating ? ' ' : placeholder}
211
+ {disabled}
212
+ {readonly}
213
+ {required}
214
+ aria-invalid={!!error}
215
+ aria-describedby={error || helpText ? `${id}-description` : undefined}
216
+ onfocus={handleFocus}
217
+ onblur={handleBlur}
218
+ oninput={handleInput}
219
+ />
220
+
221
+ {#if rightIcon}
222
+ <button
223
+ type="button"
224
+ class="form-input-icon form-input-icon-right"
225
+ onclick={handleRightIconClick}
226
+ tabindex="-1"
227
+ aria-hidden="true"
228
+ >
229
+ <Icon name={rightIcon} />
230
+ </button>
231
+ {/if}
232
+ </div>
233
+
234
+ {#if (error || helpText) && touched}
235
+ <div
236
+ id="{id}-description"
237
+ class="form-input-description"
238
+ class:form-input-error-text={!!error}
239
+ transition:slide={{ duration: 150 }}
240
+ >
241
+ {error || helpText}
242
+ </div>
243
+ {/if}
244
+ </div>
245
+
246
+ <style>
247
+ @reference "../../twintrinsic.css";
248
+
249
+ /* Container */
250
+ .form-input-container {
251
+ @apply relative space-y-1.5;
252
+ }
253
+
254
+ /* Label */
255
+ .form-input-label {
256
+ @apply block text-sm font-medium text-muted transition-all;
257
+ }
258
+
259
+ .form-input-label-error {
260
+ @apply text-error-bold;
261
+ }
262
+
263
+ .form-input-label-disabled {
264
+ @apply opacity-50 cursor-not-allowed;
265
+ }
266
+
267
+ .form-input-required {
268
+ @apply text-error-bold ml-1;
269
+ }
270
+
271
+ /* Input wrapper */
272
+ .form-input-wrapper {
273
+ @apply relative;
274
+ }
275
+
276
+ /* Base input */
277
+ .form-input {
278
+ @apply block w-full px-3 py-2 bg-surface;
279
+ @apply border border-border rounded-md shadow-sm;
280
+ @apply text-base placeholder-muted;
281
+ @apply transition-colors duration-150;
282
+ @apply focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500;
283
+ }
284
+
285
+ .form-input-disabled {
286
+ @apply opacity-50 cursor-not-allowed;
287
+ }
288
+
289
+ .form-input-field-error {
290
+ @apply border-error-bold;
291
+ @apply focus:ring-error-bold focus:border-error-bold;
292
+ }
293
+
294
+ /* Icons */
295
+ .form-input-left-icon {
296
+ @apply pl-10;
297
+ }
298
+
299
+ .form-input-right-icon {
300
+ @apply pr-10;
301
+ }
302
+
303
+ .form-input-icon {
304
+ @apply absolute inset-y-0 flex items-center;
305
+ @apply p-2 text-muted transition-colors;
306
+ @apply hover:text-primary-text focus:outline-none;
307
+ }
308
+
309
+ .form-input-icon-left {
310
+ @apply left-0;
311
+ }
312
+
313
+ .form-input-icon-right {
314
+ @apply right-0;
315
+ }
316
+
317
+ /* Floating label */
318
+ .form-input-floating .form-input-label {
319
+ @apply absolute text-sm text-muted;
320
+ transform-origin: 0 0;
321
+ transition: transform 0.15s ease-in-out;
322
+ }
323
+
324
+ .form-input-floating .form-input {
325
+ @apply pt-4 pb-1;
326
+ }
327
+
328
+ .form-input-label-float {
329
+ @apply transform -translate-y-3 scale-75 text-primary-500;
330
+ }
331
+
332
+ /* Description/Error text */
333
+ .form-input-description {
334
+ @apply mt-1 text-sm;
335
+ }
336
+
337
+ .form-input-error-text {
338
+ @apply text-error-bold;
339
+ }
340
+ </style>
@@ -0,0 +1,79 @@
1
+ export default Input;
2
+ type Input = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Input - Base component for form inputs with validation, floating labels, and input groups.
8
+ * Built with accessibility and customization in mind.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Input label="Username" />
13
+ *
14
+ * <Input
15
+ * label="Email"
16
+ * type="email"
17
+ * value="user@example.com"
18
+ * floating={true}
19
+ * required
20
+ * error="Please enter a valid email"
21
+ * />
22
+ *
23
+ * <Input
24
+ * label="Password"
25
+ * type="password"
26
+ * leftIcon="lock"
27
+ * rightIcon="eye"
28
+ * onrightIconClick={togglePassword}
29
+ * />
30
+ * ```
31
+ */
32
+ declare const Input: import("svelte").Component<{
33
+ label: any;
34
+ type?: string;
35
+ value?: string;
36
+ placeholder?: string;
37
+ name?: string;
38
+ id?: any;
39
+ disabled?: boolean;
40
+ required?: boolean;
41
+ floating?: boolean;
42
+ readonly?: boolean;
43
+ error?: string;
44
+ helpText?: string;
45
+ leftIcon?: string;
46
+ rightIcon?: string;
47
+ class?: string;
48
+ mask?: string;
49
+ ariaDescription?: string;
50
+ onfocus: any;
51
+ onblur: any;
52
+ oninput: any;
53
+ onleftIconClick: any;
54
+ onrightIconClick: any;
55
+ }, {}, "">;
56
+ type $$ComponentProps = {
57
+ label: any;
58
+ type?: string;
59
+ value?: string;
60
+ placeholder?: string;
61
+ name?: string;
62
+ id?: any;
63
+ disabled?: boolean;
64
+ required?: boolean;
65
+ floating?: boolean;
66
+ readonly?: boolean;
67
+ error?: string;
68
+ helpText?: string;
69
+ leftIcon?: string;
70
+ rightIcon?: string;
71
+ class?: string;
72
+ mask?: string;
73
+ ariaDescription?: string;
74
+ onfocus: any;
75
+ onblur: any;
76
+ oninput: any;
77
+ onleftIconClick: any;
78
+ onrightIconClick: any;
79
+ };