@dxtmisha/wiki 0.24.0 → 0.24.1

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.
@@ -0,0 +1,288 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/en/Composables/useGeoIntlRef'/>
4
+
5
+ # Composable useGeoIntlRef
6
+
7
+ Composable for creating a reactive internationalization object. Provides methods for formatting numbers, currencies, dates and names with automatic locale detection. All methods return computed values that automatically update when input data changes.
8
+
9
+ ## Key Features
10
+
11
+ - **Number formatting** — localized number representation with separators
12
+ - **Currency formatting** — displaying monetary amounts with currency symbols
13
+ - **Date formatting** — various date and time formats by regional standards
14
+ - **Country and language names** — localized region names
15
+ - **Relative time** — "2 days ago", "in 5 minutes", etc.
16
+ - **Percentages and units** — formatting percentages and measurement units
17
+ - **Reactivity** — all methods return computed that update automatically
18
+ - **Auto locale detection** — uses user geolocation by default
19
+
20
+ ## Function
21
+
22
+ ### `useGeoIntlRef()`
23
+
24
+ Creates and returns instance of `GeoIntlRef` class for working with data formatting.
25
+
26
+ **Parameters:** none
27
+
28
+ **Returns:** `GeoIntlRef` — object with formatting methods
29
+
30
+ ```javascript
31
+ import { useGeoIntlRef } from '@dxtmisha/functional'
32
+
33
+ // Create instance
34
+ const intl = useGeoIntlRef()
35
+
36
+ // All methods return ComputedRef
37
+ const formatted = intl.number(1234.56)
38
+ ```
39
+
40
+ ## Number Formatting Methods
41
+
42
+ ### `number`
43
+
44
+ Format number according to locale.
45
+
46
+ **Parameters:**
47
+ - `value: RefOrNormal<NumberOrString>` — number to format
48
+ - `options?: Intl.NumberFormatOptions` — formatting options
49
+
50
+ **Returns:** `ComputedRef<string>`
51
+
52
+ ```javascript
53
+ const intl = useGeoIntlRef()
54
+ const count = ref(1234567.89)
55
+
56
+ intl.number(count) // ComputedRef<'1,234,567.89'>
57
+ intl.number(1000, { minimumFractionDigits: 2 }) // ComputedRef<'1,000.00'>
58
+ ```
59
+
60
+ ### `decimal`
61
+
62
+ Returns decimal separator symbol for current locale.
63
+
64
+ **Returns:** `ComputedRef<string>`
65
+
66
+ ```javascript
67
+ const intl = useGeoIntlRef()
68
+ intl.decimal() // ComputedRef<'.'> (for en-US)
69
+ // ComputedRef<','> (for ru-RU)
70
+ ```
71
+
72
+ ### `percent`
73
+
74
+ Format number as percentage.
75
+
76
+ **Parameters:**
77
+ - `value: RefOrNormal<NumberOrString>` — number to format (0.15 = 15%)
78
+ - `options?: Intl.NumberFormatOptions` — formatting options
79
+
80
+ **Returns:** `ComputedRef<string>`
81
+
82
+ ```javascript
83
+ intl.percent(0.15) // ComputedRef<'15%'>
84
+ intl.percent(1.25) // ComputedRef<'125%'>
85
+ ```
86
+
87
+ ### `percentBy100`
88
+
89
+ Format number as percentage (value already in percents).
90
+
91
+ **Parameters:**
92
+ - `value: RefOrNormal<NumberOrString>` — number to format (15 = 15%)
93
+ - `options?: Intl.NumberFormatOptions` — formatting options
94
+
95
+ **Returns:** `ComputedRef<string>`
96
+
97
+ ```javascript
98
+ intl.percentBy100(15) // ComputedRef<'15%'>
99
+ intl.percentBy100(125) // ComputedRef<'125%'>
100
+ ```
101
+
102
+ ## Currency Formatting Methods
103
+
104
+ ### `currency`
105
+
106
+ Format monetary amount.
107
+
108
+ **Parameters:**
109
+ - `value: RefOrNormal<NumberOrString>` — amount to format
110
+ - `currencyOptions?: RefOrNormal<string | Intl.NumberFormatOptions>` — currency code or options
111
+ - `numberOnly?: boolean` — don't show currency symbol (default `false`)
112
+
113
+ **Returns:** `ComputedRef<string>`
114
+
115
+ ```javascript
116
+ const intl = useGeoIntlRef()
117
+ const price = ref(99.99)
118
+
119
+ intl.currency(price, 'USD') // ComputedRef<'$99.99'>
120
+ intl.currency(1234.56, 'RUB') // ComputedRef<'RUB 1,234.56'>
121
+ intl.currency(500, 'EUR', true) // ComputedRef<'500.00'> (no symbol)
122
+ ```
123
+
124
+ ### `unit`
125
+
126
+ Format with measurement units.
127
+
128
+ **Parameters:**
129
+ - `value: RefOrNormal<NumberOrString>` — value to format
130
+ - `unitOptions?: string | Intl.NumberFormatOptions` — unit or options
131
+
132
+ **Returns:** `ComputedRef<string>`
133
+
134
+ ```javascript
135
+ intl.unit(100, 'kilometer') // ComputedRef<'100 km'>
136
+ intl.unit(50, 'kilogram') // ComputedRef<'50 kg'>
137
+ intl.unit(1.5, 'hour') // ComputedRef<'1.5 hr'>
138
+ ```
139
+
140
+ ## Date Formatting Methods
141
+
142
+ ### `date`
143
+
144
+ Format date and time.
145
+
146
+ **Parameters:**
147
+ - `value: RefOrNormal<NumberOrStringOrDate>` — date to format
148
+ - `type?: GeoDate` — format type ('date' | 'time' | 'datetime' | 'full' | 'long' | 'medium' | 'short')
149
+ - `styleOptions?: Intl.DateTimeFormatOptions['month'] | Intl.DateTimeFormatOptions` — style or options
150
+ - `hour24?: boolean` — use 24-hour format
151
+
152
+ **Returns:** `ComputedRef<string>`
153
+
154
+ ```javascript
155
+ const date = ref(new Date('2024-10-15 14:30:00'))
156
+
157
+ intl.date(date) // ComputedRef<'10/15/2024'>
158
+ intl.date(date, 'time') // ComputedRef<'2:30 PM'>
159
+ intl.date(date, 'datetime') // ComputedRef<'10/15/2024, 2:30 PM'>
160
+ intl.date(date, 'full') // ComputedRef<'Tuesday, October 15, 2024'>
161
+ ```
162
+
163
+ ### `relative`
164
+
165
+ Format relative time ("2 days ago", "in 1 hour").
166
+
167
+ **Parameters:**
168
+ - `value: RefOrNormal<NumberOrStringOrDate>` — date to compare
169
+ - `styleOptions?: Intl.RelativeTimeFormatStyle | Intl.RelativeTimeFormatOptions` — style ('long' | 'short' | 'narrow')
170
+ - `todayValue?: Date` — current date (default `new Date()`)
171
+
172
+ **Returns:** `ComputedRef<string>`
173
+
174
+ ```javascript
175
+ const twoDaysAgo = new Date()
176
+ twoDaysAgo.setDate(twoDaysAgo.getDate() - 2)
177
+
178
+ intl.relative(twoDaysAgo) // ComputedRef<'2 days ago'>
179
+ intl.relative(twoDaysAgo, 'short') // ComputedRef<'2 days ago'>
180
+ ```
181
+
182
+ ### `relativeLimit`
183
+
184
+ Format relative time with limit. If difference exceeds limit, outputs absolute date.
185
+
186
+ **Parameters:**
187
+ - `value: RefOrNormal<NumberOrStringOrDate>` — date to format
188
+ - `limit: number` — limit in days
189
+ - `todayValue?: Date` — current date
190
+ - `relativeOptions?: Intl.RelativeTimeFormatStyle | Intl.RelativeTimeFormatOptions` — relative format options
191
+ - `dateOptions?: Intl.DateTimeFormatOptions['month'] | Intl.DateTimeFormatOptions` — date format options
192
+ - `type?: GeoDate` — date format type
193
+ - `hour24?: boolean` — 24-hour format
194
+
195
+ **Returns:** `ComputedRef<string>`
196
+
197
+ ```javascript
198
+ const threeDaysAgo = new Date()
199
+ threeDaysAgo.setDate(threeDaysAgo.getDate() - 3)
200
+
201
+ intl.relativeLimit(threeDaysAgo, 7) // ComputedRef<'3 days ago'>
202
+
203
+ const tenDaysAgo = new Date()
204
+ tenDaysAgo.setDate(tenDaysAgo.getDate() - 10)
205
+
206
+ intl.relativeLimit(tenDaysAgo, 7) // ComputedRef<'10/05/2024'> (absolute date)
207
+ ```
208
+
209
+ ## Name Methods
210
+
211
+ ### `display`
212
+
213
+ Get localized name (language, region, script, etc.).
214
+
215
+ **Parameters:**
216
+ - `value?: RefOrNormal<string>` — code to get name for
217
+ - `typeOptions?: Intl.DisplayNamesOptions['type'] | Intl.DisplayNamesOptions` — type ('language' | 'region' | 'script' | 'currency')
218
+
219
+ **Returns:** `ComputedRef<string>`
220
+
221
+ ```javascript
222
+ intl.display('US', 'region') // ComputedRef<'United States'>
223
+ intl.display('en', 'language') // ComputedRef<'English'>
224
+ intl.display('USD', 'currency') // ComputedRef<'US Dollar'>
225
+ ```
226
+
227
+ ### `languageName`
228
+
229
+ Get language name.
230
+
231
+ **Parameters:**
232
+ - `value?: RefOrNormal<string>` — language code
233
+ - `style?: Intl.RelativeTimeFormatStyle` — display style
234
+
235
+ **Returns:** `ComputedRef<string>`
236
+
237
+ ```javascript
238
+ intl.languageName('en') // ComputedRef<'English'>
239
+ intl.languageName('de') // ComputedRef<'German'>
240
+ ```
241
+
242
+ ### `countryName`
243
+
244
+ Get country name.
245
+
246
+ **Parameters:**
247
+ - `value?: RefOrNormal<string>` — country code
248
+ - `style?: Intl.RelativeTimeFormatStyle` — display style
249
+
250
+ **Returns:** `ComputedRef<string>`
251
+
252
+ ```javascript
253
+ intl.countryName('US') // ComputedRef<'United States'>
254
+ intl.countryName('GB') // ComputedRef<'United Kingdom'>
255
+ ```
256
+
257
+ ## Usage Examples
258
+
259
+ ### Basic Usage
260
+
261
+ ```javascript
262
+ import { ref } from 'vue'
263
+ import { useGeoIntlRef } from '@dxtmisha/functional'
264
+
265
+ const intl = useGeoIntlRef()
266
+ const price = ref(1234.56)
267
+
268
+ // All methods return ComputedRef
269
+ const formatted = intl.currency(price, 'USD')
270
+ console.log(formatted.value) // '$1,234.56'
271
+
272
+ // Automatic update on change
273
+ price.value = 2000
274
+ console.log(formatted.value) // '$2,000.00'
275
+ ```
276
+
277
+ ### Reactive Parameters
278
+
279
+ ```javascript
280
+ const price = ref(100)
281
+ const currency = ref('USD')
282
+
283
+ // Reactive currency and value
284
+ const formatted = intl.currency(price, currency)
285
+
286
+ currency.value = 'EUR'
287
+ // formatted.value automatically updates
288
+ ```
@@ -0,0 +1,302 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/en/Composables/useHashRef'/>
4
+
5
+ # Composable useHashRef
6
+
7
+ Composable for creating a reactive variable synchronized with URL hash. Automatically manages reading and writing values to the hash part of the URL, providing two-way synchronization between Vue reactive state and browser address bar parameters.
8
+
9
+ ## Key Features
10
+
11
+ - **Two-way synchronization** — automatic sync between ref and URL hash
12
+ - **Automatic persistence** — ref changes automatically reflect in URL
13
+ - **Reactivity** — URL hash changes automatically update ref
14
+ - **Instance caching** — reuses ref for same parameter names
15
+ - **Type safety** — full TypeScript support with generics
16
+ - **Default values** — supports initial values and factory functions
17
+ - **Auto initialization** — loads existing values from URL on creation
18
+
19
+ ## Function
20
+
21
+ ### `useHashRef`
22
+
23
+ Creates a reactive variable synchronized with a parameter in URL hash.
24
+
25
+ **Parameters:**
26
+ - `name: string` — parameter name in hash URL
27
+ - `defaultValue?: T | (() => T)` — default value or function to generate it (optional)
28
+
29
+ **Returns:** `Ref<T>` — Vue reactive variable linked to hash parameter
30
+
31
+ ```javascript
32
+ import { useHashRef } from '@dxtmisha/functional'
33
+
34
+ // Simple usage without default value
35
+ const currentTab = useHashRef('tab')
36
+ console.log(currentTab.value) // undefined (if hash is empty)
37
+
38
+ // With default value
39
+ const activeView = useHashRef('view', 'grid')
40
+ console.log(activeView.value) // 'grid' (if hash doesn't contain 'view')
41
+
42
+ // With factory function for default value
43
+ const userId = useHashRef('userId', () => Math.floor(Math.random() * 1000))
44
+ ```
45
+
46
+ ## Basic Usage
47
+
48
+ ### Basic Synchronization
49
+
50
+ ```javascript
51
+ import { useHashRef } from '@dxtmisha/functional'
52
+
53
+ // Create ref synchronized with hash
54
+ const currentPage = useHashRef('page', 1)
55
+
56
+ // When ref changes - URL automatically updates
57
+ currentPage.value = 2
58
+ // URL: #page=2
59
+
60
+ currentPage.value = 5
61
+ // URL: #page=5
62
+
63
+ // When URL changes manually - ref automatically updates
64
+ // User changes URL to: #page=10
65
+ console.log(currentPage.value) // 10
66
+ ```
67
+
68
+ ### Working with Multiple Parameters
69
+
70
+ ```javascript
71
+ // Multiple independent hash parameters
72
+ const searchQuery = useHashRef('q', '')
73
+ const sortOrder = useHashRef('sort', 'asc')
74
+ const pageNumber = useHashRef('page', 1)
75
+
76
+ searchQuery.value = 'vue composables'
77
+ sortOrder.value = 'desc'
78
+ pageNumber.value = 3
79
+
80
+ // URL: #q=vue composables;sort=desc;page=3
81
+
82
+ // All parameters stay synchronized
83
+ console.log(searchQuery.value) // 'vue composables'
84
+ console.log(sortOrder.value) // 'desc'
85
+ console.log(pageNumber.value) // 3
86
+ ```
87
+
88
+ ### Instance Caching
89
+
90
+ ```javascript
91
+ // Repeated calls with same name return existing ref
92
+ const tab1 = useHashRef('activeTab', 'home')
93
+ const tab2 = useHashRef('activeTab', 'profile')
94
+
95
+ console.log(tab1 === tab2) // true - same ref
96
+
97
+ tab1.value = 'settings'
98
+ console.log(tab2.value) // 'settings' - both point to same ref
99
+ ```
100
+
101
+ ## Usage in Components
102
+
103
+ ### Tab Management
104
+
105
+ ```javascript
106
+ import { useHashRef } from '@dxtmisha/functional'
107
+
108
+ export default {
109
+ setup() {
110
+ const activeTab = useHashRef('tab', 'overview')
111
+
112
+ return {
113
+ activeTab,
114
+ tabs: ['overview', 'details', 'settings']
115
+ }
116
+ }
117
+ }
118
+
119
+ // Template:
120
+ // <div>
121
+ // <button
122
+ // v-for="tab in tabs"
123
+ // :key="tab"
124
+ // @click="activeTab = tab"
125
+ // :class="{ active: activeTab === tab }"
126
+ // >
127
+ // {{ tab }}
128
+ // </button>
129
+ // </div>
130
+ ```
131
+
132
+ ### Pagination with State Persistence
133
+
134
+ ```javascript
135
+ import { computed } from 'vue'
136
+ import { useHashRef } from '@dxtmisha/functional'
137
+
138
+ export default {
139
+ setup() {
140
+ const currentPage = useHashRef('page', 1)
141
+ const itemsPerPage = 20
142
+ const totalItems = 100
143
+
144
+ const totalPages = computed(() =>
145
+ Math.ceil(totalItems / itemsPerPage)
146
+ )
147
+
148
+ const nextPage = () => {
149
+ if (currentPage.value < totalPages.value) {
150
+ currentPage.value++
151
+ }
152
+ }
153
+
154
+ const prevPage = () => {
155
+ if (currentPage.value > 1) {
156
+ currentPage.value--
157
+ }
158
+ }
159
+
160
+ return {
161
+ currentPage,
162
+ totalPages,
163
+ nextPage,
164
+ prevPage
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ ### Filters and Search
171
+
172
+ ```javascript
173
+ import { watch } from 'vue'
174
+ import { useHashRef } from '@dxtmisha/functional'
175
+
176
+ export default {
177
+ setup() {
178
+ const searchQuery = useHashRef('q', '')
179
+ const category = useHashRef('category', 'all')
180
+ const sortBy = useHashRef('sort', 'date')
181
+
182
+ // Watch changes to load data
183
+ watch([searchQuery, category, sortBy], () => {
184
+ console.log('Loading data with params:')
185
+ console.log('Search:', searchQuery.value)
186
+ console.log('Category:', category.value)
187
+ console.log('Sort:', sortBy.value)
188
+ // API request here
189
+ })
190
+
191
+ return {
192
+ searchQuery,
193
+ category,
194
+ sortBy
195
+ }
196
+ }
197
+ }
198
+ ```
199
+
200
+ ## Working with Data Types
201
+
202
+ ### Numeric Values
203
+
204
+ ```javascript
205
+ // Hash automatically converts types
206
+ const pageNumber = useHashRef<number>('page', 1)
207
+
208
+ pageNumber.value = 5
209
+ // URL: #page=5
210
+
211
+ // When loading from URL, string is automatically converted
212
+ // URL: #page=10
213
+ console.log(typeof pageNumber.value) // 'number'
214
+ console.log(pageNumber.value) // 10
215
+ ```
216
+
217
+ ### Boolean Values
218
+
219
+ ```javascript
220
+ const isActive = useHashRef<boolean>('active', false)
221
+
222
+ isActive.value = true
223
+ // URL: #active=true
224
+
225
+ // Automatic conversion from string
226
+ // URL: #active=false
227
+ console.log(typeof isActive.value) // 'boolean'
228
+ console.log(isActive.value) // false
229
+ ```
230
+
231
+ ### Objects and Arrays
232
+
233
+ ```javascript
234
+ // For complex types, serialization is used
235
+ const filters = useHashRef('filters', { min: 0, max: 100 })
236
+
237
+ filters.value = { min: 20, max: 80 }
238
+ // URL will contain serialized representation
239
+
240
+ // Values are restored on load
241
+ console.log(filters.value) // { min: 20, max: 80 }
242
+ ```
243
+
244
+ ## Integration with Hash Class
245
+
246
+ The composable uses `Hash` class to manage URL hash:
247
+
248
+ ```javascript
249
+ import { Hash } from '@dxtmisha/functional'
250
+
251
+ // Direct class usage
252
+ Hash.set('tab', 'profile')
253
+ console.log(Hash.get('tab')) // 'profile'
254
+
255
+ // useHashRef automatically syncs with Hash
256
+ const tab = useHashRef('tab')
257
+ console.log(tab.value) // 'profile'
258
+
259
+ // Changes via Hash reflect in ref
260
+ Hash.set('tab', 'settings')
261
+ console.log(tab.value) // 'settings'
262
+ ```
263
+
264
+ ## Usage Examples
265
+
266
+ ### Form State Persistence
267
+
268
+ ```javascript
269
+ const formData = {
270
+ name: useHashRef('name', ''),
271
+ email: useHashRef('email', ''),
272
+ role: useHashRef('role', 'user')
273
+ }
274
+
275
+ // When filling form, state is saved to URL
276
+ formData.name.value = 'John'
277
+ formData.email.value = 'john@example.com'
278
+ formData.role.value = 'admin'
279
+
280
+ // URL: #name=John;email=john@example.com;role=admin
281
+
282
+ // On page reload, state is restored
283
+ ```
284
+
285
+ ### Modal Window Management
286
+
287
+ ```javascript
288
+ const modalOpen = useHashRef('modal', null)
289
+
290
+ const openModal = (modalName) => {
291
+ modalOpen.value = modalName
292
+ // URL: #modal=confirmation
293
+ }
294
+
295
+ const closeModal = () => {
296
+ modalOpen.value = null
297
+ // URL: #modal=null or hash is cleared
298
+ }
299
+
300
+ // Browser "Back" button closes modal
301
+ ```
302
+