@dxtmisha/wiki 0.24.0 → 0.24.2
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/package.json +3 -2
- package/src/media/functional/en/about.mdx +55 -0
- package/src/media/functional/en/dataStorage.mdx +61 -83
- package/src/media/functional/en/useApiRef.mdx +517 -0
- package/src/media/functional/en/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/en/useCookieRef.mdx +348 -0
- package/src/media/functional/en/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/en/useHashRef.mdx +302 -0
- package/src/media/functional/en/useLazyRef.mdx +329 -0
- package/src/media/functional/en/useLoadingRef.mdx +159 -0
- package/src/media/functional/en/useSessionRef.mdx +248 -0
- package/src/media/functional/en/useStorageRef.mdx +242 -0
- package/src/media/functional/en/useTranslateRef.mdx +312 -0
- package/src/media/functional/ru/about.mdx +55 -0
- package/src/media/functional/ru/dataStorage.mdx +59 -81
- package/src/media/functional/ru/useApiRef.mdx +517 -0
- package/src/media/functional/ru/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/ru/useCookieRef.mdx +348 -0
- package/src/media/functional/ru/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/ru/useHashRef.mdx +302 -0
- package/src/media/functional/ru/useLazyRef.mdx +329 -0
- package/src/media/functional/ru/useLoadingRef.mdx +159 -0
- package/src/media/functional/ru/useSessionRef.mdx +248 -0
- package/src/media/functional/ru/useStorageRef.mdx +242 -0
- package/src/media/functional/ru/useTranslateRef.mdx +312 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/en/Composables/useSessionRef'/>
|
|
4
|
+
|
|
5
|
+
# Composable useSessionRef
|
|
6
|
+
|
|
7
|
+
Composable for creating a reactive variable synchronized with sessionStorage. Automatically manages reading and writing values to browser session storage with singleton pattern. Data persists only within the current tab/window and is deleted when it closes.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Two-way synchronization** — automatic sync between ref and sessionStorage
|
|
12
|
+
- **Automatic persistence** — ref changes automatically saved to sessionStorage
|
|
13
|
+
- **Tab isolation** — data not synchronized between tabs (unlike localStorage)
|
|
14
|
+
- **Temporary storage** — data deleted when tab/browser closes
|
|
15
|
+
- **Singleton pattern** — reuses ref for same keys
|
|
16
|
+
- **Type safety** — full TypeScript support with generics
|
|
17
|
+
- **Default values** — supports initial values and factory functions
|
|
18
|
+
- **DataStorage integration** — uses DataStorage class for storage management
|
|
19
|
+
|
|
20
|
+
## Function
|
|
21
|
+
|
|
22
|
+
### `useSessionRef`
|
|
23
|
+
|
|
24
|
+
Creates a reactive variable synchronized with sessionStorage.
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `name: string` — key name in sessionStorage
|
|
28
|
+
- `defaultValue?: T | (() => T)` — default value or function to generate it (optional)
|
|
29
|
+
|
|
30
|
+
**Returns:** `Ref<T | undefined>` — Vue reactive variable linked to sessionStorage
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
34
|
+
|
|
35
|
+
// Simple usage
|
|
36
|
+
const wizardStep = useSessionRef('wizard-step')
|
|
37
|
+
|
|
38
|
+
// With default value
|
|
39
|
+
const currentStep = useSessionRef('current-step', 1)
|
|
40
|
+
|
|
41
|
+
// With factory function
|
|
42
|
+
const sessionId = useSessionRef('session-id', () => Math.random().toString(36))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Basic Usage
|
|
46
|
+
|
|
47
|
+
### Basic Synchronization
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
51
|
+
|
|
52
|
+
// Create ref synchronized with sessionStorage
|
|
53
|
+
const wizardProgress = useSessionRef('wizard-progress', { step: 1 })
|
|
54
|
+
|
|
55
|
+
// When ref changes - sessionStorage automatically updates
|
|
56
|
+
wizardProgress.value = { step: 2, data: { name: 'John' } }
|
|
57
|
+
|
|
58
|
+
// On page reload (in same tab) value is restored
|
|
59
|
+
console.log(wizardProgress.value) // { step: 2, data: { name: 'John' } }
|
|
60
|
+
|
|
61
|
+
// When tab closes, data is deleted
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Singleton Pattern
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
// Repeated calls with same name return existing ref
|
|
68
|
+
const step1 = useSessionRef('wizard-step', 1)
|
|
69
|
+
const step2 = useSessionRef('wizard-step', 2)
|
|
70
|
+
|
|
71
|
+
console.log(step1 === step2) // true - same ref
|
|
72
|
+
|
|
73
|
+
step1.value = 3
|
|
74
|
+
console.log(step2.value) // 3 - both point to same ref
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Usage in Components
|
|
78
|
+
|
|
79
|
+
### Multi-step Wizard
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
setup() {
|
|
86
|
+
const currentStep = useSessionRef('wizard-step', 1)
|
|
87
|
+
const formData = useSessionRef('wizard-data', {
|
|
88
|
+
name: '',
|
|
89
|
+
email: '',
|
|
90
|
+
phone: ''
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const nextStep = () => {
|
|
94
|
+
currentStep.value++
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const prevStep = () => {
|
|
98
|
+
if (currentStep.value > 1) {
|
|
99
|
+
currentStep.value--
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
currentStep,
|
|
105
|
+
formData,
|
|
106
|
+
nextStep,
|
|
107
|
+
prevStep
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Template:
|
|
113
|
+
// <div>
|
|
114
|
+
// <div v-if="currentStep === 1">
|
|
115
|
+
// <input v-model="formData.name" placeholder="Name" />
|
|
116
|
+
// </div>
|
|
117
|
+
// <div v-if="currentStep === 2">
|
|
118
|
+
// <input v-model="formData.email" placeholder="Email" />
|
|
119
|
+
// </div>
|
|
120
|
+
// <button @click="prevStep">Back</button>
|
|
121
|
+
// <button @click="nextStep">Next</button>
|
|
122
|
+
// </div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Temporary Filter State
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
129
|
+
|
|
130
|
+
export default {
|
|
131
|
+
setup() {
|
|
132
|
+
const filters = useSessionRef('search-filters', {
|
|
133
|
+
category: 'all',
|
|
134
|
+
priceMin: 0,
|
|
135
|
+
priceMax: 10000,
|
|
136
|
+
sortBy: 'name'
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const resetFilters = () => {
|
|
140
|
+
filters.value = {
|
|
141
|
+
category: 'all',
|
|
142
|
+
priceMin: 0,
|
|
143
|
+
priceMax: 10000,
|
|
144
|
+
sortBy: 'name'
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { filters, resetFilters }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Differences from useStorageRef
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// useStorageRef - data persists between browser sessions
|
|
157
|
+
const persistentTheme = useStorageRef('theme', 'light')
|
|
158
|
+
// Data remains even after browser closes
|
|
159
|
+
|
|
160
|
+
// useSessionRef - data deleted when tab closes
|
|
161
|
+
const temporaryFilters = useSessionRef('filters', {})
|
|
162
|
+
// Data deleted when tab/browser closes
|
|
163
|
+
|
|
164
|
+
// useStorageRef syncs between tabs
|
|
165
|
+
// useSessionRef isolated per tab
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Working with Data Types
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
// Numbers
|
|
172
|
+
const step = useSessionRef<number>('step', 1)
|
|
173
|
+
step.value = 2
|
|
174
|
+
|
|
175
|
+
// Booleans
|
|
176
|
+
const isCompleted = useSessionRef<boolean>('completed', false)
|
|
177
|
+
isCompleted.value = true
|
|
178
|
+
|
|
179
|
+
// Objects
|
|
180
|
+
const wizardData = useSessionRef('wizard-data', {
|
|
181
|
+
step: 1,
|
|
182
|
+
userData: {},
|
|
183
|
+
timestamp: Date.now()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
// Arrays
|
|
187
|
+
const selectedItems = useSessionRef<number[]>('selected', [])
|
|
188
|
+
selectedItems.value.push(42)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Usage Examples
|
|
192
|
+
|
|
193
|
+
### Form Progress Persistence
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
const registrationForm = useSessionRef('registration', {
|
|
197
|
+
step: 1,
|
|
198
|
+
personal: { name: '', email: '' },
|
|
199
|
+
address: { street: '', city: '' },
|
|
200
|
+
completed: false
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// Data saved as form is filled
|
|
204
|
+
registrationForm.value.personal.name = 'John'
|
|
205
|
+
registrationForm.value.step = 2
|
|
206
|
+
|
|
207
|
+
// On page reload (F5) data is restored
|
|
208
|
+
// On tab close - everything is deleted
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Temporary Modal State
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
const modalState = useSessionRef('modal', {
|
|
215
|
+
isOpen: false,
|
|
216
|
+
activeTab: 'details',
|
|
217
|
+
scrollPosition: 0
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const openModal = () => {
|
|
221
|
+
modalState.value.isOpen = true
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const closeModal = () => {
|
|
225
|
+
modalState.value.isOpen = false
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Shopping Cart (Temporary)
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
const cart = useSessionRef<CartItem[]>('temp-cart', [])
|
|
233
|
+
|
|
234
|
+
const addToCart = (item: CartItem) => {
|
|
235
|
+
cart.value = [...cart.value, item]
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const removeFromCart = (itemId: number) => {
|
|
239
|
+
cart.value = cart.value.filter(item => item.id !== itemId)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const clearCart = () => {
|
|
243
|
+
cart.value = []
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Cart is automatically cleared when tab closes
|
|
247
|
+
```
|
|
248
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/en/Composables/useStorageRef'/>
|
|
4
|
+
|
|
5
|
+
# Composable useStorageRef
|
|
6
|
+
|
|
7
|
+
Composable for creating a reactive variable synchronized with localStorage. Automatically manages reading and writing values to browser local storage with caching support, cross-tab synchronization, and singleton pattern for efficient reuse.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Two-way synchronization** — automatic sync between ref and localStorage
|
|
12
|
+
- **Automatic persistence** — ref changes automatically saved to localStorage
|
|
13
|
+
- **Caching with TTL** — optional cache lifetime in seconds
|
|
14
|
+
- **Cross-tab synchronization** — automatic updates when changes occur in other tabs
|
|
15
|
+
- **Singleton pattern** — reuses ref for same keys
|
|
16
|
+
- **Type safety** — full TypeScript support with generics
|
|
17
|
+
- **Default values** — supports initial values and factory functions
|
|
18
|
+
- **DataStorage integration** — uses DataStorage class for storage management
|
|
19
|
+
|
|
20
|
+
## Function
|
|
21
|
+
|
|
22
|
+
### `useStorageRef`
|
|
23
|
+
|
|
24
|
+
Creates a reactive variable synchronized with localStorage.
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `name: string` — key name in localStorage
|
|
28
|
+
- `defaultValue?: T | (() => T)` — default value or function to generate it (optional)
|
|
29
|
+
- `cache?: number` — cache time in seconds (optional)
|
|
30
|
+
|
|
31
|
+
**Returns:** `Ref<T | undefined>` — Vue reactive variable linked to localStorage
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
35
|
+
|
|
36
|
+
// Simple usage
|
|
37
|
+
const theme = useStorageRef('app-theme')
|
|
38
|
+
|
|
39
|
+
// With default value
|
|
40
|
+
const language = useStorageRef('app-language', 'en')
|
|
41
|
+
|
|
42
|
+
// With factory function
|
|
43
|
+
const userId = useStorageRef('user-id', () => Math.random().toString(36))
|
|
44
|
+
|
|
45
|
+
// With caching (600 seconds = 10 minutes)
|
|
46
|
+
const cachedData = useStorageRef('cached-data', null, 600)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Basic Usage
|
|
50
|
+
|
|
51
|
+
### Basic Synchronization
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
55
|
+
|
|
56
|
+
// Create ref synchronized with localStorage
|
|
57
|
+
const userTheme = useStorageRef('theme', 'light')
|
|
58
|
+
|
|
59
|
+
// When ref changes - localStorage automatically updates
|
|
60
|
+
userTheme.value = 'dark'
|
|
61
|
+
// localStorage: { 'ui-storage__theme': '{"value":"dark","age":1234567890}' }
|
|
62
|
+
|
|
63
|
+
// On page reload, value is restored
|
|
64
|
+
console.log(userTheme.value) // 'dark'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Singleton Pattern
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// Repeated calls with same name return existing ref
|
|
71
|
+
const theme1 = useStorageRef('app-theme', 'light')
|
|
72
|
+
const theme2 = useStorageRef('app-theme', 'dark')
|
|
73
|
+
|
|
74
|
+
console.log(theme1 === theme2) // true - same ref
|
|
75
|
+
|
|
76
|
+
theme1.value = 'blue'
|
|
77
|
+
console.log(theme2.value) // 'blue' - both point to same ref
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Usage in Components
|
|
81
|
+
|
|
82
|
+
### User Settings
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
setup() {
|
|
89
|
+
const theme = useStorageRef('user-theme', 'light')
|
|
90
|
+
const fontSize = useStorageRef('font-size', 16)
|
|
91
|
+
const notifications = useStorageRef('notifications', true)
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
theme,
|
|
95
|
+
fontSize,
|
|
96
|
+
notifications
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Template:
|
|
102
|
+
// <div>
|
|
103
|
+
// <select v-model="theme">
|
|
104
|
+
// <option value="light">Light</option>
|
|
105
|
+
// <option value="dark">Dark</option>
|
|
106
|
+
// </select>
|
|
107
|
+
// <input v-model.number="fontSize" type="number" />
|
|
108
|
+
// <input v-model="notifications" type="checkbox" />
|
|
109
|
+
// </div>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### API Data Caching
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
116
|
+
|
|
117
|
+
export default {
|
|
118
|
+
setup() {
|
|
119
|
+
// Cache for 10 minutes (600 seconds)
|
|
120
|
+
const userData = useStorageRef('user-data', null, 600)
|
|
121
|
+
|
|
122
|
+
const loadUserData = async () => {
|
|
123
|
+
if (userData.value) {
|
|
124
|
+
console.log('Data from cache')
|
|
125
|
+
return userData.value
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log('Loading from server')
|
|
129
|
+
const response = await fetch('/api/user')
|
|
130
|
+
userData.value = await response.json()
|
|
131
|
+
return userData.value
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return { userData, loadUserData }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Cross-tab Synchronization
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
143
|
+
|
|
144
|
+
// In first tab
|
|
145
|
+
const counter = useStorageRef('counter', 0)
|
|
146
|
+
counter.value = 5
|
|
147
|
+
|
|
148
|
+
// In second tab automatically updates
|
|
149
|
+
// counter.value === 5 (thanks to storage event)
|
|
150
|
+
|
|
151
|
+
// In third tab
|
|
152
|
+
const sameCounter = useStorageRef('counter', 0)
|
|
153
|
+
console.log(sameCounter.value) // 5
|
|
154
|
+
|
|
155
|
+
// Changes in any tab update all others
|
|
156
|
+
sameCounter.value = 10
|
|
157
|
+
// All open tabs will have counter.value === 10
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Working with Data Types
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// Numbers
|
|
164
|
+
const count = useStorageRef<number>('count', 0)
|
|
165
|
+
count.value = 42
|
|
166
|
+
|
|
167
|
+
// Booleans
|
|
168
|
+
const isActive = useStorageRef<boolean>('active', false)
|
|
169
|
+
isActive.value = true
|
|
170
|
+
|
|
171
|
+
// Objects
|
|
172
|
+
const settings = useStorageRef('settings', {
|
|
173
|
+
theme: 'dark',
|
|
174
|
+
language: 'en',
|
|
175
|
+
notifications: true
|
|
176
|
+
})
|
|
177
|
+
settings.value.theme = 'light'
|
|
178
|
+
|
|
179
|
+
// Arrays
|
|
180
|
+
const items = useStorageRef<string[]>('items', [])
|
|
181
|
+
items.value.push('new item')
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Usage Examples
|
|
185
|
+
|
|
186
|
+
### Form State Persistence
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const formData = useStorageRef('contact-form', {
|
|
190
|
+
name: '',
|
|
191
|
+
email: '',
|
|
192
|
+
message: ''
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// When filling form, data is automatically saved
|
|
196
|
+
formData.value.name = 'John'
|
|
197
|
+
formData.value.email = 'john@example.com'
|
|
198
|
+
|
|
199
|
+
// On page reload, data is restored
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### User Favorites
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
const favorites = useStorageRef<number[]>('favorites', [])
|
|
206
|
+
|
|
207
|
+
const addToFavorites = (id: number) => {
|
|
208
|
+
if (!favorites.value.includes(id)) {
|
|
209
|
+
favorites.value = [...favorites.value, id]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const removeFromFavorites = (id: number) => {
|
|
214
|
+
favorites.value = favorites.value.filter(fav => fav !== id)
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Cache with Auto-refresh
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Cache for 5 minutes
|
|
222
|
+
const newsData = useStorageRef('news', null, 300)
|
|
223
|
+
|
|
224
|
+
const fetchNews = async () => {
|
|
225
|
+
// If cache is valid - return saved data
|
|
226
|
+
if (newsData.value) return newsData.value
|
|
227
|
+
|
|
228
|
+
// Otherwise load fresh data
|
|
229
|
+
const response = await fetch('/api/news')
|
|
230
|
+
newsData.value = await response.json()
|
|
231
|
+
return newsData.value
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// First call - loads from server
|
|
235
|
+
await fetchNews()
|
|
236
|
+
|
|
237
|
+
// Subsequent calls within 5 minutes - use cache
|
|
238
|
+
await fetchNews() // From cache
|
|
239
|
+
|
|
240
|
+
// After 5+ minutes - loads from server again
|
|
241
|
+
```
|
|
242
|
+
|