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,334 @@
1
+ <!--
2
+ @component
3
+ Modal - A dialog component for displaying content that requires user attention.
4
+ Provides accessible focus management, keyboard navigation, and backdrop interactions.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Modal open={showModal} onclose={() => showModal = false}>
9
+ <svelte:fragment slot="header">Modal Title</svelte:fragment>
10
+ <p>Modal content goes here</p>
11
+ <svelte:fragment slot="footer">
12
+ <Button onclick={() => showModal = false}>Close</Button>
13
+ <Button variant="primary">Save</Button>
14
+ </svelte:fragment>
15
+ </Modal>
16
+ ```
17
+ -->
18
+ <script>
19
+ import { onMount } from "svelte"
20
+ import { fade, scale } from "svelte/transition"
21
+
22
+ const {
23
+ /** @type {string} - Additional CSS classes */
24
+ class: className = "",
25
+
26
+ /** @type {string} - HTML id for accessibility */
27
+ id = crypto.randomUUID(),
28
+
29
+ /** @type {boolean} - Whether the modal is open */
30
+ open = false,
31
+
32
+ /** @type {boolean} - Whether to close when clicking outside */
33
+ closeOnOutsideClick = true,
34
+
35
+ /** @type {boolean} - Whether to close when pressing Escape */
36
+ closeOnEscape = true,
37
+
38
+ /** @type {string} - Size of the modal (sm, md, lg, xl, full) */
39
+ size = "md",
40
+
41
+ /** @type {boolean} - Whether to center the modal vertically */
42
+ centered = true,
43
+
44
+ /** @type {boolean} - Whether to show a close button in the header */
45
+ showCloseButton = true,
46
+
47
+ /** @type {string} - ARIA label for the close button */
48
+ closeButtonLabel = "Close modal",
49
+
50
+ /** @type {string} - ARIA label for the modal */
51
+ ariaLabel,
52
+
53
+ /** @type {string} - ARIA description for the modal */
54
+ ariaDescription,
55
+
56
+ /** @type {(event: CustomEvent) => void} - Close event handler */
57
+ onclose,
58
+
59
+ children,
60
+ header,
61
+ footer,
62
+ } = $props()
63
+
64
+ // Modal state
65
+ let isOpen = $state(open)
66
+ let modalElement = $state()
67
+ let previouslyFocusedElement = $state()
68
+
69
+ // Sync open state when prop changes
70
+ $effect(() => {
71
+ isOpen = open
72
+
73
+ if (isOpen) {
74
+ openModal()
75
+ } else {
76
+ closeModal()
77
+ }
78
+ })
79
+
80
+ /**
81
+ * Opens the modal
82
+ */
83
+ function openModal() {
84
+ // Save the currently focused element to restore later
85
+ previouslyFocusedElement = document.activeElement
86
+
87
+ // Add body class to prevent scrolling
88
+ document.body.classList.add("modal-open")
89
+
90
+ // Focus the modal after it's visible
91
+ setTimeout(() => {
92
+ focusFirstElement()
93
+ }, 50)
94
+
95
+ dispatch("open")
96
+ }
97
+
98
+ /**
99
+ * Closes the modal
100
+ */
101
+ function closeModal() {
102
+ // Remove body class
103
+ document.body.classList.remove("modal-open")
104
+
105
+ // Restore focus to the previously focused element
106
+ if (previouslyFocusedElement) {
107
+ previouslyFocusedElement.focus()
108
+ }
109
+
110
+ onclose?.(new CustomEvent("close"))
111
+ }
112
+
113
+ /**
114
+ * Handles backdrop clicks
115
+ * @param {MouseEvent} event - Click event
116
+ */
117
+ function handleBackdropClick(event) {
118
+ // Only close if clicking directly on the backdrop, not on the modal content
119
+ if (closeOnOutsideClick && event.target === event.currentTarget) {
120
+ isOpen = false
121
+ closeModal()
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Handles keydown events
127
+ * @param {KeyboardEvent} event - Keydown event
128
+ */
129
+ function handleKeydown(event) {
130
+ if (!isOpen) return
131
+
132
+ // Close on Escape key
133
+ if (closeOnEscape && event.key === "Escape") {
134
+ event.preventDefault()
135
+ isOpen = false
136
+ closeModal()
137
+ return
138
+ }
139
+
140
+ // Trap focus within modal
141
+ if (event.key === "Tab") {
142
+ trapFocus(event)
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Traps focus within the modal
148
+ * @param {KeyboardEvent} event - Keydown event
149
+ */
150
+ function trapFocus(event) {
151
+ if (!modalElement) return
152
+
153
+ // Get all focusable elements
154
+ const focusableElements = modalElement.querySelectorAll(
155
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
156
+ )
157
+
158
+ if (focusableElements.length === 0) return
159
+
160
+ const firstElement = focusableElements[0]
161
+ const lastElement = focusableElements[focusableElements.length - 1]
162
+
163
+ // If shift+tab on first element, move to last element
164
+ if (event.shiftKey && document.activeElement === firstElement) {
165
+ event.preventDefault()
166
+ lastElement.focus()
167
+ }
168
+ // If tab on last element, move to first element
169
+ else if (!event.shiftKey && document.activeElement === lastElement) {
170
+ event.preventDefault()
171
+ firstElement.focus()
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Focuses the first focusable element in the modal
177
+ */
178
+ function focusFirstElement() {
179
+ if (!modalElement) return
180
+
181
+ // Try to focus the first focusable element
182
+ const focusableElement = modalElement.querySelector(
183
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
184
+ )
185
+
186
+ if (focusableElement) {
187
+ focusableElement.focus()
188
+ } else {
189
+ // If no focusable element, focus the modal itself
190
+ modalElement.focus()
191
+ }
192
+ }
193
+
194
+ // Clean up when component is destroyed
195
+ onMount(() => {
196
+ if (isOpen) {
197
+ openModal()
198
+ }
199
+
200
+ return () => {
201
+ if (isOpen) {
202
+ document.body.classList.remove("modal-open")
203
+ }
204
+ }
205
+ })
206
+
207
+ // Determine size classes
208
+ const sizeClasses = $derived(
209
+ {
210
+ sm: "max-w-sm",
211
+ md: "max-w-md",
212
+ lg: "max-w-lg",
213
+ xl: "max-w-xl",
214
+ "2xl": "max-w-2xl",
215
+ "3xl": "max-w-3xl",
216
+ "4xl": "max-w-4xl",
217
+ "5xl": "max-w-5xl",
218
+ "6xl": "max-w-6xl",
219
+ "7xl": "max-w-7xl",
220
+ full: "max-w-full",
221
+ }[size] || "max-w-md"
222
+ )
223
+ </script>
224
+
225
+ <svelte:window onkeydown={handleKeydown} />
226
+
227
+ {#if isOpen}
228
+ <div
229
+ class="modal-backdrop"
230
+ onclick={handleBackdropClick}
231
+ transition:fade={{ duration: 200 }}
232
+ >
233
+ <div
234
+ {id}
235
+ class="
236
+ modal
237
+ {sizeClasses}
238
+ {centered ? 'modal-centered' : ''}
239
+ {className}
240
+ "
241
+ role="dialog"
242
+ aria-modal="true"
243
+ aria-label={ariaLabel}
244
+ aria-describedby={ariaDescription ? `${id}-description` : undefined}
245
+ tabindex="-1"
246
+ bind:this={modalElement}
247
+ transition:scale={{ duration: 200, start: 0.95 }}
248
+ >
249
+ {#if header}
250
+ <div class="modal-header">
251
+ <div class="modal-title">
252
+ {@render header()}
253
+ </div>
254
+
255
+ {#if showCloseButton}
256
+ <button
257
+ type="button"
258
+ class="modal-close-button"
259
+ aria-label={closeButtonLabel}
260
+ onclick={() => {
261
+ isOpen = false;
262
+ closeModal();
263
+ }}
264
+ >
265
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
266
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
267
+ </svg>
268
+ </button>
269
+ {/if}
270
+ </div>
271
+ {/if}
272
+
273
+ <div class="modal-body" id={ariaDescription ? `${id}-description` : undefined}>
274
+ {@render children?.()}
275
+ </div>
276
+
277
+ {#if footer}
278
+ <div class="modal-footer">
279
+ {@render footer()}
280
+ </div>
281
+ {/if}
282
+ </div>
283
+ </div>
284
+ {/if}
285
+
286
+ <style>
287
+ @reference "../../twintrinsic.css";
288
+
289
+ /* Add global style to prevent body scrolling when modal is open */
290
+ :global(body.modal-open) {
291
+ @apply overflow-hidden;
292
+ }
293
+
294
+ .modal-backdrop {
295
+ @apply fixed inset-0 z-50;
296
+ @apply bg-black/50 dark:bg-black/60 backdrop-blur-sm;
297
+ @apply flex items-center justify-center p-4;
298
+ }
299
+
300
+ .modal {
301
+ @apply w-full relative;
302
+ @apply bg-background dark:bg-background text-text dark:text-text;
303
+ @apply rounded-lg shadow-lg overflow-hidden;
304
+ @apply flex flex-col max-h-[calc(100vh-2rem)];
305
+ }
306
+
307
+ .modal-centered {
308
+ @apply my-auto;
309
+ }
310
+
311
+ .modal-header {
312
+ @apply flex items-center justify-between p-4 sm:p-6;
313
+ @apply border-b border-border dark:border-border;
314
+ }
315
+
316
+ .modal-title {
317
+ @apply text-lg font-medium;
318
+ }
319
+
320
+ .modal-close-button {
321
+ @apply p-1 rounded-md text-muted dark:text-muted;
322
+ @apply hover:bg-hover dark:hover:bg-hover hover:text-text dark:hover:text-text;
323
+ @apply focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400;
324
+ }
325
+
326
+ .modal-body {
327
+ @apply p-4 sm:p-6 overflow-y-auto;
328
+ }
329
+
330
+ .modal-footer {
331
+ @apply flex items-center justify-end gap-3 p-4 sm:p-6;
332
+ @apply border-t border-border dark:border-border;
333
+ }
334
+ </style>
@@ -0,0 +1,55 @@
1
+ export default Modal;
2
+ type Modal = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Modal - A dialog component for displaying content that requires user attention.
8
+ * Provides accessible focus management, keyboard navigation, and backdrop interactions.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Modal open={showModal} onclose={() => showModal = false}>
13
+ * <svelte:fragment slot="header">Modal Title</svelte:fragment>
14
+ * <p>Modal content goes here</p>
15
+ * <svelte:fragment slot="footer">
16
+ * <Button onclick={() => showModal = false}>Close</Button>
17
+ * <Button variant="primary">Save</Button>
18
+ * </svelte:fragment>
19
+ * </Modal>
20
+ * ```
21
+ */
22
+ declare const Modal: import("svelte").Component<{
23
+ class?: string;
24
+ id?: any;
25
+ open?: boolean;
26
+ closeOnOutsideClick?: boolean;
27
+ closeOnEscape?: boolean;
28
+ size?: string;
29
+ centered?: boolean;
30
+ showCloseButton?: boolean;
31
+ closeButtonLabel?: string;
32
+ ariaLabel: any;
33
+ ariaDescription: any;
34
+ onclose: any;
35
+ children: any;
36
+ header: any;
37
+ footer: any;
38
+ }, {}, "">;
39
+ type $$ComponentProps = {
40
+ class?: string;
41
+ id?: any;
42
+ open?: boolean;
43
+ closeOnOutsideClick?: boolean;
44
+ closeOnEscape?: boolean;
45
+ size?: string;
46
+ centered?: boolean;
47
+ showCloseButton?: boolean;
48
+ closeButtonLabel?: string;
49
+ ariaLabel: any;
50
+ ariaDescription: any;
51
+ onclose: any;
52
+ children: any;
53
+ header: any;
54
+ footer: any;
55
+ };
@@ -0,0 +1,141 @@
1
+ <!--
2
+ @component
3
+ Card - A styled container for content with optional header and footer.
4
+ Built on top of the Panel component with additional card-specific styling.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Card>
9
+ <svelte:fragment slot="header">Card Title</svelte:fragment>
10
+ <p>Card content</p>
11
+ <svelte:fragment slot="footer">Card footer</svelte:fragment>
12
+ </Card>
13
+
14
+ <Card hoverable>
15
+ <svelte:fragment slot="media">
16
+ <img src="image.jpg" alt="Card image" />
17
+ </svelte:fragment>
18
+ <h3>Title</h3>
19
+ <p>Content with hover effect</p>
20
+ </Card>
21
+ ```
22
+ -->
23
+ <script>
24
+ import Panel from "./Panel.svelte"
25
+
26
+ const {
27
+ /** @type {string} - Additional CSS classes */
28
+ class: className = "",
29
+
30
+ /** @type {string} - HTML id for accessibility */
31
+ id = crypto.randomUUID(),
32
+
33
+ /** @type {string} - ARIA label */
34
+ ariaLabel,
35
+
36
+ /** @type {boolean} - Whether to add hover effects */
37
+ hoverable = false,
38
+
39
+ /** @type {boolean} - Whether to add shadow */
40
+ shadow = true,
41
+
42
+ /** @type {"none" | "sm" | "md" | "lg" | "xl"} - Shadow size when shadow is true */
43
+ shadowSize = "md",
44
+
45
+ /** @type {boolean} - Whether the card is clickable */
46
+ clickable = false,
47
+
48
+ children,
49
+ header,
50
+ footer,
51
+ media,
52
+ } = $props()
53
+
54
+ // Handle click events if card is clickable
55
+ function handleClick(event) {
56
+ if (clickable) {
57
+ const customEvent = new CustomEvent("click", {
58
+ detail: { originalEvent: event },
59
+ bubbles: true,
60
+ })
61
+ this?.dispatchEvent(customEvent)
62
+ }
63
+ }
64
+ </script>
65
+
66
+ <div
67
+ class="
68
+ card
69
+ {shadow ? `shadow-${shadowSize}` : ''}
70
+ {hoverable ? 'card-hoverable' : ''}
71
+ {clickable ? 'card-clickable' : ''}
72
+ {className}
73
+ "
74
+ {id}
75
+ role={clickable ? 'button' : 'article'}
76
+ aria-label={ariaLabel}
77
+ onclick={handleClick}
78
+ onkeydown={event => {
79
+ if (clickable && (event.key === 'Enter' || event.key === ' ')) {
80
+ event.preventDefault();
81
+ handleClick(event);
82
+ }
83
+ }}
84
+ tabindex={clickable ? '0' : undefined}
85
+ >
86
+ {#if media}
87
+ <div class="card-media">
88
+ {@render media?.()}
89
+ </div>
90
+ {/if}
91
+
92
+ <Panel
93
+ expanded={true}
94
+ showIcon={false}
95
+ bordered={false}
96
+ >
97
+ <svelte:fragment slot="header">
98
+ {@render header?.()}
99
+ </svelte:fragment>
100
+
101
+ {@render children?.()}
102
+ </Panel>
103
+
104
+ {#if footer}
105
+ <div class="card-footer">
106
+ {@render footer?.()}
107
+ </div>
108
+ {/if}
109
+ </div>
110
+
111
+ <style>
112
+ @reference "../../twintrinsic.css";
113
+
114
+ .card {
115
+ @apply bg-surface dark:bg-surface rounded-lg overflow-hidden;
116
+ @apply border border-border dark:border-border;
117
+ }
118
+
119
+ .card-hoverable {
120
+ @apply transition-all duration-200;
121
+ @apply hover:shadow-lg hover:-translate-y-1;
122
+ }
123
+
124
+ .card-clickable {
125
+ @apply cursor-pointer;
126
+ @apply focus:outline-none focus:ring-2 focus:ring-focus-ring;
127
+ }
128
+
129
+ .card-media {
130
+ @apply w-full overflow-hidden;
131
+ }
132
+
133
+ .card-media :global(img) {
134
+ @apply w-full h-full object-cover;
135
+ }
136
+
137
+ .card-footer {
138
+ @apply px-4 py-3 bg-muted/10 dark:bg-muted/10;
139
+ @apply border-t border-border dark:border-border;
140
+ }
141
+ </style>
@@ -0,0 +1,52 @@
1
+ export default Card;
2
+ type Card = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Card - A styled container for content with optional header and footer.
8
+ * Built on top of the Panel component with additional card-specific styling.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Card>
13
+ * <svelte:fragment slot="header">Card Title</svelte:fragment>
14
+ * <p>Card content</p>
15
+ * <svelte:fragment slot="footer">Card footer</svelte:fragment>
16
+ * </Card>
17
+ *
18
+ * <Card hoverable>
19
+ * <svelte:fragment slot="media">
20
+ * <img src="image.jpg" alt="Card image" />
21
+ * </svelte:fragment>
22
+ * <h3>Title</h3>
23
+ * <p>Content with hover effect</p>
24
+ * </Card>
25
+ * ```
26
+ */
27
+ declare const Card: import("svelte").Component<{
28
+ class?: string;
29
+ id?: any;
30
+ ariaLabel: any;
31
+ hoverable?: boolean;
32
+ shadow?: boolean;
33
+ shadowSize?: string;
34
+ clickable?: boolean;
35
+ children: any;
36
+ header: any;
37
+ footer: any;
38
+ media: any;
39
+ }, {}, "">;
40
+ type $$ComponentProps = {
41
+ class?: string;
42
+ id?: any;
43
+ ariaLabel: any;
44
+ hoverable?: boolean;
45
+ shadow?: boolean;
46
+ shadowSize?: string;
47
+ clickable?: boolean;
48
+ children: any;
49
+ header: any;
50
+ footer: any;
51
+ media: any;
52
+ };
@@ -0,0 +1,9 @@
1
+ ---
2
+ group: 'panels'
3
+ icon: 'tabler:section'
4
+ ---
5
+
6
+ # Hero
7
+
8
+ A Hero, sometimes called a Jumbotron, is an inline panel in a page. It is a visible and logical break in a page,
9
+ used to showcase a feature or idea.
@@ -0,0 +1,49 @@
1
+ <script lang="ts">
2
+ // import type { HstSvelte as Histoire } from '@histoire/plugin-svelte';
3
+ export let Hst
4
+ import Hero from "./Hero.svelte"
5
+
6
+ let heading = "This is a HERO!"
7
+ let slotContent =
8
+ "Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel est nemo fugiat delectus perferendis adipisci maiores optio cupiditate hic ipsam dignissimos in quasi ea, minima, ut, reprehenderit quos tempora inventore."
9
+ </script>
10
+
11
+ <Hst.Story title="Panels/Hero" layout={{ type: 'grid', width: '100%' }} icon="tabler:section">
12
+ <svelte:fragment slot="controls">
13
+ <Hst.Text bind:value={heading} title="Heading" />
14
+ <Hst.Text bind:value={slotContent} title="slotContent" />
15
+ </svelte:fragment>
16
+
17
+ <Hst.Variant title="Default Slot" source="<Hero>&#123;slotContent}</Hero>">
18
+ <Hero>{slotContent}</Hero>
19
+ </Hst.Variant>
20
+
21
+ <Hst.Variant
22
+ title="With Heading"
23
+ source="<Hero heading='This is a HERO'>&#123;slotContent}</Hero>"
24
+ >
25
+ <Hero {heading}>
26
+ {slotContent}
27
+ </Hero>
28
+ </Hst.Variant>
29
+
30
+ <Hst.Variant title="Success" source="<Hero type='success'>&#123;slotContent}</Hero>">
31
+ <Hero type="success">{slotContent}</Hero>
32
+ </Hst.Variant>
33
+
34
+ <Hst.Variant title="Info" source="<Hero type='info'>&#123;slotContent}</Hero>">
35
+ <Hero type="info">{slotContent}</Hero>
36
+ </Hst.Variant>
37
+
38
+ <Hst.Variant title="Warning" source="<Hero type='warning'>&#123;slotContent}</Hero>">
39
+ <Hero type="warning">{slotContent}</Hero>
40
+ </Hst.Variant>
41
+
42
+ <Hst.Variant title="Failure" source="<Hero type='failure'>&#123;slotContent}</Hero>">
43
+ <Hero type="failure">{slotContent}</Hero>
44
+ </Hst.Variant>
45
+
46
+ <Hst.Variant title="Danger" source="<Hero type='danger'>&#123;slotContent}</Hero>">
47
+ <Hero type="danger">{slotContent}</Hero>
48
+ </Hst.Variant>
49
+ </Hst.Story>
@@ -0,0 +1,21 @@
1
+ import Hero from "./Hero.svelte";
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const Hero: $$__sveltets_2_IsomorphicComponent<{
16
+ Hst: any;
17
+ }, {
18
+ [evt: string]: CustomEvent<any>;
19
+ }, {}, {}, string>;
20
+ type Hero = InstanceType<typeof Hero>;
21
+ export default Hero;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import Container from "../../Container/Container.svelte"
3
+ let propClasses = ""
4
+ export let heading: string | null = ""
5
+ export let type: TypeLevel = null
6
+ let typeClass = ""
7
+ $: typeClass = type ? `bg-${type}` : "bg-light"
8
+ export { propClasses as class }
9
+ </script>
10
+
11
+ <Container as="section" {...$$restProps} class="twin-hero {typeClass} {propClasses} ">
12
+ <h1 slot="heading">{heading}</h1>
13
+ <slot></slot>
14
+ </Container>
15
+
16
+ <style>
17
+ @reference "../../../twintrinsic.css";
18
+ :global(.twin-hero) {
19
+ @apply p-4;
20
+ }
21
+ :global(.twin-hero h1) {
22
+ @apply text-4xl mb-3;
23
+ }
24
+ </style>