@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,312 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/en/Composables/useTranslateRef'/>
4
+
5
+ # Composable useTranslateRef
6
+
7
+ Composable for getting translated texts by array of keys or string with key. Provides reactive variable that automatically updates when application language changes. Supports dynamic loading of translations from server and text templating with value substitution.
8
+
9
+ ## Key Features
10
+
11
+ - **Reactive translations** — automatic updates when language changes
12
+ - **Batch loading** — fetch multiple translations at once
13
+ - **Dynamic loading** — automatic loading of missing translations from server
14
+ - **Templating** — value substitution in translation text
15
+ - **Synchronous fallback** — instant return of key before translation loads
16
+ - **Type safety** — full TypeScript support with automatic type inference
17
+ - **Request optimization** — request batching to server (160ms timeout)
18
+ - **Geo integration** — automatic language detection from geolocation
19
+
20
+ ## Function
21
+
22
+ ### `useTranslateRef`
23
+
24
+ Creates reactive variable with translations by array of keys.
25
+
26
+ **Parameters:**
27
+ - `names: (string | string[])[]` — array of translation keys or arrays with key and template parameters
28
+
29
+ **Returns:** `ShallowRef<TranslateList<T>>` — reactive object with translations
30
+
31
+ ```javascript
32
+ import { useTranslateRef } from '@dxtmisha/functional'
33
+
34
+ // Simple translation
35
+ const texts = useTranslateRef(['hello', 'goodbye', 'welcome'])
36
+ console.log(texts.value.hello) // 'Hello'
37
+ console.log(texts.value.goodbye) // 'Goodbye'
38
+
39
+ // With templating
40
+ const messages = useTranslateRef([
41
+ ['greeting', 'John'],
42
+ ['count', '5']
43
+ ])
44
+ console.log(messages.value.greeting) // 'Hello, John!'
45
+ console.log(messages.value.count) // 'Found: 5 items'
46
+ ```
47
+
48
+ ### `t` (alias)
49
+
50
+ Short alias for `useTranslateRef`.
51
+
52
+ **Parameters:**
53
+ - `names: string[]` — array of translation keys
54
+
55
+ **Returns:** `ShallowRef<TranslateList<T>>` — reactive object with translations
56
+
57
+ ```javascript
58
+ import { t } from '@dxtmisha/functional'
59
+
60
+ // Short notation
61
+ const texts = t(['save', 'cancel', 'delete'])
62
+ console.log(texts.value.save) // 'Save'
63
+ ```
64
+
65
+ ## Basic Usage
66
+
67
+ ### Basic Translation
68
+
69
+ ```javascript
70
+ import { useTranslateRef } from '@dxtmisha/functional'
71
+
72
+ // Get multiple translations
73
+ const translations = useTranslateRef([
74
+ 'button.save',
75
+ 'button.cancel',
76
+ 'message.success'
77
+ ])
78
+
79
+ // Access translations
80
+ console.log(translations.value['button.save']) // 'Save'
81
+ console.log(translations.value['button.cancel']) // 'Cancel'
82
+ console.log(translations.value['message.success']) // 'Success!'
83
+
84
+ // Automatic update on language change
85
+ // Geo.setLocation('ru-RU')
86
+ // translations.value['button.save'] === 'Сохранить'
87
+ ```
88
+
89
+ ### Using `t` alias
90
+
91
+ ```javascript
92
+ import { t } from '@dxtmisha/functional'
93
+
94
+ // Short notation for translations
95
+ const texts = t(['home', 'about', 'contact'])
96
+
97
+ console.log(texts.value.home) // 'Home'
98
+ console.log(texts.value.about) // 'About'
99
+ console.log(texts.value.contact) // 'Contact'
100
+ ```
101
+
102
+ ## Usage in Components
103
+
104
+ ### Basic Form
105
+
106
+ ```javascript
107
+ import { useTranslateRef } from '@dxtmisha/functional'
108
+
109
+ export default {
110
+ setup() {
111
+ const t = useTranslateRef([
112
+ 'form.name',
113
+ 'form.email',
114
+ 'form.submit',
115
+ 'form.reset'
116
+ ])
117
+
118
+ return { t }
119
+ }
120
+ }
121
+
122
+ // Template:
123
+ // <form>
124
+ // <input :placeholder="t['form.name']" />
125
+ // <input :placeholder="t['form.email']" />
126
+ // <button>{{ t['form.submit'] }}</button>
127
+ // <button type="reset">{{ t['form.reset'] }}</button>
128
+ // </form>
129
+ ```
130
+
131
+ ### Navigation Menu
132
+
133
+ ```javascript
134
+ import { t } from '@dxtmisha/functional'
135
+
136
+ export default {
137
+ setup() {
138
+ const menu = t([
139
+ 'menu.home',
140
+ 'menu.products',
141
+ 'menu.services',
142
+ 'menu.contact'
143
+ ])
144
+
145
+ return { menu }
146
+ }
147
+ }
148
+
149
+ // Template:
150
+ // <nav>
151
+ // <a href="/">{{ menu['menu.home'] }}</a>
152
+ // <a href="/products">{{ menu['menu.products'] }}</a>
153
+ // <a href="/services">{{ menu['menu.services'] }}</a>
154
+ // <a href="/contact">{{ menu['menu.contact'] }}</a>
155
+ // </nav>
156
+ ```
157
+
158
+ ## Text Templating
159
+
160
+ ### Value Substitution
161
+
162
+ ```javascript
163
+ import { useTranslateRef } from '@dxtmisha/functional'
164
+
165
+ // Translations with parameters
166
+ // Translation file: { "greeting": "Hello, {0}!", "items": "Found {0} of {1}" }
167
+ const messages = useTranslateRef([
168
+ ['greeting', 'John'],
169
+ ['items', '5', '10']
170
+ ])
171
+
172
+ console.log(messages.value.greeting) // 'Hello, John!'
173
+ console.log(messages.value.items) // 'Found 5 of 10'
174
+ ```
175
+
176
+ ### Dynamic Parameters
177
+
178
+ ```javascript
179
+ import { ref, computed } from 'vue'
180
+ import { useTranslateRef } from '@dxtmisha/functional'
181
+
182
+ export default {
183
+ setup() {
184
+ const userName = ref('John')
185
+ const count = ref(5)
186
+
187
+ // Base translations
188
+ const t = useTranslateRef(['welcome', 'total'])
189
+
190
+ // Dynamic substitution in template
191
+ const welcomeMessage = computed(() =>
192
+ t.value.welcome.replace('{0}', userName.value)
193
+ )
194
+
195
+ const totalMessage = computed(() =>
196
+ t.value.total.replace('{0}', count.value)
197
+ )
198
+
199
+ return { welcomeMessage, totalMessage }
200
+ }
201
+ }
202
+ ```
203
+
204
+ ## Automatic Update on Language Change
205
+
206
+ ```javascript
207
+ import { watch } from 'vue'
208
+ import { useTranslateRef } from '@dxtmisha/functional'
209
+ import { Geo } from '@dxtmisha/functional'
210
+
211
+ // Translations automatically update on language change
212
+ const texts = useTranslateRef(['title', 'description'])
213
+
214
+ console.log(texts.value.title) // 'Title' (en-US)
215
+
216
+ // Change language
217
+ Geo.setLocation('ru-RU')
218
+
219
+ // texts.value automatically updates
220
+ // texts.value.title === 'Заголовок'
221
+
222
+ // Can track changes
223
+ watch(() => texts.value, (newTranslations) => {
224
+ console.log('Translations updated:', newTranslations)
225
+ })
226
+ ```
227
+
228
+ ## Integration with Translate Class
229
+
230
+ Composable uses `Translate` class for translation management:
231
+
232
+ ```javascript
233
+ import { Translate } from '@dxtmisha/functional'
234
+
235
+ // Set URL for loading translations
236
+ Translate.setUrl('/api/translations')
237
+
238
+ // Set request parameter name
239
+ Translate.setPropsName('keys')
240
+
241
+ // Add translations manually (for SSR or tests)
242
+ Translate.addSync({
243
+ 'button.save': 'Save',
244
+ 'button.cancel': 'Cancel'
245
+ })
246
+
247
+ // Get single translation
248
+ const text = await Translate.get('button.save')
249
+ console.log(text) // 'Save'
250
+
251
+ // Synchronous get
252
+ const syncText = Translate.getSync('button.save')
253
+ console.log(syncText) // 'Save'
254
+ ```
255
+
256
+ ## Usage Examples
257
+
258
+ ### Data Table
259
+
260
+ ```javascript
261
+ const table = useTranslateRef([
262
+ 'table.name',
263
+ 'table.email',
264
+ 'table.status',
265
+ 'table.actions'
266
+ ])
267
+
268
+ // In template:
269
+ // <thead>
270
+ // <th>{{ table['table.name'] }}</th>
271
+ // <th>{{ table['table.email'] }}</th>
272
+ // <th>{{ table['table.status'] }}</th>
273
+ // <th>{{ table['table.actions'] }}</th>
274
+ // </thead>
275
+ ```
276
+
277
+ ### Validation Messages
278
+
279
+ ```javascript
280
+ const validation = useTranslateRef([
281
+ 'validation.required',
282
+ 'validation.email',
283
+ 'validation.minLength',
284
+ 'validation.maxLength'
285
+ ])
286
+
287
+ const validateField = (value) => {
288
+ if (!value) return validation.value['validation.required']
289
+ if (value.length < 3) return validation.value['validation.minLength']
290
+ return null
291
+ }
292
+ ```
293
+
294
+ ### Dynamic Content
295
+
296
+ ```javascript
297
+ import { computed } from 'vue'
298
+
299
+ const status = ref('pending')
300
+ const messages = useTranslateRef([
301
+ 'status.pending',
302
+ 'status.approved',
303
+ 'status.rejected'
304
+ ])
305
+
306
+ const statusText = computed(() =>
307
+ messages.value[`status.${status.value}`]
308
+ )
309
+
310
+ console.log(statusText.value) // 'Pending' (when status = 'pending')
311
+ ```
312
+
@@ -0,0 +1,55 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/ru/About'/>
4
+
5
+ # @dxtmisha/functional
6
+
7
+ Библиотека функциональных утилит для экосистемы DXT UI. Содержит готовые решения для типовых задач веб-разработки: работа с HTTP-запросами, геолокация, работа с датами, кеширование данных и многое другое.
8
+
9
+ ## Что входит в пакет
10
+
11
+ ### Классы (20+)
12
+
13
+ - **Api** — выполнение HTTP-запросов с поддержкой кеширования, загрузочных индикаторов и эмуляции ответов
14
+ - **Geo** — определение страны и языка пользователя, работа с геоданными и часовыми поясами
15
+ - **Datetime** — работа с датами: форматирование, манипуляции, сравнение с учётом локализации
16
+ - **Cache** — система кеширования данных с автоматической инвалидацией
17
+ - **GeoFlag** — доступ к флагам стран (200+) с локализованными названиями
18
+ - **GeoPhone** — телефонные коды и маски форматирования для всех стран
19
+ - **GeoIntl** — интернационализация: форматирование чисел, валют, дат по региональным стандартам
20
+ - **Cookie** — удобная работа с cookies
21
+ - **Hash** — управление параметрами в URL hash
22
+ - **DataStorage** — типизированная работа с localStorage и sessionStorage
23
+ - **Loading** — глобальное управление индикаторами загрузки
24
+ - **Translate** — система переводов с поддержкой подстановок
25
+ - **Icons** — управление иконками и SVG-спрайтами
26
+
27
+ ### Композаблы для Vue 3 (10+)
28
+
29
+ Реактивные обёртки над классами для использования в Vue-компонентах:
30
+
31
+ - **useApiRef** — реактивные HTTP-запросы с автоматическим управлением состоянием загрузки
32
+ - **useGeoIntlRef** — реактивное форматирование с учётом локали пользователя
33
+ - **useStorageRef** — двусторонняя синхронизация ref с localStorage/sessionStorage
34
+ - **useHashRef** — двусторонняя синхронизация ref с URL hash
35
+ - **useCookieRef** — реактивная работа с cookies
36
+ - **useLoadingRef** — реактивное отслеживание состояния загрузки
37
+ - **useTranslateRef** — реактивная система переводов
38
+
39
+ ### Функции-помощники (100+)
40
+
41
+ **Работа с массивами:** преобразование в массив, фильтрация, итерация, заполнение, уникальные значения
42
+
43
+ **Работа с объектами:** глубокое копирование, слияние объектов, получение значений по пути, сравнение
44
+
45
+ **Работа со строками:** преобразование регистра (camelCase, kebabCase), заполнение строк, применение шаблонов
46
+
47
+ **Валидация:** проверка типов данных, проверка на заполненность, сравнение значений
48
+
49
+ **DOM-утилиты:** поиск элементов, создание элементов, работа с атрибутами, прокрутка
50
+
51
+ **Математика:** безопасное преобразование в числа, проценты, случайные числа, пошаговые значения
52
+
53
+ **Асинхронность:** безопасное выполнение промисов и функций, работа с фреймами анимации
54
+
55
+ **Буфер обмена:** копирование и чтение данных из буфера
@@ -13,7 +13,7 @@ import {Meta} from '@storybook/addon-docs/blocks'
13
13
  - **Автоматическая сериализация** — JSON сериализация/десериализация обрабатывается автоматически
14
14
  - **Валидация времени кеша** — опциональное истечение кеша с автоматической очисткой
15
15
  - **Singleton паттерн** — переиспользует экземпляры для одинаковых ключей хранения
16
- - **Управление префиксами** — настраиваемый префикс для всех ключей хранения
16
+ - **Управление префиксами** — настраиваемый префикс для всех ключей хранения (по умолчанию 'ui-storage')
17
17
  - **Поддержка функций как значений** — принимает функции как значения для динамической генерации данных
18
18
  - **Совместимость с браузерами** — безопасное использование с серверным рендерингом
19
19
 
@@ -26,6 +26,8 @@ import {Meta} from '@storybook/addon-docs/blocks'
26
26
  **Параметры:**
27
27
  - `newPrefix: string` — новый префикс для ключей хранения
28
28
 
29
+ **Возвращает:** `void`
30
+
29
31
  ```javascript
30
32
  import { DataStorage } from '@dxtmisha/functional'
31
33
 
@@ -33,7 +35,8 @@ import { DataStorage } from '@dxtmisha/functional'
33
35
  DataStorage.setPrefix('myapp-storage')
34
36
 
35
37
  // Все ключи хранения теперь будут использовать этот префикс:
36
- // 'user-settings' → 'myapp-storage-user-settings'
38
+ // 'user-settings' → 'myapp-storage__user-settings'
39
+ // По умолчанию префикс: 'ui-storage'
37
40
  ```
38
41
 
39
42
  ## Конструктор
@@ -46,6 +49,8 @@ DataStorage.setPrefix('myapp-storage')
46
49
  - `name: string` — имя ключа хранения
47
50
  - `isSession?: boolean` — использовать sessionStorage вместо localStorage (по умолчанию: false)
48
51
 
52
+ **Возвращает:** `DataStorage<T>` — экземпляр класса (или существующий из кеша)
53
+
49
54
  ```javascript
50
55
  // Экземпляр localStorage
51
56
  const userPrefs = new DataStorage('user-preferences')
@@ -66,7 +71,7 @@ console.log(userPrefs === sameInstance) // true
66
71
 
67
72
  **Параметры:**
68
73
  - `defaultValue?: T | (() => T)` — значение по умолчанию или функция, если данные не найдены (опционально)
69
- - `cache?: number` — время кеширования в секундах для валидации (опционально)
74
+ - `cache?: number` — время кеширования в **секундах** для валидации (опционально)
70
75
 
71
76
  **Возвращает:** `T | undefined` — сохранённые данные, значение по умолчанию или undefined
72
77
 
@@ -88,8 +93,10 @@ const config = settings.get(() => ({
88
93
  created: Date.now()
89
94
  }))
90
95
 
91
- // Получить с валидацией кеша (10 минут)
92
- const cachedData = settings.get(null, 600) // Возвращает null если данные старше 10 минут
96
+ // Получить с валидацией кеша (600 секунд = 10 минут)
97
+ const cachedData = settings.get(null, 600)
98
+ // Возвращает undefined если данные старше 10 минут
99
+ // Если кеш валиден - возвращает сохранённые данные
93
100
  ```
94
101
 
95
102
  ### `set`
@@ -131,108 +138,79 @@ const userStorage = new DataStorage('user-data')
131
138
  userStorage.set({ name: 'Иван', preferences: { theme: 'dark' } })
132
139
  console.log(userStorage.get()) // { name: 'Иван', preferences: { theme: 'dark' } }
133
140
 
134
- // Простое удаление
141
+ // Удаление
135
142
  userStorage.remove()
136
143
  console.log(userStorage.get()) // undefined
137
144
 
138
- // Цепочка вызовов с другими экземплярами DataStorage
139
- const tempStorage = new DataStorage('temp-data')
140
- const anotherStorage = new DataStorage('another-data')
145
+ // Цепочка вызовов
146
+ userStorage
147
+ .set({ temp: 'data' })
148
+ .remove() // Удаляет только что сохранённые данные
149
+ ```
141
150
 
142
- // Операции цепочки через разные экземпляры
143
- tempStorage.set({ temp: true })
144
- anotherStorage.set({ another: true })
151
+ ### `update`
145
152
 
146
- tempStorage.remove() // Удалить временные данные
147
- anotherStorage.remove() // Удалить другие данные
153
+ Обновляет данные из хранилища, перечитывая их заново.
148
154
 
149
- console.log(tempStorage.get()) // undefined
150
- console.log(anotherStorage.get()) // undefined
151
- ```
155
+ **Возвращает:** `this` — экземпляр DataStorage для цепочки вызовов
152
156
 
153
- ## Практические примеры
157
+ ```javascript
158
+ const storage = new DataStorage('shared-data')
154
159
 
155
- ### Настройки пользователя
160
+ // Установить данные
161
+ storage.set({ value: 'initial' })
162
+ console.log(storage.get()) // { value: 'initial' }
156
163
 
157
- ```javascript
158
- class UserSettings {
159
- constructor() {
160
- this.storage = new DataStorage('user-settings')
161
- }
162
-
163
- getTheme() {
164
- return this.storage.get('theme', 'light')
165
- }
166
-
167
- setTheme(theme) {
168
- this.storage.set('theme', theme)
169
- }
170
-
171
- getLanguage() {
172
- return this.storage.get('language', 'ru')
173
- }
174
-
175
- setLanguage(language) {
176
- this.storage.set('language', language)
177
- }
178
-
179
- exportSettings() {
180
- return {
181
- theme: this.getTheme(),
182
- language: this.getLanguage(),
183
- notifications: this.storage.get('notifications', true)
184
- }
185
- }
186
- }
164
+ // Данные изменились в другой вкладке/окне браузера
165
+ // или напрямую через localStorage.setItem()
187
166
 
188
- // Использование
189
- const settings = new UserSettings()
190
- settings.setTheme('dark')
191
- console.log('Настройки:', settings.exportSettings())
167
+ // Обновить данные из хранилища
168
+ storage.update()
169
+ console.log(storage.get()) // Получит актуальные данные из хранилища
170
+
171
+ // Цепочка вызовов
172
+ storage.update().get() // Обновить и получить свежие данные
192
173
  ```
193
174
 
194
- ### Кеш данных приложения
175
+ ## Практические примеры
176
+
177
+ ### Настройки пользователя
195
178
 
196
179
  ```javascript
197
- const appCache = new DataStorage('app-cache', 'sessionStorage')
180
+ const settings = new DataStorage('user-settings')
198
181
 
199
- function cacheApiData(endpoint, data) {
200
- const key = `api_${endpoint.replace(/\//g, '_')}`
201
- appCache.set(key, { data, timestamp: Date.now() }, 5 * 60 * 1000) // 5 минут
202
- }
182
+ // Получить с значением по умолчанию
183
+ const theme = settings.get(() => 'light')
184
+ console.log(theme) // 'light' или сохранённое значение
203
185
 
204
- function getCachedData(endpoint) {
205
- const key = `api_${endpoint.replace(/\//g, '_')}`
206
- return appCache.get(key)
207
- }
186
+ // Сохранить новое значение
187
+ settings.set('dark')
208
188
 
209
- // Использование
210
- cacheApiData('/users', [{ id: 1, name: 'Иван' }])
211
- const cached = getCachedData('/users')
212
- console.log('Кешированные данные:', cached)
189
+ // Удалить настройки
190
+ settings.remove()
213
191
  ```
214
192
 
215
- ### Состояние формы
193
+ ### Кеш данных с TTL
216
194
 
217
195
  ```javascript
218
- const formStorage = new DataStorage('form-draft')
196
+ async function fetchWithCache(url, cacheDuration = 300) {
197
+ const storage = new DataStorage(`api_${url}`)
219
198
 
220
- function saveFormDraft(formData) {
221
- formStorage.set('draft', formData)
222
- }
199
+ // Попытка получить из кеша (cacheDuration в секундах)
200
+ const cached = storage.get(undefined, cacheDuration)
201
+ if (cached) return cached
223
202
 
224
- function loadFormDraft() {
225
- return formStorage.get('draft', {})
226
- }
203
+ // Загрузка свежих данных
204
+ const response = await fetch(url)
205
+ const data = await response.json()
227
206
 
228
- function clearFormDraft() {
229
- formStorage.remove('draft')
207
+ // Сохранение в кеш
208
+ storage.set(data)
209
+ return data
230
210
  }
231
211
 
232
212
  // Использование
233
- saveFormDraft({ name: 'Иван', email: 'ivan@example.com' })
234
- const draft = loadFormDraft()
235
- console.log('Черновик формы:', draft)
213
+ const users = await fetchWithCache('/api/users', 600) // Кеш на 10 минут
236
214
  ```
237
215
 
238
- Класс DataStorage предоставляет единый интерфейс для работы с браузерными хранилищами, обеспечивая типобезопасность, автоматическую сериализацию и гибкое управление TTL.
216
+ Класс DataStorage предоставляет единый интерфейс для работы с браузерными хранилищами, обеспечивая типобезопасность, автоматическую сериализацию и гибкое управление временем жизни данных с поддержкой singleton паттерна для эффективного использования памяти.