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,429 @@
1
+ <!--
2
+ @component
3
+ Calendar - A date picker component with month navigation, range selection,
4
+ and keyboard controls. Built with accessibility in mind.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Calendar
9
+ value={selectedDate}
10
+ onselect={handleSelect}
11
+ />
12
+
13
+ <Calendar
14
+ value={dateRange}
15
+ range={true}
16
+ minDate={minDate}
17
+ maxDate={maxDate}
18
+ onselect={handleRangeSelect}
19
+ />
20
+ ```
21
+ -->
22
+ <script>
23
+ import { slide } from "svelte/transition"
24
+ import { clickOutside } from "../../actions"
25
+ import Input from "./Input.svelte"
26
+
27
+ const {
28
+ /** @type {Date | [Date, Date] | null} - Selected date or date range */
29
+ value = null,
30
+ /** @type {boolean} - Whether to allow range selection */
31
+ range = false,
32
+ /** @type {Date | null} - Minimum selectable date */
33
+ minDate = null,
34
+ /** @type {Date | null} - Maximum selectable date */
35
+ maxDate = null,
36
+ /** @type {boolean} - Whether to show week numbers */
37
+ showWeekNumbers = false,
38
+ /** @type {string[]} - Custom day names */
39
+ dayNames = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
40
+ /** @type {string[]} - Custom month names */
41
+ monthNames = [
42
+ "January",
43
+ "February",
44
+ "March",
45
+ "April",
46
+ "May",
47
+ "June",
48
+ "July",
49
+ "August",
50
+ "September",
51
+ "October",
52
+ "November",
53
+ "December",
54
+ ],
55
+ /** @type {string} - Input label */
56
+ label = "Date",
57
+ /** @type {string} - Date format for display */
58
+ format = "MM/dd/yyyy",
59
+ /** @type {boolean} - Whether the calendar is disabled */
60
+ disabled = false,
61
+ /** @type {string} - Additional CSS classes */
62
+ class: className = "",
63
+ /** @type {(event: CustomEvent) => void} - Select event handler */
64
+ onselect,
65
+ } = $props()
66
+
67
+ let showCalendar = $state(false)
68
+ let currentMonth = $state(new Date())
69
+ let hoverDate = $state(null)
70
+ let inputValue = $state("")
71
+ let startDate = $state(null)
72
+ let endDate = $state(null)
73
+ let calendarElement = $state()
74
+
75
+ // Initialize dates from value prop
76
+ $effect(() => {
77
+ if (value) {
78
+ if (range && Array.isArray(value)) {
79
+ ;[startDate, endDate] = value
80
+ currentMonth = new Date(startDate)
81
+ } else if (!range && value instanceof Date) {
82
+ startDate = value
83
+ currentMonth = new Date(value)
84
+ }
85
+ updateInputValue()
86
+ }
87
+ })
88
+
89
+ // Get days in month matrix
90
+ function getDaysInMonth(date) {
91
+ const year = date.getFullYear()
92
+ const month = date.getMonth()
93
+ const firstDay = new Date(year, month, 1)
94
+ const lastDay = new Date(year, month + 1, 0)
95
+ const days = []
96
+ let week = []
97
+
98
+ // Fill in leading empty cells
99
+ for (let i = 0; i < firstDay.getDay(); i++) {
100
+ week.push(null)
101
+ }
102
+
103
+ // Fill in days
104
+ for (let day = 1; day <= lastDay.getDate(); day++) {
105
+ if (week.length === 7) {
106
+ days.push(week)
107
+ week = []
108
+ }
109
+ week.push(new Date(year, month, day))
110
+ }
111
+
112
+ // Fill in trailing empty cells
113
+ while (week.length < 7) {
114
+ week.push(null)
115
+ }
116
+ days.push(week)
117
+
118
+ return days
119
+ }
120
+
121
+ // Get week number
122
+ function getWeekNumber(date) {
123
+ const target = new Date(date.valueOf())
124
+ const dayNr = (date.getDay() + 6) % 7
125
+ target.setDate(target.getDate() - dayNr + 3)
126
+ const firstThursday = target.valueOf()
127
+ target.setMonth(0, 1)
128
+ if (target.getDay() !== 4) {
129
+ target.setMonth(0, 1 + ((4 - target.getDay() + 7) % 7))
130
+ }
131
+ return 1 + Math.ceil((firstThursday - target) / 604800000)
132
+ }
133
+
134
+ // Format date for display
135
+ function formatDate(date) {
136
+ if (!date) return ""
137
+
138
+ return format
139
+ .replace("MM", String(date.getMonth() + 1).padStart(2, "0"))
140
+ .replace("dd", String(date.getDate()).padStart(2, "0"))
141
+ .replace("yyyy", date.getFullYear())
142
+ }
143
+
144
+ // Update input value based on selected dates
145
+ function updateInputValue() {
146
+ if (range) {
147
+ inputValue = startDate && endDate ? `${formatDate(startDate)} - ${formatDate(endDate)}` : ""
148
+ } else {
149
+ inputValue = startDate ? formatDate(startDate) : ""
150
+ }
151
+ }
152
+
153
+ // Handle date selection
154
+ function handleDateSelect(date) {
155
+ if (disabled) return
156
+
157
+ if (range) {
158
+ if (!startDate || (startDate && endDate) || date < startDate) {
159
+ startDate = date
160
+ endDate = null
161
+ } else {
162
+ endDate = date
163
+ showCalendar = false
164
+ }
165
+
166
+ onselect?.(new CustomEvent("select", { detail: { start: startDate, end: endDate } }))
167
+ } else {
168
+ startDate = date
169
+ showCalendar = false
170
+ onselect?.(new CustomEvent("select", { detail: { date } }))
171
+ }
172
+
173
+ updateInputValue()
174
+ }
175
+
176
+ // Handle date hover for range selection
177
+ function handleDateHover(date) {
178
+ if (range && startDate && !endDate) {
179
+ hoverDate = date
180
+ }
181
+ }
182
+
183
+ // Check if date is in range
184
+ function isInRange(date) {
185
+ if (!date) return false
186
+ if (range) {
187
+ if (startDate && !endDate && hoverDate) {
188
+ return date >= startDate && date <= hoverDate
189
+ }
190
+ return startDate && endDate && date >= startDate && date <= endDate
191
+ }
192
+ return false
193
+ }
194
+
195
+ // Check if date is selected
196
+ function isSelected(date) {
197
+ if (!date) return false
198
+ if (range) {
199
+ return (
200
+ (startDate && date.getTime() === startDate.getTime()) ||
201
+ (endDate && date.getTime() === endDate.getTime())
202
+ )
203
+ }
204
+ return startDate && date.getTime() === startDate.getTime()
205
+ }
206
+
207
+ // Check if date is disabled
208
+ function isDisabled(date) {
209
+ if (!date) return true
210
+ if (minDate && date < minDate) return true
211
+ if (maxDate && date > maxDate) return true
212
+ return false
213
+ }
214
+
215
+ // Navigate to previous/next month
216
+ function navigateMonth(delta) {
217
+ const newMonth = new Date(currentMonth)
218
+ newMonth.setMonth(newMonth.getMonth() + delta)
219
+ currentMonth = newMonth
220
+ }
221
+
222
+ // Handle keyboard navigation
223
+ function handleKeydown(event) {
224
+ if (!showCalendar) return
225
+
226
+ const key = event.key
227
+ const newDate = new Date(currentMonth)
228
+
229
+ switch (key) {
230
+ case "ArrowLeft":
231
+ event.preventDefault()
232
+ newDate.setDate(newDate.getDate() - 1)
233
+ break
234
+ case "ArrowRight":
235
+ event.preventDefault()
236
+ newDate.setDate(newDate.getDate() + 1)
237
+ break
238
+ case "ArrowUp":
239
+ event.preventDefault()
240
+ newDate.setDate(newDate.getDate() - 7)
241
+ break
242
+ case "ArrowDown":
243
+ event.preventDefault()
244
+ newDate.setDate(newDate.getDate() + 7)
245
+ break
246
+ case "Enter":
247
+ event.preventDefault()
248
+ handleDateSelect(currentMonth)
249
+ break
250
+ case "Escape":
251
+ event.preventDefault()
252
+ showCalendar = false
253
+ break
254
+ default:
255
+ return
256
+ }
257
+
258
+ if (!isDisabled(newDate)) {
259
+ currentMonth = newDate
260
+ }
261
+ }
262
+ </script>
263
+
264
+ <div
265
+ class="calendar-container {className}"
266
+ use:clickOutside
267
+ onclickOutside={() => showCalendar = false}
268
+ >
269
+ <Input
270
+ {label}
271
+ {disabled}
272
+ value={inputValue}
273
+ readonly
274
+ rightIcon="calendar"
275
+ onclick={() => showCalendar = !showCalendar}
276
+ onrightIconClick={() => showCalendar = !showCalendar}
277
+ />
278
+
279
+ {#if showCalendar}
280
+ <div
281
+ class="calendar"
282
+ role="dialog"
283
+ aria-label="Calendar"
284
+ transition:slide={{ duration: 150 }}
285
+ onkeydown={handleKeydown}
286
+ >
287
+ <div class="calendar-header">
288
+ <button
289
+ type="button"
290
+ class="calendar-nav-btn"
291
+ onclick={() => navigateMonth(-1)}
292
+ aria-label="Previous month"
293
+ disabled={disabled}
294
+ >
295
+ <svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
296
+ <path d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" />
297
+ </svg>
298
+ </button>
299
+
300
+ <div class="calendar-title">
301
+ {monthNames[currentMonth.getMonth()]} {currentMonth.getFullYear()}
302
+ </div>
303
+
304
+ <button
305
+ type="button"
306
+ class="calendar-nav-btn"
307
+ onclick={() => navigateMonth(1)}
308
+ aria-label="Next month"
309
+ disabled={disabled}
310
+ >
311
+ <svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
312
+ <path d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" />
313
+ </svg>
314
+ </button>
315
+ </div>
316
+
317
+ <table class="calendar-grid" role="grid">
318
+ <thead>
319
+ <tr>
320
+ {#if showWeekNumbers}
321
+ <th scope="col">Wk</th>
322
+ {/if}
323
+ {#each dayNames as day}
324
+ <th scope="col">{day}</th>
325
+ {/each}
326
+ </tr>
327
+ </thead>
328
+ <tbody>
329
+ {#each getDaysInMonth(currentMonth) as week}
330
+ <tr>
331
+ {#if showWeekNumbers}
332
+ <td class="calendar-week">
333
+ {#if week[0]}
334
+ {getWeekNumber(week[0])}
335
+ {/if}
336
+ </td>
337
+ {/if}
338
+ {#each week as day}
339
+ <td
340
+ class="calendar-day"
341
+ class:calendar-day-selected={isSelected(day)}
342
+ class:calendar-day-in-range={isInRange(day)}
343
+ class:calendar-day-disabled={isDisabled(day)}
344
+ >
345
+ {#if day}
346
+ <button
347
+ type="button"
348
+ disabled={isDisabled(day)}
349
+ onclick={() => handleDateSelect(day)}
350
+ onmouseenter={() => handleDateHover(day)}
351
+ aria-label={formatDate(day)}
352
+ aria-selected={isSelected(day)}
353
+ >
354
+ {day.getDate()}
355
+ </button>
356
+ {/if}
357
+ </td>
358
+ {/each}
359
+ </tr>
360
+ {/each}
361
+ </tbody>
362
+ </table>
363
+ </div>
364
+ {/if}
365
+ </div>
366
+
367
+ <style>
368
+ @reference "../../twintrinsic.css";
369
+
370
+ .calendar-container {
371
+ @apply relative inline-block w-full;
372
+ }
373
+
374
+ .calendar {
375
+ @apply absolute z-50 mt-1 p-4;
376
+ @apply bg-surface border border-border rounded-md shadow-lg;
377
+ @apply min-w-[280px];
378
+ }
379
+
380
+ .calendar-header {
381
+ @apply flex items-center justify-between mb-4;
382
+ }
383
+
384
+ .calendar-title {
385
+ @apply text-sm font-medium;
386
+ }
387
+
388
+ .calendar-nav-btn {
389
+ @apply p-1 rounded-md;
390
+ @apply hover:bg-hover focus:bg-hover;
391
+ @apply disabled:opacity-50 disabled:cursor-not-allowed;
392
+ }
393
+
394
+ .calendar-grid {
395
+ @apply w-full border-collapse;
396
+ }
397
+
398
+ .calendar-grid th {
399
+ @apply p-1 text-xs font-medium text-muted text-center;
400
+ }
401
+
402
+ .calendar-week {
403
+ @apply p-1 text-xs text-muted text-center;
404
+ }
405
+
406
+ .calendar-day {
407
+ @apply p-0 text-center;
408
+ }
409
+
410
+ .calendar-day button {
411
+ @apply w-8 h-8 rounded-md text-sm;
412
+ @apply hover:bg-hover focus:bg-hover;
413
+ @apply disabled:opacity-50 disabled:cursor-not-allowed;
414
+ }
415
+
416
+ .calendar-day-selected button {
417
+ @apply bg-primary text-primary-text;
418
+ @apply hover:bg-primary-hover focus:bg-primary-hover;
419
+ }
420
+
421
+ .calendar-day-in-range {
422
+ @apply bg-primary-50 dark:bg-primary-900;
423
+ }
424
+
425
+ .calendar-day-disabled button {
426
+ @apply opacity-50 cursor-not-allowed;
427
+ @apply hover:bg-transparent focus:bg-transparent;
428
+ }
429
+ </style>
@@ -0,0 +1,53 @@
1
+ export default Calendar;
2
+ type Calendar = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ /**
7
+ * Calendar - A date picker component with month navigation, range selection,
8
+ * and keyboard controls. Built with accessibility in mind.
9
+ *
10
+ * Usage:
11
+ * ```svelte
12
+ * <Calendar
13
+ * value={selectedDate}
14
+ * onselect={handleSelect}
15
+ * />
16
+ *
17
+ * <Calendar
18
+ * value={dateRange}
19
+ * range={true}
20
+ * minDate={minDate}
21
+ * maxDate={maxDate}
22
+ * onselect={handleRangeSelect}
23
+ * />
24
+ * ```
25
+ */
26
+ declare const Calendar: import("svelte").Component<{
27
+ value?: any;
28
+ range?: boolean;
29
+ minDate?: any;
30
+ maxDate?: any;
31
+ showWeekNumbers?: boolean;
32
+ dayNames?: any[];
33
+ monthNames?: any[];
34
+ label?: string;
35
+ format?: string;
36
+ disabled?: boolean;
37
+ class?: string;
38
+ onselect: any;
39
+ }, {}, "">;
40
+ type $$ComponentProps = {
41
+ value?: any;
42
+ range?: boolean;
43
+ minDate?: any;
44
+ maxDate?: any;
45
+ showWeekNumbers?: boolean;
46
+ dayNames?: any[];
47
+ monthNames?: any[];
48
+ label?: string;
49
+ format?: string;
50
+ disabled?: boolean;
51
+ class?: string;
52
+ onselect: any;
53
+ };
@@ -0,0 +1,196 @@
1
+ <!--
2
+ @component
3
+ Checkbox - A form component for boolean or indeterminate input with customizable
4
+ labels, descriptions, and validation states.
5
+
6
+ Usage:
7
+ ```svelte
8
+ <Checkbox
9
+ label="Accept terms"
10
+ onchange={handleChange}
11
+ />
12
+
13
+ <Checkbox
14
+ label="Select all"
15
+ indeterminate={someSelected}
16
+ checked={allSelected}
17
+ description="Select all items in the list"
18
+ />
19
+ ```
20
+ -->
21
+ <script>
22
+ const {
23
+ /** @type {string} - Label text */
24
+ label,
25
+ /** @type {string} - Description text */
26
+ description = "",
27
+ /** @type {boolean} - Whether the checkbox is checked */
28
+ checked = false,
29
+ /** @type {boolean} - Whether the checkbox is in an indeterminate state */
30
+ indeterminate = false,
31
+ /** @type {boolean} - Whether the checkbox is disabled */
32
+ disabled = false,
33
+ /** @type {boolean} - Whether the checkbox is required */
34
+ required = false,
35
+ /** @type {string} - Error message */
36
+ error = "",
37
+ /** @type {string} - Name attribute */
38
+ name = "",
39
+ /** @type {string} - Value attribute */
40
+ value = "",
41
+ /** @type {string} - Additional CSS classes */
42
+ class: className = "",
43
+ /** @type {(event: CustomEvent) => void} - Change event handler */
44
+ onchange,
45
+ } = $props()
46
+
47
+ let checkboxEl = $state()
48
+
49
+ // Update indeterminate state
50
+ $effect(() => {
51
+ if (checkboxEl) {
52
+ checkboxEl.indeterminate = indeterminate
53
+ }
54
+ })
55
+
56
+ // Handle change event
57
+ function handleChange(event) {
58
+ const isChecked = event.target.checked
59
+ onchange?.(new CustomEvent("change", { detail: { checked: isChecked } }))
60
+ }
61
+ </script>
62
+
63
+ <div class="checkbox-container {className}">
64
+ <label
65
+ class="checkbox"
66
+ class:checkbox-disabled={disabled}
67
+ class:checkbox-error={error}
68
+ >
69
+ <input
70
+ type="checkbox"
71
+ bind:this={checkboxEl}
72
+ {name}
73
+ {value}
74
+ {checked}
75
+ {disabled}
76
+ {required}
77
+ aria-invalid={!!error}
78
+ aria-describedby={error ? `${name}-error` : undefined}
79
+ onchange={handleChange}
80
+ />
81
+ <span class="checkbox-control" aria-hidden="true">
82
+ {#if checked && !indeterminate}
83
+ <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
84
+ <path d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" />
85
+ </svg>
86
+ {:else if indeterminate}
87
+ <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
88
+ <path d="M5 10a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1z" />
89
+ </svg>
90
+ {/if}
91
+ </span>
92
+ <span class="checkbox-label">
93
+ {label}
94
+ {#if required}
95
+ <span class="checkbox-required" aria-hidden="true">*</span>
96
+ {/if}
97
+ </span>
98
+ </label>
99
+
100
+ {#if description}
101
+ <div class="checkbox-description">
102
+ {description}
103
+ </div>
104
+ {/if}
105
+
106
+ {#if error}
107
+ <div
108
+ class="checkbox-error-text"
109
+ id="{name}-error"
110
+ role="alert"
111
+ >
112
+ {error}
113
+ </div>
114
+ {/if}
115
+ </div>
116
+
117
+ <style>
118
+ @reference "../../twintrinsic.css";
119
+
120
+ .checkbox-container {
121
+ @apply flex flex-col gap-1;
122
+ }
123
+
124
+ .checkbox {
125
+ @apply relative flex items-start gap-2;
126
+ @apply cursor-pointer select-none;
127
+ }
128
+
129
+ .checkbox-disabled {
130
+ @apply cursor-not-allowed opacity-50;
131
+ }
132
+
133
+ /* Hide default checkbox */
134
+ .checkbox input {
135
+ @apply absolute w-0 h-0 opacity-0;
136
+ }
137
+
138
+ /* Custom checkbox control */
139
+ .checkbox-control {
140
+ @apply flex items-center justify-center;
141
+ @apply w-5 h-5 rounded;
142
+ @apply border-2 border-border;
143
+ @apply text-primary;
144
+ @apply transition-colors;
145
+ }
146
+
147
+ /* Hover state */
148
+ .checkbox:hover .checkbox-control {
149
+ @apply border-primary-500;
150
+ }
151
+
152
+ /* Focus state */
153
+ .checkbox input:focus + .checkbox-control {
154
+ @apply ring-2 ring-primary-500 ring-offset-2;
155
+ @apply ring-offset-background;
156
+ }
157
+
158
+ /* Checked state */
159
+ .checkbox input:checked + .checkbox-control {
160
+ @apply bg-primary-500 border-primary-500;
161
+ }
162
+
163
+ /* Error state */
164
+ .checkbox-error .checkbox-control {
165
+ @apply border-error;
166
+ }
167
+
168
+ .checkbox-error:hover .checkbox-control {
169
+ @apply border-error-bold;
170
+ }
171
+
172
+ .checkbox-error input:checked + .checkbox-control {
173
+ @apply bg-error border-error-bold;
174
+ }
175
+
176
+ /* Label */
177
+ .checkbox-label {
178
+ @apply text-sm;
179
+ }
180
+
181
+ .checkbox-required {
182
+ @apply ml-1 text-error;
183
+ }
184
+
185
+ /* Description */
186
+ .checkbox-description {
187
+ @apply text-sm text-muted;
188
+ @apply pl-7; /* Align with label text */
189
+ }
190
+
191
+ /* Error message */
192
+ .checkbox-error-text {
193
+ @apply text-sm text-error;
194
+ @apply pl-7; /* Align with label text */
195
+ }
196
+ </style>