@vuetify/nightly 3.9.5-dev.2025-08-23 → 3.9.5-dev.2025-08-24

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.
@@ -4,7 +4,7 @@ import { makeVTextFieldProps, VTextField } from "../../components/VTextField/VTe
4
4
  import { forwardRefs } from "../../composables/forwardRefs.js";
5
5
  import { isMaskDelimiter, makeMaskProps, useMask } from "../../composables/mask/index.js";
6
6
  import { useProxiedModel } from "../../composables/proxiedModel.js"; // Utilities
7
- import { computed, onBeforeMount, ref, shallowRef, toRef } from 'vue';
7
+ import { computed, nextTick, onBeforeMount, ref, shallowRef, toRef } from 'vue';
8
8
  import { genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types
9
9
  export const makeVMaskInputProps = propsFactory({
10
10
  returnMaskedValue: Boolean,
@@ -23,59 +23,140 @@ export const VMaskInput = genericComponent()({
23
23
  emit
24
24
  } = _ref;
25
25
  const vTextFieldRef = ref();
26
- const selection = shallowRef(0);
27
- const lazySelection = shallowRef(0);
26
+ const inputAction = shallowRef();
27
+ const caretPosition = shallowRef(0);
28
28
  const mask = useMask(props);
29
29
  const returnMaskedValue = computed(() => props.mask && props.returnMaskedValue);
30
30
  const model = useProxiedModel(props, 'modelValue', undefined,
31
31
  // Always display masked value in input when mask is applied
32
32
  val => props.mask ? mask.mask(mask.unmask(val)) : val, val => {
33
33
  if (props.mask) {
34
- const valueBeforeChange = mask.unmask(model.value);
34
+ const valueWithoutDelimiters = removeMaskDelimiters(val);
35
+
35
36
  // E.g. mask is #-# and the input value is '2-23'
36
37
  // model-value should be enforced to '2-2'
37
- const enforcedMaskedValue = mask.mask(mask.unmask(val));
38
- const newUnmaskedValue = mask.unmask(enforcedMaskedValue);
39
- if (newUnmaskedValue === valueBeforeChange) {
40
- vTextFieldRef.value.value = enforcedMaskedValue;
41
- }
42
- val = newUnmaskedValue;
43
- updateRange();
44
- return returnMaskedValue.value ? mask.mask(val) : val;
38
+ const newMaskedValue = mask.mask(valueWithoutDelimiters);
39
+ const newUnmaskedValue = mask.unmask(newMaskedValue);
40
+ const newCaretPosition = getNewCaretPosition({
41
+ oldValue: model.value,
42
+ newValue: newMaskedValue,
43
+ oldCaret: caretPosition.value
44
+ });
45
+ vTextFieldRef.value.value = newMaskedValue;
46
+ vTextFieldRef.value.setSelectionRange(newCaretPosition, newCaretPosition);
47
+ return returnMaskedValue.value ? mask.mask(newUnmaskedValue) : newUnmaskedValue;
45
48
  }
46
49
  return val;
47
50
  });
48
51
  const validationValue = toRef(() => returnMaskedValue.value ? model.value : mask.unmask(model.value));
52
+ function removeMaskDelimiters(val) {
53
+ return val.split('').filter(ch => !isMaskDelimiter(ch)).join('');
54
+ }
55
+ function getNewCaretPosition(_ref2) {
56
+ let {
57
+ oldValue,
58
+ newValue,
59
+ oldCaret
60
+ } = _ref2;
61
+ if (!newValue) return 0;
62
+ if (!oldValue) return newValue.length;
63
+ let newCaret;
64
+ if (inputAction.value === 'Backspace') {
65
+ newCaret = oldCaret - 1;
66
+ while (newCaret > 0 && isMaskDelimiter(newValue[newCaret - 1])) newCaret--;
67
+ } else if (inputAction.value === 'Delete') {
68
+ newCaret = oldCaret;
69
+ } else {
70
+ // insertion
71
+ newCaret = oldCaret + 1;
72
+ while (isMaskDelimiter(newValue[newCaret])) newCaret++;
73
+ if (isMaskDelimiter(newValue[oldCaret])) newCaret++;
74
+ }
75
+ return newCaret;
76
+ }
49
77
  onBeforeMount(() => {
50
78
  if (props.returnMaskedValue) {
51
79
  emit('update:modelValue', model.value);
52
80
  }
53
81
  });
54
- function setCaretPosition(newSelection) {
55
- selection.value = newSelection;
56
- vTextFieldRef.value && vTextFieldRef.value.setSelectionRange(selection.value, selection.value);
82
+ function onKeyDown(e) {
83
+ if (e.metaKey) return;
84
+ const inputElement = e.target;
85
+ caretPosition.value = inputElement.selectionStart || 0;
86
+ inputAction.value = e.key;
87
+ const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd;
88
+ if (e.key === 'Backspace' && hasSelection) {
89
+ e.preventDefault();
90
+ deleteSelection(e);
91
+ }
57
92
  }
58
- function resetSelections() {
59
- if (!vTextFieldRef.value?.selectionEnd) return;
60
- selection.value = vTextFieldRef.value.selectionEnd;
61
- lazySelection.value = 0;
62
- for (let index = 0; index < selection.value; index++) {
63
- isMaskDelimiter(vTextFieldRef.value.value[index]) || lazySelection.value++;
93
+ async function onCut(e) {
94
+ e.preventDefault();
95
+ copySelectionToClipboard(e);
96
+ deleteSelection(e);
97
+ }
98
+ async function onPaste(e) {
99
+ e.preventDefault();
100
+ const inputElement = e.target;
101
+ const pastedString = removeMaskDelimiters(e.clipboardData?.getData('text') || '');
102
+ if (!pastedString) return;
103
+ const pastedCharacters = [...pastedString];
104
+ const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd;
105
+ if (hasSelection) {
106
+ replaceSelection(inputElement, pastedCharacters);
107
+ } else {
108
+ insertCharacters(inputElement, pastedCharacters);
64
109
  }
65
110
  }
66
- function updateRange() {
67
- if (!vTextFieldRef.value) return;
68
- resetSelections();
69
- let selection = 0;
70
- const newValue = vTextFieldRef.value.value;
71
- if (newValue) {
72
- for (let index = 0; index < newValue.length; index++) {
73
- if (lazySelection.value <= 0) break;
74
- isMaskDelimiter(newValue[index]) || lazySelection.value--;
75
- selection++;
76
- }
111
+ function copySelectionToClipboard(e) {
112
+ const inputElement = e.target;
113
+ const start = inputElement.selectionStart || 0;
114
+ const end = inputElement.selectionEnd || 0;
115
+ const selectedText = inputElement.value.substring(start, end);
116
+ navigator.clipboard.writeText(selectedText);
117
+ }
118
+ async function deleteSelection(e) {
119
+ const inputElement = e.target;
120
+ const curStart = inputElement.selectionStart || 0;
121
+ caretPosition.value = inputElement.selectionEnd || 0;
122
+ while (caretPosition.value > curStart) {
123
+ const success = await simulateBackspace(inputElement);
124
+ if (!success) break;
77
125
  }
78
- setCaretPosition(selection);
126
+ }
127
+ async function simulateBackspace(inputElement) {
128
+ inputAction.value = 'Backspace';
129
+ model.value = inputElement.value.slice(0, caretPosition.value - 1) + inputElement.value.slice(caretPosition.value);
130
+ inputAction.value = '';
131
+ if (caretPosition.value === inputElement.selectionEnd) return false;
132
+ caretPosition.value = inputElement.selectionEnd || 0;
133
+ await nextTick();
134
+ return true;
135
+ }
136
+ async function insertCharacters(inputElement, pastedCharacters) {
137
+ for (let i = 0; i < pastedCharacters.length; i++) {
138
+ await insertCharacter(inputElement, pastedCharacters[i]);
139
+ }
140
+ }
141
+ async function insertCharacter(inputElement, character) {
142
+ caretPosition.value = inputElement.selectionEnd || 0;
143
+ model.value = inputElement.value.slice(0, caretPosition.value) + character + inputElement.value.slice(caretPosition.value);
144
+ await nextTick();
145
+ }
146
+ async function replaceSelection(inputElement, pastedCharacters) {
147
+ caretPosition.value = inputElement.selectionStart || 0;
148
+ for (let i = 0; i < pastedCharacters.length; i++) {
149
+ await replaceCharacter(caretPosition.value, pastedCharacters[i]);
150
+ caretPosition.value++;
151
+ }
152
+ }
153
+ async function replaceCharacter(index, character) {
154
+ let targetIndex = index;
155
+
156
+ // Find next non-delimiter position
157
+ while (targetIndex < model.value.length && isMaskDelimiter(model.value[targetIndex])) targetIndex++;
158
+ model.value = model.value.slice(0, targetIndex) + character + model.value.slice(targetIndex + 1);
159
+ await nextTick();
79
160
  }
80
161
  useRender(() => {
81
162
  const textFieldProps = VTextField.filterProps(props);
@@ -83,7 +164,10 @@ export const VMaskInput = genericComponent()({
83
164
  "modelValue": model.value,
84
165
  "onUpdate:modelValue": $event => model.value = $event,
85
166
  "ref": vTextFieldRef,
86
- "validationValue": validationValue.value
167
+ "validationValue": validationValue.value,
168
+ "onCut": onCut,
169
+ "onPaste": onPaste,
170
+ "onKeydown": onKeyDown
87
171
  }), {
88
172
  ...slots
89
173
  });
@@ -1 +1 @@
1
- {"version":3,"file":"VMaskInput.js","names":["makeVTextFieldProps","VTextField","forwardRefs","isMaskDelimiter","makeMaskProps","useMask","useProxiedModel","computed","onBeforeMount","ref","shallowRef","toRef","genericComponent","propsFactory","useRender","makeVMaskInputProps","returnMaskedValue","Boolean","VMaskInput","name","props","emits","val","setup","_ref","slots","emit","vTextFieldRef","selection","lazySelection","mask","model","undefined","unmask","valueBeforeChange","value","enforcedMaskedValue","newUnmaskedValue","updateRange","validationValue","setCaretPosition","newSelection","setSelectionRange","resetSelections","selectionEnd","index","newValue","length","textFieldProps","filterProps","_createVNode","_mergeProps","$event"],"sources":["../../../src/labs/VMaskInput/VMaskInput.tsx"],"sourcesContent":["// Components\nimport { makeVTextFieldProps, VTextField } from '@/components/VTextField/VTextField'\n\n// Composables\nimport { forwardRefs } from '@/composables/forwardRefs'\nimport { isMaskDelimiter, makeMaskProps, useMask } from '@/composables/mask'\nimport { useProxiedModel } from '@/composables/proxiedModel'\n\n// Utilities\nimport { computed, onBeforeMount, ref, shallowRef, toRef } from 'vue'\nimport { genericComponent, propsFactory, useRender } from '@/util'\n\n// Types\nimport type { VTextFieldSlots } from '@/components/VTextField/VTextField'\n\nexport type VMaskInputSlots = VTextFieldSlots\n\nexport const makeVMaskInputProps = propsFactory({\n returnMaskedValue: Boolean,\n ...makeVTextFieldProps(),\n ...makeMaskProps(),\n}, 'VMaskInput')\n\nexport const VMaskInput = genericComponent<VMaskInputSlots>()({\n name: 'VMaskInput',\n\n props: makeVMaskInputProps(),\n\n emits: {\n 'update:modelValue': (val: string) => true,\n },\n\n setup (props, { slots, emit }) {\n const vTextFieldRef = ref<VTextField>()\n\n const selection = shallowRef(0)\n const lazySelection = shallowRef(0)\n\n const mask = useMask(props)\n const returnMaskedValue = computed(() => props.mask && props.returnMaskedValue)\n\n const model = useProxiedModel(\n props,\n 'modelValue',\n undefined,\n // Always display masked value in input when mask is applied\n val => props.mask ? mask.mask(mask.unmask(val)) : val,\n val => {\n if (props.mask) {\n const valueBeforeChange = mask.unmask(model.value)\n // E.g. mask is #-# and the input value is '2-23'\n // model-value should be enforced to '2-2'\n const enforcedMaskedValue = mask.mask(mask.unmask(val))\n const newUnmaskedValue = mask.unmask(enforcedMaskedValue)\n\n if (newUnmaskedValue === valueBeforeChange) {\n vTextFieldRef.value!.value = enforcedMaskedValue\n }\n val = newUnmaskedValue\n updateRange()\n return returnMaskedValue.value ? mask.mask(val) : val\n }\n return val\n },\n )\n\n const validationValue = toRef(() => returnMaskedValue.value ? model.value : mask.unmask(model.value))\n\n onBeforeMount(() => {\n if (props.returnMaskedValue) {\n emit('update:modelValue', model.value)\n }\n })\n\n function setCaretPosition (newSelection: number) {\n selection.value = newSelection\n vTextFieldRef.value && vTextFieldRef.value.setSelectionRange(selection.value, selection.value)\n }\n\n function resetSelections () {\n if (!vTextFieldRef.value?.selectionEnd) return\n\n selection.value = vTextFieldRef.value.selectionEnd\n lazySelection.value = 0\n\n for (let index = 0; index < selection.value; index++) {\n isMaskDelimiter(vTextFieldRef.value.value[index]) || lazySelection.value++\n }\n }\n\n function updateRange () {\n if (!vTextFieldRef.value) return\n resetSelections()\n\n let selection = 0\n const newValue = vTextFieldRef.value.value\n\n if (newValue) {\n for (let index = 0; index < newValue.length; index++) {\n if (lazySelection.value <= 0) break\n isMaskDelimiter(newValue[index]) || lazySelection.value--\n selection++\n }\n }\n setCaretPosition(selection)\n }\n\n useRender(() => {\n const textFieldProps = VTextField.filterProps(props)\n\n return (\n <VTextField\n { ...textFieldProps }\n v-model={ model.value }\n ref={ vTextFieldRef }\n validationValue={ validationValue.value }\n >\n {{ ...slots }}\n </VTextField>\n )\n })\n\n return forwardRefs({}, vTextFieldRef)\n },\n})\n\nexport type VMaskInput = InstanceType<typeof VMaskInput>\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"VMaskInput.js","names":["makeVTextFieldProps","VTextField","forwardRefs","isMaskDelimiter","makeMaskProps","useMask","useProxiedModel","computed","nextTick","onBeforeMount","ref","shallowRef","toRef","genericComponent","propsFactory","useRender","makeVMaskInputProps","returnMaskedValue","Boolean","VMaskInput","name","props","emits","val","setup","_ref","slots","emit","vTextFieldRef","inputAction","caretPosition","mask","model","undefined","unmask","valueWithoutDelimiters","removeMaskDelimiters","newMaskedValue","newUnmaskedValue","newCaretPosition","getNewCaretPosition","oldValue","value","newValue","oldCaret","setSelectionRange","validationValue","split","filter","ch","join","_ref2","length","newCaret","onKeyDown","e","metaKey","inputElement","target","selectionStart","key","hasSelection","selectionEnd","preventDefault","deleteSelection","onCut","copySelectionToClipboard","onPaste","pastedString","clipboardData","getData","pastedCharacters","replaceSelection","insertCharacters","start","end","selectedText","substring","navigator","clipboard","writeText","curStart","success","simulateBackspace","slice","i","insertCharacter","character","replaceCharacter","index","targetIndex","textFieldProps","filterProps","_createVNode","_mergeProps","$event"],"sources":["../../../src/labs/VMaskInput/VMaskInput.tsx"],"sourcesContent":["// Components\nimport { makeVTextFieldProps, VTextField } from '@/components/VTextField/VTextField'\n\n// Composables\nimport { forwardRefs } from '@/composables/forwardRefs'\nimport { isMaskDelimiter, makeMaskProps, useMask } from '@/composables/mask'\nimport { useProxiedModel } from '@/composables/proxiedModel'\n\n// Utilities\nimport { computed, nextTick, onBeforeMount, ref, shallowRef, toRef } from 'vue'\nimport { genericComponent, propsFactory, useRender } from '@/util'\n\n// Types\nimport type { VTextFieldSlots } from '@/components/VTextField/VTextField'\n\nexport type VMaskInputSlots = VTextFieldSlots\n\nexport const makeVMaskInputProps = propsFactory({\n returnMaskedValue: Boolean,\n ...makeVTextFieldProps(),\n ...makeMaskProps(),\n}, 'VMaskInput')\n\nexport const VMaskInput = genericComponent<VMaskInputSlots>()({\n name: 'VMaskInput',\n\n props: makeVMaskInputProps(),\n\n emits: {\n 'update:modelValue': (val: string) => true,\n },\n\n setup (props, { slots, emit }) {\n const vTextFieldRef = ref<VTextField>()\n\n const inputAction = shallowRef()\n const caretPosition = shallowRef(0)\n\n const mask = useMask(props)\n const returnMaskedValue = computed(() => props.mask && props.returnMaskedValue)\n\n const model = useProxiedModel(\n props,\n 'modelValue',\n undefined,\n // Always display masked value in input when mask is applied\n val => props.mask ? mask.mask(mask.unmask(val)) : val,\n val => {\n if (props.mask) {\n const valueWithoutDelimiters = removeMaskDelimiters(val)\n\n // E.g. mask is #-# and the input value is '2-23'\n // model-value should be enforced to '2-2'\n const newMaskedValue = mask.mask(valueWithoutDelimiters)\n const newUnmaskedValue = mask.unmask(newMaskedValue)\n\n const newCaretPosition = getNewCaretPosition({\n oldValue: model.value,\n newValue: newMaskedValue,\n oldCaret: caretPosition.value,\n })\n\n vTextFieldRef.value!.value = newMaskedValue\n vTextFieldRef.value!.setSelectionRange(newCaretPosition, newCaretPosition)\n\n return returnMaskedValue.value ? mask.mask(newUnmaskedValue) : newUnmaskedValue\n }\n return val\n },\n )\n\n const validationValue = toRef(() => returnMaskedValue.value ? model.value : mask.unmask(model.value))\n\n function removeMaskDelimiters (val: string): string {\n return val.split('').filter(ch => !isMaskDelimiter(ch)).join('')\n }\n\n function getNewCaretPosition ({\n oldValue,\n newValue,\n oldCaret,\n }: {\n oldValue: string\n newValue: string\n oldCaret: number\n }): number {\n if (!newValue) return 0\n if (!oldValue) return newValue.length\n\n let newCaret: number\n\n if (inputAction.value === 'Backspace') {\n newCaret = oldCaret - 1\n while (newCaret > 0 && isMaskDelimiter(newValue[newCaret - 1])) newCaret--\n } else if (inputAction.value === 'Delete') {\n newCaret = oldCaret\n } else { // insertion\n newCaret = oldCaret + 1\n while (isMaskDelimiter(newValue[newCaret])) newCaret++\n if (isMaskDelimiter(newValue[oldCaret])) newCaret++\n }\n\n return newCaret\n }\n\n onBeforeMount(() => {\n if (props.returnMaskedValue) {\n emit('update:modelValue', model.value)\n }\n })\n\n function onKeyDown (e: KeyboardEvent) {\n if (e.metaKey) return\n\n const inputElement = e.target as HTMLInputElement\n\n caretPosition.value = inputElement.selectionStart || 0\n inputAction.value = e.key\n\n const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd\n if (e.key === 'Backspace' && hasSelection) {\n e.preventDefault()\n deleteSelection(e)\n }\n }\n\n async function onCut (e: Event) {\n e.preventDefault()\n\n copySelectionToClipboard(e)\n deleteSelection(e)\n }\n\n async function onPaste (e: ClipboardEvent) {\n e.preventDefault()\n\n const inputElement = e.target as HTMLInputElement\n const pastedString = removeMaskDelimiters(e.clipboardData?.getData('text') || '')\n\n if (!pastedString) return\n\n const pastedCharacters = [...pastedString]\n\n const hasSelection = inputElement.selectionStart !== inputElement.selectionEnd\n\n if (hasSelection) {\n replaceSelection(inputElement, pastedCharacters)\n } else {\n insertCharacters(inputElement, pastedCharacters)\n }\n }\n\n function copySelectionToClipboard (e: Event) {\n const inputElement = e.target as HTMLInputElement\n const start = inputElement.selectionStart || 0\n const end = inputElement.selectionEnd || 0\n const selectedText = inputElement.value.substring(start, end)\n navigator.clipboard.writeText(selectedText)\n }\n\n async function deleteSelection (e: Event) {\n const inputElement = e.target as HTMLInputElement\n const curStart = inputElement.selectionStart || 0\n caretPosition.value = inputElement.selectionEnd || 0\n\n while (caretPosition.value > curStart) {\n const success = await simulateBackspace(inputElement)\n if (!success) break\n }\n }\n\n async function simulateBackspace (inputElement: HTMLInputElement) {\n inputAction.value = 'Backspace'\n model.value = inputElement.value.slice(0, caretPosition.value - 1) + inputElement.value.slice(caretPosition.value)\n inputAction.value = ''\n if (caretPosition.value === inputElement.selectionEnd) return false\n caretPosition.value = inputElement.selectionEnd || 0\n await nextTick()\n return true\n }\n\n async function insertCharacters (inputElement: HTMLInputElement, pastedCharacters: string[]) {\n for (let i = 0; i < pastedCharacters.length; i++) {\n await insertCharacter(inputElement, pastedCharacters[i])\n }\n }\n\n async function insertCharacter (inputElement: HTMLInputElement, character: string) {\n caretPosition.value = inputElement.selectionEnd || 0\n model.value = inputElement.value.slice(0, caretPosition.value) + character + inputElement.value.slice(caretPosition.value)\n await nextTick()\n }\n\n async function replaceSelection (inputElement: HTMLInputElement, pastedCharacters: string[]) {\n caretPosition.value = inputElement.selectionStart || 0\n for (let i = 0; i < pastedCharacters.length; i++) {\n await replaceCharacter(caretPosition.value, pastedCharacters[i])\n caretPosition.value++\n }\n }\n\n async function replaceCharacter (index: number, character: string) {\n let targetIndex = index\n\n // Find next non-delimiter position\n while (targetIndex < model.value.length && isMaskDelimiter(model.value[targetIndex])) targetIndex++\n\n model.value = model.value.slice(0, targetIndex) + character + model.value.slice(targetIndex + 1)\n await nextTick()\n }\n\n useRender(() => {\n const textFieldProps = VTextField.filterProps(props)\n\n return (\n <VTextField\n { ...textFieldProps }\n v-model={ model.value }\n ref={ vTextFieldRef }\n validationValue={ validationValue.value }\n onCut={ onCut }\n onPaste={ onPaste }\n onKeydown={ onKeyDown }\n >\n {{ ...slots }}\n </VTextField>\n )\n })\n\n return forwardRefs({}, vTextFieldRef)\n },\n})\n\nexport type VMaskInput = InstanceType<typeof VMaskInput>\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vuetify/nightly",
3
3
  "description": "Vue Material Component Framework",
4
- "version": "3.9.5-dev.2025-08-23",
4
+ "version": "3.9.5-dev.2025-08-24",
5
5
  "author": {
6
6
  "name": "John Leider",
7
7
  "email": "john@vuetifyjs.com"