@dxtmisha/functional-basic 0.8.4 → 0.9.0

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/README.md CHANGED
@@ -1,829 +1,83 @@
1
1
  # @dxtmisha/functional-basic
2
2
 
3
- > Core functional utility library for modern web development without framework dependencies
4
-
5
3
  [![npm version](https://badge.fury.io/js/@dxtmisha%2Ffunctional-basic.svg)](https://www.npmjs.com/package/@dxtmisha/functional-basic)
6
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org/)
5
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org/)
8
6
 
9
- A lightweight, framework-agnostic utility library providing essential classes, functions, and types for modern JavaScript/TypeScript development. This is the core package without Vue dependencies, making it perfect for any JavaScript project.
7
+ `@dxtmisha/functional-basic` is a foundational utility library for modern web development. It's framework-agnostic and can be used in any TypeScript project whether Vue, React, Nuxt, or plain browser code.
10
8
 
11
- ## 📦 Installation
9
+ ## Why this library?
12
10
 
13
- ```bash
14
- npm install @dxtmisha/functional-basic
15
- ```
11
+ Every web application inevitably faces the same set of challenges: HTTP requests, localization, dates, cookies, caching, loading states. Typically each project solves these in its own way, accumulating scattered utilities that are spread across folders, duplicated between projects, and grow stale over time.
16
12
 
17
- ```bash
18
- yarn add @dxtmisha/functional-basic
19
- ```
13
+ `functional-basic` brings all these solutions together in one place — thoughtful, tested, and ready to use. It's not a mega-framework with strict conventions, but a library: pick only what you need and use it however works best for you.
20
14
 
21
- ```bash
22
- pnpm add @dxtmisha/functional-basic
23
- ```
15
+ ## What does it do?
24
16
 
25
- ## Features
17
+ For **networking** — a full-featured HTTP client with lifecycle hooks, response caching, header management, response mocking for development, and an integrated loading state. Requests can be cancelled, configured, and extended — without pulling in extra dependencies.
26
18
 
27
- - 🏗️ **30+ Utility Classes** — API, Cache, Geo, Datetime, Hash, Cookie, Meta, Icons, and more
28
- - 🔧 **90+ Helper Functions** — for arrays, objects, strings, DOM, validation, and math
29
- - 📝 **TypeScript Types** — full type coverage for all utilities
30
- - ⚡ **Tree-shakeable** — import only what you use
31
- - 🌍 **Geolocation & i18n** — auto-detect country, language, and formatting
32
- - 🎨 **Country Flags** — 200+ flags with localized country names
33
- - 📞 **Phone Masks** — international codes and number formatting
34
- - 💾 **Caching** — intelligent cache system with invalidation
35
- - 🌐 **HTTP Client** — extended API class with caching and loading indicators
36
- - 🚫 **No Framework Dependencies** — works with vanilla JS, React, Vue, or any framework
37
- - 📦 **Zero Dependencies** — no external runtime dependencies
19
+ For **geolocation and internationalization** — automatic detection of the user's country and language, locale-aware formatting of numbers, dates, currencies, and units of measurement, pluralization rules, country flags (200+ countries), phone codes and input masks. Everything is built on top of the native `Intl` API, ensuring correctness in any market.
38
20
 
39
- ## 🚀 Quick Start
21
+ For **browser state management** — convenient wrappers over `localStorage`, `sessionStorage`, `cookie`, and URL hash. All with TypeScript types and change subscription support. Data persists across sessions without extra boilerplate on your end.
40
22
 
41
- ### Utility Functions
23
+ For **SEO and meta tags** — a unified class that synchronizes `<title>`, Open Graph, and Twitter Card simultaneously. A single `setTitle()` call updates the browser tab, social media previews, and Twitter card at once. Works in both browser and SSR environments.
42
24
 
43
- ```typescript
44
- import {
45
- toArray,
46
- forEach,
47
- toCamelCase,
48
- toKebabCase,
49
- transformation,
50
- copyObject,
51
- isFilled
52
- } from '@dxtmisha/functional-basic'
25
+ For **data manipulation** — a rich set of utilities: deep object copying, array operations, safe type conversion, value validation, string formatting, and template substitution. Written with real edge cases in mind, not just the happy path.
53
26
 
54
- // Array operations
55
- const items = toArray('single') // ['single']
56
- forEach([1, 2, 3], (item) => console.log(item))
57
-
58
- // String case transformations
59
- const camel = toCamelCase('my-variable-name') // 'myVariableName'
60
- const kebab = toKebabCase('myVariableName') // 'my-variable-name'
61
-
62
- // Object operations
63
- const data = transformation('{"name":"test"}') // { name: 'test' }
64
- const copy = copyObject({ deep: { object: true } })
65
-
66
- // Validation
67
- if (isFilled(value)) {
68
- // value is not empty
69
- }
70
- ```
71
-
72
- ### Utility Classes
73
-
74
- ```typescript
75
- import {
76
- Cache,
77
- Datetime,
78
- Geo,
79
- Hash,
80
- Api,
81
- Cookie,
82
- DataStorage
83
- } from '@dxtmisha/functional-basic'
84
-
85
- // Caching
86
- const cache = new Cache()
87
- const userData = cache.get('user', () => fetchUser())
88
-
89
- // Date operations
90
- const datetime = new Datetime('2024-10-15')
91
- const formatted = datetime.format('YYYY-MM-DD HH:mm')
92
-
93
- // Geolocation
94
- const country = Geo.getCountry() // 'US'
95
- const language = Geo.getLanguage() // 'en'
96
-
97
- // URL Hash management
98
- Hash.set('userId', '12345')
99
- const userId = Hash.get('userId')
100
-
101
- // HTTP requests
102
- Api.setUrl('/api/')
103
- const users = await Api.get({ path: 'users' })
104
-
105
- // Cookie management
106
- const theme = new Cookie('theme')
107
- theme.set('dark')
108
-
109
- // LocalStorage wrapper
110
- const settings = new DataStorage('app-settings')
111
- settings.set({ theme: 'dark' })
112
- ```
113
-
114
- ## 📚 API Documentation
115
-
116
- ### 🏗️ Classes
117
-
118
- #### API & Network
119
-
120
- **Api** — Static HTTP client with caching, loading indicators, and locale support
121
- ```typescript
122
- Api.setUrl('/api/v1')
123
- Api.setHeaders({ Authorization: 'Bearer token' })
124
-
125
- const data = await Api.get({ path: 'users' })
126
- const result = await Api.post({ path: 'users', request: { name: 'John' } })
127
- const updated = await Api.put({ path: 'users/123', request: { name: 'Jane' } })
128
- await Api.delete({ path: 'users/123' })
129
- ```
130
-
131
- **ApiDefault** — Manage default request data
132
- ```typescript
133
- const apiDefault = new ApiDefault()
134
- apiDefault.set({ apiKey: 'key-123', version: '1.0' })
135
- const data = apiDefault.get({ userId: '456' }) // merges with defaults
136
- ```
137
-
138
- **ApiHeaders** — HTTP headers management
139
- ```typescript
140
- const headers = new ApiHeaders()
141
- headers.set({ Authorization: 'Bearer token', 'X-Api-Key': 'key-123' })
142
- const requestHeaders = headers.get({ 'Content-Type': 'application/json' })
143
- ```
144
-
145
- **ApiPreparation** — Request lifecycle hooks
146
- ```typescript
147
- const preparation = new ApiPreparation()
148
- preparation.set(async () => {
149
- // Called before request
150
- await refreshToken()
151
- })
152
- preparation.setEnd(async (response) => {
153
- // Called after request
154
- return { reset: false, data: null }
155
- })
156
- ```
157
-
158
- **ApiResponse** — Response caching and management
159
- ```typescript
160
- const response = new ApiResponse(apiDefault)
161
- response.add({ path: '/users', method: 'GET', response: userData })
162
- const cached = response.get('/users', 'GET')
163
- ```
164
-
165
- **ApiStatus** — Track API request status
166
- ```typescript
167
- const status = new ApiStatus()
168
- status.setStatus(200, 'OK')
169
- status.setError('Network error')
170
- console.log(status.getStatus()) // 200
171
- console.log(status.getError()) // 'Network error'
172
- ```
173
-
174
- **Loading** — Global loading indicator management
175
- ```typescript
176
- Loading.show() // show loading
177
- Loading.hide() // hide loading
178
- if (Loading.is()) { /* is loading */ }
179
- ```
180
-
181
- #### Caching
182
-
183
- **Cache** — Manage multiple caches with automatic invalidation
184
- ```typescript
185
- const cache = new Cache()
186
- const data = cache.get('key', () => expensiveOperation(), [dep1, dep2])
187
- const asyncData = await cache.getAsync('key', async () => await fetch())
188
- cache.clear() // clear all caches
189
- ```
190
-
191
- **CacheItem** — Low-level single cache value management
192
- ```typescript
193
- const item = new CacheItem(() => computeValue())
194
- const value = item.getCache([dependencies])
195
- item.clearCache()
196
- ```
197
-
198
- **CacheStatic** — Static cache for global data
199
- ```typescript
200
- CacheStatic.set('config', configuration)
201
- const config = CacheStatic.get('config')
202
- CacheStatic.clear('config')
203
- ```
204
-
205
- #### Data Storage
206
-
207
- **Cookie** — Cookie management with automatic serialization
208
- ```typescript
209
- const theme = new Cookie('theme')
210
- theme.set('dark', { age: 365 * 24 * 60 * 60 }) // 1 year
211
- const value = theme.get('light') // with default
212
- theme.remove()
213
- ```
214
-
215
- **CookieBlock** — Cookie consent management
216
- ```typescript
217
- CookieBlock.set(true) // allow cookies
218
- if (CookieBlock.isBlock()) { /* cookies blocked */ }
219
- ```
220
-
221
- **DataStorage** — LocalStorage/SessionStorage wrapper
222
- ```typescript
223
- const storage = new DataStorage('settings')
224
- storage.set({ theme: 'dark', lang: 'en' })
225
- const settings = storage.get({ theme: 'light' }) // with default
226
- storage.clear()
227
- ```
228
-
229
- **Hash** — URL hash parameter management
230
- ```typescript
231
- Hash.set('page', 'home')
232
- Hash.set('userId', '123')
233
- const page = Hash.get('page', 'home')
234
- Hash.addWatch('theme', (theme) => applyTheme(theme))
235
- Hash.go({ page: 'products', category: 'electronics' })
236
- ```
237
-
238
- **Global** — Global configuration storage
239
- ```typescript
240
- Global.add({ apiUrl: 'https://api.example.com', version: '1.0' })
241
- const apiUrl = Global.get('apiUrl')
242
- Global.set('apiUrl', 'https://new-api.example.com')
243
- ```
244
-
245
- #### Geolocation & Internationalization
246
-
247
- **Geo** — Location detection and geographic data
248
- ```typescript
249
- const country = Geo.getCountry() // 'US'
250
- const language = Geo.getLanguage() // 'en'
251
- const standard = Geo.getStandard() // 'en-US'
252
- Geo.set('en-US') // set locale
253
- const info = Geo.get() // full geo information
254
- ```
255
-
256
- **GeoIntl** — Locale-aware formatting (Intl API)
257
- ```typescript
258
- const intl = new GeoIntl('en-US')
259
- const formatted = intl.number(1234.56) // '1,234.56'
260
- const currency = intl.currency(99.99, 'USD') // '$99.99'
261
- const date = intl.date(new Date(), 'short') // '10/15/2024'
262
- const relative = intl.relative(-2, 'day') // '2 days ago'
263
- const percent = intl.percent(0.75) // '75%'
264
- ```
265
-
266
- **GeoFlag** — Country flags management
267
- ```typescript
268
- const flag = new GeoFlag('en-US')
269
- const usa = flag.get('US')
270
- // { country: 'United States', icon: '@flag-us', value: 'US', ... }
271
- const list = flag.getList() // list of all countries
272
- const filtered = flag.getListByFilter('united') // search countries
273
- ```
274
-
275
- **GeoPhone** — Phone codes and masks
276
- ```typescript
277
- const phone = GeoPhone.get('US')
278
- // { phone: 1, within: 1, mask: ['+1 (***) ***-****'], value: 'US' }
279
- const info = GeoPhone.getByPhone('+14155551234')
280
- // detect country by phone number
281
- const list = GeoPhone.getList() // all phone codes
282
- ```
283
-
284
- #### Date & Time
285
-
286
- **Datetime** — Date operations and formatting
287
- ```typescript
288
- const dt = new Datetime('2024-10-15', 'full', 'en-US')
289
- const formatted = dt.format('YYYY-MM-DD HH:mm:ss')
290
- const iso = dt.toIso() // ISO 8601 format
291
- dt.moveByDay(5) // +5 days
292
- dt.moveByMonth(-1) // -1 month
293
- const year = dt.getYear()
294
- const month = dt.getMonth()
295
- const day = dt.getDay()
296
- const hour = dt.getHour()
297
- ```
298
-
299
- #### Translations & Meta
300
-
301
- **Translate** — Translation system with caching
302
- ```typescript
303
- const text = await Translate.get('welcome.message')
304
- const withVars = await Translate.get('hello.user', { name: 'John' })
305
- const texts = await Translate.getList(['save', 'cancel', 'submit'])
306
- const cached = Translate.getSync('button.save') // sync from cache
307
- Translate.init(() => import('./translations.json'))
308
- ```
309
-
310
- **Meta** — HTML meta tags management
311
- ```typescript
312
- const meta = new Meta()
313
- meta.set('title', 'Page Title')
314
- meta.set('description', 'Page description')
315
- meta.set('keywords', 'key1, key2, key3')
316
- meta.render() // apply to DOM
317
- ```
318
-
319
- **MetaManager** — Manage multiple meta instances
320
- ```typescript
321
- MetaManager.add('page1', { title: 'Page 1', description: 'First page' })
322
- MetaManager.add('page2', { title: 'Page 2', description: 'Second page' })
323
- MetaManager.render() // render all
324
- ```
325
-
326
- **MetaOg** — Open Graph meta tags
327
- ```typescript
328
- const og = new MetaOg()
329
- og.set('title', 'Share Title')
330
- og.set('description', 'Share description')
331
- og.set('image', 'https://example.com/image.jpg')
332
- og.render()
333
- ```
334
-
335
- **MetaTwitter** — Twitter Card meta tags
336
- ```typescript
337
- const twitter = new MetaTwitter()
338
- twitter.set('title', 'Tweet Title')
339
- twitter.set('description', 'Tweet description')
340
- twitter.set('image', 'https://example.com/image.jpg')
341
- twitter.render()
342
- ```
343
-
344
- #### Icons & Communication
345
-
346
- **Icons** — SVG icon management
347
- ```typescript
348
- Icons.add('user', '/icons/user.svg')
349
- const icon = await Icons.get('user')
350
- const autoPath = await Icons.get('@arrow-left') // auto path
351
- if (Icons.is('settings')) { /* icon exists */ }
352
- Icons.addPath('/assets/icons/')
353
- ```
354
-
355
- **BroadcastMessage** — Cross-tab communication
356
- ```typescript
357
- const broadcast = new BroadcastMessage('app-channel')
358
- broadcast.on('update', (data) => console.log('Received:', data))
359
- broadcast.send('update', { userId: 123, action: 'refresh' })
360
- ```
361
-
362
- #### Events & DOM
363
-
364
- **EventItem** — DOM event management
365
- ```typescript
366
- const event = new EventItem(element, 'click', handler)
367
- event.start() // start listening
368
- event.stop() // stop listening
369
- event.toggle(true) // enable/disable
370
- ```
371
-
372
- **ScrollbarWidth** — Detect scrollbar width
373
- ```typescript
374
- const width = await ScrollbarWidth.get() // width in px
375
- const shouldHide = await ScrollbarWidth.is() // thin scrollbar?
376
- ```
27
+ For **DOM** — element creation, attribute handling, scrolling, querying, and image utilities. Small but essential tools that save time when working with the browser environment.
377
28
 
378
- ### 🔧 Functions
29
+ ## Installation
379
30
 
380
- #### Array Operations
381
-
382
- ```typescript
383
- toArray(value) // convert to array
384
- arrFill(value, count) // create array with repetitions
385
- forEach(data, callback) // universal iteration
386
- uniqueArray(array) // remove duplicates
387
- inArray(array, value) // check presence
388
- getColumn(array, column) // extract column
389
- splice(array, start, count) // immutable splice
390
- getLengthOfAllArray(...arrays) // total length of arrays
391
- getMaxLengthAllArray(...arrays) // max length
392
- getMinLengthAllArray(...arrays) // min length
393
- ```
394
-
395
- #### Object Operations
396
-
397
- ```typescript
398
- copyObject(obj) // deep copy
399
- isObjectNotArray(value) // check object (not array)
400
- getObjectByKeys(obj, keys) // extract by keys
401
- getObjectNoUndefined(obj) // remove undefined
402
- getObjectOrNone(obj) // get object or empty
403
- replaceRecursive(data, search, replace) // recursive replace
404
- setValues(obj, keys, value) // set values
405
- intersectKey(data1, data2) // key intersection
406
- ```
407
-
408
- #### String Operations
409
-
410
- ```typescript
411
- toCamelCase(str) // to camelCase
412
- toKebabCase(str) // to kebab-case
413
- toCamelCaseFirst(str) // capitalize first
414
- anyToString(value) // universal string conversion
415
- strFill(value, length, fill) // fill string
416
- replaceTemplate(str, replacements) // replace templates
417
- applyTemplate(text, data) // apply template
418
- getRandomText(min, max) // generate random text
419
- encodeAttribute(value) // encode for HTML attribute
420
- ```
421
-
422
- #### DOM Operations
423
-
424
- ```typescript
425
- getElement(selector) // get element
426
- createElement(parent, tag, options) // create element
427
- getElementId(element) // get/generate ID
428
- getAttributes(element) // get attributes
429
- setElementItem(element, name, value) // set attribute
430
- getElementItem(element, name) // get attribute
431
- getElementOrWindow(element) // get element or window
432
- domQuerySelector(selector) // safe querySelector
433
- domQuerySelectorAll(selector) // safe querySelectorAll
434
- goScroll(element, options) // smooth scroll
435
- initScrollbarOffset() // scrollbar compensation
436
- ```
437
-
438
- #### Events
439
-
440
- ```typescript
441
- eventStopPropagation(event) // stop propagation
442
- getKey(event) // get pressed key
443
- getMouseClient(event) // mouse/touch coordinates
444
- getMouseClientX(event) // X coordinate
445
- getMouseClientY(event) // Y coordinate
446
- getClipboardData(event) // clipboard data
447
- writeClipboardData(text) // write to clipboard
448
- ```
449
-
450
- #### Validation
451
-
452
- ```typescript
453
- isFilled(value) // check if filled
454
- isArray(value) // check array
455
- isObject(value) // check object
456
- isString(value) // check string
457
- isNumber(value) // check number
458
- isFunction(value) // check function
459
- isFloat(value) // check float
460
- isIntegerBetween(value, min, max) // check range
461
- isDifferent(value1, value2) // check difference
462
- isNull(value) // check null/undefined
463
- isDomRuntime() // check browser environment
464
- isWindow(element) // check window
465
- isInDom(element) // check if in DOM
466
- isSelected(value, check) // check selection
467
- isSelectedByList(list, value) // check in list
468
- ```
469
-
470
- #### Math Operations
471
-
472
- ```typescript
473
- random(min, max) // random number
474
- getStepPercent(value, min, max) // percent from range
475
- getStepValue(percent, min, max) // value by percent
476
- toNumber(value) // convert to number
477
- toNumberByMax(value, max) // with limit
478
- toPercent(value) // to percent
479
- toPercentBy100(value) // to percent (divide by 100)
480
- ```
481
-
482
- #### Conversions
483
-
484
- ```typescript
485
- transformation(value) // universal conversion
486
- toDate(value) // to Date object
487
- secondToTime(seconds) // seconds to time format
488
- ```
489
-
490
- #### Execution Utilities
491
-
492
- ```typescript
493
- executeFunction(callback) // execute function or return value
494
- executePromise(callback) // async execution
495
- frame(callback, next, end) // requestAnimationFrame loop
496
- ```
497
-
498
- #### Data Operations
499
-
500
- ```typescript
501
- getItemByPath(obj, path) // get by path
502
- getExp(value, flags) // create RegExp with escaping
503
- getRequestString(data) // object to query string
504
- ```
505
-
506
- ### 📝 TypeScript Types
507
-
508
- ```typescript
509
- // Basic types
510
- Undefined // undefined | null
511
- EmptyValue // all "empty" values
512
- NumberOrString // number | string
513
- NumberOrStringOrBoolean // number | string | boolean
514
- NumberOrStringOrDate // number | string | Date
515
- NormalOrArray<T> // T | T[]
516
- FunctionArgs<Args, Return> // typed function
517
- FunctionReturn<R> // () => R
518
- ObjectOrArray<T> // Record | T[]
519
- ItemList // Record<string, any>
520
- ElementOrString<E> // E | string | Window
521
-
522
- // API types
523
- ApiMethodItem // enum: GET, POST, PUT, DELETE
524
- ApiMethod // HTTP method type
525
- ApiFetch // API request options
526
- ApiPreparationEnd // preparation callback result
527
- ApiDefaultValue // default request data
528
- ApiStatusItem // status information
529
- ApiResponseItem // response cache item
530
-
531
- // Geo types
532
- GeoItemFull // full country information
533
- GeoFlagItem // flag information
534
- GeoPhoneValue // phone data
535
- GeoDate // date format types
536
-
537
- // Meta types
538
- MetaItemType // meta tag types
539
- MetaManagerItemType // meta manager item
540
- ```
541
-
542
- ## 🎯 Usage Examples
543
-
544
- ### Caching Expensive Operations
545
-
546
- ```typescript
547
- import { Cache } from '@dxtmisha/functional-basic'
548
-
549
- const cache = new Cache()
550
- let userId = 1
551
-
552
- // Data is cached on first call
553
- const userData = cache.get(
554
- 'user-data',
555
- () => {
556
- console.log('Loading user data...')
557
- return fetchUserData(userId)
558
- },
559
- [userId] // dependencies for invalidation
560
- )
561
-
562
- // When userId changes, cache invalidates
563
- userId = 2
564
- const newUserData = cache.get('user-data', () => fetchUserData(userId), [userId])
565
- ```
566
-
567
- ### Locale-Aware Formatting
568
-
569
- ```typescript
570
- import { GeoIntl } from '@dxtmisha/functional-basic'
571
-
572
- const intl = new GeoIntl('en-US')
573
-
574
- // Numbers
575
- console.log(intl.number(1234567.89)) // '1,234,567.89'
576
-
577
- // Currency
578
- console.log(intl.currency(99.99, 'USD')) // '$99.99'
579
-
580
- // Dates
581
- console.log(intl.date(new Date(), 'long')) // 'October 15, 2024'
582
-
583
- // Relative time
584
- console.log(intl.relative(-2, 'day')) // '2 days ago'
585
-
586
- // Plural forms
587
- console.log(intl.plural(5, ['item', 'items'])) // '5 items'
31
+ ```bash
32
+ npm install @dxtmisha/functional-basic
588
33
  ```
589
34
 
590
- ### REST API Client
35
+ ## Quick Start
591
36
 
592
37
  ```typescript
593
- import { Api } from '@dxtmisha/functional-basic'
38
+ import { Api, GeoIntl, Meta, Cache, isFilled } from '@dxtmisha/functional-basic'
594
39
 
595
- // Setup
40
+ // HTTP client
596
41
  Api.setUrl('/api/v1')
597
- Api.setHeaders({
598
- Authorization: 'Bearer token',
599
- 'Content-Type': 'application/json'
600
- })
601
-
602
- // GET request
603
42
  const users = await Api.get({ path: 'users' })
604
43
 
605
- // POST with data
606
- const newUser = await Api.post({
607
- path: 'users',
608
- request: { name: 'John Doe', email: 'john@example.com' }
609
- })
610
-
611
- // PUT
612
- await Api.put({
613
- path: 'users/123',
614
- request: { name: 'Jane Doe' }
615
- })
616
-
617
- // DELETE
618
- await Api.delete({ path: 'users/123' })
619
-
620
- // With query parameters
621
- const filtered = await Api.get({
622
- path: 'users',
623
- request: { role: 'admin', active: true }
624
- })
625
- // GET /api/v1/users?role=admin&active=true
626
- ```
627
-
628
- ### URL Hash Management
629
-
630
- ```typescript
631
- import { Hash } from '@dxtmisha/functional-basic'
632
-
633
- // Set parameters
634
- Hash.set('page', 'products')
635
- Hash.set('category', 'electronics')
636
- Hash.set('sort', 'price')
637
-
638
- // URL becomes: #page:products/category:electronics/sort:price
639
-
640
- // Get parameters
641
- const page = Hash.get('page', 'home')
642
- const category = Hash.get('category')
643
-
644
- // Watch for changes
645
- Hash.addWatch('page', (newPage) => {
646
- console.log(`Page changed to: ${newPage}`)
647
- loadPageContent(newPage)
648
- })
649
-
650
- // Bulk update
651
- Hash.go({ page: 'checkout', step: '1' })
652
- ```
653
-
654
- ### Meta Tags Management
44
+ // Locale-aware formatting
45
+ const intl = new GeoIntl()
46
+ intl.number(1234567.89) // '1,234,567.89'
47
+ intl.currency(99.99, 'USD') // '$99.99'
48
+ intl.date(new Date(), 'date')
655
49
 
656
- ```typescript
657
- import { Meta, MetaOg, MetaTwitter } from '@dxtmisha/functional-basic'
50
+ // Caching
51
+ const cache = new Cache()
52
+ const data = cache.get('key', () => expensiveOperation(), [dep])
658
53
 
659
- // Basic meta tags
54
+ // Unified SEO — one call updates title, og:title and twitter:title
660
55
  const meta = new Meta()
661
- meta.set('title', 'My Awesome Page')
662
- meta.set('description', 'This is an awesome page description')
663
- meta.set('keywords', 'awesome, page, example')
664
- meta.render()
665
-
666
- // Open Graph
667
- const og = new MetaOg()
668
- og.set('title', 'Share Title')
669
- og.set('description', 'Share description for social media')
670
- og.set('image', 'https://example.com/share-image.jpg')
671
- og.set('url', 'https://example.com/page')
672
- og.render()
673
-
674
- // Twitter Card
675
- const twitter = new MetaTwitter()
676
- twitter.set('title', 'Tweet Title')
677
- twitter.set('description', 'Tweet description')
678
- twitter.set('image', 'https://example.com/twitter-image.jpg')
679
- twitter.render()
680
- ```
681
-
682
- ### Cross-Tab Communication
683
-
684
- ```typescript
685
- import { BroadcastMessage } from '@dxtmisha/functional-basic'
686
-
687
- const channel = new BroadcastMessage('app-sync')
688
-
689
- // Listen for messages
690
- channel.on('user-updated', (data) => {
691
- console.log('User updated in another tab:', data)
692
- updateUI(data)
693
- })
694
-
695
- // Send message to all tabs
696
- channel.send('user-updated', {
697
- userId: 123,
698
- name: 'John Doe',
699
- timestamp: Date.now()
700
- })
701
- ```
702
-
703
- ### Date Operations
704
-
705
- ```typescript
706
- import { Datetime } from '@dxtmisha/functional-basic'
707
-
708
- const dt = new Datetime('2024-10-15 14:30:00', 'full', 'en-US')
709
-
710
- // Formatting
711
- console.log(dt.format('YYYY-MM-DD')) // '2024-10-15'
712
- console.log(dt.format('DD/MM/YYYY HH:mm')) // '15/10/2024 14:30'
713
- console.log(dt.toIso()) // '2024-10-15T14:30:00.000Z'
714
-
715
- // Manipulation
716
- dt.moveByDay(7) // +7 days
717
- dt.moveByMonth(-1) // -1 month
718
- dt.moveByHour(3) // +3 hours
719
-
720
- // Getters
721
- console.log(dt.getYear()) // 2024
722
- console.log(dt.getMonth()) // 10
723
- console.log(dt.getDay()) // 15
724
- console.log(dt.getDayWeek()) // 2 (Tuesday)
725
- ```
726
-
727
- ## 📁 Export Structure
728
-
729
- ```
730
- @dxtmisha/functional-basic
731
- ├── / # All utilities (recommended)
732
- └── /types/* # TypeScript types
733
- ```
734
-
735
- ## 🔧 Requirements
736
-
737
- - **Node.js**: ≥18.0.0
738
- - **TypeScript**: 4.0+ (optional)
739
- - **No Framework Required**: Works with vanilla JS or any framework
740
-
741
- ## 🤝 Compatibility
742
-
743
- | Environment | Support |
744
- |-------------|---------|
745
- | **Browsers** | ✅ ES2020+ (Chrome 80+, Firefox 72+, Safari 13.1+, Edge 80+) |
746
- | **Node.js** | ✅ 18+ |
747
- | **TypeScript** | ✅ 4+ |
748
- | **Vanilla JS** | ✅ Full support |
749
- | **React** | ✅ Full support |
750
- | **Vue** | ✅ Full support |
751
- | **Angular** | ✅ Full support |
752
- | **SSR** | ✅ With environment checks |
753
-
754
- ## 📊 Bundle Size
755
-
756
- - **Full library**: ~90KB (minified)
757
- - **With tree-shaking**: only used functions are imported
758
- - **Minimal import**: ~1KB (single function)
759
- - **Dependencies**: zero runtime dependencies
56
+ meta.setSuffix('My Site')
57
+ meta.setTitle('Article').setDescription('...').setImage('https://...')
760
58
 
761
- ## 🎯 Tree-shaking
762
-
763
- The library fully supports tree-shaking:
764
-
765
- ```typescript
766
- // ❌ Bad - imports entire library
767
- import * as functional from '@dxtmisha/functional-basic'
768
-
769
- // ✅ Good - imports only what's needed
770
- import { toArray, forEach, Cache } from '@dxtmisha/functional-basic'
59
+ // Validation
60
+ if (isFilled(value)) { /* ... */ }
771
61
  ```
772
62
 
773
- ## 🏆 Advantages
774
-
775
- - ✅ **Full TypeScript support** — TypeScript out of the box
776
- - ✅ **Zero dependencies** — no external runtime dependencies
777
- - ✅ **Framework agnostic** — works with any framework or vanilla JS
778
- - ✅ **Tree-shakeable** — optimal bundle size
779
- - ✅ **SSR friendly** — safe for server-side rendering
780
- - ✅ **Comprehensive** — everything you need in one library
781
- - ✅ **Well tested** — comprehensive test coverage
782
- - ✅ **Well documented** — complete API documentation
783
- - ✅ **Production ready** — used in production projects
784
- - ✅ **Regular updates** — active development and support
785
-
786
- ## 📖 Difference from @dxtmisha/functional
787
-
788
- - **@dxtmisha/functional-basic**: Core utilities without Vue dependencies
789
- - **@dxtmisha/functional**: Includes Vue composables and reactive utilities
790
-
791
- Use `functional-basic` if:
792
- - You're not using Vue.js
793
- - You want minimal dependencies
794
- - You're building a library
795
- - You need maximum compatibility
796
-
797
- Use `functional` if:
798
- - You're building a Vue.js application
799
- - You want reactive composables
800
- - You need Vue-specific utilities
801
-
802
- ## 📖 Additional Documentation
803
-
804
- - [GitHub Repository](https://github.com/dxtmisha/dxt-ui)
805
- - [Full API Documentation](https://github.com/dxtmisha/dxt-ui/tree/main/packages/wiki/src/media/functional-basic)
806
- - [DXT UI Documentation](https://dxtmisha.github.io/dxt-ui/)
807
-
808
- ## 🐛 Report Issues
809
-
810
- If you found a bug or want to suggest an improvement:
811
-
812
- - [GitHub Issues](https://github.com/dxtmisha/dxt-ui/issues)
813
-
814
- ## 📄 License
63
+ ## Principles
815
64
 
816
- MIT © [dxtmisha](https://github.com/dxtmisha)
65
+ - **Zero external dependencies** — no third-party packages are pulled in. Fewer conflicts, fewer vulnerabilities, fewer surprises during updates.
66
+ - **TypeScript-first** — strict typing and autocomplete out of the box. Types aren't an "add-on" — they're an integral part of the API.
67
+ - **Clean API** — method chaining, predictable behavior, clear naming. You don't need to read the docs to understand what `isFilled` or `setTitle` does.
68
+ - **Test coverage** — every class and function ships with tests. Library changes won't silently break your project.
817
69
 
818
- ## 🤝 Contributing
70
+ ## Documentation
819
71
 
820
- Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
72
+ Full API reference, examples, and guides:
821
73
 
822
- ## ⭐ Support the Project
74
+ **[📖 https://dxtmisha.github.io/dxt-ui/](https://dxtmisha.github.io/dxt-ui/)**
823
75
 
824
- If this library was helpful, please star it on [GitHub](https://github.com/dxtmisha/dxt-ui)!
76
+ ## Difference from @dxtmisha/functional
825
77
 
826
- ---
78
+ - **`@dxtmisha/functional-basic`** — core utilities, no framework dependencies. Use this with vanilla JS, React, or any non-Vue stack, or when building a library.
79
+ - **`@dxtmisha/functional`** — extends `functional-basic` with Vue 3 composables and reactive utilities. Use this in Vue / Nuxt applications.
827
80
 
828
- Made with ❤️ by [dxtmisha](https://github.com/dxtmisha)
81
+ ## License
829
82
 
83
+ [MIT](LICENSE)