@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.
Files changed (188) hide show
  1. package/dist/{Sidebar-yb115a2w.stx → Sidebar-4hn7vw4n.stx} +18 -0
  2. package/dist/index.js +5 -5
  3. package/package.json +5 -6
  4. package/src/components/CodeBlock.stx +0 -54
  5. package/src/components/Footer.stx +0 -66
  6. package/src/components/Hero.stx +0 -25
  7. package/src/components/Installation.stx +0 -37
  8. package/src/components/index.ts +0 -4
  9. package/src/composables/index.ts +0 -4
  10. package/src/composables/useCopyCode.ts +0 -73
  11. package/src/composables/useDarkMode.ts +0 -100
  12. package/src/composables/useSEO.ts +0 -230
  13. package/src/composables/utilities/index.ts +0 -7
  14. package/src/composables/utilities/useClickOutside.ts +0 -72
  15. package/src/composables/utilities/useFocusTrap.ts +0 -159
  16. package/src/composables/utilities/useKeyboard.ts +0 -124
  17. package/src/composables/utilities/useLocalStorage.ts +0 -132
  18. package/src/composables/utilities/useMediaQuery.ts +0 -118
  19. package/src/index.ts +0 -99
  20. package/src/stx.d.ts +0 -4
  21. package/src/ui/accordion/Accordion.stx +0 -146
  22. package/src/ui/accordion/AccordionItem.stx +0 -37
  23. package/src/ui/accordion/index.ts +0 -47
  24. package/src/ui/audio/Audio.stx +0 -50
  25. package/src/ui/audio/README.md +0 -41
  26. package/src/ui/audio/index.ts +0 -13
  27. package/src/ui/auth/Login.stx +0 -161
  28. package/src/ui/auth/README.md +0 -142
  29. package/src/ui/auth/Signup.stx +0 -159
  30. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  31. package/src/ui/auth/index.ts +0 -32
  32. package/src/ui/avatar/Avatar.stx +0 -77
  33. package/src/ui/avatar/index.ts +0 -12
  34. package/src/ui/badge/Badge.stx +0 -62
  35. package/src/ui/badge/index.ts +0 -10
  36. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  37. package/src/ui/breadcrumb/index.ts +0 -15
  38. package/src/ui/button/Button.stx +0 -74
  39. package/src/ui/button/README.md +0 -80
  40. package/src/ui/button/index.ts +0 -85
  41. package/src/ui/calendar/Calendar.stx +0 -189
  42. package/src/ui/calendar/README.md +0 -254
  43. package/src/ui/calendar/index.ts +0 -14
  44. package/src/ui/card/Card.stx +0 -68
  45. package/src/ui/card/index.ts +0 -13
  46. package/src/ui/checkbox/Checkbox.stx +0 -86
  47. package/src/ui/checkbox/index.ts +0 -16
  48. package/src/ui/combobox/Combobox.stx +0 -96
  49. package/src/ui/combobox/ComboboxButton.stx +0 -25
  50. package/src/ui/combobox/ComboboxInput.stx +0 -32
  51. package/src/ui/combobox/ComboboxOption.stx +0 -49
  52. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  53. package/src/ui/combobox/README.md +0 -150
  54. package/src/ui/combobox/index.ts +0 -40
  55. package/src/ui/command-palette/CommandPalette.stx +0 -81
  56. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  57. package/src/ui/command-palette/README.md +0 -42
  58. package/src/ui/command-palette/index.ts +0 -15
  59. package/src/ui/dialog/Dialog.stx +0 -41
  60. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  61. package/src/ui/dialog/DialogDescription.stx +0 -11
  62. package/src/ui/dialog/DialogPanel.stx +0 -16
  63. package/src/ui/dialog/DialogTitle.stx +0 -11
  64. package/src/ui/dialog/README.md +0 -121
  65. package/src/ui/dialog/index.ts +0 -32
  66. package/src/ui/drawer/Drawer.stx +0 -120
  67. package/src/ui/drawer/README.md +0 -90
  68. package/src/ui/drawer/index.ts +0 -9
  69. package/src/ui/dropdown/Dropdown.stx +0 -82
  70. package/src/ui/dropdown/DropdownButton.stx +0 -29
  71. package/src/ui/dropdown/DropdownItem.stx +0 -35
  72. package/src/ui/dropdown/DropdownItems.stx +0 -18
  73. package/src/ui/dropdown/README.md +0 -114
  74. package/src/ui/dropdown/index.ts +0 -29
  75. package/src/ui/form/Form.stx +0 -95
  76. package/src/ui/form/index.ts +0 -67
  77. package/src/ui/heatmap/Heatmap.stx +0 -294
  78. package/src/ui/image/Image.stx +0 -165
  79. package/src/ui/image/README.md +0 -164
  80. package/src/ui/image/index.ts +0 -22
  81. package/src/ui/input/EmailInput.stx +0 -30
  82. package/src/ui/input/NumberInput.stx +0 -126
  83. package/src/ui/input/PasswordInput.stx +0 -143
  84. package/src/ui/input/SearchInput.stx +0 -44
  85. package/src/ui/input/TextInput.stx +0 -132
  86. package/src/ui/input/index.ts +0 -180
  87. package/src/ui/listbox/Listbox.stx +0 -101
  88. package/src/ui/listbox/ListboxButton.stx +0 -28
  89. package/src/ui/listbox/ListboxLabel.stx +0 -11
  90. package/src/ui/listbox/ListboxOption.stx +0 -49
  91. package/src/ui/listbox/ListboxOptions.stx +0 -16
  92. package/src/ui/listbox/README.md +0 -135
  93. package/src/ui/listbox/index.ts +0 -39
  94. package/src/ui/navigator/Navigator.stx +0 -113
  95. package/src/ui/navigator/README.md +0 -352
  96. package/src/ui/navigator/index.ts +0 -20
  97. package/src/ui/notification/Notification.stx +0 -117
  98. package/src/ui/notification/README.md +0 -114
  99. package/src/ui/notification/index.ts +0 -12
  100. package/src/ui/pagination/Pagination.stx +0 -150
  101. package/src/ui/pagination/index.ts +0 -11
  102. package/src/ui/payment/Checkout.stx +0 -31
  103. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  104. package/src/ui/payment/PaymentMethods.stx +0 -104
  105. package/src/ui/payment/README.md +0 -345
  106. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  107. package/src/ui/payment/index.ts +0 -59
  108. package/src/ui/popover/Popover.stx +0 -60
  109. package/src/ui/popover/PopoverButton.stx +0 -29
  110. package/src/ui/popover/PopoverPanel.stx +0 -23
  111. package/src/ui/popover/README.md +0 -91
  112. package/src/ui/popover/index.ts +0 -22
  113. package/src/ui/portal/Portal.stx +0 -57
  114. package/src/ui/portal/index.ts +0 -6
  115. package/src/ui/progress/Progress.stx +0 -131
  116. package/src/ui/progress/index.ts +0 -12
  117. package/src/ui/radio/Radio.stx +0 -77
  118. package/src/ui/radio/index.ts +0 -15
  119. package/src/ui/radio-group/README.md +0 -139
  120. package/src/ui/radio-group/RadioGroup.stx +0 -60
  121. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  123. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  124. package/src/ui/radio-group/index.ts +0 -30
  125. package/src/ui/select/README.md +0 -180
  126. package/src/ui/select/Select.stx +0 -82
  127. package/src/ui/select/index.ts +0 -21
  128. package/src/ui/sidebar/Sidebar.stx +0 -458
  129. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  130. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  131. package/src/ui/sidebar/SidebarItem.stx +0 -86
  132. package/src/ui/sidebar/SidebarSection.stx +0 -83
  133. package/src/ui/sidebar/index.ts +0 -153
  134. package/src/ui/sidebar/themes.ts +0 -240
  135. package/src/ui/skeleton/Skeleton.stx +0 -48
  136. package/src/ui/skeleton/index.ts +0 -11
  137. package/src/ui/spinner/Spinner.stx +0 -109
  138. package/src/ui/spinner/index.ts +0 -9
  139. package/src/ui/stepper/README.md +0 -36
  140. package/src/ui/stepper/Stepper.stx +0 -17
  141. package/src/ui/stepper/StepperStep.stx +0 -57
  142. package/src/ui/stepper/index.ts +0 -19
  143. package/src/ui/storage/README.md +0 -193
  144. package/src/ui/storage/index.ts +0 -347
  145. package/src/ui/switch/README.md +0 -114
  146. package/src/ui/switch/Switch.stx +0 -72
  147. package/src/ui/switch/index.ts +0 -10
  148. package/src/ui/table/README.md +0 -39
  149. package/src/ui/table/Table.stx +0 -14
  150. package/src/ui/table/TableBody.stx +0 -10
  151. package/src/ui/table/TableCell.stx +0 -10
  152. package/src/ui/table/TableHead.stx +0 -10
  153. package/src/ui/table/TableHeader.stx +0 -20
  154. package/src/ui/table/TableRow.stx +0 -11
  155. package/src/ui/table/index.ts +0 -35
  156. package/src/ui/tabs/TabPanel.stx +0 -25
  157. package/src/ui/tabs/Tabs.stx +0 -202
  158. package/src/ui/tabs/index.ts +0 -50
  159. package/src/ui/teleport/Teleport.stx +0 -65
  160. package/src/ui/teleport/index.ts +0 -7
  161. package/src/ui/textarea/Textarea.stx +0 -108
  162. package/src/ui/textarea/index.ts +0 -20
  163. package/src/ui/tooltip/Tooltip.stx +0 -71
  164. package/src/ui/tooltip/index.ts +0 -10
  165. package/src/ui/transition/README.md +0 -30
  166. package/src/ui/transition/Transition.stx +0 -102
  167. package/src/ui/transition/index.ts +0 -25
  168. package/src/ui/video/README.md +0 -47
  169. package/src/ui/video/Video.stx +0 -45
  170. package/src/ui/video/index.ts +0 -16
  171. package/src/ui/virtual-list/VirtualList.stx +0 -67
  172. package/src/ui/virtual-list/index.ts +0 -10
  173. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  174. package/src/ui/virtual-table/index.ts +0 -21
  175. package/src/utils/PROP_VALIDATION.md +0 -458
  176. package/src/utils/THEME_SYSTEM.md +0 -702
  177. package/src/utils/accessibility.ts +0 -841
  178. package/src/utils/animation/easing.ts +0 -368
  179. package/src/utils/animation/helpers.ts +0 -223
  180. package/src/utils/animation/index.ts +0 -5
  181. package/src/utils/animation/keyframes.ts +0 -230
  182. package/src/utils/error-handling.ts +0 -475
  183. package/src/utils/highlighter.ts +0 -93
  184. package/src/utils/i18n.ts +0 -634
  185. package/src/utils/keep-alive.ts +0 -819
  186. package/src/utils/lazy-loading.ts +0 -530
  187. package/src/utils/prop-validation.ts +0 -478
  188. package/src/utils/theme.ts +0 -626
@@ -1,109 +0,0 @@
1
- <script server>
2
- export const variant = $props.variant || 'circle'
3
- export const size = $props.size || 'md'
4
- export const color = $props.color || 'primary'
5
- export const label = $props.label || ''
6
- export const className = $props.className || ''
7
-
8
- // Size classes
9
- const sizeClasses = {
10
- xs: 'w-3 h-3',
11
- sm: 'w-4 h-4',
12
- md: 'w-6 h-6',
13
- lg: 'w-8 h-8',
14
- xl: 'w-12 h-12',
15
- }
16
-
17
- // Color classes
18
- const colorClasses = {
19
- primary: 'text-blue-600 dark:text-blue-500',
20
- secondary: 'text-purple-600 dark:text-purple-500',
21
- success: 'text-green-600 dark:text-green-500',
22
- warning: 'text-yellow-600 dark:text-yellow-500',
23
- danger: 'text-red-600 dark:text-red-500',
24
- info: 'text-cyan-600 dark:text-cyan-500',
25
- white: 'text-white',
26
- gray: 'text-gray-600 dark:text-gray-400',
27
- }
28
-
29
- export const containerClasses = `inline-flex flex-col items-center gap-2 ${className}`.trim()
30
- export const spinnerClasses = `${sizeClasses[size]} ${colorClasses[color]} animate-spin`.trim()
31
- export const labelClasses = `text-sm font-medium text-gray-700 dark:text-gray-300`.trim()
32
-
33
- // Dots size classes
34
- const dotsSizeClasses = {
35
- xs: 'w-1 h-1',
36
- sm: 'w-1.5 h-1.5',
37
- md: 'w-2 h-2',
38
- lg: 'w-2.5 h-2.5',
39
- xl: 'w-3 h-3',
40
- }
41
-
42
- const dotsColorClasses = {
43
- primary: 'bg-blue-600 dark:bg-blue-500',
44
- secondary: 'bg-purple-600 dark:bg-purple-500',
45
- success: 'bg-green-600 dark:bg-green-500',
46
- warning: 'bg-yellow-600 dark:bg-yellow-500',
47
- danger: 'bg-red-600 dark:bg-red-500',
48
- info: 'bg-cyan-600 dark:bg-cyan-500',
49
- white: 'bg-white',
50
- gray: 'bg-gray-600 dark:bg-gray-400',
51
- }
52
-
53
- export const dotClasses = `${dotsSizeClasses[size]} ${dotsColorClasses[color]} rounded-full`.trim()
54
- </script>
55
-
56
- <div class="{{ containerClasses }}" role="status" aria-live="polite" aria-busy="true">
57
- @if(variant === 'circle')
58
- <!-- Circle spinner (default) -->
59
- <svg class="{{ spinnerClasses }}" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
60
- <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
61
- <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>
62
- </svg>
63
- @elseif(variant === 'dots')
64
- <!-- Dots spinner -->
65
- <div class="flex items-center gap-1">
66
- <div class="{{ dotClasses }}" style="animation: bounce 1.4s infinite ease-in-out both; animation-delay: -0.32s"></div>
67
- <div class="{{ dotClasses }}" style="animation: bounce 1.4s infinite ease-in-out both; animation-delay: -0.16s"></div>
68
- <div class="{{ dotClasses }}" style="animation: bounce 1.4s infinite ease-in-out both"></div>
69
- </div>
70
- @elseif(variant === 'bars')
71
- <!-- Bars spinner -->
72
- <div class="flex items-center gap-1">
73
- <div class="w-1 bg-current rounded-full" style="height: {{ size === 'xs' ? '8px' : size === 'sm' ? '12px' : size === 'md' ? '16px' : size === 'lg' ? '20px' : '24px' }}; animation: bars 1.2s infinite ease-in-out; animation-delay: -0.24s"></div>
74
- <div class="w-1 bg-current rounded-full" style="height: {{ size === 'xs' ? '8px' : size === 'sm' ? '12px' : size === 'md' ? '16px' : size === 'lg' ? '20px' : '24px' }}; animation: bars 1.2s infinite ease-in-out; animation-delay: -0.12s"></div>
75
- <div class="w-1 bg-current rounded-full" style="height: {{ size === 'xs' ? '8px' : size === 'sm' ? '12px' : size === 'md' ? '16px' : size === 'lg' ? '20px' : '24px' }}; animation: bars 1.2s infinite ease-in-out"></div>
76
- </div>
77
- @elseif(variant === 'ring')
78
- <!-- Ring spinner -->
79
- <div class="{{ spinnerClasses }}" style="border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%;"></div>
80
- @endif
81
-
82
- @if(label)
83
- <span class="{{ labelClasses }}">{{ label }}</span>
84
- @endif
85
-
86
- <span class="sr-only">{{ label || 'Loading...' }}</span>
87
- </div>
88
-
89
- <style>
90
- @keyframes bounce {
91
- 0%, 80%, 100% {
92
- transform: scale(0);
93
- opacity: 0.5;
94
- }
95
- 40% {
96
- transform: scale(1);
97
- opacity: 1;
98
- }
99
- }
100
-
101
- @keyframes bars {
102
- 0%, 40%, 100% {
103
- transform: scaleY(0.4);
104
- }
105
- 20% {
106
- transform: scaleY(1);
107
- }
108
- }
109
- </style>
@@ -1,9 +0,0 @@
1
- export { default as Spinner } from './Spinner.stx'
2
-
3
- export interface SpinnerProps {
4
- variant?: 'circle' | 'dots' | 'bars' | 'ring'
5
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
6
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'white' | 'gray'
7
- label?: string
8
- className?: string
9
- }
@@ -1,36 +0,0 @@
1
- # Stepper Component
2
-
3
- A step-by-step progress indicator for multi-step processes.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <script server>
15
- let currentStep = 0
16
-
17
- function handleStepClick(step) {
18
- currentStep = step
19
- }
20
- </script>
21
-
22
- <Stepper :currentStep="currentStep">
23
- <StepperStep :stepNumber="0" :currentStep="currentStep" label="Account" :onClick="handleStepClick" />
24
- <StepperStep :stepNumber="1" :currentStep="currentStep" label="Profile" :onClick="handleStepClick" />
25
- <StepperStep :stepNumber="2" :currentStep="currentStep" label="Confirmation" :onClick="handleStepClick" />
26
- </Stepper>
27
- ```
28
-
29
- ## Features
30
-
31
- - Horizontal and vertical orientation
32
- - Clickable steps
33
- - Complete/current/upcoming states
34
- - Dark mode support
35
- - Accessible
36
- - Customizable styling
@@ -1,17 +0,0 @@
1
- <script server>
2
- export const currentStep = $props.currentStep || 0
3
- export const orientation = $props.orientation || 'horizontal'
4
- export const className = $props.className || ''
5
- export const as = $props.as || 'div'
6
-
7
- const orientationClasses = orientation === 'horizontal'
8
- ? 'flex flex-row'
9
- : 'flex flex-col'
10
-
11
- const baseClasses = 'w-full'
12
- const stepperClasses = `${baseClasses} ${orientationClasses} ${className}`.trim()
13
- </script>
14
-
15
- <component :is="{{ as }}" class="{{ stepperClasses }}">
16
- <slot :currentStep="currentStep" />
17
- </component>
@@ -1,57 +0,0 @@
1
- <script server>
2
- export const stepNumber = $props.stepNumber
3
- export const currentStep = $props.currentStep || 0
4
- export const label = $props.label || ''
5
- export const description = $props.description || ''
6
- export const className = $props.className || ''
7
- export const as = $props.as || 'div'
8
-
9
- export const isComplete = stepNumber < currentStep
10
- export const isCurrent = stepNumber === currentStep
11
- export const isUpcoming = stepNumber > currentStep
12
-
13
- const baseClasses = 'flex items-center'
14
- export const stepClasses = `${baseClasses} ${className}`.trim()
15
- </script>
16
-
17
- <script client>
18
- const emit = defineEmits()
19
- const stepNumber = {{ stepNumber }}
20
-
21
- function onClick() {
22
- emit('click', stepNumber)
23
- }
24
- </script>
25
-
26
- <component :is="{{ as }}" class="{{ stepClasses }}">
27
- <button
28
- type="button"
29
- @click="onClick()"
30
- class="flex items-center gap-3 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded-lg p-2"
31
- >
32
- <div class="{{ isComplete ? 'bg-blue-600 dark:bg-blue-500' : isCurrent ? 'bg-blue-600 dark:bg-blue-500 ring-4 ring-blue-200 dark:ring-blue-800' : 'bg-neutral-300 dark:bg-neutral-600' }} w-10 h-10 rounded-full flex items-center justify-center text-white font-semibold transition-all">
33
- @if(isComplete)
34
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
35
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
36
- </svg>
37
- @else
38
- {{ stepNumber + 1 }}
39
- @endif
40
- </div>
41
-
42
- @if(label)
43
- <div class="text-left">
44
- <div class="text-sm font-medium {{ isCurrent ? 'text-blue-600 dark:text-blue-400' : 'text-neutral-900 dark:text-white' }}">
45
- {{ label }}
46
- </div>
47
- @if(description)
48
- <div class="text-xs text-neutral-500 dark:text-neutral-400">
49
- {{ description }}
50
- </div>
51
- @endif
52
- </div>
53
- @endif
54
- </button>
55
-
56
- <slot :isComplete="isComplete" :isCurrent="isCurrent" :isUpcoming="isUpcoming" />
57
- </component>
@@ -1,19 +0,0 @@
1
- export { default as Stepper } from './Stepper.stx'
2
- export { default as StepperStep } from './StepperStep.stx'
3
-
4
- export interface StepperProps {
5
- currentStep?: number
6
- orientation?: 'horizontal' | 'vertical'
7
- className?: string
8
- as?: string
9
- }
10
-
11
- export interface StepperStepProps {
12
- stepNumber: number
13
- currentStep?: number
14
- label?: string
15
- description?: string
16
- className?: string
17
- as?: string
18
- onClick?: (step: number) => void
19
- }
@@ -1,193 +0,0 @@
1
- # Storage Utilities
2
-
3
- Type-safe utilities for localStorage and sessionStorage with expiration support.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ### Basic Usage
14
-
15
- ```typescript
16
- import { localStorage, sessionStorage } from '@stacksjs/components'
17
-
18
- // Set a value
19
- localStorage.set('user', { name: 'John', age: 30 })
20
-
21
- // Get a value
22
- const user = localStorage.get('user')
23
- console.log(user) // { name: 'John', age: 30 }
24
-
25
- // Remove a value
26
- localStorage.remove('user')
27
-
28
- // Clear all
29
- localStorage.clear()
30
- ```
31
-
32
- ### With Expiration
33
-
34
- ```typescript
35
- // Expire after 1 hour (3600000 ms)
36
- localStorage.set('token', 'abc123', { expire: 3600000 })
37
-
38
- // After 1 hour, get() returns null
39
- const token = localStorage.get('token') // null if expired
40
- ```
41
-
42
- ### With Namespace
43
-
44
- ```typescript
45
- import { createStorage } from '@stacksjs/components'
46
-
47
- const userStorage = createStorage('local', 'user')
48
- const appStorage = createStorage('local', 'app')
49
-
50
- userStorage.set('preferences', { theme: 'dark' })
51
- appStorage.set('preferences', { language: 'en' })
52
-
53
- // These are stored as 'user:preferences' and 'app:preferences'
54
- ```
55
-
56
- ### Session Storage
57
-
58
- ```typescript
59
- import { sessionStorage } from '@stacksjs/components'
60
-
61
- // Same API as localStorage
62
- sessionStorage.set('tempData', { value: 123 })
63
- const data = sessionStorage.get('tempData')
64
- ```
65
-
66
- ## API
67
-
68
- ### Storage Methods
69
-
70
- #### `set(key: string, value: any, options?: StorageOptions): void`
71
- Store a value with optional expiration.
72
-
73
- #### `get<T>(key: string): T | null`
74
- Retrieve a value. Returns null if expired or not found.
75
-
76
- #### `remove(key: string): void`
77
- Remove a specific key.
78
-
79
- #### `clear(): void`
80
- Clear all items (or all namespaced items).
81
-
82
- #### `has(key: string): boolean`
83
- Check if a key exists and hasn't expired.
84
-
85
- #### `keys(): string[]`
86
- Get all keys (without namespace prefix).
87
-
88
- #### `size(): number`
89
- Get the number of stored items.
90
-
91
- ## StorageOptions
92
-
93
- ```typescript
94
- interface StorageOptions {
95
- expire?: number // Expiration in milliseconds
96
- namespace?: string // Prefix for keys (in createStorage)
97
- }
98
- ```
99
-
100
- ## Features
101
-
102
- - **Type-safe** - Full TypeScript support
103
- - **Expiration** - Automatic expiration handling
104
- - **Namespacing** - Prevent key collisions
105
- - **Error handling** - Graceful error handling
106
- - **JSON serialization** - Automatic serialization/deserialization
107
- - **Both storages** - localStorage and sessionStorage support
108
-
109
- ## Examples
110
-
111
- ### User Authentication Token
112
-
113
- ```typescript
114
- import { localStorage } from '@stacksjs/components'
115
-
116
- // Store token with 24-hour expiration
117
- function login(token: string) {
118
- localStorage.set('auth_token', token, {
119
- expire: 24 * 60 * 60 * 1000, // 24 hours
120
- })
121
- }
122
-
123
- // Get token (returns null if expired)
124
- function getToken(): string | null {
125
- return localStorage.get('auth_token')
126
- }
127
-
128
- // Check if logged in
129
- function isLoggedIn(): boolean {
130
- return localStorage.has('auth_token')
131
- }
132
-
133
- // Logout
134
- function logout() {
135
- localStorage.remove('auth_token')
136
- }
137
- ```
138
-
139
- ### User Preferences
140
-
141
- ```typescript
142
- import { createStorage } from '@stacksjs/components'
143
-
144
- const prefs = createStorage('local', 'preferences')
145
-
146
- interface UserPreferences {
147
- theme: 'light' | 'dark'
148
- language: string
149
- notifications: boolean
150
- }
151
-
152
- // Save preferences
153
- function savePreferences(preferences: UserPreferences) {
154
- prefs.set('user', preferences)
155
- }
156
-
157
- // Load preferences with defaults
158
- function loadPreferences(): UserPreferences {
159
- const saved = prefs.get<UserPreferences>('user')
160
- return saved || {
161
- theme: 'light',
162
- language: 'en',
163
- notifications: true,
164
- }
165
- }
166
- ```
167
-
168
- ### Shopping Cart
169
-
170
- ```typescript
171
- import { localStorage } from '@stacksjs/components'
172
-
173
- interface CartItem {
174
- id: string
175
- name: string
176
- quantity: number
177
- price: number
178
- }
179
-
180
- function addToCart(item: CartItem) {
181
- const cart = localStorage.get<CartItem[]>('cart') || []
182
- cart.push(item)
183
- localStorage.set('cart', cart)
184
- }
185
-
186
- function getCart(): CartItem[] {
187
- return localStorage.get<CartItem[]>('cart') || []
188
- }
189
-
190
- function clearCart() {
191
- localStorage.remove('cart')
192
- }
193
- ```