@stacksjs/components 0.2.35 → 0.2.54

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 +5 -5
  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,24 +1,82 @@
1
1
  <script server>
2
2
  export const className = $props.className || ''
3
3
  export const as = $props.as || 'div'
4
- export let isOpen = false
5
4
 
6
- export function toggle() {
7
- isOpen = !isOpen
5
+ const baseClasses = 'relative inline-block text-left'
6
+ export const dropdownClasses = `${baseClasses} ${className}`.trim()
7
+ export const dropdownInstanceId = `stx-dd-${Math.random().toString(36).slice(2, 11)}`
8
+ </script>
9
+
10
+ <script client>
11
+ const emit = defineEmits()
12
+ const dropdownInstanceId = {{ dropdownInstanceId }}
13
+ const isOpen = state(false)
14
+ let rootEl = null
15
+ let outsideHandler = null
16
+
17
+ function toggle() {
18
+ isOpen.set(!isOpen())
19
+ emit('change', isOpen())
8
20
  }
9
21
 
10
- export function close() {
11
- isOpen = false
22
+ function open() {
23
+ if (isOpen()) return
24
+ isOpen.set(true)
25
+ emit('change', true)
12
26
  }
13
27
 
14
- export function open() {
15
- isOpen = true
28
+ function close() {
29
+ if (!isOpen()) return
30
+ isOpen.set(false)
31
+ emit('change', false)
16
32
  }
17
33
 
18
- const baseClasses = 'relative inline-block text-left'
19
- const dropdownClasses = `${baseClasses} ${className}`.trim()
34
+ function onItemSelect(event) {
35
+ event.stopPropagation()
36
+ emit('select', event.detail)
37
+ close()
38
+ }
39
+
40
+ function onToggle(event) { event.stopPropagation(); toggle() }
41
+ function onOpen(event) { event.stopPropagation(); open() }
42
+ function onClose(event) { event.stopPropagation(); close() }
43
+
44
+ onMount(() => {
45
+ rootEl = document.querySelector(`[data-dropdown-id="${dropdownInstanceId}"]`)
46
+ outsideHandler = (event) => {
47
+ if (!isOpen()) return
48
+ if (rootEl && !rootEl.contains(event.target)) close()
49
+ }
50
+ document.addEventListener('click', outsideHandler, true)
51
+ })
52
+
53
+ onDestroy(() => {
54
+ if (outsideHandler) document.removeEventListener('click', outsideHandler, true)
55
+ })
56
+
57
+ const dataState = derived(() => isOpen() ? 'open' : 'closed')
58
+ const dataExpanded = derived(() => isOpen() ? 'true' : 'false')
59
+
60
+ defineExpose({ isOpen, toggle, open, close })
20
61
  </script>
21
62
 
22
- <component :is="{{ as }}" class="{{ dropdownClasses }}">
23
- <slot :isOpen="isOpen" :toggle="toggle" :close="close" :open="open" />
63
+ <component
64
+ :is="{{ as }}"
65
+ class="{{ dropdownClasses }}"
66
+ data-stx-dropdown
67
+ data-dropdown-id="{{ dropdownInstanceId }}"
68
+ :data-state="dataState()"
69
+ :data-expanded="dataExpanded()"
70
+ @stx:dropdown-toggle="onToggle($event)"
71
+ @stx:dropdown-open="onOpen($event)"
72
+ @stx:dropdown-close="onClose($event)"
73
+ @stx:dropdown-select="onItemSelect($event)"
74
+ >
75
+ <slot />
24
76
  </component>
77
+
78
+ <style>
79
+ [data-stx-dropdown][data-state="closed"] [data-stx-dropdown-items] {
80
+ display: none;
81
+ }
82
+ </style>
@@ -2,22 +2,28 @@
2
2
  export const className = $props.className || ''
3
3
  export const as = $props.as || 'button'
4
4
  export const disabled = $props.disabled || false
5
- export const onClick = $props.onClick
6
5
 
7
6
  const baseClasses = 'inline-flex justify-center items-center rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75'
8
- const buttonClasses = `${baseClasses} ${className}`.trim()
7
+ export const buttonClasses = `${baseClasses} ${className}`.trim()
8
+ </script>
9
+
10
+ <script client>
11
+ const emit = defineEmits()
12
+ const isDisabled = {{ disabled }}
9
13
 
10
- export function handleClick(e) {
11
- if (disabled) return
12
- onClick?.(e)
14
+ function onClick(event) {
15
+ if (isDisabled) return
16
+ emit('click', event)
17
+ event.currentTarget.dispatchEvent(new CustomEvent('stx:dropdown-toggle', { bubbles: true }))
13
18
  }
14
19
  </script>
15
20
 
16
21
  <component
17
22
  :is="{{ as }}"
18
23
  class="{{ buttonClasses }}"
24
+ data-stx-dropdown-button
19
25
  @if(disabled)disabled aria-disabled="true"@endif
20
- @click="handleClick"
26
+ @click="onClick($event)"
21
27
  >
22
28
  <slot />
23
29
  </component>
@@ -2,42 +2,34 @@
2
2
  export const className = $props.className || ''
3
3
  export const as = $props.as || 'div'
4
4
  export const disabled = $props.disabled || false
5
- export const onClick = $props.onClick
5
+ export const value = $props.value
6
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
- }
7
+ const baseClasses = 'group flex w-full items-center px-2 py-2 text-sm transition-colors text-neutral-900 dark:text-neutral-100 hover:bg-blue-500 hover:text-white dark:hover:bg-blue-600'
8
+ const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
9
+ export const itemClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
10
+ </script>
23
11
 
24
- export function handleMouseEnter() {
25
- if (!disabled) active = true
26
- }
12
+ <script client>
13
+ const emit = defineEmits()
14
+ const isDisabled = {{ disabled }}
15
+ const itemValue = {{ value === undefined ? 'null' : value }}
27
16
 
28
- export function handleMouseLeave() {
29
- active = false
17
+ function onClick(event) {
18
+ if (isDisabled) return
19
+ emit('click', event)
20
+ event.currentTarget.dispatchEvent(
21
+ new CustomEvent('stx:dropdown-select', { bubbles: true, detail: itemValue }),
22
+ )
30
23
  }
31
24
  </script>
32
25
 
33
26
  <component
34
27
  :is="{{ as }}"
35
28
  class="{{ itemClasses }}"
29
+ data-stx-dropdown-item
36
30
  role="menuitem"
37
31
  @if(disabled)aria-disabled="true"@endif
38
- @click="handleClick"
39
- @mouseenter="handleMouseEnter"
40
- @mouseleave="handleMouseLeave"
32
+ @click="onClick($event)"
41
33
  >
42
- <slot :active="active" :disabled="disabled" />
34
+ <slot :disabled="disabled" />
43
35
  </component>
@@ -1,15 +1,15 @@
1
1
  <script server>
2
2
  export const className = $props.className || ''
3
3
  export const as = $props.as || 'div'
4
- export const static_ = $props.static || false
5
4
 
6
5
  const baseClasses = 'absolute z-10 mt-2 origin-top-right divide-y divide-neutral-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-neutral-800 dark:divide-neutral-700 dark:ring-neutral-600'
7
- const itemsClasses = `${baseClasses} ${className}`.trim()
6
+ export const itemsClasses = `${baseClasses} ${className}`.trim()
8
7
  </script>
9
8
 
10
9
  <component
11
10
  :is="{{ as }}"
12
11
  class="{{ itemsClasses }}"
12
+ data-stx-dropdown-items
13
13
  role="menu"
14
14
  aria-orientation="vertical"
15
15
  tabindex="-1"
@@ -2,208 +2,94 @@
2
2
  export const action = $props.action || ''
3
3
  export const method = $props.method || 'POST'
4
4
  export const validationSchema = $props.validationSchema || {}
5
- export const initialValues = $props.initialValues || {}
6
- export const validateOnChange = $props.validateOnChange ?? true
7
- export const validateOnBlur = $props.validateOnBlur ?? true
8
- export const onSubmit = $props.onSubmit
9
- export const onError = $props.onError
10
5
  export const className = $props.className || ''
11
6
 
12
- let values = { ...initialValues }
13
- let errors = {}
14
- let touched = {}
15
- let isSubmitting = false
16
- let isValidating = false
17
- let submitCount = 0
7
+ export const formClasses = `space-y-6 ${className}`.trim()
8
+ export const errorClasses = `mt-1 text-sm text-red-600 dark:text-red-400`.trim()
9
+ </script>
18
10
 
19
- // Validate a single field
20
- function validateField(name, value) {
21
- const fieldSchema = validationSchema[name]
22
- if (!fieldSchema)
23
- return null
11
+ <script client>
12
+ const emit = defineEmits()
13
+ const validationSchema = {{ validationSchema }}
24
14
 
25
- // Required validation
26
- if (fieldSchema.required && !value) {
27
- return fieldSchema.requiredMessage || `${name} is required`
28
- }
15
+ const errors = state({})
16
+ const isSubmitting = state(false)
17
+ const submitCount = state(0)
29
18
 
30
- // Min length validation
31
- if (fieldSchema.minLength && value.length < fieldSchema.minLength) {
32
- return fieldSchema.minLengthMessage || `${name} must be at least ${fieldSchema.minLength} characters`
19
+ function validateField(name, value, allValues) {
20
+ const schema = validationSchema[name]
21
+ if (!schema) return null
22
+ if (schema.required && !value) {
23
+ return schema.requiredMessage || `${name} is required`
33
24
  }
34
-
35
- // Max length validation
36
- if (fieldSchema.maxLength && value.length > fieldSchema.maxLength) {
37
- return fieldSchema.maxLengthMessage || `${name} must be at most ${fieldSchema.maxLength} characters`
25
+ if (schema.minLength && String(value).length < schema.minLength) {
26
+ return schema.minLengthMessage || `${name} must be at least ${schema.minLength} characters`
38
27
  }
39
-
40
- // Pattern validation
41
- if (fieldSchema.pattern && !fieldSchema.pattern.test(value)) {
42
- return fieldSchema.patternMessage || `${name} is invalid`
28
+ if (schema.maxLength && String(value).length > schema.maxLength) {
29
+ return schema.maxLengthMessage || `${name} must be at most ${schema.maxLength} characters`
43
30
  }
44
-
45
- // Custom validation
46
- if (fieldSchema.validate && typeof fieldSchema.validate === 'function') {
47
- return fieldSchema.validate(value, values)
31
+ if (schema.pattern && !new RegExp(schema.pattern).test(value)) {
32
+ return schema.patternMessage || `${name} is invalid`
48
33
  }
49
-
50
34
  return null
51
35
  }
52
36
 
53
- // Validate all fields
54
- function validateForm() {
55
- const newErrors = {}
56
- let isValid = true
57
-
58
- Object.keys(validationSchema).forEach((name) => {
59
- const error = validateField(name, values[name])
60
- if (error) {
61
- newErrors[name] = error
62
- isValid = false
63
- }
64
- })
65
-
66
- errors = newErrors
67
- return isValid
68
- }
69
-
70
- // Handle field change
71
- function handleChange(event) {
72
- const { name, value } = event.target
73
- values[name] = value
74
-
75
- if (validateOnChange && touched[name]) {
76
- const error = validateField(name, value)
77
- if (error) {
78
- errors[name] = error
79
- }
80
- else {
81
- delete errors[name]
82
- }
83
- }
84
- }
85
-
86
- // Handle field blur
87
- function handleBlur(event) {
88
- const { name } = event.target
89
- touched[name] = true
90
-
91
- if (validateOnBlur) {
92
- const error = validateField(name, values[name])
93
- if (error) {
94
- errors[name] = error
95
- }
96
- else {
97
- delete errors[name]
37
+ function validateForm(values) {
38
+ const next = {}
39
+ let valid = true
40
+ for (const name of Object.keys(validationSchema)) {
41
+ const err = validateField(name, values[name], values)
42
+ if (err) {
43
+ next[name] = err
44
+ valid = false
98
45
  }
99
46
  }
47
+ errors.set(next)
48
+ return valid
100
49
  }
101
50
 
102
- // Handle form submission
103
- async function handleSubmit(event) {
51
+ async function onSubmit(event) {
104
52
  event.preventDefault()
105
- submitCount++
106
-
107
- // Mark all fields as touched
108
- Object.keys(validationSchema).forEach((name) => {
109
- touched[name] = true
110
- })
53
+ submitCount.set(submitCount() + 1)
111
54
 
112
- // Validate
113
- isValidating = true
114
- const isValid = validateForm()
115
- isValidating = false
55
+ const formData = new FormData(event.target)
56
+ const values = {}
57
+ for (const [k, v] of formData.entries()) values[k] = v
116
58
 
117
- if (!isValid) {
118
- if (onError) {
119
- onError(errors)
120
- }
59
+ if (!validateForm(values)) {
60
+ emit('error', errors())
121
61
  return
122
62
  }
123
63
 
124
- // Submit
125
- isSubmitting = true
126
-
64
+ isSubmitting.set(true)
127
65
  try {
128
- if (onSubmit) {
129
- await onSubmit(values, { setErrors, setValues, resetForm })
130
- }
131
- }
132
- catch (error) {
133
- if (onError) {
134
- onError(error)
135
- }
66
+ emit('submit', values)
136
67
  }
137
68
  finally {
138
- isSubmitting = false
69
+ isSubmitting.set(false)
139
70
  }
140
71
  }
141
72
 
142
- // Helper functions
143
- function setErrors(newErrors) {
144
- errors = { ...errors, ...newErrors }
145
- }
146
-
147
- function setValues(newValues) {
148
- values = { ...values, ...newValues }
73
+ function setErrors(next) {
74
+ errors.set({ ...errors(), ...next })
149
75
  }
150
76
 
151
- function resetForm() {
152
- values = { ...initialValues }
153
- errors = {}
154
- touched = {}
155
- isSubmitting = false
156
- submitCount = 0
77
+ function reset(form) {
78
+ errors.set({})
79
+ isSubmitting.set(false)
80
+ submitCount.set(0)
81
+ if (form?.reset) form.reset()
157
82
  }
158
83
 
159
- function getFieldProps(name) {
160
- return {
161
- name,
162
- value: values[name] || '',
163
- error: errors[name],
164
- touched: touched[name],
165
- onChange: handleChange,
166
- onBlur: handleBlur,
167
- }
168
- }
169
-
170
- export const formClasses = `space-y-6 ${className}`.trim()
171
- export const errorClasses = `mt-1 text-sm text-red-600 dark:text-red-400`.trim()
84
+ defineExpose({ errors, isSubmitting, submitCount, setErrors, reset, validateForm })
172
85
  </script>
173
86
 
174
87
  <form
175
88
  class="{{ formClasses }}"
176
89
  @if(action)action="{{ action }}"@endif
177
90
  method="{{ method }}"
178
- onsubmit="handleSubmit(event)"
91
+ @submit="onSubmit($event)"
179
92
  novalidate
180
93
  >
181
- <slot
182
- values="{{ values }}"
183
- errors="{{ errors }}"
184
- touched="{{ touched }}"
185
- isSubmitting="{{ isSubmitting }}"
186
- isValidating="{{ isValidating }}"
187
- submitCount="{{ submitCount }}"
188
- getFieldProps="{{ getFieldProps }}"
189
- setErrors="{{ setErrors }}"
190
- setValues="{{ setValues }}"
191
- resetForm="{{ resetForm }}"
192
- />
94
+ <slot />
193
95
  </form>
194
-
195
- <script>
196
- // Export context for child components
197
- if (typeof window !== 'undefined') {
198
- window.__formContext = {
199
- values,
200
- errors,
201
- touched,
202
- isSubmitting,
203
- isValidating,
204
- getFieldProps,
205
- handleChange,
206
- handleBlur,
207
- }
208
- }
209
- </script>
@@ -1,46 +1,25 @@
1
- <script>
2
- /**
3
- * Heatmap Component
4
- *
5
- * A privacy-compliant heatmap visualization component that displays user interaction data.
6
- * Can be used to show click heatmaps, movement heatmaps, or scroll depth visualizations.
7
- *
8
- * Props:
9
- * @prop {string} id - Unique identifier for the heatmap container
10
- * @prop {string} mode - Visualization mode: 'overlay' | 'standalone' | 'thumbnail' (default: 'overlay')
11
- * @prop {number} width - Width in pixels (default: 100% of container)
12
- * @prop {number} height - Height in pixels (default: 100% of container)
13
- * @prop {number} radius - Heat point radius (default: 20)
14
- * @prop {number} blur - Blur amount for heatmap (default: 15)
15
- * @prop {number} opacity - Maximum opacity (default: 0.6)
16
- * @prop {boolean} showLegend - Show color legend (default: true)
17
- * @prop {boolean} interactive - Enable zoom/pan interactions (default: false)
18
- * @prop {string} dataSource - Source of data: 'auto' | 'manual' | 'endpoint' (default: 'auto')
19
- * @prop {string} endpoint - API endpoint for fetching heatmap data
20
- * @prop {string} colorScheme - Color scheme: 'default' | 'fire' | 'cool' | 'grayscale' (default: 'default')
21
- */
22
- const id = props.id || 'stx-heatmap-' + Math.random().toString(36).slice(2, 8)
23
- const mode = props.mode || 'overlay'
24
- const width = props.width || null
25
- const height = props.height || null
26
- const radius = props.radius || 20
27
- const blur = props.blur || 15
28
- const opacity = props.opacity || 0.6
29
- const showLegend = props.showLegend !== false
30
- const interactive = props.interactive || false
31
- const dataSource = props.dataSource || 'auto'
32
- const endpoint = props.endpoint || ''
33
- const colorScheme = props.colorScheme || 'default'
34
-
35
- // Color schemes
1
+ <script server>
2
+ export const id = $props.id || `stx-heatmap-${Math.random().toString(36).slice(2, 8)}`
3
+ export const mode = $props.mode || 'overlay'
4
+ export const width = $props.width || null
5
+ export const height = $props.height || null
6
+ export const radius = $props.radius || 20
7
+ export const blur = $props.blur || 15
8
+ export const opacity = $props.opacity || 0.6
9
+ export const showLegend = $props.showLegend !== false
10
+ export const interactive = $props.interactive || false
11
+ export const dataSource = $props.dataSource || 'auto'
12
+ export const endpoint = $props.endpoint || ''
13
+ export const colorScheme = $props.colorScheme || 'default'
14
+
36
15
  const colorSchemes = {
37
16
  default: ['#0000ff', '#00ffff', '#00ff00', '#ffff00', '#ff0000'],
38
17
  fire: ['#000000', '#ff0000', '#ffff00', '#ffffff'],
39
18
  cool: ['#000033', '#0066ff', '#00ccff', '#ffffff'],
40
- grayscale: ['#000000', '#444444', '#888888', '#cccccc', '#ffffff']
19
+ grayscale: ['#000000', '#444444', '#888888', '#cccccc', '#ffffff'],
41
20
  }
42
21
 
43
- const colors = colorSchemes[colorScheme] || colorSchemes.default
22
+ export const colors = colorSchemes[colorScheme] || colorSchemes.default
44
23
  </script>
45
24
 
46
25
  <div