@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,96 +0,0 @@
1
- <script server>
2
- export const value = $props.value
3
- export const className = $props.className || ''
4
- export const as = $props.as || 'div'
5
-
6
- const baseClasses = 'relative'
7
- export const comboboxClasses = `${baseClasses} ${className}`.trim()
8
- export const comboboxInstanceId = `stx-cb-${Math.random().toString(36).slice(2, 11)}`
9
- </script>
10
-
11
- <script client>
12
- const emit = defineEmits()
13
- const comboboxInstanceId = {{ comboboxInstanceId }}
14
- const initialValue = {{ value === undefined ? 'null' : value }}
15
-
16
- const isOpen = state(false)
17
- const selected = state(initialValue)
18
- const query = state('')
19
- let rootEl = null
20
- let outsideHandler = null
21
-
22
- function isSelectedValue(v) {
23
- return selected() === v
24
- }
25
-
26
- function selectValue(v) {
27
- selected.set(v)
28
- isOpen.set(false)
29
- syncOptionStates()
30
- emit('change', v)
31
- }
32
-
33
- function syncOptionStates() {
34
- if (!rootEl) return
35
- const options = rootEl.querySelectorAll('[data-stx-combobox-option]')
36
- for (const opt of options) {
37
- const raw = opt.dataset.optionValue
38
- let v
39
- try { v = JSON.parse(raw ?? 'null') }
40
- catch { v = raw }
41
- const sel = isSelectedValue(v)
42
- opt.setAttribute('aria-selected', sel ? 'true' : 'false')
43
- opt.setAttribute('data-selected', sel ? 'true' : 'false')
44
- }
45
- }
46
-
47
- function open() { if (!isOpen()) { isOpen.set(true) } }
48
- function close() { if (isOpen()) isOpen.set(false) }
49
- function toggle() { isOpen() ? close() : open() }
50
-
51
- function onToggle(event) { event.stopPropagation(); toggle() }
52
- function onSelect(event) { event.stopPropagation(); selectValue(event.detail) }
53
- function onQuery(event) {
54
- event.stopPropagation()
55
- query.set(event.detail)
56
- if (!isOpen()) open()
57
- emit('query', event.detail)
58
- }
59
-
60
- onMount(() => {
61
- rootEl = document.querySelector(`[data-combobox-id="${comboboxInstanceId}"]`)
62
- syncOptionStates()
63
- outsideHandler = (event) => {
64
- if (!isOpen()) return
65
- if (rootEl && !rootEl.contains(event.target)) close()
66
- }
67
- document.addEventListener('click', outsideHandler, true)
68
- })
69
-
70
- onDestroy(() => {
71
- if (outsideHandler) document.removeEventListener('click', outsideHandler, true)
72
- })
73
-
74
- const dataState = derived(() => isOpen() ? 'open' : 'closed')
75
-
76
- defineExpose({ isOpen, selected, query, toggle, open, close, selectValue })
77
- </script>
78
-
79
- <component
80
- :is="{{ as }}"
81
- class="{{ comboboxClasses }}"
82
- data-stx-combobox
83
- data-combobox-id="{{ comboboxInstanceId }}"
84
- :data-state="dataState()"
85
- @stx:combobox-toggle="onToggle($event)"
86
- @stx:combobox-select="onSelect($event)"
87
- @stx:combobox-query="onQuery($event)"
88
- >
89
- <slot />
90
- </component>
91
-
92
- <style>
93
- [data-stx-combobox][data-state="closed"] [data-stx-combobox-options] {
94
- display: none;
95
- }
96
- </style>
@@ -1,25 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'button'
4
-
5
- const baseClasses = 'absolute inset-y-0 right-0 flex items-center pr-2'
6
- export const buttonClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <script client>
10
- function onClick(event) {
11
- event.currentTarget.dispatchEvent(new CustomEvent('stx:combobox-toggle', { bubbles: true }))
12
- }
13
- </script>
14
-
15
- <component
16
- :is="{{ as }}"
17
- class="{{ buttonClasses }}"
18
- data-stx-combobox-button
19
- tabindex="-1"
20
- @click="onClick($event)"
21
- >
22
- <svg class="h-5 w-5 text-neutral-400" viewBox="0 0 20 20" fill="none" stroke="currentColor">
23
- <path d="M7 7l3-3 3 3m0 6l-3 3-3-3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
24
- </svg>
25
- </component>
@@ -1,32 +0,0 @@
1
- <script server>
2
- export const displayValue = $props.displayValue
3
- export const className = $props.className || ''
4
- export const placeholder = $props.placeholder || ''
5
- export const disabled = $props.disabled || false
6
-
7
- const baseClasses = 'w-full rounded-lg border-none bg-white dark:bg-neutral-800 py-2 pl-3 pr-10 text-sm leading-5 text-neutral-900 dark:text-white focus:ring-0 focus:outline-none focus-visible:border-blue-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2'
8
- const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
9
- export const inputClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
10
- </script>
11
-
12
- <script client>
13
- const isDisabled = {{ disabled }}
14
-
15
- function onInput(event) {
16
- if (isDisabled) return
17
- event.currentTarget.dispatchEvent(
18
- new CustomEvent('stx:combobox-query', { bubbles: true, detail: event.target.value }),
19
- )
20
- }
21
- </script>
22
-
23
- <input
24
- type="text"
25
- class="{{ inputClasses }}"
26
- data-stx-combobox-input
27
- placeholder="{{ placeholder }}"
28
- value="{{ displayValue }}"
29
- @if(disabled)disabled@endif
30
- @input="onInput($event)"
31
- autocomplete="off"
32
- />
@@ -1,49 +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
-
7
- const baseClasses = 'relative cursor-pointer select-none py-2 pl-10 pr-4 text-neutral-900 dark:text-neutral-100 hover:bg-blue-100 dark:hover:bg-blue-900'
8
- const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
9
- export const optionClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
10
- export const valueJson = JSON.stringify(value === undefined ? null : value)
11
- </script>
12
-
13
- <script client>
14
- const isDisabled = {{ disabled }}
15
- const optionValue = {{ value === undefined ? 'null' : value }}
16
-
17
- function onClick(event) {
18
- if (isDisabled) return
19
- event.currentTarget.dispatchEvent(
20
- new CustomEvent('stx:combobox-select', { bubbles: true, detail: optionValue }),
21
- )
22
- }
23
- </script>
24
-
25
- <component
26
- :is="{{ as }}"
27
- class="{{ optionClasses }}"
28
- data-stx-combobox-option
29
- data-option-value="{{ valueJson }}"
30
- role="option"
31
- aria-selected="false"
32
- @if(disabled)aria-disabled="true"@endif
33
- @click="onClick($event)"
34
- >
35
- <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600 dark:text-blue-400" data-stx-combobox-check>
36
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
37
- <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" />
38
- </svg>
39
- </span>
40
-
41
- <slot :disabled="disabled" />
42
- </component>
43
-
44
- <style>
45
- [data-stx-combobox-option][data-selected="false"] [data-stx-combobox-check],
46
- [data-stx-combobox-option]:not([data-selected]) [data-stx-combobox-check] {
47
- display: none;
48
- }
49
- </style>
@@ -1,16 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'ul'
4
-
5
- const baseClasses = 'absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-neutral-800 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none'
6
- export const optionsClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component
10
- :is="{{ as }}"
11
- class="{{ optionsClasses }}"
12
- data-stx-combobox-options
13
- role="listbox"
14
- >
15
- <slot />
16
- </component>
@@ -1,150 +0,0 @@
1
- # Combobox Component
2
-
3
- A searchable select component that combines an input with a listbox.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- const people = [
16
- { id: 1, name: 'Wade Cooper' },
17
- { id: 2, name: 'Arlene Mccoy' },
18
- { id: 3, name: 'Devon Webb' }
19
- ]
20
-
21
- let selected = people[0]
22
- let query = ''
23
-
24
- const filtered = query === ''
25
- ? people
26
- : people.filter(person =>
27
- person.name.toLowerCase().includes(query.toLowerCase())
28
- )
29
-
30
- function handleChange(person) {
31
- selected = person
32
- query = ''
33
- }
34
-
35
- function handleQueryChange(value) {
36
- query = value
37
- }
38
- </script>
39
-
40
- <Combobox :value="selected" :onChange="handleChange">
41
- <div class="relative mt-1">
42
- <ComboboxInput
43
- :displayValue="selected.name"
44
- :onChange="handleQueryChange"
45
- placeholder="Search people..."
46
- />
47
-
48
- <ComboboxButton />
49
-
50
- <ComboboxOptions>
51
- @if(filtered.length === 0 && query !== '')
52
- <div class="relative cursor-default select-none py-2 px-4 text-neutral-700 dark:text-neutral-300">
53
- Nothing found.
54
- </div>
55
- @else
56
- @foreach(person in filtered)
57
- <ComboboxOption :value="person" :currentValue="selected" :onChange="handleChange">
58
- {{ person.name }}
59
- </ComboboxOption>
60
- @endforeach
61
- @endif
62
- </ComboboxOptions>
63
- </div>
64
- </Combobox>
65
- ```
66
-
67
- ## Props
68
-
69
- ### Combobox
70
- | Prop | Type | Default | Description |
71
- |------|------|---------|-------------|
72
- | `value` | `any` | - | Currently selected value |
73
- | `onChange` | `(value: any) => void` | - | Change handler |
74
- | `className` | `string` | `''` | Additional CSS classes |
75
- | `as` | `string` | `'div'` | HTML element to render |
76
-
77
- ### ComboboxInput
78
- | Prop | Type | Default | Description |
79
- |------|------|---------|-------------|
80
- | `displayValue` | `any` | - | Value to display in input |
81
- | `onChange` | `(value: string) => void` | - | Input change handler |
82
- | `className` | `string` | `''` | Additional CSS classes |
83
- | `placeholder` | `string` | `''` | Input placeholder |
84
- | `disabled` | `boolean` | `false` | Disable the input |
85
-
86
- ### ComboboxButton
87
- | Prop | Type | Default | Description |
88
- |------|------|---------|-------------|
89
- | `className` | `string` | `''` | Additional CSS classes |
90
- | `as` | `string` | `'button'` | HTML element to render |
91
-
92
- ### ComboboxOptions
93
- | Prop | Type | Default | Description |
94
- |------|------|---------|-------------|
95
- | `className` | `string` | `''` | Additional CSS classes |
96
- | `as` | `string` | `'ul'` | HTML element to render |
97
- | `static` | `boolean` | `false` | Keep visible regardless of state |
98
-
99
- ### ComboboxOption
100
- | Prop | Type | Default | Description |
101
- |------|------|---------|-------------|
102
- | `value` | `any` | - | Option value |
103
- | `disabled` | `boolean` | `false` | Disable the option |
104
- | `className` | `string` | `''` | Additional CSS classes |
105
- | `as` | `string` | `'li'` | HTML element to render |
106
- | `currentValue` | `any` | - | Current selected value |
107
- | `onChange` | `(value: any) => void` | - | Change handler |
108
-
109
- ## Examples
110
-
111
- ### With Empty State
112
-
113
- ```stx
114
- <ComboboxOptions>
115
- @if(filtered.length === 0)
116
- <div class="py-2 px-4 text-neutral-500 dark:text-neutral-400">
117
- No results found for "{{ query }}"
118
- </div>
119
- @else
120
- @foreach(item in filtered)
121
- <ComboboxOption :value="item">
122
- {{ item.name }}
123
- </ComboboxOption>
124
- @endforeach
125
- @endif
126
- </ComboboxOptions>
127
- ```
128
-
129
- ### With Avatars
130
-
131
- ```stx
132
- <ComboboxOption :value="person">
133
- <div class="flex items-center gap-2">
134
- <img src="{{ person.avatar }}" alt="" class="h-6 w-6 rounded-full" />
135
- <span>{{ person.name }}</span>
136
- </div>
137
- </ComboboxOption>
138
- ```
139
-
140
- ## Features
141
-
142
- - Searchable/filterable
143
- - Keyboard navigation
144
- - Empty state support
145
- - Dark mode support
146
- - Accessible (WAI-ARIA)
147
- - Disabled state
148
- - Active state on hover
149
- - Check icon for selected item
150
- - Customizable styling
@@ -1,40 +0,0 @@
1
- export { default as Combobox } from './Combobox.stx'
2
- export { default as ComboboxButton } from './ComboboxButton.stx'
3
- export { default as ComboboxInput } from './ComboboxInput.stx'
4
- export { default as ComboboxOption } from './ComboboxOption.stx'
5
- export { default as ComboboxOptions } from './ComboboxOptions.stx'
6
-
7
- export interface ComboboxProps {
8
- value?: any
9
- onChange?: (value: any) => void
10
- className?: string
11
- as?: string
12
- }
13
-
14
- export interface ComboboxInputProps {
15
- displayValue?: any
16
- onChange?: (value: string) => void
17
- className?: string
18
- placeholder?: string
19
- disabled?: boolean
20
- }
21
-
22
- export interface ComboboxButtonProps {
23
- className?: string
24
- as?: string
25
- }
26
-
27
- export interface ComboboxOptionsProps {
28
- className?: string
29
- as?: string
30
- static?: boolean
31
- }
32
-
33
- export interface ComboboxOptionProps {
34
- value: any
35
- disabled?: boolean
36
- className?: string
37
- as?: string
38
- currentValue?: any
39
- onChange?: (value: any) => void
40
- }
@@ -1,81 +0,0 @@
1
- <script server>
2
- export const open = $props.open || false
3
- export const initialQuery = $props.query || ''
4
- export const className = $props.className || ''
5
-
6
- const baseClasses = 'fixed inset-0 z-50 overflow-y-auto p-4 sm:p-6 md:p-20'
7
- export const paletteClasses = `${baseClasses} ${className}`.trim()
8
- export const paletteInstanceId = `stx-cmd-${Math.random().toString(36).slice(2, 11)}`
9
- </script>
10
-
11
- <script client>
12
- const emit = defineEmits()
13
- const paletteInstanceId = {{ paletteInstanceId }}
14
- const isOpen = state({{ open }})
15
- const query = state({{ initialQuery }})
16
- let escHandler = null
17
-
18
- function close() {
19
- if (!isOpen()) return
20
- isOpen.set(false)
21
- emit('close')
22
- }
23
-
24
- function show() {
25
- if (isOpen()) return
26
- isOpen.set(true)
27
- }
28
-
29
- function onQueryInput(event) {
30
- query.set(event.target.value)
31
- emit('query', event.target.value)
32
- }
33
-
34
- function onItemSelect(event) {
35
- event.stopPropagation()
36
- emit('select', event.detail)
37
- close()
38
- }
39
-
40
- onMount(() => {
41
- escHandler = (event) => {
42
- if (event.key === 'Escape' && isOpen()) close()
43
- }
44
- document.addEventListener('keydown', escHandler)
45
- })
46
-
47
- onDestroy(() => {
48
- if (escHandler) document.removeEventListener('keydown', escHandler)
49
- })
50
-
51
- defineExpose({ isOpen, query, show, close })
52
- </script>
53
-
54
- <div
55
- :show="isOpen()"
56
- class="{{ paletteClasses }}"
57
- data-stx-command-palette
58
- data-palette-id="{{ paletteInstanceId }}"
59
- @stx:command-select="onItemSelect($event)"
60
- >
61
- <div class="fixed inset-0 bg-neutral-500 bg-opacity-25 dark:bg-opacity-50 transition-opacity" @click="close()"></div>
62
-
63
- <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 relative">
64
- <div class="relative">
65
- <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">
66
- <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" />
67
- </svg>
68
- <input
69
- type="text"
70
- 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"
71
- placeholder="Search..."
72
- :value="query()"
73
- @input="onQueryInput($event)"
74
- />
75
- </div>
76
-
77
- <div class="max-h-96 overflow-y-auto py-2">
78
- <slot />
79
- </div>
80
- </div>
81
- </div>
@@ -1,27 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const value = $props.value
4
-
5
- const baseClasses = 'flex cursor-pointer select-none items-center px-4 py-2 text-neutral-900 dark:text-neutral-100 hover:bg-blue-600 hover:text-white'
6
- export const itemClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <script client>
10
- const emit = defineEmits()
11
- const itemValue = {{ value === undefined ? 'null' : value }}
12
-
13
- function onClick(event) {
14
- emit('click', event)
15
- event.currentTarget.dispatchEvent(
16
- new CustomEvent('stx:command-select', { bubbles: true, detail: itemValue }),
17
- )
18
- }
19
- </script>
20
-
21
- <div
22
- class="{{ itemClasses }}"
23
- data-stx-command-item
24
- @click="onClick($event)"
25
- >
26
- <slot />
27
- </div>
@@ -1,42 +0,0 @@
1
- # Command Palette Component
2
-
3
- A searchable command menu for quick actions and navigation.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let open = false
16
- let query = ''
17
-
18
- const commands = [
19
- { name: 'Create new file', action: () => console.log('create') },
20
- { name: 'Open settings', action: () => console.log('settings') }
21
- ]
22
-
23
- const filtered = query === ''
24
- ? commands
25
- : commands.filter(cmd => cmd.name.toLowerCase().includes(query.toLowerCase()))
26
- </script>
27
-
28
- <CommandPalette :open="open" :onClose="() => open = false" :query="query" :onQueryChange="(q) => query = q">
29
- @foreach(command in filtered)
30
- <CommandPaletteItem :onClick="command.action">
31
- {{ command.name }}
32
- </CommandPaletteItem>
33
- @endforeach
34
- </CommandPalette>
35
- ```
36
-
37
- ## Features
38
-
39
- - Searchable
40
- - Keyboard navigation
41
- - Dark mode support
42
- - Accessible
@@ -1,15 +0,0 @@
1
- export { default as CommandPalette } from './CommandPalette.stx'
2
- export { default as CommandPaletteItem } from './CommandPaletteItem.stx'
3
-
4
- export interface CommandPaletteProps {
5
- open?: boolean
6
- onClose?: () => void
7
- query?: string
8
- onQueryChange?: (query: string) => void
9
- className?: string
10
- }
11
-
12
- export interface CommandPaletteItemProps {
13
- className?: string
14
- onClick?: () => void
15
- }
@@ -1,41 +0,0 @@
1
- <script server>
2
- export const open = $props.open || false
3
- export const className = $props.className || ''
4
-
5
- const baseClasses = 'relative z-50'
6
- export const dialogClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <script client>
10
- const emit = defineEmits()
11
- // useReactiveProp wires `:open="parentSignal()"` from the parent into our
12
- // local `isOpen` signal — when the parent's signal changes, bindAttr
13
- // updates the root's `open` attribute, our MutationObserver picks it up,
14
- // and isOpen flips. See stacksjs/stx#1704.
15
- const isOpen = useReactiveProp('open', {{ open }})
16
-
17
- function close() {
18
- isOpen.set(false)
19
- emit('close')
20
- }
21
-
22
- function onBackdropKey(event) {
23
- if (event.key === 'Escape') close()
24
- }
25
-
26
- defineExpose({
27
- open: () => isOpen.set(true),
28
- close,
29
- isOpen,
30
- })
31
- </script>
32
-
33
- <div
34
- :show="isOpen()"
35
- class="{{ dialogClasses }}"
36
- role="dialog"
37
- aria-modal="true"
38
- @keydown="onBackdropKey($event)"
39
- >
40
- <slot />
41
- </div>
@@ -1,9 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'fixed inset-0 bg-black bg-opacity-25 dark:bg-opacity-50 transition-opacity'
6
- const backdropClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ backdropClasses }}" aria-hidden="true" />
@@ -1,11 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'p'
4
-
5
- const baseClasses = 'mt-2 text-sm text-neutral-500 dark:text-neutral-400'
6
- const descriptionClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ descriptionClasses }}">
10
- <slot />
11
- </component>
@@ -1,16 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'fixed inset-0 overflow-y-auto'
6
- const panelWrapperClasses = 'flex min-h-full items-center justify-center p-4 text-center'
7
- const panelClasses = `transform overflow-hidden rounded-lg bg-white dark:bg-neutral-800 p-6 text-left align-middle shadow-xl transition-all ${className}`.trim()
8
- </script>
9
-
10
- <component :is="{{ as }}" class="{{ baseClasses }}">
11
- <div class="{{ panelWrapperClasses }}">
12
- <div class="{{ panelClasses }}">
13
- <slot />
14
- </div>
15
- </div>
16
- </component>
@@ -1,11 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'h3'
4
-
5
- const baseClasses = 'text-lg font-medium leading-6 text-neutral-900 dark:text-white'
6
- const titleClasses = `${baseClasses} ${className}`.trim()
7
- </script>
8
-
9
- <component :is="{{ as }}" class="{{ titleClasses }}">
10
- <slot />
11
- </component>