@stacksjs/components 0.2.35 → 0.2.53

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 (237) hide show
  1. package/dist/Accordion-19x8q4rj.stx +88 -0
  2. package/dist/{Audio-vdmg1258.stx → Audio-hjywk3qc.stx} +4 -4
  3. package/dist/{Avatar-365cvrh4.stx → Avatar-h3jmwcq0.stx} +23 -34
  4. package/dist/{Badge-8m3qete4.stx → Badge-k8dy3d53.stx} +11 -19
  5. package/dist/{Button-3tt4vsqt.stx → Button-1vknasy3.stx} +18 -33
  6. package/dist/Calendar-reny0et7.stx +189 -0
  7. package/dist/{Card-6wdbexqr.stx → Card-c1g1fd1w.stx} +27 -33
  8. package/dist/{Checkbox-p3q3e3nf.stx → Checkbox-zgdmy3p5.stx} +36 -44
  9. package/dist/{Checkout-e4037tyy.stx → Checkout-agt0ngpw.stx} +8 -16
  10. package/dist/Combobox-fdkr6cdq.stx +96 -0
  11. package/dist/{ComboboxButton-8gxwkhdx.stx → ComboboxButton-g76stp1e.stx} +14 -2
  12. package/dist/{ComboboxInput-mk99z65n.stx → ComboboxInput-z1293bbh.stx} +12 -5
  13. package/dist/ComboboxOption-hmxt3gte.stx +49 -0
  14. package/dist/{ListboxOptions-8kqvfp7z.stx → ComboboxOptions-sq5360ae.stx} +2 -2
  15. package/dist/CommandPalette-36mxf05w.stx +81 -0
  16. package/dist/CommandPaletteItem-mvk6q7a2.stx +27 -0
  17. package/dist/Dialog-hczpexs4.stx +37 -0
  18. package/dist/{Drawer-p7m351bn.stx → Drawer-xhevp5cw.stx} +29 -49
  19. package/dist/Dropdown-vvhemtc0.stx +82 -0
  20. package/dist/{DropdownButton-9w8zkfwj.stx → DropdownButton-wcz67dxy.stx} +12 -6
  21. package/dist/DropdownItem-c7rz08e5.stx +35 -0
  22. package/dist/{DropdownItems-aygjpxkx.stx → DropdownItems-1sxnd5qn.stx} +2 -2
  23. package/dist/EmailInput-vak3kkmk.stx +30 -0
  24. package/dist/Form-mas630hy.stx +95 -0
  25. package/dist/{Image-jhkm6w1f.stx → Image-yhxcvgzs.stx} +68 -100
  26. package/dist/Listbox-q49tnr90.stx +101 -0
  27. package/dist/{ListboxButton-spwx7513.stx → ListboxButton-keb8gm0q.stx} +12 -1
  28. package/dist/ListboxOption-e0dtv1gc.stx +49 -0
  29. package/dist/{ComboboxOptions-6b5ywc5x.stx → ListboxOptions-ejkatcfg.stx} +7 -3
  30. package/dist/{Login-rx9gyqhx.stx → Login-gepemsth.stx} +17 -19
  31. package/dist/Navigator-rk2a5wvk.stx +113 -0
  32. package/dist/Notification-tb9b525s.stx +78 -0
  33. package/dist/{NumberInput-nzpkx1ry.stx → NumberInput-drnvtqej.stx} +40 -53
  34. package/dist/{Pagination-h61eq390.stx → Pagination-n3d31cns.stx} +73 -108
  35. package/dist/PasswordInput-n02x6053.stx +142 -0
  36. package/dist/{PaymentMethods-j42jsk5x.stx → PaymentMethods-x4vrx9yb.stx} +21 -30
  37. package/dist/Popover-et2q44m7.stx +60 -0
  38. package/dist/{PopoverButton-fnaqc77g.stx → PopoverButton-mffzc9pr.stx} +12 -6
  39. package/dist/{PopoverPanel-y0vtf5w9.stx → PopoverPanel-054yh38h.stx} +6 -6
  40. package/dist/{Portal-s2q37yp0.stx → Portal-1vf14s4x.stx} +20 -37
  41. package/dist/{Progress-vmdkm06p.stx → Progress-yxcntr4x.stx} +36 -48
  42. package/dist/{Radio-04bs3d21.stx → Radio-cgjv2hb2.stx} +29 -34
  43. package/dist/RadioGroup-qxmnm3xm.stx +60 -0
  44. package/dist/RadioGroupOption-s1d6r221.stx +58 -0
  45. package/dist/SearchInput-pdx7agn0.stx +44 -0
  46. package/dist/{Select-g4mmvfv8.stx → Select-28y0pg83.stx} +23 -31
  47. package/dist/Sidebar-73vc78as.stx +236 -0
  48. package/dist/SidebarFooter-zsfsgcxb.stx +109 -0
  49. package/dist/SidebarHeader-7v174a9c.stx +122 -0
  50. package/dist/SidebarItem-3y3e8g2t.stx +92 -0
  51. package/dist/SidebarSection-z5ey6awe.stx +113 -0
  52. package/dist/{Signup-c4dyv6f3.stx → Signup-hxm5hwkr.stx} +26 -28
  53. package/dist/{StepperStep-en4r00zv.stx → StepperStep-wxgembat.stx} +9 -5
  54. package/dist/{SubscriptionCheckout-gawjzf3q.stx → SubscriptionCheckout-zy2ycrmw.stx} +99 -129
  55. package/dist/Switch-r5t5w04w.stx +70 -0
  56. package/dist/{TableHeader-ydys9rzz.stx → TableHeader-0eyzbqpz.stx} +10 -3
  57. package/dist/Tabs-bzvvn4ke.stx +126 -0
  58. package/dist/Teleport-tsx4bt4n.stx +65 -0
  59. package/dist/{TextInput-k2kfkgy1.stx → TextInput-kf084763.stx} +42 -59
  60. package/dist/{Textarea-szad57dz.stx → Textarea-xg4rr2xz.stx} +42 -54
  61. package/dist/{Tooltip-em7t551n.stx → Tooltip-m0tqd72e.stx} +34 -40
  62. package/dist/Transition-7smenaz8.stx +102 -0
  63. package/dist/{TwoFactorChallenge-an9yvxvq.stx → TwoFactorChallenge-y5m3nk79.stx} +49 -63
  64. package/dist/{Video-crxva65p.stx → Video-84j4pv6h.stx} +4 -4
  65. package/dist/VirtualList-fa7v5a3h.stx +67 -0
  66. package/dist/VirtualTable-f9crbfjr.stx +103 -0
  67. package/dist/components/CodeBlock.stx +1 -6
  68. package/dist/index.js +13 -13
  69. package/dist/ui/accordion/Accordion.stx +1 -3
  70. package/dist/ui/auth/Login.stx +0 -1
  71. package/dist/ui/auth/Signup.stx +0 -1
  72. package/dist/ui/auth/TwoFactorChallenge.stx +1 -3
  73. package/dist/ui/avatar/Avatar.stx +0 -2
  74. package/dist/ui/badge/Badge.stx +0 -1
  75. package/dist/ui/button/Button.stx +1 -2
  76. package/dist/ui/calendar/Calendar.stx +12 -2
  77. package/dist/ui/card/Card.stx +0 -2
  78. package/dist/ui/checkbox/Checkbox.stx +2 -2
  79. package/dist/ui/combobox/Combobox.stx +2 -1
  80. package/dist/ui/combobox/ComboboxButton.stx +1 -0
  81. package/dist/ui/combobox/ComboboxInput.stx +1 -4
  82. package/dist/ui/combobox/ComboboxOption.stx +2 -9
  83. package/dist/ui/combobox/ComboboxOptions.stx +1 -1
  84. package/dist/ui/command-palette/CommandPalette.stx +3 -6
  85. package/dist/ui/command-palette/CommandPaletteItem.stx +2 -7
  86. package/dist/ui/dialog/Dialog.stx +1 -3
  87. package/dist/ui/drawer/Drawer.stx +1 -3
  88. package/dist/ui/dropdown/Dropdown.stx +2 -5
  89. package/dist/ui/dropdown/DropdownButton.stx +1 -3
  90. package/dist/ui/dropdown/DropdownItem.stx +2 -7
  91. package/dist/ui/dropdown/DropdownItems.stx +1 -1
  92. package/dist/ui/form/Form.stx +0 -5
  93. package/dist/ui/image/Image.stx +1 -6
  94. package/dist/ui/input/EmailInput.stx +1 -1
  95. package/dist/ui/input/NumberInput.stx +0 -1
  96. package/dist/ui/input/PasswordInput.stx +1 -4
  97. package/dist/ui/input/SearchInput.stx +2 -2
  98. package/dist/ui/input/TextInput.stx +1 -2
  99. package/dist/ui/listbox/Listbox.stx +2 -1
  100. package/dist/ui/listbox/ListboxButton.stx +1 -0
  101. package/dist/ui/listbox/ListboxOption.stx +2 -9
  102. package/dist/ui/listbox/ListboxOptions.stx +1 -1
  103. package/dist/ui/navigator/Navigator.stx +4 -4
  104. package/dist/ui/notification/Notification.stx +1 -5
  105. package/dist/ui/pagination/Pagination.stx +1 -2
  106. package/dist/ui/payment/Checkout.stx +0 -4
  107. package/dist/ui/payment/PaymentMethods.stx +15 -2
  108. package/dist/ui/payment/SubscriptionCheckout.stx +3 -184
  109. package/dist/ui/popover/Popover.stx +2 -5
  110. package/dist/ui/popover/PopoverButton.stx +1 -3
  111. package/dist/ui/popover/PopoverPanel.stx +1 -1
  112. package/dist/ui/portal/Portal.stx +1 -0
  113. package/dist/ui/progress/Progress.stx +6 -1
  114. package/dist/ui/radio/Radio.stx +1 -1
  115. package/dist/ui/radio-group/RadioGroup.stx +2 -1
  116. package/dist/ui/radio-group/RadioGroupOption.stx +2 -9
  117. package/dist/ui/select/Select.stx +1 -1
  118. package/dist/ui/sidebar/Sidebar.stx +9 -26
  119. package/dist/ui/sidebar/SidebarFooter.stx +6 -21
  120. package/dist/ui/sidebar/SidebarHeader.stx +7 -18
  121. package/dist/ui/sidebar/SidebarItem.stx +4 -20
  122. package/dist/ui/sidebar/SidebarSection.stx +5 -18
  123. package/dist/ui/sidebar/index.d.ts +13 -1
  124. package/dist/ui/stepper/StepperStep.stx +1 -5
  125. package/dist/ui/switch/Switch.stx +4 -10
  126. package/dist/ui/table/TableHeader.stx +1 -1
  127. package/dist/ui/tabs/Tabs.stx +0 -1
  128. package/dist/ui/teleport/Teleport.stx +1 -0
  129. package/dist/ui/textarea/Textarea.stx +1 -1
  130. package/dist/ui/tooltip/Tooltip.stx +1 -2
  131. package/dist/ui/transition/Transition.stx +9 -16
  132. package/dist/ui/virtual-list/VirtualList.stx +2 -4
  133. package/dist/ui/virtual-table/VirtualTable.stx +1 -1
  134. package/package.json +3 -3
  135. package/src/components/CodeBlock.stx +26 -29
  136. package/src/components/Footer.stx +1 -1
  137. package/src/components/Hero.stx +1 -1
  138. package/src/components/Installation.stx +5 -7
  139. package/src/ui/accordion/Accordion.stx +48 -68
  140. package/src/ui/audio/Audio.stx +4 -4
  141. package/src/ui/auth/Login.stx +17 -19
  142. package/src/ui/auth/Signup.stx +26 -28
  143. package/src/ui/auth/TwoFactorChallenge.stx +49 -63
  144. package/src/ui/avatar/Avatar.stx +23 -34
  145. package/src/ui/badge/Badge.stx +11 -19
  146. package/src/ui/button/Button.stx +18 -33
  147. package/src/ui/calendar/Calendar.stx +93 -136
  148. package/src/ui/card/Card.stx +27 -33
  149. package/src/ui/checkbox/Checkbox.stx +36 -44
  150. package/src/ui/combobox/Combobox.stx +87 -4
  151. package/src/ui/combobox/ComboboxButton.stx +14 -2
  152. package/src/ui/combobox/ComboboxInput.stx +12 -5
  153. package/src/ui/combobox/ComboboxOption.stx +29 -32
  154. package/src/ui/combobox/ComboboxOptions.stx +7 -3
  155. package/src/ui/command-palette/CommandPalette.stx +70 -28
  156. package/src/ui/command-palette/CommandPaletteItem.stx +15 -20
  157. package/src/ui/dialog/Dialog.stx +28 -10
  158. package/src/ui/drawer/Drawer.stx +29 -49
  159. package/src/ui/dropdown/Dropdown.stx +69 -11
  160. package/src/ui/dropdown/DropdownButton.stx +12 -6
  161. package/src/ui/dropdown/DropdownItem.stx +18 -26
  162. package/src/ui/dropdown/DropdownItems.stx +2 -2
  163. package/src/ui/form/Form.stx +50 -164
  164. package/src/ui/heatmap/Heatmap.stx +16 -37
  165. package/src/ui/image/Image.stx +68 -100
  166. package/src/ui/input/EmailInput.stx +16 -27
  167. package/src/ui/input/NumberInput.stx +40 -53
  168. package/src/ui/input/PasswordInput.stx +64 -77
  169. package/src/ui/input/SearchInput.stx +27 -46
  170. package/src/ui/input/TextInput.stx +42 -59
  171. package/src/ui/listbox/Listbox.stx +91 -4
  172. package/src/ui/listbox/ListboxButton.stx +12 -1
  173. package/src/ui/listbox/ListboxOption.stx +30 -38
  174. package/src/ui/listbox/ListboxOptions.stx +2 -2
  175. package/src/ui/navigator/Navigator.stx +52 -77
  176. package/src/ui/notification/Notification.stx +46 -39
  177. package/src/ui/pagination/Pagination.stx +73 -108
  178. package/src/ui/payment/Checkout.stx +8 -16
  179. package/src/ui/payment/PaymentMethods.stx +21 -30
  180. package/src/ui/payment/SubscriptionCheckout.stx +99 -129
  181. package/src/ui/popover/Popover.stx +50 -14
  182. package/src/ui/popover/PopoverButton.stx +12 -6
  183. package/src/ui/popover/PopoverPanel.stx +6 -6
  184. package/src/ui/portal/Portal.stx +20 -37
  185. package/src/ui/progress/Progress.stx +36 -48
  186. package/src/ui/radio/Radio.stx +29 -34
  187. package/src/ui/radio-group/RadioGroup.stx +51 -4
  188. package/src/ui/radio-group/RadioGroupOption.stx +37 -30
  189. package/src/ui/select/Select.stx +23 -31
  190. package/src/ui/sidebar/Sidebar.stx +136 -188
  191. package/src/ui/sidebar/SidebarFooter.stx +49 -35
  192. package/src/ui/sidebar/SidebarHeader.stx +52 -30
  193. package/src/ui/sidebar/SidebarItem.stx +52 -78
  194. package/src/ui/sidebar/SidebarSection.stx +56 -51
  195. package/src/ui/sidebar/index.ts +21 -1
  196. package/src/ui/stepper/StepperStep.stx +9 -5
  197. package/src/ui/switch/Switch.stx +38 -42
  198. package/src/ui/table/TableHeader.stx +10 -3
  199. package/src/ui/tabs/Tabs.stx +68 -87
  200. package/src/ui/teleport/Teleport.stx +23 -59
  201. package/src/ui/textarea/Textarea.stx +42 -54
  202. package/src/ui/tooltip/Tooltip.stx +34 -40
  203. package/src/ui/transition/Transition.stx +76 -148
  204. package/src/ui/video/Video.stx +4 -4
  205. package/src/ui/virtual-list/VirtualList.stx +45 -61
  206. package/src/ui/virtual-table/VirtualTable.stx +62 -72
  207. package/dist/Accordion-sbfra0mz.stx +0 -108
  208. package/dist/Calendar-58nnkdh8.stx +0 -232
  209. package/dist/Combobox-th5ebw62.stx +0 -13
  210. package/dist/ComboboxOption-an9zyan6.stx +0 -52
  211. package/dist/CommandPalette-kwmdf2np.stx +0 -39
  212. package/dist/CommandPaletteItem-zx2fbpts.stx +0 -32
  213. package/dist/Dialog-rgmj8q2j.stx +0 -19
  214. package/dist/Dropdown-jz4jy0n3.stx +0 -24
  215. package/dist/DropdownItem-wagdspb8.stx +0 -43
  216. package/dist/EmailInput-ajsp9vw6.stx +0 -41
  217. package/dist/Form-1mdmx9b6.stx +0 -209
  218. package/dist/Listbox-pqqh72g8.stx +0 -14
  219. package/dist/ListboxOption-7nxzaexq.stx +0 -57
  220. package/dist/Navigator-aay8bjab.stx +0 -138
  221. package/dist/Notification-gk33gv7b.stx +0 -71
  222. package/dist/PasswordInput-zv4hm43j.stx +0 -155
  223. package/dist/Popover-469gbt6r.stx +0 -24
  224. package/dist/RadioGroup-bvb1mrhd.stx +0 -13
  225. package/dist/RadioGroupOption-cpdwgnhw.stx +0 -51
  226. package/dist/SearchInput-2521m475.stx +0 -63
  227. package/dist/Sidebar-40ckbzh8.stx +0 -288
  228. package/dist/SidebarFooter-hnth56mg.stx +0 -95
  229. package/dist/SidebarHeader-3wrte2p2.stx +0 -100
  230. package/dist/SidebarItem-zqtvvzpc.stx +0 -118
  231. package/dist/SidebarSection-3etwnbjr.stx +0 -108
  232. package/dist/Switch-036j9vm1.stx +0 -74
  233. package/dist/Tabs-svh721m0.stx +0 -145
  234. package/dist/Teleport-qfch3w0b.stx +0 -101
  235. package/dist/Transition-0hmr6zxb.stx +0 -174
  236. package/dist/VirtualList-cndhjejh.stx +0 -83
  237. package/dist/VirtualTable-ng0b48yp.stx +0 -113
@@ -1,108 +0,0 @@
1
- <script server>
2
- export const items = $props.items || []
3
- export const allowMultiple = $props.allowMultiple || false
4
- export const defaultOpen = $props.defaultOpen || []
5
- export const className = $props.className || ''
6
- export const onChange = $props.onChange
7
-
8
- // Track which items are open
9
- let openItems = defaultOpen
10
-
11
- // Toggle an item
12
- function toggleItem(index) {
13
- if (allowMultiple) {
14
- // Multiple items can be open
15
- if (openItems.includes(index)) {
16
- openItems = openItems.filter(i => i !== index)
17
- } else {
18
- openItems = [...openItems, index]
19
- }
20
- } else {
21
- // Only one item can be open
22
- if (openItems.includes(index)) {
23
- openItems = []
24
- } else {
25
- openItems = [index]
26
- }
27
- }
28
-
29
- if (onChange) {
30
- onChange(openItems)
31
- }
32
- }
33
-
34
- // Check if item is open
35
- function isOpen(index) {
36
- return openItems.includes(index)
37
- }
38
-
39
- export const accordionClasses = `divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg ${className}`.trim()
40
- export const itemClasses = ``.trim()
41
- export const headerClasses = `w-full flex items-center justify-between px-4 py-3 text-left font-medium text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900`.trim()
42
- export const iconClasses = `w-5 h-5 text-gray-500 dark:text-gray-400 transition-transform duration-200`.trim()
43
- export const contentClasses = `px-4 py-3 text-gray-700 dark:text-gray-300`.trim()
44
- </script>
45
-
46
- <div class="{{ accordionClasses }}" role="region">
47
- @foreach(item in items)
48
- <div class="{{ itemClasses }}">
49
- <button
50
- type="button"
51
- class="{{ headerClasses }}"
52
- @click="toggleItem({{ $loop.index }})"
53
- aria-expanded="{{ isOpen($loop.index) ? 'true' : 'false' }}"
54
- aria-controls="accordion-content-{{ $loop.index }}"
55
- >
56
- <span>{{ item.title }}</span>
57
- <svg
58
- class="{{ iconClasses }}"
59
- style="transform: rotate({{ isOpen($loop.index) ? '180' : '0' }}deg)"
60
- fill="none"
61
- viewBox="0 0 24 24"
62
- stroke="currentColor"
63
- >
64
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
65
- </svg>
66
- </button>
67
-
68
- @if(isOpen($loop.index))
69
- <div
70
- id="accordion-content-{{ $loop.index }}"
71
- class="{{ contentClasses }}"
72
- role="region"
73
- >
74
- {!! item.content !!}
75
- </div>
76
- @endif
77
- </div>
78
- @endforeach
79
- </div>
80
-
81
- <script>
82
- // Keyboard navigation
83
- if (typeof window !== 'undefined') {
84
- window.addEventListener('DOMContentLoaded', () => {
85
- const buttons = document.querySelectorAll('[aria-expanded]')
86
-
87
- buttons.forEach((button, index) => {
88
- button.addEventListener('keydown', (event) => {
89
- if (event.key === 'ArrowDown') {
90
- event.preventDefault()
91
- const nextButton = buttons[index + 1]
92
- if (nextButton) nextButton.focus()
93
- } else if (event.key === 'ArrowUp') {
94
- event.preventDefault()
95
- const prevButton = buttons[index - 1]
96
- if (prevButton) prevButton.focus()
97
- } else if (event.key === 'Home') {
98
- event.preventDefault()
99
- buttons[0].focus()
100
- } else if (event.key === 'End') {
101
- event.preventDefault()
102
- buttons[buttons.length - 1].focus()
103
- }
104
- })
105
- })
106
- })
107
- }
108
- </script>
@@ -1,232 +0,0 @@
1
- <script server>
2
- // Calendar Component Props
3
- export const value = $props.value || new Date()
4
- export const onChange = $props.onChange
5
- export const minDate = $props.minDate
6
- export const maxDate = $props.maxDate
7
- export const disabledDates = $props.disabledDates || []
8
- export const locale = $props.locale || 'en-US'
9
- export const firstDayOfWeek = $props.firstDayOfWeek || 0 // 0 = Sunday, 1 = Monday
10
- export const showToday = $props.showToday !== false
11
- export const className = $props.className || ''
12
- export const highlightToday = $props.highlightToday !== false
13
-
14
- // State
15
- let currentMonth = value ? new Date(value) : new Date()
16
- let selectedDate = value ? new Date(value) : null
17
- const today = new Date()
18
-
19
- // Helper functions
20
- function getDaysInMonth(date) {
21
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
22
- }
23
-
24
- function getFirstDayOfMonth(date) {
25
- return new Date(date.getFullYear(), date.getMonth(), 1).getDay()
26
- }
27
-
28
- function isSameDay(date1, date2) {
29
- if (!date1 || !date2) return false
30
- return date1.getFullYear() === date2.getFullYear() &&
31
- date1.getMonth() === date2.getMonth() &&
32
- date1.getDate() === date2.getDate()
33
- }
34
-
35
- function isToday(date) {
36
- return isSameDay(date, today)
37
- }
38
-
39
- function isDisabled(date) {
40
- if (minDate && date < minDate) return true
41
- if (maxDate && date > maxDate) return true
42
- return disabledDates.some(d => isSameDay(d, date))
43
- }
44
-
45
- function getMonthName(date) {
46
- return date.toLocaleDateString(locale, { month: 'long' })
47
- }
48
-
49
- function getYear(date) {
50
- return date.getFullYear()
51
- }
52
-
53
- function getDayNames() {
54
- const days = []
55
- const baseDate = new Date(2024, 0, firstDayOfWeek) // Jan 2024 started on Monday
56
- for (let i = 0; i < 7; i++) {
57
- const day = new Date(baseDate)
58
- day.setDate(baseDate.getDate() + i)
59
- days.push(day.toLocaleDateString(locale, { weekday: 'short' }))
60
- }
61
- return days
62
- }
63
-
64
- function getCalendarDays() {
65
- const daysInMonth = getDaysInMonth(currentMonth)
66
- const firstDay = (getFirstDayOfMonth(currentMonth) - firstDayOfWeek + 7) % 7
67
- const days = []
68
-
69
- // Previous month days
70
- const prevMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
71
- const daysInPrevMonth = getDaysInMonth(prevMonth)
72
- for (let i = firstDay - 1; i >= 0; i--) {
73
- days.push({
74
- date: new Date(prevMonth.getFullYear(), prevMonth.getMonth(), daysInPrevMonth - i),
75
- isCurrentMonth: false,
76
- })
77
- }
78
-
79
- // Current month days
80
- for (let i = 1; i <= daysInMonth; i++) {
81
- days.push({
82
- date: new Date(currentMonth.getFullYear(), currentMonth.getMonth(), i),
83
- isCurrentMonth: true,
84
- })
85
- }
86
-
87
- // Next month days to fill the grid
88
- const remainingDays = 42 - days.length // 6 rows * 7 days
89
- const nextMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
90
- for (let i = 1; i <= remainingDays; i++) {
91
- days.push({
92
- date: new Date(nextMonth.getFullYear(), nextMonth.getMonth(), i),
93
- isCurrentMonth: false,
94
- })
95
- }
96
-
97
- return days
98
- }
99
-
100
- function previousMonth() {
101
- currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
102
- }
103
-
104
- function nextMonth() {
105
- currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
106
- }
107
-
108
- function selectDate(date) {
109
- if (isDisabled(date)) return
110
- selectedDate = date
111
- onChange?.(date)
112
- }
113
-
114
- function goToToday() {
115
- currentMonth = new Date(today)
116
- selectDate(today)
117
- }
118
-
119
- // Base classes
120
- const baseClasses = 'bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 w-full max-w-sm'
121
- const calendarClasses = `${baseClasses} ${className}`.trim()
122
-
123
- const headerClasses = 'flex items-center justify-between mb-4'
124
- const monthYearClasses = 'text-lg font-semibold text-gray-900 dark:text-gray-100'
125
- const buttonClasses = 'p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors'
126
-
127
- const weekdaysClasses = 'grid grid-cols-7 gap-1 mb-2'
128
- const weekdayClasses = 'text-center text-xs font-medium text-gray-600 dark:text-gray-400 py-2'
129
-
130
- const daysGridClasses = 'grid grid-cols-7 gap-1'
131
-
132
- function getDayClasses(day) {
133
- const base = 'flex items-center justify-center h-10 w-10 rounded-md text-sm transition-colors'
134
- const isSelected = isSameDay(day.date, selectedDate)
135
- const isTodayDate = isToday(day.date)
136
- const disabled = isDisabled(day.date)
137
-
138
- let classes = base
139
-
140
- if (!day.isCurrentMonth) {
141
- classes += ' text-gray-400 dark:text-gray-600'
142
- } else {
143
- classes += ' text-gray-900 dark:text-gray-100'
144
- }
145
-
146
- if (disabled) {
147
- classes += ' opacity-50 cursor-not-allowed'
148
- } else {
149
- classes += ' cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700'
150
- }
151
-
152
- if (isSelected) {
153
- classes += ' bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600'
154
- }
155
-
156
- if (isTodayDate && highlightToday && !isSelected) {
157
- classes += ' border-2 border-blue-600 dark:border-blue-400'
158
- }
159
-
160
- return classes
161
- }
162
-
163
- const dayNames = getDayNames()
164
- const calendarDays = getCalendarDays()
165
- </script>
166
-
167
- <div class="{{ calendarClasses }}">
168
- <!-- Header -->
169
- <div class="{{ headerClasses }}">
170
- <button
171
- type="button"
172
- class="{{ buttonClasses }}"
173
- @click="previousMonth()"
174
- aria-label="Previous month"
175
- >
176
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
177
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
178
- </svg>
179
- </button>
180
-
181
- <div class="{{ monthYearClasses }}">
182
- {{ getMonthName(currentMonth) }} {{ getYear(currentMonth) }}
183
- </div>
184
-
185
- <button
186
- type="button"
187
- class="{{ buttonClasses }}"
188
- @click="nextMonth()"
189
- aria-label="Next month"
190
- >
191
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
192
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
193
- </svg>
194
- </button>
195
- </div>
196
-
197
- <!-- Weekday names -->
198
- <div class="{{ weekdaysClasses }}">
199
- @foreach(dayNames as day)
200
- <div class="{{ weekdayClasses }}">{{ day }}</div>
201
- @endforeach
202
- </div>
203
-
204
- <!-- Calendar grid -->
205
- <div class="{{ daysGridClasses }}">
206
- @foreach(calendarDays as day)
207
- <button
208
- type="button"
209
- class="{{ getDayClasses(day) }}"
210
- @click="selectDate(day.date)"
211
- aria-label="{{ day.date.toLocaleDateString(locale) }}"
212
- @if(isDisabled(day.date))
213
- disabled
214
- @endif
215
- >
216
- {{ day.date.getDate() }}
217
- </button>
218
- @endforeach
219
- </div>
220
-
221
- @if(showToday)
222
- <div class="mt-4 flex justify-center">
223
- <button
224
- type="button"
225
- class="px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-gray-700 rounded-md transition-colors"
226
- @click="goToToday()"
227
- >
228
- Today
229
- </button>
230
- </div>
231
- @endif
232
- </div>
@@ -1,13 +0,0 @@
1
- <script server>
2
- export const value = $props.value
3
- export const onChange = $props.onChange
4
- export const className = $props.className || ''
5
- export const as = $props.as || 'div'
6
-
7
- const baseClasses = 'relative'
8
- const comboboxClasses = `${baseClasses} ${className}`.trim()
9
- </script>
10
-
11
- <component :is="{{ as }}" class="{{ comboboxClasses }}">
12
- <slot :value="value" :onChange="onChange" />
13
- </component>
@@ -1,52 +0,0 @@
1
- <script server>
2
- export const value = $props.value
3
- export const disabled = $props.disabled || false
4
- export const className = $props.className || ''
5
- export const as = $props.as || 'li'
6
- export const currentValue = $props.currentValue
7
- export const onChange = $props.onChange
8
-
9
- export let active = false
10
- export const selected = currentValue === value
11
-
12
- const baseClasses = 'relative cursor-pointer select-none py-2 pl-10 pr-4'
13
- const stateClasses = active
14
- ? 'bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100'
15
- : 'text-neutral-900 dark:text-neutral-100'
16
- const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
17
- const optionClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${className}`.trim()
18
-
19
- export function handleClick() {
20
- if (disabled) return
21
- onChange?.(value)
22
- }
23
-
24
- export function handleMouseEnter() {
25
- if (!disabled) active = true
26
- }
27
-
28
- export function handleMouseLeave() {
29
- active = false
30
- }
31
- </script>
32
-
33
- <component
34
- :is="{{ as }}"
35
- class="{{ optionClasses }}"
36
- role="option"
37
- aria-selected="{{ selected ? 'true' : 'false' }}"
38
- @if(disabled)aria-disabled="true"@endif
39
- @click="handleClick"
40
- @mouseenter="handleMouseEnter"
41
- @mouseleave="handleMouseLeave"
42
- >
43
- @if(selected)
44
- <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600 dark:text-blue-400">
45
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
46
- <path fill-rule="evenodd" 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" clip-rule="evenodd" />
47
- </svg>
48
- </span>
49
- @endif
50
-
51
- <slot :active="active" :selected="selected" :disabled="disabled" />
52
- </component>
@@ -1,39 +0,0 @@
1
- <script server>
2
- export const open = $props.open || false
3
- export const onClose = $props.onClose
4
- export const query = $props.query || ''
5
- export const onQueryChange = $props.onQueryChange
6
- export const className = $props.className || ''
7
-
8
- const baseClasses = 'fixed inset-0 z-50 overflow-y-auto p-4 sm:p-6 md:p-20'
9
- const paletteClasses = `${baseClasses} ${className}`.trim()
10
-
11
- export function handleClose() {
12
- onClose?.()
13
- }
14
- </script>
15
-
16
- @if(open)
17
- <div class="{{ paletteClasses }}">
18
- <div class="fixed inset-0 bg-neutral-500 bg-opacity-25 dark:bg-opacity-50 transition-opacity" @click="handleClose" />
19
-
20
- <div class="mx-auto max-w-xl transform divide-y divide-neutral-100 dark:divide-neutral-800 overflow-hidden rounded-xl bg-white dark:bg-neutral-900 shadow-2xl ring-1 ring-black ring-opacity-5 transition-all">
21
- <div class="relative">
22
- <svg class="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-neutral-400" viewBox="0 0 20 20" fill="currentColor">
23
- <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" />
24
- </svg>
25
- <input
26
- type="text"
27
- class="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-neutral-900 dark:text-white placeholder-neutral-400 focus:ring-0 sm:text-sm"
28
- placeholder="Search..."
29
- value="{{ query }}"
30
- @input="(e) => onQueryChange?.(e.target.value)"
31
- />
32
- </div>
33
-
34
- <div class="max-h-96 overflow-y-auto py-2">
35
- <slot :query="query" />
36
- </div>
37
- </div>
38
- </div>
39
- @endif
@@ -1,32 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const onClick = $props.onClick
4
- export let active = false
5
-
6
- const baseClasses = 'flex cursor-pointer select-none items-center px-4 py-2'
7
- const activeClasses = active
8
- ? 'bg-blue-600 text-white'
9
- : 'text-neutral-900 dark:text-neutral-100'
10
- const itemClasses = `${baseClasses} ${activeClasses} ${className}`.trim()
11
-
12
- export function handleClick() {
13
- onClick?.()
14
- }
15
-
16
- export function handleMouseEnter() {
17
- active = true
18
- }
19
-
20
- export function handleMouseLeave() {
21
- active = false
22
- }
23
- </script>
24
-
25
- <div
26
- class="{{ itemClasses }}"
27
- @click="handleClick"
28
- @mouseenter="handleMouseEnter"
29
- @mouseleave="handleMouseLeave"
30
- >
31
- <slot :active="active" />
32
- </div>
@@ -1,19 +0,0 @@
1
- <script server>
2
- export const open = $props.open || false
3
- export const onClose = $props.onClose
4
- export const className = $props.className || ''
5
- export const as = $props.as || 'div'
6
-
7
- const baseClasses = 'relative z-50'
8
- const dialogClasses = `${baseClasses} ${className}`.trim()
9
-
10
- export function handleClose() {
11
- onClose?.(false)
12
- }
13
- </script>
14
-
15
- @if(open)
16
- <div class="{{ dialogClasses }}" role="dialog" aria-modal="true">
17
- <slot />
18
- </div>
19
- @endif
@@ -1,24 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
- export let isOpen = false
5
-
6
- export function toggle() {
7
- isOpen = !isOpen
8
- }
9
-
10
- export function close() {
11
- isOpen = false
12
- }
13
-
14
- export function open() {
15
- isOpen = true
16
- }
17
-
18
- const baseClasses = 'relative inline-block text-left'
19
- const dropdownClasses = `${baseClasses} ${className}`.trim()
20
- </script>
21
-
22
- <component :is="{{ as }}" class="{{ dropdownClasses }}">
23
- <slot :isOpen="isOpen" :toggle="toggle" :close="close" :open="open" />
24
- </component>
@@ -1,43 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
- export const disabled = $props.disabled || false
5
- export const onClick = $props.onClick
6
-
7
- export let active = false
8
-
9
- const baseClasses = 'group flex w-full items-center px-2 py-2 text-sm transition-colors'
10
- const stateClasses = active
11
- ? 'bg-blue-500 text-white dark:bg-blue-600'
12
- : 'text-neutral-900 dark:text-neutral-100'
13
- const disabledClasses = disabled
14
- ? 'opacity-50 cursor-not-allowed'
15
- : 'cursor-pointer'
16
-
17
- const itemClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${className}`.trim()
18
-
19
- export function handleClick(e) {
20
- if (disabled) return
21
- onClick?.(e)
22
- }
23
-
24
- export function handleMouseEnter() {
25
- if (!disabled) active = true
26
- }
27
-
28
- export function handleMouseLeave() {
29
- active = false
30
- }
31
- </script>
32
-
33
- <component
34
- :is="{{ as }}"
35
- class="{{ itemClasses }}"
36
- role="menuitem"
37
- @if(disabled)aria-disabled="true"@endif
38
- @click="handleClick"
39
- @mouseenter="handleMouseEnter"
40
- @mouseleave="handleMouseLeave"
41
- >
42
- <slot :active="active" :disabled="disabled" />
43
- </component>
@@ -1,41 +0,0 @@
1
- <script server>
2
- export const value = $props.value || ''
3
- export const onChange = $props.onChange || (() => {})
4
- export const placeholder = $props.placeholder || 'Enter your email'
5
- export const disabled = $props.disabled || false
6
- export const readonly = $props.readonly || false
7
- export const size = $props.size || 'md'
8
- export const error = $props.error || false
9
- export const label = $props.label || ''
10
- export const helperText = $props.helperText || ''
11
- export const required = $props.required || false
12
- export const className = $props.className || ''
13
-
14
- // Email icon SVG
15
- const emailIcon = '<svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></svg>'
16
- </script>
17
-
18
- @component('TextInput', {
19
- value,
20
- onChange,
21
- placeholder,
22
- disabled,
23
- readonly,
24
- size,
25
- error,
26
- label,
27
- helperText,
28
- required,
29
- leftIcon: emailIcon,
30
- clearable: true,
31
- className,
32
- inputClassName: 'font-mono'
33
- })
34
- @endcomponent
35
-
36
- <script>
37
- // Add additional email validation logic if needed
38
- function validateEmail(email) {
39
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
40
- }
41
- </script>