@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,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
- ```