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,207 @@
1
+ <!--
2
+ @component
3
+ Textarea - A styled textarea component for multi-line text input.
4
+ Provides consistent styling, accessibility features, and integration with the Form component.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Textarea
9
+ name="description"
10
+ placeholder="Enter description"
11
+ rows={4}
12
+ />
13
+
14
+ <FormField label="Message">
15
+ <Textarea name="message" required />
16
+ </FormField>
17
+ ```
18
+ -->
19
+ <script>
20
+ import { getContext } from "svelte"
21
+
22
+ const {
23
+ /** @type {string} - Additional CSS classes */
24
+ class: className = "",
25
+
26
+ /** @type {string} - HTML id for accessibility */
27
+ id,
28
+
29
+ /** @type {string} - Textarea name */
30
+ name,
31
+
32
+ /** @type {string} - Textarea placeholder */
33
+ placeholder = "",
34
+
35
+ /** @type {string} - Textarea value */
36
+ value = "",
37
+
38
+ /** @type {number} - Number of rows */
39
+ rows = 3,
40
+
41
+ /** @type {boolean} - Whether the textarea is required */
42
+ required = false,
43
+
44
+ /** @type {boolean} - Whether the textarea is disabled */
45
+ disabled = false,
46
+
47
+ /** @type {boolean} - Whether the textarea is readonly */
48
+ readonly = false,
49
+
50
+ /** @type {string} - Minimum length */
51
+ minlength,
52
+
53
+ /** @type {string} - Maximum length */
54
+ maxlength,
55
+
56
+ /** @type {string} - Autocomplete attribute */
57
+ autocomplete,
58
+
59
+ /** @type {boolean} - Whether to auto-resize based on content */
60
+ autoResize = false,
61
+
62
+ /** @type {string} - ARIA label for accessibility */
63
+ ariaLabel,
64
+ /** @type {(event: CustomEvent) => void} - Input event handler */
65
+ oninput,
66
+ /** @type {(event: CustomEvent) => void} - Change event handler */
67
+ onchange,
68
+ /** @type {(event: Event) => void} - Focus event handler */
69
+ onfocus,
70
+ /** @type {(event: Event) => void} - Blur event handler */
71
+ onblur,
72
+ /** @type {object} - Additional props to pass to the input element */
73
+ ...restProps
74
+ } = $props()
75
+
76
+ // Get form context if available
77
+ const formContext = getContext("form")
78
+
79
+ // Generate unique ID if not provided
80
+ const textareaId = id || `textarea-${crypto.randomUUID()}`
81
+
82
+ // Textarea state
83
+ let textareaValue = $state(value)
84
+ let isFocused = $state(false)
85
+ let textareaEl = $state()
86
+ let fieldApi = $state()
87
+
88
+ // Register with form if available
89
+ $effect(() => {
90
+ if (formContext && name) {
91
+ fieldApi = formContext.registerField(name, value)
92
+ }
93
+ })
94
+
95
+ // Update value when form field changes
96
+ $effect(() => {
97
+ if (fieldApi) {
98
+ const formValue = fieldApi.getValue()
99
+ if (formValue !== undefined && formValue !== textareaValue) {
100
+ textareaValue = formValue
101
+ }
102
+ }
103
+ })
104
+
105
+ // Update textarea value when prop changes
106
+ $effect(() => {
107
+ textareaValue = value
108
+ })
109
+
110
+ /**
111
+ * Handles textarea input
112
+ * @param {Event} event - Input event
113
+ */
114
+ function handleInput(event) {
115
+ const newValue = event.target.value
116
+ textareaValue = newValue
117
+
118
+ // Update form field if available
119
+ if (fieldApi) {
120
+ fieldApi.setValue(newValue)
121
+ }
122
+
123
+ // Auto-resize if enabled
124
+ if (autoResize && textareaEl) {
125
+ resizeTextarea()
126
+ }
127
+
128
+ oninput?.(new CustomEvent("input", { detail: { value: newValue } }))
129
+ onchange?.(new CustomEvent("change", { detail: { value: newValue } }))
130
+ }
131
+
132
+ /**
133
+ * Handles focus events
134
+ */
135
+ function handleFocus(event) {
136
+ isFocused = true
137
+ onfocus?.(event)
138
+ }
139
+
140
+ /**
141
+ * Handles blur events
142
+ */
143
+ function handleBlur(event) {
144
+ isFocused = false
145
+ onblur?.(event)
146
+ }
147
+
148
+ /**
149
+ * Resizes the textarea based on content
150
+ */
151
+ function resizeTextarea() {
152
+ if (!textareaEl) return
153
+
154
+ // Reset height to calculate scroll height
155
+ textareaEl.style.height = "auto"
156
+
157
+ // Set height to scroll height
158
+ textareaEl.style.height = `${textareaEl.scrollHeight}px`
159
+ }
160
+
161
+ // Initialize auto-resize
162
+ $effect(() => {
163
+ if (autoResize && textareaEl) {
164
+ // Use setTimeout to ensure content is rendered
165
+ setTimeout(resizeTextarea, 0)
166
+ }
167
+ })
168
+ </script>
169
+
170
+ <div class="textarea-wrapper {className}">
171
+ <textarea
172
+ id={textareaId}
173
+ {name}
174
+ {placeholder}
175
+ value={textareaValue}
176
+ {rows}
177
+ {required}
178
+ disabled={disabled || (fieldApi && fieldApi.isDisabled())}
179
+ {readonly}
180
+ {minlength}
181
+ {maxlength}
182
+ {autocomplete}
183
+ aria-label={ariaLabel}
184
+ class="textarea {isFocused ? 'is-focused' : ''}"
185
+ oninput={handleInput}
186
+ onfocus={handleFocus}
187
+ onblur={handleBlur}
188
+ bind:this={textareaEl}
189
+ {...restProps}
190
+ ></textarea>
191
+ </div>
192
+
193
+ <style>
194
+ @reference "../../twintrinsic.css";
195
+
196
+ .textarea-wrapper {
197
+ @apply w-full;
198
+ }
199
+
200
+ .textarea {
201
+ @apply w-full rounded-md border-border dark:border-border bg-background dark:bg-background text-text dark:text-text;
202
+ @apply border focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400 focus:border-primary-500 dark:focus:border-primary-400;
203
+ @apply disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-surface dark:disabled:bg-surface;
204
+ @apply placeholder:text-muted dark:placeholder:text-muted;
205
+ @apply p-3 resize-y;
206
+ }
207
+ </style>
@@ -0,0 +1,62 @@
1
+ export default Textarea;
2
+ type Textarea = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Textarea - A styled textarea component for multi-line text input.
8
+ * Provides consistent styling, accessibility features, and integration with the Form component.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Textarea
13
+ * name="description"
14
+ * placeholder="Enter description"
15
+ * rows={4}
16
+ * />
17
+ *
18
+ * <FormField label="Message">
19
+ * <Textarea name="message" required />
20
+ * </FormField>
21
+ * ```
22
+ */
23
+ declare const Textarea: import("svelte").Component<{
24
+ class?: string;
25
+ id: any;
26
+ name: any;
27
+ placeholder?: string;
28
+ value?: string;
29
+ rows?: number;
30
+ required?: boolean;
31
+ disabled?: boolean;
32
+ readonly?: boolean;
33
+ minlength: any;
34
+ maxlength: any;
35
+ autocomplete: any;
36
+ autoResize?: boolean;
37
+ ariaLabel: any;
38
+ oninput: any;
39
+ onchange: any;
40
+ onfocus: any;
41
+ onblur: any;
42
+ } & Record<string, any>, {}, "">;
43
+ type $$ComponentProps = {
44
+ class?: string;
45
+ id: any;
46
+ name: any;
47
+ placeholder?: string;
48
+ value?: string;
49
+ rows?: number;
50
+ required?: boolean;
51
+ disabled?: boolean;
52
+ readonly?: boolean;
53
+ minlength: any;
54
+ maxlength: any;
55
+ autocomplete: any;
56
+ autoResize?: boolean;
57
+ ariaLabel: any;
58
+ oninput: any;
59
+ onchange: any;
60
+ onfocus: any;
61
+ onblur: any;
62
+ } & Record<string, any>;
@@ -0,0 +1,140 @@
1
+ <!--
2
+ @component
3
+ Icon - A component for displaying SVG icons with consistent styling.
4
+
5
+ Usage:
6
+ ```svelte
7
+ <Icon name="check" />
8
+ <Icon name="arrow-right" size="lg" />
9
+ <Icon name="close" class="text-error" />
10
+ ```
11
+ -->
12
+ <script>
13
+ const {
14
+ /** @type {string} - Name of the icon to display */
15
+ name = "",
16
+ /** @type {'sm' | 'md' | 'lg' | 'xl'} - Size of the icon */
17
+ size = "md",
18
+ /** @type {string} - Additional CSS classes */
19
+ class: className = "",
20
+ } = $props()
21
+
22
+ // Icon size mappings
23
+ const sizes = {
24
+ sm: 16,
25
+ md: 20,
26
+ lg: 24,
27
+ xl: 32,
28
+ }
29
+
30
+ // Icon paths mapping
31
+ const icons = {
32
+ // Interface
33
+ check: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z",
34
+ close:
35
+ "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",
36
+ plus: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z",
37
+ minus: "M19 13H5v-2h14v2z",
38
+ search:
39
+ "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
40
+ settings:
41
+ "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z",
42
+ menu: "M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z",
43
+ more: "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z",
44
+
45
+ // Navigation
46
+ "arrow-left": "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z",
47
+ "arrow-right": "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z",
48
+ "arrow-up": "M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8z",
49
+ "arrow-down": "M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8z",
50
+ "chevron-left": "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z",
51
+ "chevron-right": "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z",
52
+ "chevron-up": "M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z",
53
+ "chevron-down": "M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z",
54
+
55
+ // Actions
56
+ edit: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z",
57
+ delete: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z",
58
+ save: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z",
59
+ refresh:
60
+ "M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z",
61
+ download: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z",
62
+ upload: "M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z",
63
+ copy: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z",
64
+
65
+ // Forms
66
+ calendar:
67
+ "M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z",
68
+ eye: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z",
69
+ "eye-off":
70
+ "M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z",
71
+ lock: "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z",
72
+ unlock:
73
+ "M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z",
74
+
75
+ // Media
76
+ play: "M8 5v14l11-7z",
77
+ pause: "M6 19h4V5H6v14zm8-14v14h4V5h-4z",
78
+ stop: "M6 6h12v12H6z",
79
+ "volume-up":
80
+ "M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z",
81
+ "volume-down":
82
+ "M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z",
83
+ "volume-mute": "M7 9v6h4l5 5V4l-5 5H7z",
84
+ "volume-off":
85
+ "M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z",
86
+
87
+ // Status
88
+ info: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",
89
+ warning: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z",
90
+ error:
91
+ "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z",
92
+ success:
93
+ "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",
94
+ help: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z",
95
+ }
96
+
97
+ // Get icon path
98
+ const path = $derived(icons[name] || "")
99
+ const pixelSize = $derived(sizes[size] || sizes.md)
100
+ </script>
101
+
102
+ <svg
103
+ class="icon {className}"
104
+ class:icon-sm={size === 'sm'}
105
+ class:icon-md={size === 'md'}
106
+ class:icon-lg={size === 'lg'}
107
+ class:icon-xl={size === 'xl'}
108
+ viewBox="0 0 24 24"
109
+ width={pixelSize}
110
+ height={pixelSize}
111
+ fill="currentColor"
112
+ aria-hidden="true"
113
+ >
114
+ <path d={path} />
115
+ </svg>
116
+
117
+ <style>
118
+ @reference '../../twintrinsic.css';
119
+
120
+ .icon {
121
+ @apply inline-block align-middle;
122
+ @apply transition-colors duration-150;
123
+ }
124
+
125
+ .icon-sm {
126
+ @apply w-4 h-4;
127
+ }
128
+
129
+ .icon-md {
130
+ @apply w-5 h-5;
131
+ }
132
+
133
+ .icon-lg {
134
+ @apply w-6 h-6;
135
+ }
136
+
137
+ .icon-xl {
138
+ @apply w-8 h-8;
139
+ }
140
+ </style>
@@ -0,0 +1,25 @@
1
+ export default Icon;
2
+ type Icon = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Icon - A component for displaying SVG icons with consistent styling.
8
+ *
9
+ * Usage:
10
+ * ```svelte
11
+ * <Icon name="check" />
12
+ * <Icon name="arrow-right" size="lg" />
13
+ * <Icon name="close" class="text-error" />
14
+ * ```
15
+ */
16
+ declare const Icon: import("svelte").Component<{
17
+ name?: string;
18
+ size?: string;
19
+ class?: string;
20
+ }, {}, "">;
21
+ type $$ComponentProps = {
22
+ name?: string;
23
+ size?: string;
24
+ class?: string;
25
+ };
@@ -0,0 +1 @@
1
+ export { default as Icon } from "./Icon.svelte";
@@ -0,0 +1 @@
1
+ export { default as Icon } from "./Icon.svelte";
@@ -0,0 +1,158 @@
1
+ <!--
2
+ @component
3
+ Lazy - A component that renders its content only when it becomes visible in the viewport.
4
+ Useful for performance optimization by deferring the rendering of off-screen content.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Lazy>
9
+ <div>This content will only be rendered when visible</div>
10
+ </Lazy>
11
+
12
+ <Lazy placeholder={<div>Loading...</div>}>
13
+ <HeavyComponent />
14
+ </Lazy>
15
+ ```
16
+ -->
17
+ <script>
18
+ import { onMount } from "svelte"
19
+
20
+ const {
21
+ /** @type {string} - Additional CSS classes */
22
+ class: className = "",
23
+
24
+ /** @type {string} - HTML id for accessibility */
25
+ id = crypto.randomUUID(),
26
+
27
+ /** @type {number} - Threshold for intersection (0-1), where 1 means fully visible */
28
+ threshold = 0.1,
29
+
30
+ /** @type {string} - Margin around the root element for intersection detection */
31
+ rootMargin = "0px",
32
+
33
+ /** @type {boolean} - Whether to keep content rendered after it's been visible once */
34
+ keepRendered = true,
35
+
36
+ /** @type {boolean} - Whether to show a loading indicator while content is loading */
37
+ showLoading = false,
38
+
39
+ /** @type {number} - Delay in ms before showing content after it becomes visible */
40
+ delay = 0,
41
+
42
+ children,
43
+ placeholder,
44
+ } = $props()
45
+
46
+ // State
47
+ let isVisible = $state(false)
48
+ let hasBeenVisible = $state(false)
49
+ let shouldRender = $state(false)
50
+ let element
51
+
52
+ /**
53
+ * Handles intersection changes
54
+ * @param {IntersectionObserverEntry[]} entries - Intersection entries
55
+ */
56
+ function handleIntersection(entries) {
57
+ const [entry] = entries
58
+
59
+ if (entry.isIntersecting) {
60
+ isVisible = true
61
+ hasBeenVisible = true
62
+
63
+ if (delay > 0) {
64
+ setTimeout(() => {
65
+ shouldRender = true
66
+ }, delay)
67
+ } else {
68
+ shouldRender = true
69
+ }
70
+
71
+ // If we only need to detect visibility once, disconnect the observer
72
+ if (keepRendered) {
73
+ observer?.disconnect()
74
+ }
75
+ } else {
76
+ isVisible = false
77
+
78
+ // If we're not keeping rendered content, unrender when not visible
79
+ if (!keepRendered) {
80
+ shouldRender = false
81
+ }
82
+ }
83
+ }
84
+
85
+ let observer
86
+
87
+ onMount(() => {
88
+ // Check if IntersectionObserver is available
89
+ if ("IntersectionObserver" in window) {
90
+ observer = new IntersectionObserver(handleIntersection, {
91
+ root: null, // viewport
92
+ rootMargin,
93
+ threshold,
94
+ })
95
+
96
+ if (element) {
97
+ observer.observe(element)
98
+ }
99
+ } else {
100
+ // Fallback for browsers that don't support IntersectionObserver
101
+ shouldRender = true
102
+ isVisible = true
103
+ hasBeenVisible = true
104
+ }
105
+
106
+ return () => {
107
+ observer?.disconnect()
108
+ }
109
+ })
110
+ </script>
111
+
112
+ <div
113
+ {id}
114
+ class="lazy-container {className}"
115
+ bind:this={element}
116
+ >
117
+ {#if shouldRender}
118
+ <div class="lazy-content">
119
+ {@render children?.()}
120
+ </div>
121
+ {:else if placeholder}
122
+ <div class="lazy-placeholder">
123
+ {@render placeholder()}
124
+ </div>
125
+ {:else if showLoading && hasBeenVisible}
126
+ <div class="lazy-loading" aria-live="polite" aria-busy="true">
127
+ <div class="loading-spinner" aria-hidden="true"></div>
128
+ <span class="sr-only">Loading content</span>
129
+ </div>
130
+ {/if}
131
+ </div>
132
+
133
+ <style>
134
+ @reference "../../twintrinsic.css";
135
+
136
+ .lazy-container {
137
+ @apply min-h-[20px];
138
+ }
139
+
140
+ .lazy-loading {
141
+ @apply flex items-center justify-center p-4;
142
+ }
143
+
144
+ .loading-spinner {
145
+ @apply w-8 h-8 rounded-full border-4 border-primary-200 dark:border-primary-800;
146
+ @apply border-t-primary-500 dark:border-t-primary-400;
147
+ animation: spin 1s linear infinite;
148
+ }
149
+
150
+ @keyframes spin {
151
+ from {
152
+ transform: rotate(0deg);
153
+ }
154
+ to {
155
+ transform: rotate(360deg);
156
+ }
157
+ }
158
+ </style>
@@ -0,0 +1,42 @@
1
+ export default Lazy;
2
+ type Lazy = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Lazy - A component that renders its content only when it becomes visible in the viewport.
8
+ * Useful for performance optimization by deferring the rendering of off-screen content.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Lazy>
13
+ * <div>This content will only be rendered when visible</div>
14
+ * </Lazy>
15
+ *
16
+ * <Lazy placeholder={<div>Loading...</div>}>
17
+ * <HeavyComponent />
18
+ * </Lazy>
19
+ * ```
20
+ */
21
+ declare const Lazy: import("svelte").Component<{
22
+ class?: string;
23
+ id?: any;
24
+ threshold?: number;
25
+ rootMargin?: string;
26
+ keepRendered?: boolean;
27
+ showLoading?: boolean;
28
+ delay?: number;
29
+ children: any;
30
+ placeholder: any;
31
+ }, {}, "">;
32
+ type $$ComponentProps = {
33
+ class?: string;
34
+ id?: any;
35
+ threshold?: number;
36
+ rootMargin?: string;
37
+ keepRendered?: boolean;
38
+ showLoading?: boolean;
39
+ delay?: number;
40
+ children: any;
41
+ placeholder: any;
42
+ };