@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.
Files changed (187) hide show
  1. package/dist/index.js +4 -4
  2. package/package.json +5 -6
  3. package/src/components/CodeBlock.stx +0 -54
  4. package/src/components/Footer.stx +0 -66
  5. package/src/components/Hero.stx +0 -25
  6. package/src/components/Installation.stx +0 -37
  7. package/src/components/index.ts +0 -4
  8. package/src/composables/index.ts +0 -4
  9. package/src/composables/useCopyCode.ts +0 -73
  10. package/src/composables/useDarkMode.ts +0 -100
  11. package/src/composables/useSEO.ts +0 -230
  12. package/src/composables/utilities/index.ts +0 -7
  13. package/src/composables/utilities/useClickOutside.ts +0 -72
  14. package/src/composables/utilities/useFocusTrap.ts +0 -159
  15. package/src/composables/utilities/useKeyboard.ts +0 -124
  16. package/src/composables/utilities/useLocalStorage.ts +0 -132
  17. package/src/composables/utilities/useMediaQuery.ts +0 -118
  18. package/src/index.ts +0 -99
  19. package/src/stx.d.ts +0 -4
  20. package/src/ui/accordion/Accordion.stx +0 -146
  21. package/src/ui/accordion/AccordionItem.stx +0 -37
  22. package/src/ui/accordion/index.ts +0 -47
  23. package/src/ui/audio/Audio.stx +0 -50
  24. package/src/ui/audio/README.md +0 -41
  25. package/src/ui/audio/index.ts +0 -13
  26. package/src/ui/auth/Login.stx +0 -161
  27. package/src/ui/auth/README.md +0 -142
  28. package/src/ui/auth/Signup.stx +0 -159
  29. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  30. package/src/ui/auth/index.ts +0 -32
  31. package/src/ui/avatar/Avatar.stx +0 -77
  32. package/src/ui/avatar/index.ts +0 -12
  33. package/src/ui/badge/Badge.stx +0 -62
  34. package/src/ui/badge/index.ts +0 -10
  35. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  36. package/src/ui/breadcrumb/index.ts +0 -15
  37. package/src/ui/button/Button.stx +0 -74
  38. package/src/ui/button/README.md +0 -80
  39. package/src/ui/button/index.ts +0 -85
  40. package/src/ui/calendar/Calendar.stx +0 -189
  41. package/src/ui/calendar/README.md +0 -254
  42. package/src/ui/calendar/index.ts +0 -14
  43. package/src/ui/card/Card.stx +0 -68
  44. package/src/ui/card/index.ts +0 -13
  45. package/src/ui/checkbox/Checkbox.stx +0 -86
  46. package/src/ui/checkbox/index.ts +0 -16
  47. package/src/ui/combobox/Combobox.stx +0 -96
  48. package/src/ui/combobox/ComboboxButton.stx +0 -25
  49. package/src/ui/combobox/ComboboxInput.stx +0 -32
  50. package/src/ui/combobox/ComboboxOption.stx +0 -49
  51. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  52. package/src/ui/combobox/README.md +0 -150
  53. package/src/ui/combobox/index.ts +0 -40
  54. package/src/ui/command-palette/CommandPalette.stx +0 -81
  55. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  56. package/src/ui/command-palette/README.md +0 -42
  57. package/src/ui/command-palette/index.ts +0 -15
  58. package/src/ui/dialog/Dialog.stx +0 -41
  59. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  60. package/src/ui/dialog/DialogDescription.stx +0 -11
  61. package/src/ui/dialog/DialogPanel.stx +0 -16
  62. package/src/ui/dialog/DialogTitle.stx +0 -11
  63. package/src/ui/dialog/README.md +0 -121
  64. package/src/ui/dialog/index.ts +0 -32
  65. package/src/ui/drawer/Drawer.stx +0 -120
  66. package/src/ui/drawer/README.md +0 -90
  67. package/src/ui/drawer/index.ts +0 -9
  68. package/src/ui/dropdown/Dropdown.stx +0 -82
  69. package/src/ui/dropdown/DropdownButton.stx +0 -29
  70. package/src/ui/dropdown/DropdownItem.stx +0 -35
  71. package/src/ui/dropdown/DropdownItems.stx +0 -18
  72. package/src/ui/dropdown/README.md +0 -114
  73. package/src/ui/dropdown/index.ts +0 -29
  74. package/src/ui/form/Form.stx +0 -95
  75. package/src/ui/form/index.ts +0 -67
  76. package/src/ui/heatmap/Heatmap.stx +0 -294
  77. package/src/ui/image/Image.stx +0 -165
  78. package/src/ui/image/README.md +0 -164
  79. package/src/ui/image/index.ts +0 -22
  80. package/src/ui/input/EmailInput.stx +0 -30
  81. package/src/ui/input/NumberInput.stx +0 -126
  82. package/src/ui/input/PasswordInput.stx +0 -143
  83. package/src/ui/input/SearchInput.stx +0 -44
  84. package/src/ui/input/TextInput.stx +0 -132
  85. package/src/ui/input/index.ts +0 -180
  86. package/src/ui/listbox/Listbox.stx +0 -101
  87. package/src/ui/listbox/ListboxButton.stx +0 -28
  88. package/src/ui/listbox/ListboxLabel.stx +0 -11
  89. package/src/ui/listbox/ListboxOption.stx +0 -49
  90. package/src/ui/listbox/ListboxOptions.stx +0 -16
  91. package/src/ui/listbox/README.md +0 -135
  92. package/src/ui/listbox/index.ts +0 -39
  93. package/src/ui/navigator/Navigator.stx +0 -113
  94. package/src/ui/navigator/README.md +0 -352
  95. package/src/ui/navigator/index.ts +0 -20
  96. package/src/ui/notification/Notification.stx +0 -117
  97. package/src/ui/notification/README.md +0 -114
  98. package/src/ui/notification/index.ts +0 -12
  99. package/src/ui/pagination/Pagination.stx +0 -150
  100. package/src/ui/pagination/index.ts +0 -11
  101. package/src/ui/payment/Checkout.stx +0 -31
  102. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  103. package/src/ui/payment/PaymentMethods.stx +0 -104
  104. package/src/ui/payment/README.md +0 -345
  105. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  106. package/src/ui/payment/index.ts +0 -59
  107. package/src/ui/popover/Popover.stx +0 -60
  108. package/src/ui/popover/PopoverButton.stx +0 -29
  109. package/src/ui/popover/PopoverPanel.stx +0 -23
  110. package/src/ui/popover/README.md +0 -91
  111. package/src/ui/popover/index.ts +0 -22
  112. package/src/ui/portal/Portal.stx +0 -57
  113. package/src/ui/portal/index.ts +0 -6
  114. package/src/ui/progress/Progress.stx +0 -131
  115. package/src/ui/progress/index.ts +0 -12
  116. package/src/ui/radio/Radio.stx +0 -77
  117. package/src/ui/radio/index.ts +0 -15
  118. package/src/ui/radio-group/README.md +0 -139
  119. package/src/ui/radio-group/RadioGroup.stx +0 -60
  120. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  121. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  123. package/src/ui/radio-group/index.ts +0 -30
  124. package/src/ui/select/README.md +0 -180
  125. package/src/ui/select/Select.stx +0 -82
  126. package/src/ui/select/index.ts +0 -21
  127. package/src/ui/sidebar/Sidebar.stx +0 -476
  128. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  129. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  130. package/src/ui/sidebar/SidebarItem.stx +0 -86
  131. package/src/ui/sidebar/SidebarSection.stx +0 -83
  132. package/src/ui/sidebar/index.ts +0 -153
  133. package/src/ui/sidebar/themes.ts +0 -240
  134. package/src/ui/skeleton/Skeleton.stx +0 -48
  135. package/src/ui/skeleton/index.ts +0 -11
  136. package/src/ui/spinner/Spinner.stx +0 -109
  137. package/src/ui/spinner/index.ts +0 -9
  138. package/src/ui/stepper/README.md +0 -36
  139. package/src/ui/stepper/Stepper.stx +0 -17
  140. package/src/ui/stepper/StepperStep.stx +0 -57
  141. package/src/ui/stepper/index.ts +0 -19
  142. package/src/ui/storage/README.md +0 -193
  143. package/src/ui/storage/index.ts +0 -347
  144. package/src/ui/switch/README.md +0 -114
  145. package/src/ui/switch/Switch.stx +0 -72
  146. package/src/ui/switch/index.ts +0 -10
  147. package/src/ui/table/README.md +0 -39
  148. package/src/ui/table/Table.stx +0 -14
  149. package/src/ui/table/TableBody.stx +0 -10
  150. package/src/ui/table/TableCell.stx +0 -10
  151. package/src/ui/table/TableHead.stx +0 -10
  152. package/src/ui/table/TableHeader.stx +0 -20
  153. package/src/ui/table/TableRow.stx +0 -11
  154. package/src/ui/table/index.ts +0 -35
  155. package/src/ui/tabs/TabPanel.stx +0 -25
  156. package/src/ui/tabs/Tabs.stx +0 -202
  157. package/src/ui/tabs/index.ts +0 -50
  158. package/src/ui/teleport/Teleport.stx +0 -65
  159. package/src/ui/teleport/index.ts +0 -7
  160. package/src/ui/textarea/Textarea.stx +0 -108
  161. package/src/ui/textarea/index.ts +0 -20
  162. package/src/ui/tooltip/Tooltip.stx +0 -71
  163. package/src/ui/tooltip/index.ts +0 -10
  164. package/src/ui/transition/README.md +0 -30
  165. package/src/ui/transition/Transition.stx +0 -102
  166. package/src/ui/transition/index.ts +0 -25
  167. package/src/ui/video/README.md +0 -47
  168. package/src/ui/video/Video.stx +0 -45
  169. package/src/ui/video/index.ts +0 -16
  170. package/src/ui/virtual-list/VirtualList.stx +0 -67
  171. package/src/ui/virtual-list/index.ts +0 -10
  172. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  173. package/src/ui/virtual-table/index.ts +0 -21
  174. package/src/utils/PROP_VALIDATION.md +0 -458
  175. package/src/utils/THEME_SYSTEM.md +0 -702
  176. package/src/utils/accessibility.ts +0 -841
  177. package/src/utils/animation/easing.ts +0 -368
  178. package/src/utils/animation/helpers.ts +0 -223
  179. package/src/utils/animation/index.ts +0 -5
  180. package/src/utils/animation/keyframes.ts +0 -230
  181. package/src/utils/error-handling.ts +0 -475
  182. package/src/utils/highlighter.ts +0 -93
  183. package/src/utils/i18n.ts +0 -634
  184. package/src/utils/keep-alive.ts +0 -819
  185. package/src/utils/lazy-loading.ts +0 -530
  186. package/src/utils/prop-validation.ts +0 -478
  187. 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>
@@ -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>