@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.
- package/dist/{Sidebar-yb115a2w.stx → Sidebar-4hn7vw4n.stx} +18 -0
- package/dist/index.js +5 -5
- 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 -458
- 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,139 +0,0 @@
|
|
|
1
|
-
# Radio Group Component
|
|
2
|
-
|
|
3
|
-
A set of checkable buttons (radio buttons) where only one can be checked at a time.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun add @stacksjs/components
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
```stx
|
|
14
|
-
<script server>
|
|
15
|
-
let selected = 'option1'
|
|
16
|
-
|
|
17
|
-
function handleChange(value) {
|
|
18
|
-
selected = value
|
|
19
|
-
}
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<RadioGroup :value="selected" :onChange="handleChange">
|
|
23
|
-
<RadioGroupLabel>Choose an option</RadioGroupLabel>
|
|
24
|
-
|
|
25
|
-
<RadioGroupOption value="option1" :currentValue="selected" :onChange="handleChange">
|
|
26
|
-
Option 1
|
|
27
|
-
</RadioGroupOption>
|
|
28
|
-
|
|
29
|
-
<RadioGroupOption value="option2" :currentValue="selected" :onChange="handleChange">
|
|
30
|
-
Option 2
|
|
31
|
-
</RadioGroupOption>
|
|
32
|
-
</RadioGroup>
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Props
|
|
36
|
-
|
|
37
|
-
### RadioGroup
|
|
38
|
-
| Prop | Type | Default | Description |
|
|
39
|
-
|------|------|---------|-------------|
|
|
40
|
-
| `value` | `any` | - | Currently selected value |
|
|
41
|
-
| `onChange` | `(value: any) => void` | - | Change handler |
|
|
42
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
43
|
-
| `as` | `string` | `'div'` | HTML element to render |
|
|
44
|
-
|
|
45
|
-
### RadioGroupLabel
|
|
46
|
-
| Prop | Type | Default | Description |
|
|
47
|
-
|------|------|---------|-------------|
|
|
48
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
49
|
-
| `as` | `string` | `'label'` | HTML element to render |
|
|
50
|
-
|
|
51
|
-
### RadioGroupOption
|
|
52
|
-
| Prop | Type | Default | Description |
|
|
53
|
-
|------|------|---------|-------------|
|
|
54
|
-
| `value` | `any` | - | Option value |
|
|
55
|
-
| `disabled` | `boolean` | `false` | Disable the option |
|
|
56
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
57
|
-
| `as` | `string` | `'div'` | HTML element to render |
|
|
58
|
-
| `currentValue` | `any` | - | Current selected value |
|
|
59
|
-
| `onChange` | `(value: any) => void` | - | Change handler |
|
|
60
|
-
|
|
61
|
-
### RadioGroupDescription
|
|
62
|
-
| Prop | Type | Default | Description |
|
|
63
|
-
|------|------|---------|-------------|
|
|
64
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
65
|
-
| `as` | `string` | `'span'` | HTML element to render |
|
|
66
|
-
|
|
67
|
-
## Examples
|
|
68
|
-
|
|
69
|
-
### Server Plans
|
|
70
|
-
|
|
71
|
-
```stx
|
|
72
|
-
<script server>
|
|
73
|
-
const plans = [
|
|
74
|
-
{ name: 'Startup', ram: '12GB', cpus: '6 CPUs', disk: '160 GB SSD' },
|
|
75
|
-
{ name: 'Business', ram: '16GB', cpus: '8 CPUs', disk: '512 GB SSD' },
|
|
76
|
-
{ name: 'Enterprise', ram: '32GB', cpus: '12 CPUs', disk: '1024 GB SSD' }
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
let selected = plans[0]
|
|
80
|
-
|
|
81
|
-
function handleChange(plan) {
|
|
82
|
-
selected = plan
|
|
83
|
-
}
|
|
84
|
-
</script>
|
|
85
|
-
|
|
86
|
-
<RadioGroup :value="selected" :onChange="handleChange">
|
|
87
|
-
<RadioGroupLabel className="sr-only">Server size</RadioGroupLabel>
|
|
88
|
-
|
|
89
|
-
<div class="space-y-2">
|
|
90
|
-
@foreach(plan in plans)
|
|
91
|
-
<RadioGroupOption
|
|
92
|
-
:value="plan"
|
|
93
|
-
:currentValue="selected"
|
|
94
|
-
:onChange="handleChange"
|
|
95
|
-
>
|
|
96
|
-
<div class="w-full flex items-center justify-between">
|
|
97
|
-
<div class="flex items-center">
|
|
98
|
-
<div class="text-sm">
|
|
99
|
-
<RadioGroupLabel className="font-medium">
|
|
100
|
-
{{ plan.name }}
|
|
101
|
-
</RadioGroupLabel>
|
|
102
|
-
|
|
103
|
-
<RadioGroupDescription>
|
|
104
|
-
{{ plan.ram }}/{{ plan.cpus }} · {{ plan.disk }}
|
|
105
|
-
</RadioGroupDescription>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
@if(selected === plan)
|
|
110
|
-
<svg class="h-6 w-6 shrink-0 text-white" viewBox="0 0 24 24" fill="none">
|
|
111
|
-
<circle cx="12" cy="12" r="12" fill="#fff" fill-opacity="0.2" />
|
|
112
|
-
<path d="M7 13l3 3 7-7" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
113
|
-
</svg>
|
|
114
|
-
@endif
|
|
115
|
-
</div>
|
|
116
|
-
</RadioGroupOption>
|
|
117
|
-
@endforeach
|
|
118
|
-
</div>
|
|
119
|
-
</RadioGroup>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### With Disabled Option
|
|
123
|
-
|
|
124
|
-
```stx
|
|
125
|
-
<RadioGroupOption value="disabled" disabled>
|
|
126
|
-
This option is disabled
|
|
127
|
-
</RadioGroupOption>
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Features
|
|
131
|
-
|
|
132
|
-
- Single selection from multiple options
|
|
133
|
-
- Keyboard navigation
|
|
134
|
-
- Focus management
|
|
135
|
-
- Dark mode support
|
|
136
|
-
- Accessible (WAI-ARIA)
|
|
137
|
-
- Disabled state support
|
|
138
|
-
- Active state on focus
|
|
139
|
-
- Customizable styling
|
|
@@ -1,60 +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 = 'w-full'
|
|
7
|
-
export const groupClasses = `${baseClasses} ${className}`.trim()
|
|
8
|
-
export const radioGroupInstanceId = `stx-rg-${Math.random().toString(36).slice(2, 11)}`
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script client>
|
|
12
|
-
const emit = defineEmits()
|
|
13
|
-
const radioGroupInstanceId = {{ radioGroupInstanceId }}
|
|
14
|
-
const initialValue = {{ value === undefined ? 'null' : value }}
|
|
15
|
-
const selected = state(initialValue)
|
|
16
|
-
let rootEl = null
|
|
17
|
-
|
|
18
|
-
function selectValue(v) {
|
|
19
|
-
selected.set(v)
|
|
20
|
-
syncOptionStates()
|
|
21
|
-
emit('change', v)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function syncOptionStates() {
|
|
25
|
-
if (!rootEl) return
|
|
26
|
-
const options = rootEl.querySelectorAll('[data-stx-radio-option]')
|
|
27
|
-
for (const opt of options) {
|
|
28
|
-
const raw = opt.dataset.optionValue
|
|
29
|
-
let v
|
|
30
|
-
try { v = JSON.parse(raw ?? 'null') }
|
|
31
|
-
catch { v = raw }
|
|
32
|
-
const checked = selected() === v
|
|
33
|
-
opt.setAttribute('aria-checked', checked ? 'true' : 'false')
|
|
34
|
-
opt.setAttribute('data-checked', checked ? 'true' : 'false')
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function onSelect(event) {
|
|
39
|
-
event.stopPropagation()
|
|
40
|
-
selectValue(event.detail)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
onMount(() => {
|
|
44
|
-
rootEl = document.querySelector(`[data-radio-group-id="${radioGroupInstanceId}"]`)
|
|
45
|
-
syncOptionStates()
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
defineExpose({ selected, selectValue })
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
<component
|
|
52
|
-
:is="{{ as }}"
|
|
53
|
-
class="{{ groupClasses }}"
|
|
54
|
-
data-stx-radio-group
|
|
55
|
-
data-radio-group-id="{{ radioGroupInstanceId }}"
|
|
56
|
-
role="radiogroup"
|
|
57
|
-
@stx:radio-select="onSelect($event)"
|
|
58
|
-
>
|
|
59
|
-
<slot />
|
|
60
|
-
</component>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const className = $props.className || ''
|
|
3
|
-
export const as = $props.as || 'span'
|
|
4
|
-
|
|
5
|
-
const baseClasses = 'inline 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,11 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const className = $props.className || ''
|
|
3
|
-
export const as = $props.as || 'label'
|
|
4
|
-
|
|
5
|
-
const baseClasses = 'block text-sm font-medium text-neutral-900 dark:text-white'
|
|
6
|
-
const labelClasses = `${baseClasses} ${className}`.trim()
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<component :is="{{ as }}" class="{{ labelClasses }}">
|
|
10
|
-
<slot />
|
|
11
|
-
</component>
|
|
@@ -1,58 +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 || 'div'
|
|
6
|
-
|
|
7
|
-
const baseClasses = 'relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none transition-all bg-white dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-60 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 dark:focus-visible:ring-offset-blue-700'
|
|
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:radio-select', { bubbles: true, detail: optionValue }),
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function onKey(event) {
|
|
25
|
-
if (isDisabled) return
|
|
26
|
-
if (event.key === ' ' || event.key === 'Enter') {
|
|
27
|
-
event.preventDefault()
|
|
28
|
-
event.currentTarget.dispatchEvent(
|
|
29
|
-
new CustomEvent('stx:radio-select', { bubbles: true, detail: optionValue }),
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<component
|
|
36
|
-
:is="{{ as }}"
|
|
37
|
-
class="{{ optionClasses }}"
|
|
38
|
-
data-stx-radio-option
|
|
39
|
-
data-option-value="{{ valueJson }}"
|
|
40
|
-
role="radio"
|
|
41
|
-
aria-checked="false"
|
|
42
|
-
@if(disabled)aria-disabled="true"@endif
|
|
43
|
-
tabindex="{{ disabled ? '-1' : '0' }}"
|
|
44
|
-
@click="onClick($event)"
|
|
45
|
-
@keydown="onKey($event)"
|
|
46
|
-
>
|
|
47
|
-
<slot :disabled="disabled" />
|
|
48
|
-
</component>
|
|
49
|
-
|
|
50
|
-
<style>
|
|
51
|
-
[data-stx-radio-option][data-checked="true"] {
|
|
52
|
-
background-color: rgb(30 58 138 / 0.75);
|
|
53
|
-
color: white;
|
|
54
|
-
}
|
|
55
|
-
.dark [data-stx-radio-option][data-checked="true"] {
|
|
56
|
-
background-color: rgb(30 64 175 / 1);
|
|
57
|
-
}
|
|
58
|
-
</style>
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export { default as RadioGroup } from './RadioGroup.stx'
|
|
2
|
-
export { default as RadioGroupDescription } from './RadioGroupDescription.stx'
|
|
3
|
-
export { default as RadioGroupLabel } from './RadioGroupLabel.stx'
|
|
4
|
-
export { default as RadioGroupOption } from './RadioGroupOption.stx'
|
|
5
|
-
|
|
6
|
-
export interface RadioGroupProps {
|
|
7
|
-
value?: any
|
|
8
|
-
onChange?: (value: any) => void
|
|
9
|
-
className?: string
|
|
10
|
-
as?: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface RadioGroupLabelProps {
|
|
14
|
-
className?: string
|
|
15
|
-
as?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface RadioGroupOptionProps {
|
|
19
|
-
value: any
|
|
20
|
-
disabled?: boolean
|
|
21
|
-
className?: string
|
|
22
|
-
as?: string
|
|
23
|
-
currentValue?: any
|
|
24
|
-
onChange?: (value: any) => void
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface RadioGroupDescriptionProps {
|
|
28
|
-
className?: string
|
|
29
|
-
as?: string
|
|
30
|
-
}
|
package/src/ui/select/README.md
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
# Select Component
|
|
2
|
-
|
|
3
|
-
A styled native select dropdown with support for labels, validation, and dark mode.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun add @stacksjs/components
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
### Basic Select
|
|
14
|
-
|
|
15
|
-
```stx
|
|
16
|
-
<script server>
|
|
17
|
-
const options = [
|
|
18
|
-
{ value: 'option1', label: 'Option 1' },
|
|
19
|
-
{ value: 'option2', label: 'Option 2' },
|
|
20
|
-
{ value: 'option3', label: 'Option 3' },
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
const selected = 'option1'
|
|
24
|
-
|
|
25
|
-
const handleChange = (value) => {
|
|
26
|
-
console.log('Selected:', value)
|
|
27
|
-
selected = value
|
|
28
|
-
}
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<Select
|
|
32
|
-
:value="selected"
|
|
33
|
-
:onChange="handleChange"
|
|
34
|
-
:options="options"
|
|
35
|
-
placeholder="Choose an option"
|
|
36
|
-
/>
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### With Label and Helper Text
|
|
40
|
-
|
|
41
|
-
```stx
|
|
42
|
-
<Select
|
|
43
|
-
label="Country"
|
|
44
|
-
helperText="Select your country of residence"
|
|
45
|
-
:value="country"
|
|
46
|
-
:onChange="(val) => country = val"
|
|
47
|
-
:options="countries"
|
|
48
|
-
required
|
|
49
|
-
/>
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### With Error State
|
|
53
|
-
|
|
54
|
-
```stx
|
|
55
|
-
<Select
|
|
56
|
-
label="Category"
|
|
57
|
-
:value="category"
|
|
58
|
-
:onChange="(val) => category = val"
|
|
59
|
-
:options="categories"
|
|
60
|
-
error
|
|
61
|
-
helperText="Please select a valid category"
|
|
62
|
-
required
|
|
63
|
-
/>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Different Sizes
|
|
67
|
-
|
|
68
|
-
```stx
|
|
69
|
-
<!-- Small -->
|
|
70
|
-
<Select size="sm" :options="options" />
|
|
71
|
-
|
|
72
|
-
<!-- Medium (default) -->
|
|
73
|
-
<Select size="md" :options="options" />
|
|
74
|
-
|
|
75
|
-
<!-- Large -->
|
|
76
|
-
<Select size="lg" :options="options" />
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Disabled State
|
|
80
|
-
|
|
81
|
-
```stx
|
|
82
|
-
<Select disabled value="locked" :options="options" />
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### With Disabled Options
|
|
86
|
-
|
|
87
|
-
```stx
|
|
88
|
-
<script server>
|
|
89
|
-
const options = [
|
|
90
|
-
{ value: '1', label: 'Available Option' },
|
|
91
|
-
{ value: '2', label: 'Disabled Option', disabled: true },
|
|
92
|
-
{ value: '3', label: 'Another Available' },
|
|
93
|
-
]
|
|
94
|
-
</script>
|
|
95
|
-
|
|
96
|
-
<Select :options="options" />
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Props
|
|
100
|
-
|
|
101
|
-
| Prop | Type | Default | Description |
|
|
102
|
-
|------|------|---------|-------------|
|
|
103
|
-
| `value` | `string \| number` | `''` | Selected value |
|
|
104
|
-
| `onChange` | `function` | - | Callback when selection changes |
|
|
105
|
-
| `options` | `SelectOption[]` | `[]` | Array of options |
|
|
106
|
-
| `placeholder` | `string` | `'Select an option'` | Placeholder text |
|
|
107
|
-
| `disabled` | `boolean` | `false` | Disable the select |
|
|
108
|
-
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Select size |
|
|
109
|
-
| `error` | `boolean` | `false` | Show error state |
|
|
110
|
-
| `label` | `string` | `''` | Label text |
|
|
111
|
-
| `helperText` | `string` | `''` | Helper/error text below select |
|
|
112
|
-
| `required` | `boolean` | `false` | Mark as required |
|
|
113
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
114
|
-
|
|
115
|
-
## SelectOption Interface
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
interface SelectOption {
|
|
119
|
-
value: string | number
|
|
120
|
-
label: string
|
|
121
|
-
disabled?: boolean
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Features
|
|
126
|
-
|
|
127
|
-
- **Native select** - Uses native `<select>` element for best UX
|
|
128
|
-
- **3 sizes** - Small, medium, and large
|
|
129
|
-
- **Dark mode** - Full dark mode support
|
|
130
|
-
- **Validation states** - Error and required states
|
|
131
|
-
- **Disabled options** - Individual options can be disabled
|
|
132
|
-
- **Labels and helpers** - Support for labels and helper text
|
|
133
|
-
- **Accessible** - Proper ARIA attributes and labels
|
|
134
|
-
- **Keyboard navigation** - Full keyboard support
|
|
135
|
-
- **Modern ES modules** - Clean export syntax
|
|
136
|
-
- **Headwind styling** - Utility-first CSS classes
|
|
137
|
-
|
|
138
|
-
## Accessibility
|
|
139
|
-
|
|
140
|
-
- Proper `label` associations with `for` attribute
|
|
141
|
-
- `aria-invalid` for error states
|
|
142
|
-
- `aria-describedby` for helper text
|
|
143
|
-
- Required field indicator
|
|
144
|
-
- Disabled state properly communicated
|
|
145
|
-
- Keyboard navigable
|
|
146
|
-
|
|
147
|
-
## Example: Form Select
|
|
148
|
-
|
|
149
|
-
```stx
|
|
150
|
-
<script server>
|
|
151
|
-
const countries = [
|
|
152
|
-
{ value: 'us', label: 'United States' },
|
|
153
|
-
{ value: 'ca', label: 'Canada' },
|
|
154
|
-
{ value: 'mx', label: 'Mexico' },
|
|
155
|
-
{ value: 'uk', label: 'United Kingdom' },
|
|
156
|
-
{ value: 'de', label: 'Germany' },
|
|
157
|
-
]
|
|
158
|
-
|
|
159
|
-
let selectedCountry = ''
|
|
160
|
-
let hasError = false
|
|
161
|
-
|
|
162
|
-
const handleCountryChange = (value) => {
|
|
163
|
-
selectedCountry = value
|
|
164
|
-
hasError = !value
|
|
165
|
-
}
|
|
166
|
-
</script>
|
|
167
|
-
|
|
168
|
-
<form>
|
|
169
|
-
<Select
|
|
170
|
-
label="Country"
|
|
171
|
-
:value="selectedCountry"
|
|
172
|
-
:onChange="handleCountryChange"
|
|
173
|
-
:options="countries"
|
|
174
|
-
placeholder="Select your country"
|
|
175
|
-
required
|
|
176
|
-
:error="hasError"
|
|
177
|
-
:helperText="hasError ? 'Country is required' : 'Choose your country'"
|
|
178
|
-
/>
|
|
179
|
-
</form>
|
|
180
|
-
```
|
package/src/ui/select/Select.stx
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const value = $props.value || ''
|
|
3
|
-
export const options = $props.options || []
|
|
4
|
-
export const placeholder = $props.placeholder || 'Select an option'
|
|
5
|
-
export const disabled = $props.disabled || false
|
|
6
|
-
export const size = $props.size || 'md'
|
|
7
|
-
export const error = $props.error || false
|
|
8
|
-
export const label = $props.label || ''
|
|
9
|
-
export const helperText = $props.helperText || ''
|
|
10
|
-
export const required = $props.required || false
|
|
11
|
-
export const className = $props.className || ''
|
|
12
|
-
|
|
13
|
-
const sizeClasses = { sm: 'px-3 py-1.5 text-sm h-8', md: 'px-4 py-2 text-base h-10', lg: 'px-5 py-3 text-lg h-12' }
|
|
14
|
-
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset dark:bg-blue-gray-700 dark:text-gray-100'
|
|
15
|
-
const stateClasses = error
|
|
16
|
-
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
17
|
-
: 'ring-gray-300 dark:ring-gray-600 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-indigo-600 dark:focus:ring-indigo-400'
|
|
18
|
-
const disabledClasses = disabled
|
|
19
|
-
? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
|
|
20
|
-
: 'bg-white dark:bg-blue-gray-700 cursor-pointer hover:ring-gray-400 dark:hover:ring-gray-500'
|
|
21
|
-
|
|
22
|
-
export const selectClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${className}`.trim()
|
|
23
|
-
export const labelClasses = `block text-sm font-medium leading-6 ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'}`.trim()
|
|
24
|
-
export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
25
|
-
export const selectId = `select-${value}`
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<script client>
|
|
29
|
-
const emit = defineEmits()
|
|
30
|
-
// Reactive prop binding — parent can drive `value` via signals. See #1704.
|
|
31
|
-
const selectedValue = useReactiveProp('value', {{ value }}, { parse: (v) => v == null ? '' : String(v) })
|
|
32
|
-
|
|
33
|
-
function onChange(event) {
|
|
34
|
-
selectedValue.set(event.target.value)
|
|
35
|
-
emit('change', selectedValue())
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
defineExpose({ value: selectedValue })
|
|
39
|
-
</script>
|
|
40
|
-
|
|
41
|
-
<div class="w-full">
|
|
42
|
-
@if(label)
|
|
43
|
-
<label for="{{ selectId }}" class="{{ labelClasses }}">
|
|
44
|
-
{{ label }}
|
|
45
|
-
@if(required)
|
|
46
|
-
<span class="text-red-500 ml-1">*</span>
|
|
47
|
-
@endif
|
|
48
|
-
</label>
|
|
49
|
-
@endif
|
|
50
|
-
|
|
51
|
-
<div class="{{ label ? 'mt-2' : '' }}">
|
|
52
|
-
<select
|
|
53
|
-
id="{{ selectId }}"
|
|
54
|
-
class="{{ selectClasses }}"
|
|
55
|
-
:value="selectedValue()"
|
|
56
|
-
@if(disabled)disabled@endif
|
|
57
|
-
@if(required)required@endif
|
|
58
|
-
@change="onChange($event)"
|
|
59
|
-
:aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
60
|
-
aria-describedby="{{ helperText ? 'helper-text' : '' }}"
|
|
61
|
-
>
|
|
62
|
-
@if(placeholder)
|
|
63
|
-
<option value="" disabled>{{ placeholder }}</option>
|
|
64
|
-
@endif
|
|
65
|
-
|
|
66
|
-
@foreach(option in options)
|
|
67
|
-
<option
|
|
68
|
-
value="{{ option.value }}"
|
|
69
|
-
@if(option.disabled)disabled@endif
|
|
70
|
-
>
|
|
71
|
-
{{ option.label }}
|
|
72
|
-
</option>
|
|
73
|
-
@endforeach
|
|
74
|
-
</select>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
@if(helperText)
|
|
78
|
-
<p id="helper-text" class="{{ helperClasses }}">
|
|
79
|
-
{{ helperText }}
|
|
80
|
-
</p>
|
|
81
|
-
@endif
|
|
82
|
-
</div>
|
package/src/ui/select/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export { default as Select } from './Select.stx'
|
|
2
|
-
|
|
3
|
-
export interface SelectOption {
|
|
4
|
-
value: string | number
|
|
5
|
-
label: string
|
|
6
|
-
disabled?: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface SelectProps {
|
|
10
|
-
value?: string | number
|
|
11
|
-
onChange?: (value: string | number) => void
|
|
12
|
-
options?: SelectOption[]
|
|
13
|
-
placeholder?: string
|
|
14
|
-
disabled?: boolean
|
|
15
|
-
size?: 'sm' | 'md' | 'lg'
|
|
16
|
-
error?: boolean
|
|
17
|
-
label?: string
|
|
18
|
-
helperText?: string
|
|
19
|
-
required?: boolean
|
|
20
|
-
className?: string
|
|
21
|
-
}
|