@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,44 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const value = $props.value || ''
|
|
3
|
-
export const placeholder = $props.placeholder || 'Search...'
|
|
4
|
-
export const disabled = $props.disabled || false
|
|
5
|
-
export const size = $props.size || 'md'
|
|
6
|
-
export const error = $props.error || false
|
|
7
|
-
export const label = $props.label || ''
|
|
8
|
-
export const helperText = $props.helperText || ''
|
|
9
|
-
export const loading = $props.loading || false
|
|
10
|
-
export const className = $props.className || ''
|
|
11
|
-
|
|
12
|
-
export const searchIcon = '<svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>'
|
|
13
|
-
export const spinnerIcon = '<svg class="animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>'
|
|
14
|
-
export const rightIcon = loading ? spinnerIcon : ''
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<script client>
|
|
18
|
-
const emit = defineEmits()
|
|
19
|
-
let searchTimeout = null
|
|
20
|
-
|
|
21
|
-
function onSearchInput(event) {
|
|
22
|
-
const target = event.target
|
|
23
|
-
const value = target?.value ?? event.detail
|
|
24
|
-
if (searchTimeout) clearTimeout(searchTimeout)
|
|
25
|
-
searchTimeout = setTimeout(() => emit('search', value), 300)
|
|
26
|
-
}
|
|
27
|
-
</script>
|
|
28
|
-
|
|
29
|
-
<div @input="onSearchInput($event)">
|
|
30
|
-
<TextInput
|
|
31
|
-
:value="value"
|
|
32
|
-
:placeholder="placeholder"
|
|
33
|
-
:disabled="disabled"
|
|
34
|
-
:size="size"
|
|
35
|
-
:error="error"
|
|
36
|
-
:label="label"
|
|
37
|
-
:helperText="helperText"
|
|
38
|
-
:leftIcon="searchIcon"
|
|
39
|
-
:rightIcon="rightIcon"
|
|
40
|
-
:clearable="!loading"
|
|
41
|
-
:className="className"
|
|
42
|
-
inputClassName="pr-20"
|
|
43
|
-
/>
|
|
44
|
-
</div>
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const value = $props.value || ''
|
|
3
|
-
export const placeholder = $props.placeholder || ''
|
|
4
|
-
export const disabled = $props.disabled || false
|
|
5
|
-
export const readonly = $props.readonly || 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 leftIcon = $props.leftIcon || ''
|
|
12
|
-
export const rightIcon = $props.rightIcon || ''
|
|
13
|
-
export const clearable = $props.clearable || false
|
|
14
|
-
export const maxLength = $props.maxLength
|
|
15
|
-
export const showCount = $props.showCount || false
|
|
16
|
-
export const className = $props.className || ''
|
|
17
|
-
export const inputClassName = $props.inputClassName || ''
|
|
18
|
-
|
|
19
|
-
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' }
|
|
20
|
-
const iconSizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' }
|
|
21
|
-
|
|
22
|
-
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'
|
|
23
|
-
const stateClasses = error
|
|
24
|
-
? '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'
|
|
25
|
-
: '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'
|
|
26
|
-
const disabledClasses = disabled
|
|
27
|
-
? 'opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-800'
|
|
28
|
-
: readonly
|
|
29
|
-
? 'bg-gray-50 dark:bg-gray-800 cursor-default'
|
|
30
|
-
: 'bg-white dark:bg-blue-gray-700'
|
|
31
|
-
const paddingClasses = leftIcon ? 'pl-10' : rightIcon || clearable ? 'pr-10' : ''
|
|
32
|
-
|
|
33
|
-
export const inputClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${paddingClasses} ${inputClassName}`.trim()
|
|
34
|
-
export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'}`.trim()
|
|
35
|
-
export const helperClasses = `mt-2 text-sm ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
|
|
36
|
-
export const iconClasses = iconSizeClasses[size]
|
|
37
|
-
export const inputId = `input-${label}`
|
|
38
|
-
</script>
|
|
39
|
-
|
|
40
|
-
<script client>
|
|
41
|
-
const emit = defineEmits()
|
|
42
|
-
// Reactive prop binding so the parent can drive `value` via signals.
|
|
43
|
-
// Parent listens to @input to push user changes back into its signal.
|
|
44
|
-
// See stacksjs/stx#1704.
|
|
45
|
-
const inputValue = useReactiveProp('value', {{ value }}, { parse: (v) => v == null ? '' : String(v) })
|
|
46
|
-
|
|
47
|
-
function onInput(event) {
|
|
48
|
-
inputValue.set(event.target.value)
|
|
49
|
-
emit('input', inputValue())
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function onClear() {
|
|
53
|
-
inputValue.set('')
|
|
54
|
-
emit('input', '')
|
|
55
|
-
emit('clear')
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const hasValue = derived(() => inputValue().length > 0)
|
|
59
|
-
const charCount = derived(() => `${inputValue().length} / {{ maxLength || 0 }}`)
|
|
60
|
-
|
|
61
|
-
defineExpose({ value: inputValue, clear: onClear })
|
|
62
|
-
</script>
|
|
63
|
-
|
|
64
|
-
<div class="w-full {{ className }}">
|
|
65
|
-
@if(label)
|
|
66
|
-
<label for="{{ inputId }}" class="{{ labelClasses }}">
|
|
67
|
-
{{ label }}
|
|
68
|
-
@if(required)
|
|
69
|
-
<span class="text-red-500 ml-1">*</span>
|
|
70
|
-
@endif
|
|
71
|
-
</label>
|
|
72
|
-
@endif
|
|
73
|
-
|
|
74
|
-
<div class="relative">
|
|
75
|
-
@if(leftIcon)
|
|
76
|
-
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
77
|
-
<span class="{{ iconClasses }} text-gray-400 dark:text-gray-500">{!! leftIcon !!}</span>
|
|
78
|
-
</div>
|
|
79
|
-
@endif
|
|
80
|
-
|
|
81
|
-
<input
|
|
82
|
-
type="text"
|
|
83
|
-
id="{{ inputId }}"
|
|
84
|
-
class="{{ inputClasses }}"
|
|
85
|
-
:value="inputValue()"
|
|
86
|
-
placeholder="{{ placeholder }}"
|
|
87
|
-
@if(disabled)disabled@endif
|
|
88
|
-
@if(readonly)readonly@endif
|
|
89
|
-
@if(required)required@endif
|
|
90
|
-
@if(maxLength)maxlength="{{ maxLength }}"@endif
|
|
91
|
-
@input="onInput($event)"
|
|
92
|
-
:aria-invalid="{{ error ? 'true' : 'false' }}"
|
|
93
|
-
@if(helperText)aria-describedby="helper-text"@endif
|
|
94
|
-
/>
|
|
95
|
-
|
|
96
|
-
@if(clearable)
|
|
97
|
-
<div :show="hasValue() && !{{ disabled }} && !{{ readonly }}" class="absolute inset-y-0 right-0 flex items-center pr-3">
|
|
98
|
-
<button
|
|
99
|
-
type="button"
|
|
100
|
-
@click="onClear()"
|
|
101
|
-
class="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 focus:outline-none"
|
|
102
|
-
aria-label="Clear input"
|
|
103
|
-
>
|
|
104
|
-
<svg class="{{ iconClasses }}" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
105
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
106
|
-
</svg>
|
|
107
|
-
</button>
|
|
108
|
-
</div>
|
|
109
|
-
@endif
|
|
110
|
-
@if(rightIcon && !clearable)
|
|
111
|
-
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
|
|
112
|
-
<span class="{{ iconClasses }} text-gray-400 dark:text-gray-500">{!! rightIcon !!}</span>
|
|
113
|
-
</div>
|
|
114
|
-
@endif
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
@if(helperText || (showCount && maxLength))
|
|
118
|
-
<div class="flex items-center justify-between mt-2">
|
|
119
|
-
@if(helperText)
|
|
120
|
-
<p id="helper-text" class="{{ helperClasses }}">
|
|
121
|
-
{{ helperText }}
|
|
122
|
-
</p>
|
|
123
|
-
@else
|
|
124
|
-
<span></span>
|
|
125
|
-
@endif
|
|
126
|
-
|
|
127
|
-
@if(showCount && maxLength)
|
|
128
|
-
<p class="text-sm text-gray-500 dark:text-gray-400" x-text="charCount()"></p>
|
|
129
|
-
@endif
|
|
130
|
-
</div>
|
|
131
|
-
@endif
|
|
132
|
-
</div>
|
package/src/ui/input/index.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import type { PropSchema, ValidationResult } from '../../utils/prop-validation'
|
|
2
|
-
import { createPropValidator, PropTypes } from '../../utils/prop-validation'
|
|
3
|
-
|
|
4
|
-
export { default as EmailInput } from './EmailInput.stx'
|
|
5
|
-
export { default as NumberInput } from './NumberInput.stx'
|
|
6
|
-
export { default as PasswordInput } from './PasswordInput.stx'
|
|
7
|
-
export { default as SearchInput } from './SearchInput.stx'
|
|
8
|
-
export { default as TextInput } from './TextInput.stx'
|
|
9
|
-
|
|
10
|
-
export interface BaseInputProps {
|
|
11
|
-
value?: string
|
|
12
|
-
onChange?: (value: string) => void
|
|
13
|
-
placeholder?: string
|
|
14
|
-
disabled?: boolean
|
|
15
|
-
readonly?: boolean
|
|
16
|
-
size?: 'sm' | 'md' | 'lg'
|
|
17
|
-
error?: boolean
|
|
18
|
-
label?: string
|
|
19
|
-
helperText?: string
|
|
20
|
-
required?: boolean
|
|
21
|
-
className?: string
|
|
22
|
-
inputClassName?: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface TextInputProps extends BaseInputProps {
|
|
26
|
-
leftIcon?: string
|
|
27
|
-
rightIcon?: string
|
|
28
|
-
clearable?: boolean
|
|
29
|
-
maxLength?: number
|
|
30
|
-
showCount?: boolean
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface EmailInputProps extends Omit<BaseInputProps, 'placeholder'> {
|
|
34
|
-
placeholder?: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface PasswordInputProps extends Omit<BaseInputProps, 'placeholder'> {
|
|
38
|
-
placeholder?: string
|
|
39
|
-
showStrength?: boolean
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface NumberInputProps extends BaseInputProps {
|
|
43
|
-
min?: number
|
|
44
|
-
max?: number
|
|
45
|
-
step?: number
|
|
46
|
-
showControls?: boolean
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface SearchInputProps extends Omit<BaseInputProps, 'placeholder'> {
|
|
50
|
-
placeholder?: string
|
|
51
|
-
onSearch?: (value: string) => void
|
|
52
|
-
loading?: boolean
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Base input prop validation schema
|
|
57
|
-
*/
|
|
58
|
-
const baseInputPropSchema: PropSchema = {
|
|
59
|
-
value: PropTypes.string,
|
|
60
|
-
onChange: PropTypes.func,
|
|
61
|
-
placeholder: PropTypes.string,
|
|
62
|
-
disabled: PropTypes.boolean,
|
|
63
|
-
readonly: PropTypes.boolean,
|
|
64
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
65
|
-
error: PropTypes.boolean,
|
|
66
|
-
label: PropTypes.string,
|
|
67
|
-
helperText: PropTypes.string,
|
|
68
|
-
required: PropTypes.boolean,
|
|
69
|
-
className: PropTypes.string,
|
|
70
|
-
inputClassName: PropTypes.string,
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* TextInput prop validation schema
|
|
75
|
-
*/
|
|
76
|
-
export const textInputPropSchema: PropSchema = {
|
|
77
|
-
value: PropTypes.string,
|
|
78
|
-
onChange: PropTypes.func,
|
|
79
|
-
placeholder: PropTypes.string,
|
|
80
|
-
disabled: PropTypes.boolean,
|
|
81
|
-
readonly: PropTypes.boolean,
|
|
82
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
83
|
-
error: PropTypes.boolean,
|
|
84
|
-
label: PropTypes.string,
|
|
85
|
-
helperText: PropTypes.string,
|
|
86
|
-
required: PropTypes.boolean,
|
|
87
|
-
className: PropTypes.string,
|
|
88
|
-
inputClassName: PropTypes.string,
|
|
89
|
-
leftIcon: PropTypes.string,
|
|
90
|
-
rightIcon: PropTypes.string,
|
|
91
|
-
clearable: PropTypes.boolean,
|
|
92
|
-
maxLength: PropTypes.number,
|
|
93
|
-
showCount: PropTypes.boolean,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* NumberInput prop validation schema
|
|
98
|
-
*/
|
|
99
|
-
export const numberInputPropSchema: PropSchema = {
|
|
100
|
-
value: PropTypes.string,
|
|
101
|
-
onChange: PropTypes.func,
|
|
102
|
-
placeholder: PropTypes.string,
|
|
103
|
-
disabled: PropTypes.boolean,
|
|
104
|
-
readonly: PropTypes.boolean,
|
|
105
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
106
|
-
error: PropTypes.boolean,
|
|
107
|
-
label: PropTypes.string,
|
|
108
|
-
helperText: PropTypes.string,
|
|
109
|
-
required: PropTypes.boolean,
|
|
110
|
-
className: PropTypes.string,
|
|
111
|
-
inputClassName: PropTypes.string,
|
|
112
|
-
min: PropTypes.number,
|
|
113
|
-
max: PropTypes.number,
|
|
114
|
-
step: PropTypes.number,
|
|
115
|
-
showControls: PropTypes.boolean,
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* PasswordInput prop validation schema
|
|
120
|
-
*/
|
|
121
|
-
const passwordInputPropSchema: PropSchema = {
|
|
122
|
-
value: PropTypes.string,
|
|
123
|
-
onChange: PropTypes.func,
|
|
124
|
-
placeholder: PropTypes.string,
|
|
125
|
-
disabled: PropTypes.boolean,
|
|
126
|
-
readonly: PropTypes.boolean,
|
|
127
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
128
|
-
error: PropTypes.boolean,
|
|
129
|
-
label: PropTypes.string,
|
|
130
|
-
helperText: PropTypes.string,
|
|
131
|
-
required: PropTypes.boolean,
|
|
132
|
-
className: PropTypes.string,
|
|
133
|
-
inputClassName: PropTypes.string,
|
|
134
|
-
showStrength: PropTypes.boolean,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* SearchInput prop validation schema
|
|
139
|
-
*/
|
|
140
|
-
const searchInputPropSchema: PropSchema = {
|
|
141
|
-
value: PropTypes.string,
|
|
142
|
-
onChange: PropTypes.func,
|
|
143
|
-
placeholder: PropTypes.string,
|
|
144
|
-
disabled: PropTypes.boolean,
|
|
145
|
-
readonly: PropTypes.boolean,
|
|
146
|
-
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
147
|
-
error: PropTypes.boolean,
|
|
148
|
-
label: PropTypes.string,
|
|
149
|
-
helperText: PropTypes.string,
|
|
150
|
-
required: PropTypes.boolean,
|
|
151
|
-
className: PropTypes.string,
|
|
152
|
-
inputClassName: PropTypes.string,
|
|
153
|
-
onSearch: PropTypes.func,
|
|
154
|
-
loading: PropTypes.boolean,
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Validate TextInput component props
|
|
159
|
-
*/
|
|
160
|
-
export const validateTextInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('TextInput', textInputPropSchema)
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Validate EmailInput component props
|
|
164
|
-
*/
|
|
165
|
-
export const validateEmailInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('EmailInput', baseInputPropSchema)
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Validate PasswordInput component props
|
|
169
|
-
*/
|
|
170
|
-
export const validatePasswordInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('PasswordInput', passwordInputPropSchema)
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Validate NumberInput component props
|
|
174
|
-
*/
|
|
175
|
-
export const validateNumberInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('NumberInput', numberInputPropSchema)
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Validate SearchInput component props
|
|
179
|
-
*/
|
|
180
|
-
export const validateSearchInputProps: (props: Record<string, any>) => ValidationResult = createPropValidator('SearchInput', searchInputPropSchema)
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const value = $props.value
|
|
3
|
-
export const multiple = $props.multiple || false
|
|
4
|
-
export const className = $props.className || ''
|
|
5
|
-
export const as = $props.as || 'div'
|
|
6
|
-
|
|
7
|
-
const baseClasses = 'relative'
|
|
8
|
-
export const listboxClasses = `${baseClasses} ${className}`.trim()
|
|
9
|
-
export const listboxInstanceId = `stx-lb-${Math.random().toString(36).slice(2, 11)}`
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<script client>
|
|
13
|
-
const emit = defineEmits()
|
|
14
|
-
const listboxInstanceId = {{ listboxInstanceId }}
|
|
15
|
-
const multiple = {{ multiple }}
|
|
16
|
-
const initialValue = {{ value === undefined ? 'null' : value }}
|
|
17
|
-
|
|
18
|
-
const isOpen = state(false)
|
|
19
|
-
const selected = state(initialValue)
|
|
20
|
-
let rootEl = null
|
|
21
|
-
let outsideHandler = null
|
|
22
|
-
|
|
23
|
-
function isSelectedValue(v) {
|
|
24
|
-
const cur = selected()
|
|
25
|
-
if (multiple && Array.isArray(cur)) return cur.includes(v)
|
|
26
|
-
return cur === v
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function selectValue(v) {
|
|
30
|
-
if (multiple) {
|
|
31
|
-
const cur = Array.isArray(selected()) ? selected() : []
|
|
32
|
-
selected.set(cur.includes(v) ? cur.filter(x => x !== v) : [...cur, v])
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
selected.set(v)
|
|
36
|
-
isOpen.set(false)
|
|
37
|
-
}
|
|
38
|
-
syncOptionStates()
|
|
39
|
-
emit('change', selected())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function syncOptionStates() {
|
|
43
|
-
if (!rootEl) return
|
|
44
|
-
const options = rootEl.querySelectorAll('[data-stx-listbox-option]')
|
|
45
|
-
for (const opt of options) {
|
|
46
|
-
const raw = opt.dataset.optionValue
|
|
47
|
-
let v
|
|
48
|
-
try { v = JSON.parse(raw ?? 'null') }
|
|
49
|
-
catch { v = raw }
|
|
50
|
-
const sel = isSelectedValue(v)
|
|
51
|
-
opt.setAttribute('aria-selected', sel ? 'true' : 'false')
|
|
52
|
-
opt.setAttribute('data-selected', sel ? 'true' : 'false')
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function open() { if (!isOpen()) { isOpen.set(true); emit('change', selected()) } }
|
|
57
|
-
function close() { if (isOpen()) { isOpen.set(false) } }
|
|
58
|
-
function toggle() { isOpen() ? close() : open() }
|
|
59
|
-
|
|
60
|
-
function onToggle(event) { event.stopPropagation(); toggle() }
|
|
61
|
-
function onSelect(event) {
|
|
62
|
-
event.stopPropagation()
|
|
63
|
-
selectValue(event.detail)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
onMount(() => {
|
|
67
|
-
rootEl = document.querySelector(`[data-listbox-id="${listboxInstanceId}"]`)
|
|
68
|
-
syncOptionStates()
|
|
69
|
-
outsideHandler = (event) => {
|
|
70
|
-
if (!isOpen()) return
|
|
71
|
-
if (rootEl && !rootEl.contains(event.target)) close()
|
|
72
|
-
}
|
|
73
|
-
document.addEventListener('click', outsideHandler, true)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
onDestroy(() => {
|
|
77
|
-
if (outsideHandler) document.removeEventListener('click', outsideHandler, true)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
const dataState = derived(() => isOpen() ? 'open' : 'closed')
|
|
81
|
-
|
|
82
|
-
defineExpose({ isOpen, selected, toggle, open, close, selectValue })
|
|
83
|
-
</script>
|
|
84
|
-
|
|
85
|
-
<component
|
|
86
|
-
:is="{{ as }}"
|
|
87
|
-
class="{{ listboxClasses }}"
|
|
88
|
-
data-stx-listbox
|
|
89
|
-
data-listbox-id="{{ listboxInstanceId }}"
|
|
90
|
-
:data-state="dataState()"
|
|
91
|
-
@stx:listbox-toggle="onToggle($event)"
|
|
92
|
-
@stx:listbox-select="onSelect($event)"
|
|
93
|
-
>
|
|
94
|
-
<slot />
|
|
95
|
-
</component>
|
|
96
|
-
|
|
97
|
-
<style>
|
|
98
|
-
[data-stx-listbox][data-state="closed"] [data-stx-listbox-options] {
|
|
99
|
-
display: none;
|
|
100
|
-
}
|
|
101
|
-
</style>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const className = $props.className || ''
|
|
3
|
-
export const as = $props.as || 'button'
|
|
4
|
-
export const disabled = $props.disabled || false
|
|
5
|
-
|
|
6
|
-
const baseClasses = 'relative w-full cursor-pointer rounded-lg bg-white dark:bg-neutral-800 py-2 pl-3 pr-10 text-left shadow-md 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 focus-visible:ring-offset-blue-300'
|
|
7
|
-
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
|
|
8
|
-
export const buttonClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script client>
|
|
12
|
-
const isDisabled = {{ disabled }}
|
|
13
|
-
|
|
14
|
-
function onClick(event) {
|
|
15
|
-
if (isDisabled) return
|
|
16
|
-
event.currentTarget.dispatchEvent(new CustomEvent('stx:listbox-toggle', { bubbles: true }))
|
|
17
|
-
}
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<component
|
|
21
|
-
:is="{{ as }}"
|
|
22
|
-
class="{{ buttonClasses }}"
|
|
23
|
-
data-stx-listbox-button
|
|
24
|
-
@if(disabled)disabled aria-disabled="true"@endif
|
|
25
|
-
@click="onClick($event)"
|
|
26
|
-
>
|
|
27
|
-
<slot />
|
|
28
|
-
</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,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:listbox-select', { bubbles: true, detail: optionValue }),
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<component
|
|
26
|
-
:is="{{ as }}"
|
|
27
|
-
class="{{ optionClasses }}"
|
|
28
|
-
data-stx-listbox-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-listbox-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-listbox-option][data-selected="false"] [data-stx-listbox-check],
|
|
46
|
-
[data-stx-listbox-option]:not([data-selected]) [data-stx-listbox-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-listbox-options
|
|
13
|
-
role="listbox"
|
|
14
|
-
>
|
|
15
|
-
<slot />
|
|
16
|
-
</component>
|