@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,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reactive localStorage hook with cross-tab synchronization
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* ```ts
|
|
6
|
-
* const { value, setValue, removeValue } = useLocalStorage('user', { name: 'John' })
|
|
7
|
-
*
|
|
8
|
-
* setValue({ name: 'Jane' })
|
|
9
|
-
* setValue(prev => ({ ...prev, age: 30 }))
|
|
10
|
-
* removeValue()
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Options for useLocalStorage hook
|
|
16
|
-
*/
|
|
17
|
-
export interface UseLocalStorageOptions<T> {
|
|
18
|
-
/** Custom serializer function - defaults to JSON.stringify */
|
|
19
|
-
serializer?: (value: T) => string
|
|
20
|
-
/** Custom deserializer function - defaults to JSON.parse */
|
|
21
|
-
deserializer?: (value: string) => T
|
|
22
|
-
/** Error handler function */
|
|
23
|
-
onError?: (error: Error) => void
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Hook for reactive localStorage with cross-tab sync
|
|
28
|
-
*
|
|
29
|
-
* @param key - Storage key
|
|
30
|
-
* @param initialValue - Initial value if key doesn't exist
|
|
31
|
-
* @param options - Configuration options
|
|
32
|
-
* @returns Object with value, setValue, and removeValue
|
|
33
|
-
*/
|
|
34
|
-
export function useLocalStorage<T>(
|
|
35
|
-
key: string,
|
|
36
|
-
initialValue: T,
|
|
37
|
-
options: UseLocalStorageOptions<T> = {},
|
|
38
|
-
): {
|
|
39
|
-
value: T
|
|
40
|
-
setValue: (newValue: T | ((_prev: T) => T)) => void
|
|
41
|
-
removeValue: () => void
|
|
42
|
-
} {
|
|
43
|
-
const {
|
|
44
|
-
serializer = JSON.stringify,
|
|
45
|
-
deserializer = JSON.parse,
|
|
46
|
-
onError = console.error,
|
|
47
|
-
} = options
|
|
48
|
-
|
|
49
|
-
// Get initial value from storage
|
|
50
|
-
let storedValue: T = initialValue
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
if (typeof window !== 'undefined') {
|
|
54
|
-
const item = window.localStorage.getItem(key)
|
|
55
|
-
if (item !== null) {
|
|
56
|
-
storedValue = deserializer(item)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
onError(error as Error)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
let value = storedValue
|
|
65
|
-
const listeners = new Set<(newValue: T) => void>()
|
|
66
|
-
|
|
67
|
-
// Set value
|
|
68
|
-
function setValue(newValue: T | ((prev: T) => T)) {
|
|
69
|
-
try {
|
|
70
|
-
// Allow value to be a function for same API as useState
|
|
71
|
-
const valueToStore = typeof newValue === 'function' ? (newValue as (_prev: T) => T)(value) : newValue
|
|
72
|
-
|
|
73
|
-
value = valueToStore
|
|
74
|
-
|
|
75
|
-
// Save to localStorage
|
|
76
|
-
if (typeof window !== 'undefined') {
|
|
77
|
-
window.localStorage.setItem(key, serializer(valueToStore))
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Notify listeners
|
|
81
|
-
listeners.forEach(listener => listener(valueToStore))
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
onError(error as Error)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Remove value
|
|
89
|
-
function removeValue() {
|
|
90
|
-
try {
|
|
91
|
-
value = initialValue
|
|
92
|
-
|
|
93
|
-
if (typeof window !== 'undefined') {
|
|
94
|
-
window.localStorage.removeItem(key)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Notify listeners
|
|
98
|
-
listeners.forEach(listener => listener(initialValue))
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
onError(error as Error)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Listen for storage events (changes from other tabs/windows)
|
|
106
|
-
if (typeof window !== 'undefined') {
|
|
107
|
-
const handleStorageChange = (event: StorageEvent) => {
|
|
108
|
-
if (event.key === key && event.newValue !== null) {
|
|
109
|
-
try {
|
|
110
|
-
const newValue = deserializer(event.newValue)
|
|
111
|
-
value = newValue
|
|
112
|
-
listeners.forEach(listener => listener(newValue))
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
onError(error as Error)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else if (event.key === key && event.newValue === null) {
|
|
119
|
-
value = initialValue
|
|
120
|
-
listeners.forEach(listener => listener(initialValue))
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
window.addEventListener('storage', handleStorageChange)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
value,
|
|
129
|
-
setValue,
|
|
130
|
-
removeValue,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook for responsive media queries
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* ```ts
|
|
6
|
-
* const { matches } = useMediaQuery('(min-width: 768px)')
|
|
7
|
-
* const { matches: isDark } = useIsDarkMode()
|
|
8
|
-
* const { matches: isMobile } = useIsMobile()
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Options for useMediaQuery hook
|
|
14
|
-
*/
|
|
15
|
-
export interface UseMediaQueryOptions {
|
|
16
|
-
/** Default value when window.matchMedia is not available */
|
|
17
|
-
defaultValue?: boolean
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Hook for responsive media queries
|
|
22
|
-
*
|
|
23
|
-
* @param query - Media query string
|
|
24
|
-
* @param options - Configuration options
|
|
25
|
-
* @returns Object with matches boolean and updateMatches function
|
|
26
|
-
*/
|
|
27
|
-
export function useMediaQuery(
|
|
28
|
-
query: string,
|
|
29
|
-
options: UseMediaQueryOptions = {},
|
|
30
|
-
): { matches: boolean, updateMatches: () => void } {
|
|
31
|
-
const { defaultValue = false } = options
|
|
32
|
-
|
|
33
|
-
let matches = defaultValue
|
|
34
|
-
let mediaQueryList: MediaQueryList | null = null
|
|
35
|
-
|
|
36
|
-
// Initialize
|
|
37
|
-
if (typeof window !== 'undefined' && 'matchMedia' in window) {
|
|
38
|
-
mediaQueryList = window.matchMedia(query)
|
|
39
|
-
matches = mediaQueryList.matches
|
|
40
|
-
|
|
41
|
-
// Listen for changes
|
|
42
|
-
const handleChange = (event: MediaQueryListEvent) => {
|
|
43
|
-
matches = event.matches
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (mediaQueryList.addEventListener) {
|
|
47
|
-
mediaQueryList.addEventListener('change', handleChange)
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// Fallback for older browsers
|
|
51
|
-
mediaQueryList.addListener(handleChange)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function updateMatches() {
|
|
56
|
-
if (mediaQueryList) {
|
|
57
|
-
matches = mediaQueryList.matches
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return { matches, updateMatches }
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Common responsive breakpoints
|
|
66
|
-
*/
|
|
67
|
-
export const Breakpoints = {
|
|
68
|
-
'xs': '(min-width: 320px)',
|
|
69
|
-
'sm': '(min-width: 640px)',
|
|
70
|
-
'md': '(min-width: 768px)',
|
|
71
|
-
'lg': '(min-width: 1024px)',
|
|
72
|
-
'xl': '(min-width: 1280px)',
|
|
73
|
-
'2xl': '(min-width: 1536px)',
|
|
74
|
-
'mobile': '(max-width: 767px)',
|
|
75
|
-
'tablet': '(min-width: 768px) and (max-width: 1023px)',
|
|
76
|
-
'desktop': '(min-width: 1024px)',
|
|
77
|
-
'dark': '(prefers-color-scheme: dark)',
|
|
78
|
-
'light': '(prefers-color-scheme: light)',
|
|
79
|
-
'reducedMotion': '(prefers-reduced-motion: reduce)',
|
|
80
|
-
'portrait': '(orientation: portrait)',
|
|
81
|
-
'landscape': '(orientation: landscape)',
|
|
82
|
-
} as const
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Use a predefined breakpoint
|
|
86
|
-
* @param breakpoint - Breakpoint name from Breakpoints constant
|
|
87
|
-
*/
|
|
88
|
-
export function useBreakpoint(breakpoint: keyof typeof Breakpoints): { matches: boolean, updateMatches: () => void } {
|
|
89
|
-
return useMediaQuery(Breakpoints[breakpoint])
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Check if viewport is mobile (max-width: 767px)
|
|
94
|
-
*/
|
|
95
|
-
export function useIsMobile(): { matches: boolean, updateMatches: () => void } {
|
|
96
|
-
return useMediaQuery(Breakpoints.mobile)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Check if viewport is desktop (min-width: 1024px)
|
|
101
|
-
*/
|
|
102
|
-
export function useIsDesktop(): { matches: boolean, updateMatches: () => void } {
|
|
103
|
-
return useMediaQuery(Breakpoints.desktop)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Check if user prefers dark color scheme
|
|
108
|
-
*/
|
|
109
|
-
export function useIsDarkMode(): { matches: boolean, updateMatches: () => void } {
|
|
110
|
-
return useMediaQuery(Breakpoints.dark)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Check if user prefers reduced motion
|
|
115
|
-
*/
|
|
116
|
-
export function usePrefersReducedMotion(): { matches: boolean, updateMatches: () => void } {
|
|
117
|
-
return useMediaQuery(Breakpoints.reducedMotion)
|
|
118
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// Export shared components (these will be imported as .stx files)
|
|
2
|
-
export { default as CodeBlock } from './components/CodeBlock.stx'
|
|
3
|
-
|
|
4
|
-
export { default as Footer } from './components/Footer.stx'
|
|
5
|
-
export { default as Hero } from './components/Hero.stx'
|
|
6
|
-
export { default as Installation } from './components/Installation.stx'
|
|
7
|
-
// Export composables
|
|
8
|
-
export * from './composables'
|
|
9
|
-
// Export UI components
|
|
10
|
-
export * from './ui/accordion'
|
|
11
|
-
export * from './ui/audio'
|
|
12
|
-
export * from './ui/auth'
|
|
13
|
-
export * from './ui/avatar'
|
|
14
|
-
export * from './ui/badge'
|
|
15
|
-
|
|
16
|
-
export * from './ui/breadcrumb'
|
|
17
|
-
export * from './ui/button'
|
|
18
|
-
export * from './ui/calendar'
|
|
19
|
-
export * from './ui/card'
|
|
20
|
-
|
|
21
|
-
export * from './ui/checkbox'
|
|
22
|
-
export * from './ui/combobox'
|
|
23
|
-
export * from './ui/command-palette'
|
|
24
|
-
export * from './ui/dialog'
|
|
25
|
-
export * from './ui/drawer'
|
|
26
|
-
export * from './ui/dropdown'
|
|
27
|
-
export * from './ui/form'
|
|
28
|
-
export * from './ui/image'
|
|
29
|
-
export * from './ui/input'
|
|
30
|
-
export * from './ui/listbox'
|
|
31
|
-
export * from './ui/navigator'
|
|
32
|
-
export * from './ui/notification'
|
|
33
|
-
export * from './ui/pagination'
|
|
34
|
-
export * from './ui/payment'
|
|
35
|
-
export * from './ui/popover'
|
|
36
|
-
export * from './ui/portal'
|
|
37
|
-
export * from './ui/progress'
|
|
38
|
-
export * from './ui/radio'
|
|
39
|
-
export * from './ui/radio-group'
|
|
40
|
-
export * from './ui/select'
|
|
41
|
-
export * from './ui/sidebar'
|
|
42
|
-
export * from './ui/skeleton'
|
|
43
|
-
export * from './ui/spinner'
|
|
44
|
-
export * from './ui/stepper'
|
|
45
|
-
export * from './ui/storage'
|
|
46
|
-
export * from './ui/switch'
|
|
47
|
-
export * from './ui/table'
|
|
48
|
-
export * from './ui/tabs'
|
|
49
|
-
export * from './ui/teleport'
|
|
50
|
-
export * from './ui/textarea'
|
|
51
|
-
export * from './ui/tooltip'
|
|
52
|
-
export * from './ui/transition'
|
|
53
|
-
export * from './ui/video'
|
|
54
|
-
export * from './ui/virtual-list'
|
|
55
|
-
export * from './ui/virtual-table'
|
|
56
|
-
export * from './utils/accessibility'
|
|
57
|
-
export * from './utils/animation'
|
|
58
|
-
export * from './utils/error-handling'
|
|
59
|
-
// Export utilities
|
|
60
|
-
export * from './utils/highlighter'
|
|
61
|
-
export * from './utils/i18n'
|
|
62
|
-
export * from './utils/keep-alive'
|
|
63
|
-
export * from './utils/lazy-loading'
|
|
64
|
-
export * from './utils/prop-validation'
|
|
65
|
-
export * from './utils/theme'
|
|
66
|
-
|
|
67
|
-
// Types
|
|
68
|
-
export interface ComponentProps {
|
|
69
|
-
className?: string
|
|
70
|
-
[key: string]: any
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface CodeBlockProps extends ComponentProps {
|
|
74
|
-
code: string
|
|
75
|
-
language?: string
|
|
76
|
-
theme?: 'light' | 'dark' | 'auto'
|
|
77
|
-
lineNumbers?: boolean
|
|
78
|
-
copyable?: boolean
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface HeroProps extends ComponentProps {
|
|
82
|
-
title?: string
|
|
83
|
-
description?: string
|
|
84
|
-
githubUrl?: string
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface FooterProps extends ComponentProps {
|
|
88
|
-
author?: string
|
|
89
|
-
authorUrl?: string
|
|
90
|
-
project?: string
|
|
91
|
-
projectUrl?: string
|
|
92
|
-
twitterUrl?: string
|
|
93
|
-
sponsorUrl?: string
|
|
94
|
-
coffeeUrl?: string
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface InstallationProps extends ComponentProps {
|
|
98
|
-
packageName?: string
|
|
99
|
-
}
|
package/src/stx.d.ts
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
// Two modes (see stacksjs/stx#1703):
|
|
3
|
-
// 1. Legacy prop API — pass `items={[{title, content}, …]}` for simple
|
|
4
|
-
// string-content accordions (kept for backward compatibility with
|
|
5
|
-
// existing visual snapshots and consumers).
|
|
6
|
-
// 2. Slot API — drop `<AccordionItem title="…">` children for arbitrary
|
|
7
|
-
// content. Each AccordionItem renders its own header + content panel;
|
|
8
|
-
// this parent attaches click handlers and toggles content visibility.
|
|
9
|
-
export const items = $props.items || []
|
|
10
|
-
export const allowMultiple = $props.allowMultiple || false
|
|
11
|
-
export const defaultOpen = $props.defaultOpen || []
|
|
12
|
-
export const className = $props.className || ''
|
|
13
|
-
|
|
14
|
-
export const accordionClasses = `divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg ${className}`.trim()
|
|
15
|
-
export const headerClasses = `w-full flex items-center justify-between px-4 py-3 text-left font-medium text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900`.trim()
|
|
16
|
-
export const iconClasses = `w-5 h-5 text-gray-500 dark:text-gray-400 transition-transform duration-200`.trim()
|
|
17
|
-
export const contentClasses = `px-4 py-3 text-gray-700 dark:text-gray-300`.trim()
|
|
18
|
-
export const hasPropItems = Array.isArray(items) && items.length > 0
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
<script client>
|
|
22
|
-
const emit = defineEmits()
|
|
23
|
-
const allowMultiple = {{ allowMultiple }}
|
|
24
|
-
const hasPropItems = {{ hasPropItems }}
|
|
25
|
-
const containerRef = useRef()
|
|
26
|
-
const openItems = state({{ defaultOpen }})
|
|
27
|
-
|
|
28
|
-
function findOwnItems() {
|
|
29
|
-
const root = containerRef.value
|
|
30
|
-
if (!root) return []
|
|
31
|
-
return Array.from(root.querySelectorAll('[data-stx-accordion-item]'))
|
|
32
|
-
.filter(item => item.closest('[data-stx-accordion]') === root)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
onMount(() => {
|
|
36
|
-
if (hasPropItems) return // legacy mode: server-rendered, no wiring needed
|
|
37
|
-
const items = findOwnItems()
|
|
38
|
-
items.forEach((item, idx) => {
|
|
39
|
-
const header = item.querySelector(':scope > [data-stx-accordion-header]')
|
|
40
|
-
if (header && !header.__stx_wired) {
|
|
41
|
-
header.__stx_wired = true
|
|
42
|
-
header.addEventListener('click', () => toggleItem(idx))
|
|
43
|
-
header.addEventListener('keydown', (e) => onHeaderKey(e, idx))
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
// Sync the open state into the DOM: show/hide content panels, update
|
|
49
|
-
// aria-expanded on headers, rotate chevrons.
|
|
50
|
-
effect(() => {
|
|
51
|
-
if (hasPropItems) return
|
|
52
|
-
const items = findOwnItems()
|
|
53
|
-
const open = openItems()
|
|
54
|
-
items.forEach((item, idx) => {
|
|
55
|
-
const isOpenItem = open.includes(idx)
|
|
56
|
-
const header = item.querySelector(':scope > [data-stx-accordion-header]')
|
|
57
|
-
const content = item.querySelector(':scope > [data-stx-accordion-content]')
|
|
58
|
-
const chevron = item.querySelector(':scope > [data-stx-accordion-header] [data-stx-accordion-chevron]')
|
|
59
|
-
if (header) header.setAttribute('aria-expanded', isOpenItem ? 'true' : 'false')
|
|
60
|
-
if (content) {
|
|
61
|
-
if (isOpenItem) content.removeAttribute('hidden')
|
|
62
|
-
else content.setAttribute('hidden', '')
|
|
63
|
-
}
|
|
64
|
-
if (chevron) chevron.style.transform = `rotate(${isOpenItem ? 180 : 0}deg)`
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
function toggleItem(index) {
|
|
69
|
-
const cur = openItems()
|
|
70
|
-
if (allowMultiple) {
|
|
71
|
-
openItems.set(cur.includes(index) ? cur.filter(i => i !== index) : [...cur, index])
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
openItems.set(cur.includes(index) ? [] : [index])
|
|
75
|
-
}
|
|
76
|
-
emit('change', openItems())
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function isOpen(index) {
|
|
80
|
-
return openItems().includes(index)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function onHeaderKey(event, index) {
|
|
84
|
-
const root = containerRef.value
|
|
85
|
-
if (!root) return
|
|
86
|
-
const buttons = root.querySelectorAll('button[data-stx-accordion-header], button[data-accordion-header]')
|
|
87
|
-
if (event.key === 'ArrowDown') {
|
|
88
|
-
event.preventDefault()
|
|
89
|
-
buttons[index + 1]?.focus()
|
|
90
|
-
}
|
|
91
|
-
else if (event.key === 'ArrowUp') {
|
|
92
|
-
event.preventDefault()
|
|
93
|
-
buttons[index - 1]?.focus()
|
|
94
|
-
}
|
|
95
|
-
else if (event.key === 'Home') {
|
|
96
|
-
event.preventDefault()
|
|
97
|
-
buttons[0]?.focus()
|
|
98
|
-
}
|
|
99
|
-
else if (event.key === 'End') {
|
|
100
|
-
event.preventDefault()
|
|
101
|
-
buttons[buttons.length - 1]?.focus()
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
defineExpose({ openItems, toggleItem })
|
|
106
|
-
</script>
|
|
107
|
-
|
|
108
|
-
<div x-ref="containerRef" data-stx-accordion class="{{ accordionClasses }}" role="region">
|
|
109
|
-
@if(hasPropItems)
|
|
110
|
-
@foreach(item in items)
|
|
111
|
-
<div>
|
|
112
|
-
<button
|
|
113
|
-
type="button"
|
|
114
|
-
data-accordion-header
|
|
115
|
-
class="{{ headerClasses }}"
|
|
116
|
-
@click="toggleItem({{ $loop.index }})"
|
|
117
|
-
@keydown="onHeaderKey($event, {{ $loop.index }})"
|
|
118
|
-
:aria-expanded="isOpen({{ $loop.index }}) ? 'true' : 'false'"
|
|
119
|
-
aria-controls="accordion-content-{{ $loop.index }}"
|
|
120
|
-
>
|
|
121
|
-
<span>{{ item.title }}</span>
|
|
122
|
-
<svg
|
|
123
|
-
class="{{ iconClasses }}"
|
|
124
|
-
:style="`transform: rotate(${isOpen({{ $loop.index }}) ? 180 : 0}deg)`"
|
|
125
|
-
fill="none"
|
|
126
|
-
viewBox="0 0 24 24"
|
|
127
|
-
stroke="currentColor"
|
|
128
|
-
>
|
|
129
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
130
|
-
</svg>
|
|
131
|
-
</button>
|
|
132
|
-
|
|
133
|
-
<div
|
|
134
|
-
:show="isOpen({{ $loop.index }})"
|
|
135
|
-
id="accordion-content-{{ $loop.index }}"
|
|
136
|
-
class="{{ contentClasses }}"
|
|
137
|
-
role="region"
|
|
138
|
-
>
|
|
139
|
-
{!! item.content !!}
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
@endforeach
|
|
143
|
-
@else
|
|
144
|
-
<slot />
|
|
145
|
-
@endif
|
|
146
|
-
</div>
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
// Slot wrapper that the parent <Accordion> discovers and wires up on mount.
|
|
3
|
-
// Renders its own header button + content panel; the parent attaches click
|
|
4
|
-
// handlers and toggles the content panel's `hidden` attribute as openItems
|
|
5
|
-
// changes. Hard-coded styling here matches the legacy prop-mode markup so
|
|
6
|
-
// snapshots compare cleanly in both modes. See stacksjs/stx#1703.
|
|
7
|
-
export const title = $props.title || ''
|
|
8
|
-
export const className = $props.className || ''
|
|
9
|
-
|
|
10
|
-
const headerClasses = 'w-full flex items-center justify-between px-4 py-3 text-left font-medium text-gray-900 dark:text-gray-100 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900'
|
|
11
|
-
const iconClasses = 'w-5 h-5 text-gray-500 dark:text-gray-400 transition-transform duration-200'
|
|
12
|
-
const contentClasses = 'px-4 py-3 text-gray-700 dark:text-gray-300'
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<div data-stx-accordion-item data-title="{{ title }}" class="{{ className }}">
|
|
16
|
-
<button
|
|
17
|
-
type="button"
|
|
18
|
-
data-stx-accordion-header
|
|
19
|
-
data-accordion-header
|
|
20
|
-
class="{{ headerClasses }}"
|
|
21
|
-
aria-expanded="false"
|
|
22
|
-
>
|
|
23
|
-
<span>{{ title }}</span>
|
|
24
|
-
<svg
|
|
25
|
-
data-stx-accordion-chevron
|
|
26
|
-
class="{{ iconClasses }}"
|
|
27
|
-
fill="none"
|
|
28
|
-
viewBox="0 0 24 24"
|
|
29
|
-
stroke="currentColor"
|
|
30
|
-
>
|
|
31
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
|
32
|
-
</svg>
|
|
33
|
-
</button>
|
|
34
|
-
<div data-stx-accordion-content class="{{ contentClasses }}" role="region" hidden>
|
|
35
|
-
<slot />
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export { default as Accordion } from './Accordion.stx'
|
|
2
|
-
export { default as AccordionItem } from './AccordionItem.stx'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Legacy prop API — pass `items` as an array of `{ title, content }` where
|
|
6
|
-
* `content` is a HTML string. Kept for backward compatibility; prefer the
|
|
7
|
-
* slot API below for any accordion whose content needs to be a component tree.
|
|
8
|
-
*
|
|
9
|
-
* See stacksjs/stx#1703.
|
|
10
|
-
*/
|
|
11
|
-
export interface AccordionLegacyItem {
|
|
12
|
-
title: string
|
|
13
|
-
content: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type AccordionItemDefinition = AccordionLegacyItem
|
|
17
|
-
|
|
18
|
-
export interface AccordionProps {
|
|
19
|
-
/** Legacy: array of item definitions with string content. */
|
|
20
|
-
items?: AccordionItemDefinition[]
|
|
21
|
-
allowMultiple?: boolean
|
|
22
|
-
defaultOpen?: number[]
|
|
23
|
-
onChange?: (openItems: number[]) => void
|
|
24
|
-
className?: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Slot API — wrap each section's content in `<AccordionItem title="…">`.
|
|
29
|
-
* Each `<AccordionItem>` renders its own header + content panel; the parent
|
|
30
|
-
* `<Accordion>` attaches click handlers and toggles the content visibility.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```html
|
|
34
|
-
* <Accordion allowMultiple>
|
|
35
|
-
* <AccordionItem title="Profile">
|
|
36
|
-
* <ProfileEditor :user="user()" />
|
|
37
|
-
* </AccordionItem>
|
|
38
|
-
* <AccordionItem title="Zones">
|
|
39
|
-
* <ZonesEditor />
|
|
40
|
-
* </AccordionItem>
|
|
41
|
-
* </Accordion>
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export interface AccordionItemProps {
|
|
45
|
-
title: string
|
|
46
|
-
className?: string
|
|
47
|
-
}
|
package/src/ui/audio/Audio.stx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const src = $props.src || ''
|
|
3
|
-
export const autoplay = $props.autoplay || false
|
|
4
|
-
export const loop = $props.loop || false
|
|
5
|
-
export const muted = $props.muted || false
|
|
6
|
-
export const controls = $props.controls ?? true
|
|
7
|
-
export const preload = $props.preload || 'metadata'
|
|
8
|
-
export const className = $props.className || ''
|
|
9
|
-
export const showWaveform = $props.showWaveform || false
|
|
10
|
-
export const title = $props.title || ''
|
|
11
|
-
|
|
12
|
-
export const containerClasses = `relative w-full ${className}`.trim()
|
|
13
|
-
export const audioClasses = 'w-full rounded-md bg-gray-100 dark:bg-gray-800'
|
|
14
|
-
</script>
|
|
15
|
-
|
|
16
|
-
<div class="{{ containerClasses }}">
|
|
17
|
-
@if(title)
|
|
18
|
-
<div class="mb-2 px-1">
|
|
19
|
-
<h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
20
|
-
{{ title }}
|
|
21
|
-
</h3>
|
|
22
|
-
</div>
|
|
23
|
-
@endif
|
|
24
|
-
|
|
25
|
-
<audio
|
|
26
|
-
class="{{ audioClasses }}"
|
|
27
|
-
src="{{ src }}"
|
|
28
|
-
@if(controls)controls@endif
|
|
29
|
-
@if(autoplay)autoplay@endif
|
|
30
|
-
@if(loop)loop@endif
|
|
31
|
-
@if(muted)muted@endif
|
|
32
|
-
preload="{{ preload }}"
|
|
33
|
-
>
|
|
34
|
-
Your browser does not support the audio element.
|
|
35
|
-
</audio>
|
|
36
|
-
|
|
37
|
-
@if(showWaveform)
|
|
38
|
-
<div class="mt-2 h-16 bg-gray-100 dark:bg-gray-800 rounded-md flex items-center justify-center">
|
|
39
|
-
<svg class="w-full h-full px-4" viewBox="0 0 100 40" preserveAspectRatio="none">
|
|
40
|
-
<path
|
|
41
|
-
d="M 0,20 L 10,15 L 20,10 L 30,5 L 40,15 L 50,20 L 60,25 L 70,30 L 80,20 L 90,15 L 100,20"
|
|
42
|
-
fill="none"
|
|
43
|
-
stroke="currentColor"
|
|
44
|
-
stroke-width="2"
|
|
45
|
-
class="text-indigo-500 dark:text-indigo-400"
|
|
46
|
-
/>
|
|
47
|
-
</svg>
|
|
48
|
-
</div>
|
|
49
|
-
@endif
|
|
50
|
-
</div>
|
package/src/ui/audio/README.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# Audio Component
|
|
2
|
-
|
|
3
|
-
A styled audio player with optional waveform visualization.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun add @stacksjs/components
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
```stx
|
|
14
|
-
<Audio
|
|
15
|
-
src="/audio/podcast.mp3"
|
|
16
|
-
title="Episode 42: Building with STX"
|
|
17
|
-
controls
|
|
18
|
-
/>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Props
|
|
22
|
-
|
|
23
|
-
| Prop | Type | Default | Description |
|
|
24
|
-
|------|------|---------|-------------|
|
|
25
|
-
| `src` | `string` | - | Audio file URL (required) |
|
|
26
|
-
| `autoplay` | `boolean` | `false` | Auto-play on load |
|
|
27
|
-
| `loop` | `boolean` | `false` | Loop playback |
|
|
28
|
-
| `muted` | `boolean` | `false` | Start muted |
|
|
29
|
-
| `controls` | `boolean` | `true` | Show native controls |
|
|
30
|
-
| `preload` | `'none' \| 'metadata' \| 'auto'` | `'metadata'` | Preload strategy |
|
|
31
|
-
| `className` | `string` | `''` | Additional CSS classes |
|
|
32
|
-
| `showWaveform` | `boolean` | `false` | Show waveform visualization |
|
|
33
|
-
| `title` | `string` | `''` | Optional title above player |
|
|
34
|
-
|
|
35
|
-
## Features
|
|
36
|
-
|
|
37
|
-
- **Native controls** - Uses browser's native audio controls
|
|
38
|
-
- **Dark mode** - Styled for dark mode
|
|
39
|
-
- **Waveform** - Optional visual waveform display
|
|
40
|
-
- **Accessible** - Proper fallback text
|
|
41
|
-
- **Responsive** - Full-width design
|
package/src/ui/audio/index.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export { default as Audio } from './Audio.stx'
|
|
2
|
-
|
|
3
|
-
export interface AudioProps {
|
|
4
|
-
src: string
|
|
5
|
-
autoplay?: boolean
|
|
6
|
-
loop?: boolean
|
|
7
|
-
muted?: boolean
|
|
8
|
-
controls?: boolean
|
|
9
|
-
preload?: 'none' | 'metadata' | 'auto'
|
|
10
|
-
className?: string
|
|
11
|
-
showWaveform?: boolean
|
|
12
|
-
title?: string
|
|
13
|
-
}
|