@stacksjs/components 0.2.93 → 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.
- package/dist/index.js +4 -4
- package/package.json +5 -6
- package/src/components/CodeBlock.stx +0 -54
- package/src/components/Footer.stx +0 -66
- package/src/components/Hero.stx +0 -25
- package/src/components/Installation.stx +0 -37
- package/src/components/index.ts +0 -4
- package/src/composables/index.ts +0 -4
- package/src/composables/useCopyCode.ts +0 -73
- package/src/composables/useDarkMode.ts +0 -100
- package/src/composables/useSEO.ts +0 -230
- package/src/composables/utilities/index.ts +0 -7
- package/src/composables/utilities/useClickOutside.ts +0 -72
- package/src/composables/utilities/useFocusTrap.ts +0 -159
- package/src/composables/utilities/useKeyboard.ts +0 -124
- package/src/composables/utilities/useLocalStorage.ts +0 -132
- package/src/composables/utilities/useMediaQuery.ts +0 -118
- package/src/index.ts +0 -99
- package/src/stx.d.ts +0 -4
- package/src/ui/accordion/Accordion.stx +0 -146
- package/src/ui/accordion/AccordionItem.stx +0 -37
- package/src/ui/accordion/index.ts +0 -47
- package/src/ui/audio/Audio.stx +0 -50
- package/src/ui/audio/README.md +0 -41
- package/src/ui/audio/index.ts +0 -13
- package/src/ui/auth/Login.stx +0 -161
- package/src/ui/auth/README.md +0 -142
- package/src/ui/auth/Signup.stx +0 -159
- package/src/ui/auth/TwoFactorChallenge.stx +0 -111
- package/src/ui/auth/index.ts +0 -32
- package/src/ui/avatar/Avatar.stx +0 -77
- package/src/ui/avatar/index.ts +0 -12
- package/src/ui/badge/Badge.stx +0 -62
- package/src/ui/badge/index.ts +0 -10
- package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
- package/src/ui/breadcrumb/index.ts +0 -15
- package/src/ui/button/Button.stx +0 -74
- package/src/ui/button/README.md +0 -80
- package/src/ui/button/index.ts +0 -85
- package/src/ui/calendar/Calendar.stx +0 -189
- package/src/ui/calendar/README.md +0 -254
- package/src/ui/calendar/index.ts +0 -14
- package/src/ui/card/Card.stx +0 -68
- package/src/ui/card/index.ts +0 -13
- package/src/ui/checkbox/Checkbox.stx +0 -86
- package/src/ui/checkbox/index.ts +0 -16
- package/src/ui/combobox/Combobox.stx +0 -96
- package/src/ui/combobox/ComboboxButton.stx +0 -25
- package/src/ui/combobox/ComboboxInput.stx +0 -32
- package/src/ui/combobox/ComboboxOption.stx +0 -49
- package/src/ui/combobox/ComboboxOptions.stx +0 -16
- package/src/ui/combobox/README.md +0 -150
- package/src/ui/combobox/index.ts +0 -40
- package/src/ui/command-palette/CommandPalette.stx +0 -81
- package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
- package/src/ui/command-palette/README.md +0 -42
- package/src/ui/command-palette/index.ts +0 -15
- package/src/ui/dialog/Dialog.stx +0 -41
- package/src/ui/dialog/DialogBackdrop.stx +0 -9
- package/src/ui/dialog/DialogDescription.stx +0 -11
- package/src/ui/dialog/DialogPanel.stx +0 -16
- package/src/ui/dialog/DialogTitle.stx +0 -11
- package/src/ui/dialog/README.md +0 -121
- package/src/ui/dialog/index.ts +0 -32
- package/src/ui/drawer/Drawer.stx +0 -120
- package/src/ui/drawer/README.md +0 -90
- package/src/ui/drawer/index.ts +0 -9
- package/src/ui/dropdown/Dropdown.stx +0 -82
- package/src/ui/dropdown/DropdownButton.stx +0 -29
- package/src/ui/dropdown/DropdownItem.stx +0 -35
- package/src/ui/dropdown/DropdownItems.stx +0 -18
- package/src/ui/dropdown/README.md +0 -114
- package/src/ui/dropdown/index.ts +0 -29
- package/src/ui/form/Form.stx +0 -95
- package/src/ui/form/index.ts +0 -67
- package/src/ui/heatmap/Heatmap.stx +0 -294
- package/src/ui/image/Image.stx +0 -165
- package/src/ui/image/README.md +0 -164
- package/src/ui/image/index.ts +0 -22
- package/src/ui/input/EmailInput.stx +0 -30
- package/src/ui/input/NumberInput.stx +0 -126
- package/src/ui/input/PasswordInput.stx +0 -143
- package/src/ui/input/SearchInput.stx +0 -44
- package/src/ui/input/TextInput.stx +0 -132
- package/src/ui/input/index.ts +0 -180
- package/src/ui/listbox/Listbox.stx +0 -101
- package/src/ui/listbox/ListboxButton.stx +0 -28
- package/src/ui/listbox/ListboxLabel.stx +0 -11
- package/src/ui/listbox/ListboxOption.stx +0 -49
- package/src/ui/listbox/ListboxOptions.stx +0 -16
- package/src/ui/listbox/README.md +0 -135
- package/src/ui/listbox/index.ts +0 -39
- package/src/ui/navigator/Navigator.stx +0 -113
- package/src/ui/navigator/README.md +0 -352
- package/src/ui/navigator/index.ts +0 -20
- package/src/ui/notification/Notification.stx +0 -117
- package/src/ui/notification/README.md +0 -114
- package/src/ui/notification/index.ts +0 -12
- package/src/ui/pagination/Pagination.stx +0 -150
- package/src/ui/pagination/index.ts +0 -11
- package/src/ui/payment/Checkout.stx +0 -31
- package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
- package/src/ui/payment/PaymentMethods.stx +0 -104
- package/src/ui/payment/README.md +0 -345
- package/src/ui/payment/SubscriptionCheckout.stx +0 -323
- package/src/ui/payment/index.ts +0 -59
- package/src/ui/popover/Popover.stx +0 -60
- package/src/ui/popover/PopoverButton.stx +0 -29
- package/src/ui/popover/PopoverPanel.stx +0 -23
- package/src/ui/popover/README.md +0 -91
- package/src/ui/popover/index.ts +0 -22
- package/src/ui/portal/Portal.stx +0 -57
- package/src/ui/portal/index.ts +0 -6
- package/src/ui/progress/Progress.stx +0 -131
- package/src/ui/progress/index.ts +0 -12
- package/src/ui/radio/Radio.stx +0 -77
- package/src/ui/radio/index.ts +0 -15
- package/src/ui/radio-group/README.md +0 -139
- package/src/ui/radio-group/RadioGroup.stx +0 -60
- package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
- package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
- package/src/ui/radio-group/RadioGroupOption.stx +0 -58
- package/src/ui/radio-group/index.ts +0 -30
- package/src/ui/select/README.md +0 -180
- package/src/ui/select/Select.stx +0 -82
- package/src/ui/select/index.ts +0 -21
- package/src/ui/sidebar/Sidebar.stx +0 -476
- package/src/ui/sidebar/SidebarFooter.stx +0 -71
- package/src/ui/sidebar/SidebarHeader.stx +0 -103
- package/src/ui/sidebar/SidebarItem.stx +0 -86
- package/src/ui/sidebar/SidebarSection.stx +0 -83
- package/src/ui/sidebar/index.ts +0 -153
- package/src/ui/sidebar/themes.ts +0 -240
- package/src/ui/skeleton/Skeleton.stx +0 -48
- package/src/ui/skeleton/index.ts +0 -11
- package/src/ui/spinner/Spinner.stx +0 -109
- package/src/ui/spinner/index.ts +0 -9
- package/src/ui/stepper/README.md +0 -36
- package/src/ui/stepper/Stepper.stx +0 -17
- package/src/ui/stepper/StepperStep.stx +0 -57
- package/src/ui/stepper/index.ts +0 -19
- package/src/ui/storage/README.md +0 -193
- package/src/ui/storage/index.ts +0 -347
- package/src/ui/switch/README.md +0 -114
- package/src/ui/switch/Switch.stx +0 -72
- package/src/ui/switch/index.ts +0 -10
- package/src/ui/table/README.md +0 -39
- package/src/ui/table/Table.stx +0 -14
- package/src/ui/table/TableBody.stx +0 -10
- package/src/ui/table/TableCell.stx +0 -10
- package/src/ui/table/TableHead.stx +0 -10
- package/src/ui/table/TableHeader.stx +0 -20
- package/src/ui/table/TableRow.stx +0 -11
- package/src/ui/table/index.ts +0 -35
- package/src/ui/tabs/TabPanel.stx +0 -25
- package/src/ui/tabs/Tabs.stx +0 -202
- package/src/ui/tabs/index.ts +0 -50
- package/src/ui/teleport/Teleport.stx +0 -65
- package/src/ui/teleport/index.ts +0 -7
- package/src/ui/textarea/Textarea.stx +0 -108
- package/src/ui/textarea/index.ts +0 -20
- package/src/ui/tooltip/Tooltip.stx +0 -71
- package/src/ui/tooltip/index.ts +0 -10
- package/src/ui/transition/README.md +0 -30
- package/src/ui/transition/Transition.stx +0 -102
- package/src/ui/transition/index.ts +0 -25
- package/src/ui/video/README.md +0 -47
- package/src/ui/video/Video.stx +0 -45
- package/src/ui/video/index.ts +0 -16
- package/src/ui/virtual-list/VirtualList.stx +0 -67
- package/src/ui/virtual-list/index.ts +0 -10
- package/src/ui/virtual-table/VirtualTable.stx +0 -103
- package/src/ui/virtual-table/index.ts +0 -21
- package/src/utils/PROP_VALIDATION.md +0 -458
- package/src/utils/THEME_SYSTEM.md +0 -702
- package/src/utils/accessibility.ts +0 -841
- package/src/utils/animation/easing.ts +0 -368
- package/src/utils/animation/helpers.ts +0 -223
- package/src/utils/animation/index.ts +0 -5
- package/src/utils/animation/keyframes.ts +0 -230
- package/src/utils/error-handling.ts +0 -475
- package/src/utils/highlighter.ts +0 -93
- package/src/utils/i18n.ts +0 -634
- package/src/utils/keep-alive.ts +0 -819
- package/src/utils/lazy-loading.ts +0 -530
- package/src/utils/prop-validation.ts +0 -478
- package/src/utils/theme.ts +0 -626
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const checked = $props.checked || false
|
|
3
|
-
export const disabled = $props.disabled || false
|
|
4
|
-
export const indeterminate = $props.indeterminate || false
|
|
5
|
-
export const size = $props.size || 'md'
|
|
6
|
-
export const label = $props.label || ''
|
|
7
|
-
export const description = $props.description || ''
|
|
8
|
-
export const error = $props.error || false
|
|
9
|
-
export const required = $props.required || false
|
|
10
|
-
export const value = $props.value || ''
|
|
11
|
-
export const name = $props.name || ''
|
|
12
|
-
export const className = $props.className || ''
|
|
13
|
-
|
|
14
|
-
const sizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' }
|
|
15
|
-
const baseClasses = 'rounded border-gray-300 dark:border-gray-600 text-indigo-600 dark:text-indigo-500 focus:ring-indigo-600 dark:focus:ring-indigo-500 focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 transition-colors'
|
|
16
|
-
const stateClasses = error ? 'border-red-300 dark:border-red-600 text-red-600 dark:text-red-500 focus:ring-red-500 dark:focus:ring-red-400' : ''
|
|
17
|
-
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
|
|
18
|
-
|
|
19
|
-
export const checkboxClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses}`.trim()
|
|
20
|
-
export const labelClasses = `text-sm font-medium ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'} ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`.trim()
|
|
21
|
-
export const descriptionClasses = `text-sm ${error ? 'text-red-500 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
22
|
-
export const inputId = `checkbox-${value || label}`
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<script client>
|
|
26
|
-
const emit = defineEmits()
|
|
27
|
-
const isDisabled = {{ disabled }}
|
|
28
|
-
const isIndeterminate = {{ indeterminate }}
|
|
29
|
-
// Reactive prop binding so the parent can drive `checked` via signals.
|
|
30
|
-
// See stacksjs/stx#1704.
|
|
31
|
-
const isChecked = useReactiveProp('checked', {{ checked }})
|
|
32
|
-
|
|
33
|
-
function onInputChange(event) {
|
|
34
|
-
if (isDisabled) {
|
|
35
|
-
event.target.checked = isChecked()
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
isChecked.set(event.target.checked)
|
|
39
|
-
emit('change', isChecked())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
onMount(() => {
|
|
43
|
-
if (isIndeterminate) {
|
|
44
|
-
const el = document.getElementById({{ inputId }})
|
|
45
|
-
if (el) el.indeterminate = true
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
defineExpose({ isChecked })
|
|
50
|
-
</script>
|
|
51
|
-
|
|
52
|
-
<div class="relative flex items-start {{ className }}">
|
|
53
|
-
<div class="flex h-6 items-center">
|
|
54
|
-
<input
|
|
55
|
-
id="{{ inputId }}"
|
|
56
|
-
type="checkbox"
|
|
57
|
-
name="{{ name }}"
|
|
58
|
-
value="{{ value }}"
|
|
59
|
-
:checked="isChecked()"
|
|
60
|
-
@if(disabled)disabled@endif
|
|
61
|
-
@if(required)required@endif
|
|
62
|
-
class="{{ checkboxClasses }}"
|
|
63
|
-
@change="onInputChange($event)"
|
|
64
|
-
:aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
65
|
-
@if(description)aria-describedby="checkbox-description"@endif
|
|
66
|
-
/>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
@if(label || description)
|
|
70
|
-
<div class="ml-3 text-sm leading-6">
|
|
71
|
-
@if(label)
|
|
72
|
-
<label for="{{ inputId }}" class="{{ labelClasses }}">
|
|
73
|
-
{{ label }}
|
|
74
|
-
@if(required)
|
|
75
|
-
<span class="text-red-500 ml-1">*</span>
|
|
76
|
-
@endif
|
|
77
|
-
</label>
|
|
78
|
-
@endif
|
|
79
|
-
@if(description)
|
|
80
|
-
<p id="checkbox-description" class="{{ descriptionClasses }}">
|
|
81
|
-
{{ description }}
|
|
82
|
-
</p>
|
|
83
|
-
@endif
|
|
84
|
-
</div>
|
|
85
|
-
@endif
|
|
86
|
-
</div>
|
package/src/ui/checkbox/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export { default as Checkbox } from './Checkbox.stx'
|
|
2
|
-
|
|
3
|
-
export interface CheckboxProps {
|
|
4
|
-
checked?: boolean
|
|
5
|
-
onChange?: (checked: boolean) => void
|
|
6
|
-
disabled?: boolean
|
|
7
|
-
indeterminate?: boolean
|
|
8
|
-
size?: 'sm' | 'md' | 'lg'
|
|
9
|
-
label?: string
|
|
10
|
-
description?: string
|
|
11
|
-
error?: boolean
|
|
12
|
-
required?: boolean
|
|
13
|
-
value?: string
|
|
14
|
-
name?: string
|
|
15
|
-
className?: string
|
|
16
|
-
}
|
|
@@ -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
|
package/src/ui/combobox/index.ts
DELETED
|
@@ -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
|
-
}
|