@desource/phone-mask-vue 0.3.0 → 1.1.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +157 -11
  3. package/dist/index.cjs +868 -978
  4. package/dist/index.js +868 -978
  5. package/dist/index.mjs +869 -979
  6. package/dist/phone-mask-vue.css +64 -64
  7. package/dist/types/components/PhoneInput.vue.d.ts +7 -7
  8. package/dist/types/components/PhoneInput.vue.d.ts.map +1 -1
  9. package/dist/types/composables/internal/useCopyAction.d.ts +14 -0
  10. package/dist/types/composables/internal/useCopyAction.d.ts.map +1 -0
  11. package/dist/types/composables/internal/useCountry.d.ts +22 -0
  12. package/dist/types/composables/internal/useCountry.d.ts.map +1 -0
  13. package/dist/types/composables/internal/useCountrySelector.d.ts +30 -0
  14. package/dist/types/composables/internal/useCountrySelector.d.ts.map +1 -0
  15. package/dist/types/composables/internal/useFormatter.d.ts +46 -0
  16. package/dist/types/composables/internal/useFormatter.d.ts.map +1 -0
  17. package/dist/types/composables/internal/useInputHandlers.d.ts +20 -0
  18. package/dist/types/composables/internal/useInputHandlers.d.ts.map +1 -0
  19. package/dist/types/composables/internal/useTheme.d.ts +10 -0
  20. package/dist/types/composables/internal/useTheme.d.ts.map +1 -0
  21. package/dist/types/composables/internal/useValidationHint.d.ts +6 -0
  22. package/dist/types/composables/internal/useValidationHint.d.ts.map +1 -0
  23. package/dist/types/composables/usePhoneMask.d.ts +8 -0
  24. package/dist/types/composables/usePhoneMask.d.ts.map +1 -0
  25. package/dist/types/composables/{useClipboard.d.ts → utility/useClipboard.d.ts} +1 -2
  26. package/dist/types/composables/utility/useClipboard.d.ts.map +1 -0
  27. package/dist/types/composables/utility/useTimer.d.ts +9 -0
  28. package/dist/types/composables/utility/useTimer.d.ts.map +1 -0
  29. package/dist/types/directives/vPhoneMask.d.ts +1 -2
  30. package/dist/types/directives/vPhoneMask.d.ts.map +1 -1
  31. package/dist/types/index.d.ts +7 -5
  32. package/dist/types/index.d.ts.map +1 -1
  33. package/dist/types/types.d.ts +33 -9
  34. package/dist/types/types.d.ts.map +1 -1
  35. package/package.json +17 -11
  36. package/dist/types/composables/useClipboard.d.ts.map +0 -1
  37. package/dist/types/composables/useCountrySelector.d.ts +0 -21
  38. package/dist/types/composables/useCountrySelector.d.ts.map +0 -1
  39. package/dist/types/composables/useMask.d.ts +0 -20
  40. package/dist/types/composables/useMask.d.ts.map +0 -1
  41. package/dist/types/composables/usePhoneFormatter.d.ts +0 -16
  42. package/dist/types/composables/usePhoneFormatter.d.ts.map +0 -1
  43. package/dist/types/consts.d.ts +0 -4
  44. package/dist/types/consts.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # @desource/phone-mask-vue
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Svelte Upgrades:
8
+ - Added attachment `phoneMaskAttachment` for usage in native input (for Svelte 5.29+ versions)
9
+ - Added action `phoneMaskAction` for usage in native input (for Svelte 5.0+ versions)
10
+ - Improved keyboard country selection flow and active-descendant accessibility behavior
11
+ - Refined dropdown/key navigation handling and related focus behavior
12
+ - `usePhoneMask` now exposes `formatter` in the return object
13
+
14
+ - Vue Upgrades:
15
+ - Directive was refactored to align with Svelte action
16
+ - Improved keyboard country selection flow and active-descendant accessibility behavior
17
+ - Refined dropdown/key navigation handling and related focus behavior
18
+ - `usePhoneMask` now exposes `formatter` in the return object
19
+
20
+ - React Upgrades:
21
+ - Improved keyboard country selection flow and active-descendant accessibility behavior
22
+ - Refined dropdown/key navigation handling and related focus behavior
23
+ - `usePhoneMask` now exposes `formatter` in the return object
24
+
25
+ - Core Upgrades:
26
+ - Fixed edge cases in mask variant selection and improved input handler robustness
27
+ - Applied reliability-focused refactors in formatter/handlers and build script generation logic
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies []:
32
+ - @desource/phone-mask@1.1.0
33
+
34
+ ## 1.0.0
35
+
36
+ ### Major Changes
37
+
38
+ - Core Upgrades:
39
+ - Refactored core architecture for better separation of concerns and reusability
40
+ - Added zero-config browser script support path
41
+ - Improved Intl.DisplayNames caching for performance
42
+ - Fixed various edge cases in formatting and event handling
43
+ - Added comprehensive unit tests for core utilities and handlers
44
+
45
+ - React Upgrades:
46
+ - Major internal refactor to a controlled pattern with consistent hooks
47
+ - Improved React 18/19 compatibility for ref behavior
48
+ - Added and expanded unit/e2e tests for React components and behavior
49
+
50
+ - Vue Upgrades:
51
+ - Refactored to align composable structure and reuse core utilities
52
+ - Fixed directive behavior for external value updates and dropdown close logic
53
+ - Added substantial unit/e2e test coverage for Vue composables and directive
54
+
55
+ - 🚀 Svelte Upgrades:
56
+ - Introduced Svelte version of phone-mask library
57
+
58
+ - Nuxt Upgrades:
59
+ - Added full test foundation with @nuxt/test-utils
60
+ - Added unit tests for module and runtime behavior
61
+ - Added e2e fixtures/tests and shared e2e utilities
62
+
63
+ ### Patch Changes
64
+
65
+ - Updated dependencies []:
66
+ - @desource/phone-mask@1.0.0
67
+
3
68
  ## 0.3.0
4
69
 
5
70
  ### Minor Changes
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![bundle size](https://img.shields.io/bundlephobia/minzip/@desource/phone-mask-vue?label=gzip%20size&color=purple)](https://bundlephobia.com/package/@desource/phone-mask-vue)
7
7
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/DeSource-Labs/phone-mask/blob/main/LICENSE)
8
8
 
9
- Beautiful, accessible, extreme small & tree-shackable Vue 3 phone input with auto-formatting, country selector, and validation.
9
+ Beautiful, accessible, extreme small & tree-shakeable Vue 3 phone input with auto-formatting, country selector, and validation.
10
10
 
11
11
  ## ✨ Features
12
12
 
@@ -19,7 +19,7 @@ Beautiful, accessible, extreme small & tree-shackable Vue 3 phone input with aut
19
19
  - ♿ **Accessible** — ARIA labels, keyboard navigation
20
20
  - 📱 **Mobile-friendly** — Optimized for touch devices
21
21
  - 🎯 **TypeScript** — Full type safety
22
- - 🧩 **Two modes** — Component or directive
22
+ - 🧩 **Three modes** — Component, composable, or directive
23
23
  - ⚡ **Optimized** — Tree-shaking and code splitting
24
24
 
25
25
  ## 📦 Installation
@@ -36,19 +36,36 @@ pnpm add @desource/phone-mask-vue
36
36
 
37
37
  ### Importing
38
38
 
39
+ Component mode:
40
+
39
41
  ```ts
40
42
  import { createApp } from 'vue';
41
- import { PhoneInput, vPhoneMask } from '@desource/phone-mask-vue';
42
- import '@desource/phone-mask-vue/assets/lib.css'; // Import styles (for component mode only)
43
+ import { PhoneInput } from '@desource/phone-mask-vue';
44
+ import '@desource/phone-mask-vue/assets/lib.css'; // Import styles
43
45
 
44
46
  const app = createApp(App);
47
+ app.component('PhoneInput', PhoneInput);
48
+ app.mount('#app');
49
+ ```
50
+
51
+ Directive mode (for custom input implementations):
45
52
 
46
- app.component('PhoneInput', PhoneInput); // Register component if you need component mode
47
- app.directive('phone-mask', vPhoneMask); // Register directive if you need directive mode
53
+ ```ts
54
+ import { createApp } from 'vue';
55
+ import { vPhoneMask } from '@desource/phone-mask-vue';
56
+
57
+ const app = createApp(App);
58
+ app.directive('phone-mask', vPhoneMask);
48
59
  app.mount('#app');
49
60
  ```
50
61
 
51
- If you need both modes:
62
+ Composable mode (for custom input implementations in case even directive doesn't fit your needs):
63
+
64
+ ```ts
65
+ import { usePhoneMask } from '@desource/phone-mask-vue';
66
+ ```
67
+
68
+ Register all at once (component + directive):
52
69
 
53
70
  ```ts
54
71
  import { createApp } from 'vue';
@@ -56,8 +73,7 @@ import phoneMask from '@desource/phone-mask-vue';
56
73
  import '@desource/phone-mask-vue/assets/lib.css'; // Import styles for component mode
57
74
 
58
75
  const app = createApp(App);
59
-
60
- app.use(phoneMask); // Registers both component and directive
76
+ app.use(phoneMask); // Registers component and directive
61
77
  app.mount('#app');
62
78
  ```
63
79
 
@@ -119,6 +135,35 @@ const handleChange = (phone: PMaskPhoneNumber) => {
119
135
  </template>
120
136
  ```
121
137
 
138
+ ### Composable Mode
139
+
140
+ For custom input implementations (in case even directive doesn't fit your needs):
141
+
142
+ ```vue
143
+ <script setup lang="ts">
144
+ import { ref } from 'vue';
145
+ import { usePhoneMask } from '@desource/phone-mask-vue';
146
+
147
+ const value = ref('');
148
+
149
+ const { inputRef, digits, full, fullFormatted, isComplete, setCountry } = usePhoneMask({
150
+ value,
151
+ onChange: (newValue) => (value.value = newValue),
152
+ country: 'US',
153
+ detect: true
154
+ });
155
+ </script>
156
+
157
+ <template>
158
+ <div>
159
+ <input ref="inputRef" type="tel" placeholder="Phone number" />
160
+ <p>Formatted: {{ fullFormatted }}</p>
161
+ <p>Valid: {{ isComplete ? 'Yes' : 'No' }}</p>
162
+ <button @click="setCountry('GB')">Use UK</button>
163
+ </div>
164
+ </template>
165
+ ```
166
+
122
167
  ## 📖 Component API
123
168
 
124
169
  ### Props
@@ -405,6 +450,106 @@ const handleChange = (phone: PMaskPhoneNumber) => {
405
450
  </template>
406
451
  ```
407
452
 
453
+ ## 🪝 Composable API
454
+
455
+ ### `usePhoneMask`
456
+
457
+ For custom input implementations:
458
+
459
+ ```vue
460
+ <script setup lang="ts">
461
+ import { ref } from 'vue';
462
+ import { usePhoneMask } from '@desource/phone-mask-vue';
463
+
464
+ const value = ref('');
465
+
466
+ const { inputRef, digits, full, fullFormatted, isComplete, setCountry, clear } = usePhoneMask({
467
+ value,
468
+ onChange: (newValue) => (value.value = newValue),
469
+ country: 'US',
470
+ detect: false
471
+ });
472
+ </script>
473
+
474
+ <template>
475
+ <div>
476
+ <input ref="inputRef" type="tel" />
477
+ <button @click="setCountry('GB')">Switch to UK</button>
478
+ <button @click="clear">Clear</button>
479
+ <p>Full: {{ fullFormatted || '—' }}</p>
480
+ <p>Valid: {{ isComplete ? 'Yes' : 'No' }}</p>
481
+ </div>
482
+ </template>
483
+ ```
484
+
485
+ ### Options
486
+
487
+ > **Note:** The composable requires controlled behavior. Both `value` and `onChange` options are required.
488
+
489
+ ```ts
490
+ interface UsePhoneMaskOptions {
491
+ // Controlled value (digits only, without country code) - REQUIRED
492
+ value: MaybeRefOrGetter<string>;
493
+
494
+ // Callback when the digits value changes - REQUIRED
495
+ onChange: (digits: string) => void;
496
+
497
+ // Predefined country ISO code (e.g., 'US', 'DE', 'GB')
498
+ country?: MaybeRefOrGetter<string | undefined>;
499
+
500
+ // Locale for country names (default: navigator.language)
501
+ locale?: MaybeRefOrGetter<string | undefined>;
502
+
503
+ // Auto-detect country from IP/locale (default: false)
504
+ detect?: MaybeRefOrGetter<boolean | undefined>;
505
+
506
+ // Callback when the phone changes (full, fullFormatted, digits)
507
+ onPhoneChange?: (phone: PhoneNumber) => void;
508
+
509
+ // Country change callback
510
+ onCountryChange?: (country: MaskFull) => void;
511
+ }
512
+ ```
513
+
514
+ ### Return Value
515
+
516
+ ```ts
517
+ interface UsePhoneMaskReturn {
518
+ // Ref to attach to your input element
519
+ inputRef: ShallowRef<HTMLInputElement | null>;
520
+
521
+ // Raw digits without formatting (e.g., "1234567890")
522
+ digits: ComputedRef<string>;
523
+
524
+ // Phone formatter instance
525
+ formatter: ComputedRef<FormatterHelpers>;
526
+
527
+ // Full phone number with country code (e.g., "+11234567890")
528
+ full: ComputedRef<string>;
529
+
530
+ // Full phone number formatted (e.g., "+1 123-456-7890")
531
+ fullFormatted: ComputedRef<string>;
532
+
533
+ // Whether the phone number is complete
534
+ isComplete: ComputedRef<boolean>;
535
+
536
+ // Whether the input is empty
537
+ isEmpty: ComputedRef<boolean>;
538
+
539
+ // Whether to show validation warning
540
+ shouldShowWarn: ComputedRef<boolean>;
541
+
542
+ // Current country data
543
+ country: ComputedRef<MaskFull>;
544
+
545
+ // Change country programmatically
546
+ setCountry: (countryCode?: string | null) => boolean;
547
+
548
+ // Clear the input
549
+ clear: () => void;
550
+ }
551
+ ```
552
+
408
553
  ## 📚 Examples
409
554
 
410
555
  ### With Validation
@@ -439,12 +584,12 @@ const errorMessage = computed(() => {
439
584
  ```vue
440
585
  <script setup lang="ts">
441
586
  import { ref } from 'vue';
442
- import { PhoneInput, type MaskFull } from '@desource/phone-mask-vue';
587
+ import { PhoneInput, type PMaskFull } from '@desource/phone-mask-vue';
443
588
 
444
589
  const phone = ref('');
445
590
  const detectedCountry = ref('');
446
591
 
447
- const handleCountryChange = (country: MaskFull) => {
592
+ const handleCountryChange = (country: PMaskFull) => {
448
593
  detectedCountry.value = country.name;
449
594
  };
450
595
  </script>
@@ -538,6 +683,7 @@ const form = reactive({
538
683
 
539
684
  - [@desource/phone-mask](../phone-mask) — Core library
540
685
  - [@desource/phone-mask-nuxt](../phone-mask-nuxt) — Nuxt module
686
+ - [@desource/phone-mask-react](../phone-mask-react) — React bindings
541
687
 
542
688
  ## 📄 License
543
689