@stacksjs/components 0.2.92 → 0.2.94

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 (188) hide show
  1. package/dist/{Sidebar-yb115a2w.stx → Sidebar-4hn7vw4n.stx} +18 -0
  2. package/dist/index.js +5 -5
  3. package/package.json +5 -6
  4. package/src/components/CodeBlock.stx +0 -54
  5. package/src/components/Footer.stx +0 -66
  6. package/src/components/Hero.stx +0 -25
  7. package/src/components/Installation.stx +0 -37
  8. package/src/components/index.ts +0 -4
  9. package/src/composables/index.ts +0 -4
  10. package/src/composables/useCopyCode.ts +0 -73
  11. package/src/composables/useDarkMode.ts +0 -100
  12. package/src/composables/useSEO.ts +0 -230
  13. package/src/composables/utilities/index.ts +0 -7
  14. package/src/composables/utilities/useClickOutside.ts +0 -72
  15. package/src/composables/utilities/useFocusTrap.ts +0 -159
  16. package/src/composables/utilities/useKeyboard.ts +0 -124
  17. package/src/composables/utilities/useLocalStorage.ts +0 -132
  18. package/src/composables/utilities/useMediaQuery.ts +0 -118
  19. package/src/index.ts +0 -99
  20. package/src/stx.d.ts +0 -4
  21. package/src/ui/accordion/Accordion.stx +0 -146
  22. package/src/ui/accordion/AccordionItem.stx +0 -37
  23. package/src/ui/accordion/index.ts +0 -47
  24. package/src/ui/audio/Audio.stx +0 -50
  25. package/src/ui/audio/README.md +0 -41
  26. package/src/ui/audio/index.ts +0 -13
  27. package/src/ui/auth/Login.stx +0 -161
  28. package/src/ui/auth/README.md +0 -142
  29. package/src/ui/auth/Signup.stx +0 -159
  30. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  31. package/src/ui/auth/index.ts +0 -32
  32. package/src/ui/avatar/Avatar.stx +0 -77
  33. package/src/ui/avatar/index.ts +0 -12
  34. package/src/ui/badge/Badge.stx +0 -62
  35. package/src/ui/badge/index.ts +0 -10
  36. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  37. package/src/ui/breadcrumb/index.ts +0 -15
  38. package/src/ui/button/Button.stx +0 -74
  39. package/src/ui/button/README.md +0 -80
  40. package/src/ui/button/index.ts +0 -85
  41. package/src/ui/calendar/Calendar.stx +0 -189
  42. package/src/ui/calendar/README.md +0 -254
  43. package/src/ui/calendar/index.ts +0 -14
  44. package/src/ui/card/Card.stx +0 -68
  45. package/src/ui/card/index.ts +0 -13
  46. package/src/ui/checkbox/Checkbox.stx +0 -86
  47. package/src/ui/checkbox/index.ts +0 -16
  48. package/src/ui/combobox/Combobox.stx +0 -96
  49. package/src/ui/combobox/ComboboxButton.stx +0 -25
  50. package/src/ui/combobox/ComboboxInput.stx +0 -32
  51. package/src/ui/combobox/ComboboxOption.stx +0 -49
  52. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  53. package/src/ui/combobox/README.md +0 -150
  54. package/src/ui/combobox/index.ts +0 -40
  55. package/src/ui/command-palette/CommandPalette.stx +0 -81
  56. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  57. package/src/ui/command-palette/README.md +0 -42
  58. package/src/ui/command-palette/index.ts +0 -15
  59. package/src/ui/dialog/Dialog.stx +0 -41
  60. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  61. package/src/ui/dialog/DialogDescription.stx +0 -11
  62. package/src/ui/dialog/DialogPanel.stx +0 -16
  63. package/src/ui/dialog/DialogTitle.stx +0 -11
  64. package/src/ui/dialog/README.md +0 -121
  65. package/src/ui/dialog/index.ts +0 -32
  66. package/src/ui/drawer/Drawer.stx +0 -120
  67. package/src/ui/drawer/README.md +0 -90
  68. package/src/ui/drawer/index.ts +0 -9
  69. package/src/ui/dropdown/Dropdown.stx +0 -82
  70. package/src/ui/dropdown/DropdownButton.stx +0 -29
  71. package/src/ui/dropdown/DropdownItem.stx +0 -35
  72. package/src/ui/dropdown/DropdownItems.stx +0 -18
  73. package/src/ui/dropdown/README.md +0 -114
  74. package/src/ui/dropdown/index.ts +0 -29
  75. package/src/ui/form/Form.stx +0 -95
  76. package/src/ui/form/index.ts +0 -67
  77. package/src/ui/heatmap/Heatmap.stx +0 -294
  78. package/src/ui/image/Image.stx +0 -165
  79. package/src/ui/image/README.md +0 -164
  80. package/src/ui/image/index.ts +0 -22
  81. package/src/ui/input/EmailInput.stx +0 -30
  82. package/src/ui/input/NumberInput.stx +0 -126
  83. package/src/ui/input/PasswordInput.stx +0 -143
  84. package/src/ui/input/SearchInput.stx +0 -44
  85. package/src/ui/input/TextInput.stx +0 -132
  86. package/src/ui/input/index.ts +0 -180
  87. package/src/ui/listbox/Listbox.stx +0 -101
  88. package/src/ui/listbox/ListboxButton.stx +0 -28
  89. package/src/ui/listbox/ListboxLabel.stx +0 -11
  90. package/src/ui/listbox/ListboxOption.stx +0 -49
  91. package/src/ui/listbox/ListboxOptions.stx +0 -16
  92. package/src/ui/listbox/README.md +0 -135
  93. package/src/ui/listbox/index.ts +0 -39
  94. package/src/ui/navigator/Navigator.stx +0 -113
  95. package/src/ui/navigator/README.md +0 -352
  96. package/src/ui/navigator/index.ts +0 -20
  97. package/src/ui/notification/Notification.stx +0 -117
  98. package/src/ui/notification/README.md +0 -114
  99. package/src/ui/notification/index.ts +0 -12
  100. package/src/ui/pagination/Pagination.stx +0 -150
  101. package/src/ui/pagination/index.ts +0 -11
  102. package/src/ui/payment/Checkout.stx +0 -31
  103. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  104. package/src/ui/payment/PaymentMethods.stx +0 -104
  105. package/src/ui/payment/README.md +0 -345
  106. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  107. package/src/ui/payment/index.ts +0 -59
  108. package/src/ui/popover/Popover.stx +0 -60
  109. package/src/ui/popover/PopoverButton.stx +0 -29
  110. package/src/ui/popover/PopoverPanel.stx +0 -23
  111. package/src/ui/popover/README.md +0 -91
  112. package/src/ui/popover/index.ts +0 -22
  113. package/src/ui/portal/Portal.stx +0 -57
  114. package/src/ui/portal/index.ts +0 -6
  115. package/src/ui/progress/Progress.stx +0 -131
  116. package/src/ui/progress/index.ts +0 -12
  117. package/src/ui/radio/Radio.stx +0 -77
  118. package/src/ui/radio/index.ts +0 -15
  119. package/src/ui/radio-group/README.md +0 -139
  120. package/src/ui/radio-group/RadioGroup.stx +0 -60
  121. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  123. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  124. package/src/ui/radio-group/index.ts +0 -30
  125. package/src/ui/select/README.md +0 -180
  126. package/src/ui/select/Select.stx +0 -82
  127. package/src/ui/select/index.ts +0 -21
  128. package/src/ui/sidebar/Sidebar.stx +0 -458
  129. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  130. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  131. package/src/ui/sidebar/SidebarItem.stx +0 -86
  132. package/src/ui/sidebar/SidebarSection.stx +0 -83
  133. package/src/ui/sidebar/index.ts +0 -153
  134. package/src/ui/sidebar/themes.ts +0 -240
  135. package/src/ui/skeleton/Skeleton.stx +0 -48
  136. package/src/ui/skeleton/index.ts +0 -11
  137. package/src/ui/spinner/Spinner.stx +0 -109
  138. package/src/ui/spinner/index.ts +0 -9
  139. package/src/ui/stepper/README.md +0 -36
  140. package/src/ui/stepper/Stepper.stx +0 -17
  141. package/src/ui/stepper/StepperStep.stx +0 -57
  142. package/src/ui/stepper/index.ts +0 -19
  143. package/src/ui/storage/README.md +0 -193
  144. package/src/ui/storage/index.ts +0 -347
  145. package/src/ui/switch/README.md +0 -114
  146. package/src/ui/switch/Switch.stx +0 -72
  147. package/src/ui/switch/index.ts +0 -10
  148. package/src/ui/table/README.md +0 -39
  149. package/src/ui/table/Table.stx +0 -14
  150. package/src/ui/table/TableBody.stx +0 -10
  151. package/src/ui/table/TableCell.stx +0 -10
  152. package/src/ui/table/TableHead.stx +0 -10
  153. package/src/ui/table/TableHeader.stx +0 -20
  154. package/src/ui/table/TableRow.stx +0 -11
  155. package/src/ui/table/index.ts +0 -35
  156. package/src/ui/tabs/TabPanel.stx +0 -25
  157. package/src/ui/tabs/Tabs.stx +0 -202
  158. package/src/ui/tabs/index.ts +0 -50
  159. package/src/ui/teleport/Teleport.stx +0 -65
  160. package/src/ui/teleport/index.ts +0 -7
  161. package/src/ui/textarea/Textarea.stx +0 -108
  162. package/src/ui/textarea/index.ts +0 -20
  163. package/src/ui/tooltip/Tooltip.stx +0 -71
  164. package/src/ui/tooltip/index.ts +0 -10
  165. package/src/ui/transition/README.md +0 -30
  166. package/src/ui/transition/Transition.stx +0 -102
  167. package/src/ui/transition/index.ts +0 -25
  168. package/src/ui/video/README.md +0 -47
  169. package/src/ui/video/Video.stx +0 -45
  170. package/src/ui/video/index.ts +0 -16
  171. package/src/ui/virtual-list/VirtualList.stx +0 -67
  172. package/src/ui/virtual-list/index.ts +0 -10
  173. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  174. package/src/ui/virtual-table/index.ts +0 -21
  175. package/src/utils/PROP_VALIDATION.md +0 -458
  176. package/src/utils/THEME_SYSTEM.md +0 -702
  177. package/src/utils/accessibility.ts +0 -841
  178. package/src/utils/animation/easing.ts +0 -368
  179. package/src/utils/animation/helpers.ts +0 -223
  180. package/src/utils/animation/index.ts +0 -5
  181. package/src/utils/animation/keyframes.ts +0 -230
  182. package/src/utils/error-handling.ts +0 -475
  183. package/src/utils/highlighter.ts +0 -93
  184. package/src/utils/i18n.ts +0 -634
  185. package/src/utils/keep-alive.ts +0 -819
  186. package/src/utils/lazy-loading.ts +0 -530
  187. package/src/utils/prop-validation.ts +0 -478
  188. package/src/utils/theme.ts +0 -626
@@ -1,121 +0,0 @@
1
- # Dialog Component
2
-
3
- A modal dialog component for overlays, alerts, and confirmations. Built with STX and headwind.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let isOpen = false
16
-
17
- function closeModal() {
18
- isOpen = false
19
- }
20
-
21
- function openModal() {
22
- isOpen = true
23
- }
24
- </script>
25
-
26
- <Dialog :open="isOpen" :onClose="closeModal">
27
- <DialogBackdrop />
28
-
29
- <DialogPanel className="max-w-md">
30
- <DialogTitle>Payment successful</DialogTitle>
31
-
32
- <DialogDescription>
33
- Your payment has been successfully submitted.
34
- </DialogDescription>
35
-
36
- <div class="mt-4">
37
- <Button :onClick="closeModal">Got it, thanks!</Button>
38
- </div>
39
- </DialogPanel>
40
- </Dialog>
41
- ```
42
-
43
- ## Props
44
-
45
- ### Dialog
46
- | Prop | Type | Default | Description |
47
- |------|------|---------|-------------|
48
- | `open` | `boolean` | `false` | Whether dialog is open |
49
- | `onClose` | `(value: boolean) => void` | - | Close handler |
50
- | `className` | `string` | `''` | Additional CSS classes |
51
- | `as` | `string` | `'div'` | HTML element to render |
52
-
53
- ### DialogBackdrop
54
- | Prop | Type | Default | Description |
55
- |------|------|---------|-------------|
56
- | `className` | `string` | `''` | Additional CSS classes |
57
- | `as` | `string` | `'div'` | HTML element to render |
58
-
59
- ### DialogPanel
60
- | Prop | Type | Default | Description |
61
- |------|------|---------|-------------|
62
- | `className` | `string` | `''` | Additional CSS classes |
63
- | `as` | `string` | `'div'` | HTML element to render |
64
-
65
- ### DialogTitle
66
- | Prop | Type | Default | Description |
67
- |------|------|---------|-------------|
68
- | `className` | `string` | `''` | Additional CSS classes |
69
- | `as` | `string` | `'h3'` | HTML element to render |
70
-
71
- ### DialogDescription
72
- | Prop | Type | Default | Description |
73
- |------|------|---------|-------------|
74
- | `className` | `string` | `''` | Additional CSS classes |
75
- | `as` | `string` | `'p'` | HTML element to render |
76
-
77
- ## Examples
78
-
79
- ### Confirmation Dialog
80
-
81
- ```stx
82
- <Dialog :open="isOpen" :onClose="closeModal">
83
- <DialogBackdrop />
84
-
85
- <DialogPanel className="max-w-md">
86
- <DialogTitle>Delete account</DialogTitle>
87
-
88
- <DialogDescription>
89
- Are you sure you want to delete your account? This action cannot be undone.
90
- </DialogDescription>
91
-
92
- <div class="mt-4 flex gap-2">
93
- <Button variant="danger" :onClick="handleDelete">Delete</Button>
94
- <Button variant="secondary" :onClick="closeModal">Cancel</Button>
95
- </div>
96
- </DialogPanel>
97
- </Dialog>
98
- ```
99
-
100
- ### Large Dialog
101
-
102
- ```stx
103
- <DialogPanel className="max-w-4xl">
104
- <DialogTitle>Terms and Conditions</DialogTitle>
105
-
106
- <div class="mt-4 max-h-96 overflow-y-auto">
107
- <!-- Long content -->
108
- </div>
109
- </DialogPanel>
110
- ```
111
-
112
- ## Features
113
-
114
- - Focus trap
115
- - Backdrop overlay
116
- - Keyboard support (ESC to close)
117
- - Dark mode support
118
- - Accessible (WAI-ARIA)
119
- - Customizable with headwind classes
120
- - Multiple sizes
121
- - Scrollable content support
@@ -1,32 +0,0 @@
1
- export { default as Dialog } from './Dialog.stx'
2
- export { default as DialogBackdrop } from './DialogBackdrop.stx'
3
- export { default as DialogDescription } from './DialogDescription.stx'
4
- export { default as DialogPanel } from './DialogPanel.stx'
5
- export { default as DialogTitle } from './DialogTitle.stx'
6
-
7
- export interface DialogProps {
8
- open?: boolean
9
- onClose?: (value: boolean) => void
10
- className?: string
11
- as?: string
12
- }
13
-
14
- export interface DialogBackdropProps {
15
- className?: string
16
- as?: string
17
- }
18
-
19
- export interface DialogPanelProps {
20
- className?: string
21
- as?: string
22
- }
23
-
24
- export interface DialogTitleProps {
25
- className?: string
26
- as?: string
27
- }
28
-
29
- export interface DialogDescriptionProps {
30
- className?: string
31
- as?: string
32
- }
@@ -1,120 +0,0 @@
1
- <script server>
2
- export const open = $props.open ?? false
3
- export const position = $props.position || 'right'
4
- export const title = $props.title || ''
5
- export const className = $props.className || ''
6
-
7
- const positionClasses = {
8
- right: 'inset-y-0 right-0 pl-10 sm:pl-16',
9
- left: 'inset-y-0 left-0 pr-10 sm:pr-16',
10
- top: 'inset-x-0 top-0 pb-10',
11
- bottom: 'inset-x-0 bottom-0 pt-10',
12
- }
13
-
14
- const sizeClasses = {
15
- right: 'max-w-md w-screen',
16
- left: 'max-w-md w-screen',
17
- top: 'max-h-[90vh] w-full',
18
- bottom: 'max-h-[90vh] w-full',
19
- }
20
-
21
- const closeButtonPosition = {
22
- right: 'left-0 -ml-8 sm:-ml-10',
23
- left: 'right-0 -mr-8 sm:-mr-10',
24
- top: 'right-0 -mr-8',
25
- bottom: 'right-0 -mr-8',
26
- }
27
-
28
- export const containerClasses = `pointer-events-none fixed ${positionClasses[position]} flex max-w-full`.trim()
29
- export const panelClasses = `pointer-events-auto relative ${sizeClasses[position]} ${className}`.trim()
30
- export const closeButtonClasses = `absolute top-0 ${closeButtonPosition[position]} flex pt-4 pr-2 sm:pr-4`.trim()
31
- </script>
32
-
33
- <script client>
34
- const emit = defineEmits()
35
- // useReactiveProp lets the parent drive `open` via signals
36
- // (`:open="drawerOpen()"`) instead of the prop being captured once.
37
- // See stacksjs/stx#1704.
38
- const isOpen = useReactiveProp('open', {{ open }})
39
-
40
- function close() {
41
- isOpen.set(false)
42
- emit('close')
43
- }
44
-
45
- function onBackdropClick() {
46
- close()
47
- }
48
-
49
- function onPanelKey(event) {
50
- if (event.key === 'Escape') close()
51
- }
52
-
53
- defineExpose({
54
- open: () => isOpen.set(true),
55
- close,
56
- isOpen,
57
- })
58
- </script>
59
-
60
- <div :show="isOpen()">
61
- <div
62
- class="fixed inset-0 z-50 bg-gray-500/75 dark:bg-gray-900/75 transition-opacity duration-500"
63
- style="animation: fadeIn 0.5s ease-in-out"
64
- @click="onBackdropClick()"
65
- ></div>
66
-
67
- <div class="fixed inset-0 z-50 overflow-hidden" @keydown="onPanelKey($event)">
68
- <div class="absolute inset-0 overflow-hidden">
69
- <div class="{{ containerClasses }}">
70
- <div
71
- class="{{ panelClasses }}"
72
- style="animation: slideIn 0.5s ease-in-out"
73
- >
74
- <div class="{{ closeButtonClasses }}">
75
- <button
76
- type="button"
77
- class="relative rounded-md text-gray-300 dark:text-gray-400 hover:text-white dark:hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
78
- @click="close()"
79
- >
80
- <span class="absolute -inset-2.5"></span>
81
- <span class="sr-only">Close panel</span>
82
- <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
83
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
84
- </svg>
85
- </button>
86
- </div>
87
-
88
- <div class="relative flex h-full flex-col overflow-y-auto bg-white dark:bg-blue-gray-800 py-6 shadow-xl">
89
- @if(title)
90
- <div class="px-4 sm:px-6">
91
- <h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">
92
- {{ title }}
93
- </h2>
94
- </div>
95
- @endif
96
- <div class="relative mt-6 flex-1 px-4 sm:px-6">
97
- <slot />
98
- </div>
99
- </div>
100
- </div>
101
- </div>
102
- </div>
103
- </div>
104
- </div>
105
-
106
- <style>
107
- @keyframes fadeIn {
108
- from { opacity: 0; }
109
- to { opacity: 1; }
110
- }
111
-
112
- @keyframes slideIn {
113
- from {
114
- transform: {{ position === 'right' ? 'translateX(100%)' : position === 'left' ? 'translateX(-100%)' : position === 'top' ? 'translateY(-100%)' : 'translateY(100%)' }};
115
- }
116
- to {
117
- transform: translate(0, 0);
118
- }
119
- }
120
- </style>
@@ -1,90 +0,0 @@
1
- # Drawer Component
2
-
3
- A slide-out panel component that can appear from any side of the screen.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let drawerOpen = false
16
- </script>
17
-
18
- <button
19
- class="rounded-md bg-gray-950/5 px-2.5 py-1.5 text-sm font-semibold text-gray-900 hover:bg-gray-950/10"
20
- onclick="drawerOpen = true"
21
- >
22
- Open drawer
23
- </button>
24
-
25
- <Drawer
26
- :open="drawerOpen"
27
- :onClose="() => drawerOpen = false"
28
- position="right"
29
- title="Panel title"
30
- >
31
- <p class="text-sm text-gray-500 dark:text-gray-400">
32
- Your drawer content goes here.
33
- </p>
34
- </Drawer>
35
- ```
36
-
37
- ## Props
38
-
39
- | Prop | Type | Default | Description |
40
- |------|------|---------|-------------|
41
- | `open` | `boolean` | `false` | Controls drawer visibility |
42
- | `onClose` | `function` | - | Callback when drawer should close |
43
- | `position` | `'right' \| 'left' \| 'top' \| 'bottom'` | `'right'` | Position of the drawer |
44
- | `title` | `string` | `''` | Optional title for the drawer |
45
- | `className` | `string` | `''` | Additional CSS classes |
46
-
47
- ## Positions
48
-
49
- ### Right (default)
50
- ```stx
51
- <Drawer open position="right">Content</Drawer>
52
- ```
53
-
54
- ### Left
55
- ```stx
56
- <Drawer open position="left">Content</Drawer>
57
- ```
58
-
59
- ### Top
60
- ```stx
61
- <Drawer open position="top">Content</Drawer>
62
- ```
63
-
64
- ### Bottom
65
- ```stx
66
- <Drawer open position="bottom">Content</Drawer>
67
- ```
68
-
69
- ## Features
70
-
71
- - **4 positions** - Slide from right, left, top, or bottom
72
- - **Smooth animations** - CSS transitions for slide and fade effects
73
- - **Backdrop click** - Closes drawer when clicking outside
74
- - **Close button** - Positioned appropriately for each direction
75
- - **Dark mode** - Full dark mode support
76
- - **Accessible** - Screen reader support and focus management
77
- - **Responsive** - Mobile-friendly with adjusted spacing
78
- - **Modern ES modules** - Clean export syntax
79
- - **Headwind styling** - Utility-first CSS classes
80
-
81
- ## Accessibility
82
-
83
- - Close button includes `sr-only` text for screen readers
84
- - Backdrop and close button have proper ARIA labels
85
- - Keyboard accessible (ESC key closes drawer - handled by parent)
86
- - Focus management for modal behavior
87
-
88
- ## Customization
89
-
90
- The drawer accepts a `className` prop for additional styling and supports slot content for complete customization of the drawer body.
@@ -1,9 +0,0 @@
1
- export { default as Drawer } from './Drawer.stx'
2
-
3
- export interface DrawerProps {
4
- open?: boolean
5
- onClose?: () => void
6
- position?: 'right' | 'left' | 'top' | 'bottom'
7
- title?: string
8
- className?: string
9
- }
@@ -1,82 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
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())
20
- }
21
-
22
- function open() {
23
- if (isOpen()) return
24
- isOpen.set(true)
25
- emit('change', true)
26
- }
27
-
28
- function close() {
29
- if (!isOpen()) return
30
- isOpen.set(false)
31
- emit('change', false)
32
- }
33
-
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 })
61
- </script>
62
-
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 />
76
- </component>
77
-
78
- <style>
79
- [data-stx-dropdown][data-state="closed"] [data-stx-dropdown-items] {
80
- display: none;
81
- }
82
- </style>
@@ -1,29 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'button'
4
- export const disabled = $props.disabled || false
5
-
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'
7
- export const buttonClasses = `${baseClasses} ${className}`.trim()
8
- </script>
9
-
10
- <script client>
11
- const emit = defineEmits()
12
- const isDisabled = {{ disabled }}
13
-
14
- function onClick(event) {
15
- if (isDisabled) return
16
- emit('click', event)
17
- event.currentTarget.dispatchEvent(new CustomEvent('stx:dropdown-toggle', { bubbles: true }))
18
- }
19
- </script>
20
-
21
- <component
22
- :is="{{ as }}"
23
- class="{{ buttonClasses }}"
24
- data-stx-dropdown-button
25
- @if(disabled)disabled aria-disabled="true"@endif
26
- @click="onClick($event)"
27
- >
28
- <slot />
29
- </component>
@@ -1,35 +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 value = $props.value
6
-
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>
11
-
12
- <script client>
13
- const emit = defineEmits()
14
- const isDisabled = {{ disabled }}
15
- const itemValue = {{ value === undefined ? 'null' : value }}
16
-
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
- )
23
- }
24
- </script>
25
-
26
- <component
27
- :is="{{ as }}"
28
- class="{{ itemClasses }}"
29
- data-stx-dropdown-item
30
- role="menuitem"
31
- @if(disabled)aria-disabled="true"@endif
32
- @click="onClick($event)"
33
- >
34
- <slot :disabled="disabled" />
35
- </component>
@@ -1,18 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
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'
6
- export const itemsClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component
10
- :is="{{ as }}"
11
- class="{{ itemsClasses }}"
12
- data-stx-dropdown-items
13
- role="menu"
14
- aria-orientation="vertical"
15
- tabindex="-1"
16
- >
17
- <slot />
18
- </component>
@@ -1,114 +0,0 @@
1
- # Dropdown Component
2
-
3
- A flexible dropdown menu component inspired by Headless UI, built with STX and headwind.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <Dropdown>
15
- <DropdownButton className="btn-primary">Options</DropdownButton>
16
-
17
- <DropdownItems>
18
- <DropdownItem>Edit</DropdownItem>
19
- <DropdownItem>Delete</DropdownItem>
20
- </DropdownItems>
21
- </Dropdown>
22
- ```
23
-
24
- ## Props
25
-
26
- ### Dropdown
27
- | Prop | Type | Default | Description |
28
- |------|------|---------|-------------|
29
- | `className` | `string` | `''` | Additional CSS classes |
30
- | `as` | `string` | `'div'` | HTML element to render |
31
-
32
- ### DropdownButton
33
- | Prop | Type | Default | Description |
34
- |------|------|---------|-------------|
35
- | `className` | `string` | `''` | Additional CSS classes |
36
- | `as` | `string` | `'button'` | HTML element to render |
37
- | `disabled` | `boolean` | `false` | Disable the button |
38
- | `onClick` | `(e: Event) => void` | - | Click handler |
39
-
40
- ### DropdownItems
41
- | Prop | Type | Default | Description |
42
- |------|------|---------|-------------|
43
- | `className` | `string` | `''` | Additional CSS classes |
44
- | `as` | `string` | `'div'` | HTML element to render |
45
- | `static` | `boolean` | `false` | Keep visible regardless of state |
46
-
47
- ### DropdownItem
48
- | Prop | Type | Default | Description |
49
- |------|------|---------|-------------|
50
- | `className` | `string` | `''` | Additional CSS classes |
51
- | `as` | `string` | `'div'` | HTML element to render |
52
- | `disabled` | `boolean` | `false` | Disable the item |
53
- | `onClick` | `(e: Event) => void` | - | Click handler |
54
-
55
- ## Examples
56
-
57
- ### Basic Dropdown
58
-
59
- ```stx
60
- <Dropdown>
61
- <DropdownButton className="px-4 py-2 bg-blue-500 text-white rounded-md">
62
- Actions
63
- </DropdownButton>
64
-
65
- <DropdownItems className="w-56">
66
- <DropdownItem>Edit</DropdownItem>
67
- <DropdownItem>Duplicate</DropdownItem>
68
- <DropdownItem disabled>Archive (coming soon)</DropdownItem>
69
- <DropdownItem>Delete</DropdownItem>
70
- </DropdownItems>
71
- </Dropdown>
72
- ```
73
-
74
- ### With Icons
75
-
76
- ```stx
77
- <DropdownItem>
78
- <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
79
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
80
- </svg>
81
- Edit
82
- </DropdownItem>
83
- ```
84
-
85
- ### Grouped Items
86
-
87
- ```stx
88
- <DropdownItems>
89
- <div class="px-1 py-1">
90
- <DropdownItem>Edit</DropdownItem>
91
- <DropdownItem>Duplicate</DropdownItem>
92
- </div>
93
-
94
- <div class="px-1 py-1">
95
- <DropdownItem>Archive</DropdownItem>
96
- <DropdownItem>Move</DropdownItem>
97
- </div>
98
-
99
- <div class="px-1 py-1">
100
- <DropdownItem>Delete</DropdownItem>
101
- </div>
102
- </DropdownItems>
103
- ```
104
-
105
- ## Features
106
-
107
- - Automatic positioning
108
- - Keyboard navigation
109
- - Focus management
110
- - Dark mode support
111
- - Accessible (WAI-ARIA)
112
- - Customizable styling with headwind
113
- - Disabled state support
114
- - Active state on hover
@@ -1,29 +0,0 @@
1
- export { default as Dropdown } from './Dropdown.stx'
2
- export { default as DropdownButton } from './DropdownButton.stx'
3
- export { default as DropdownItem } from './DropdownItem.stx'
4
- export { default as DropdownItems } from './DropdownItems.stx'
5
-
6
- export interface DropdownProps {
7
- className?: string
8
- as?: string
9
- }
10
-
11
- export interface DropdownButtonProps {
12
- className?: string
13
- as?: string
14
- disabled?: boolean
15
- onClick?: (e: Event) => void
16
- }
17
-
18
- export interface DropdownItemsProps {
19
- className?: string
20
- as?: string
21
- static?: boolean
22
- }
23
-
24
- export interface DropdownItemProps {
25
- className?: string
26
- as?: string
27
- disabled?: boolean
28
- onClick?: (e: Event) => void
29
- }