@zag-js/number-input 1.24.1 → 1.25.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/dist/index.js +80 -45
- package/dist/index.mjs +80 -45
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -106,6 +106,83 @@ var createVirtualCursor = (ctx, point) => {
|
|
|
106
106
|
doc.body.appendChild(el);
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
// src/cursor.ts
|
|
110
|
+
function recordCursor(inputEl, scope) {
|
|
111
|
+
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
112
|
+
try {
|
|
113
|
+
const { selectionStart: start, selectionEnd: end, value } = inputEl;
|
|
114
|
+
if (start == null || end == null) return void 0;
|
|
115
|
+
return { start, end, value };
|
|
116
|
+
} catch {
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function restoreCursor(inputEl, selection, scope) {
|
|
121
|
+
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
122
|
+
if (!selection) {
|
|
123
|
+
const len = inputEl.value.length;
|
|
124
|
+
inputEl.setSelectionRange(len, len);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const newValue = inputEl.value;
|
|
129
|
+
const { start, end, value: oldValue } = selection;
|
|
130
|
+
if (newValue === oldValue) {
|
|
131
|
+
inputEl.setSelectionRange(start, end);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const newStart = getNewCursorPosition(oldValue, newValue, start);
|
|
135
|
+
const newEnd = start === end ? newStart : getNewCursorPosition(oldValue, newValue, end);
|
|
136
|
+
const clampedStart = Math.max(0, Math.min(newStart, newValue.length));
|
|
137
|
+
const clampedEnd = Math.max(clampedStart, Math.min(newEnd, newValue.length));
|
|
138
|
+
inputEl.setSelectionRange(clampedStart, clampedEnd);
|
|
139
|
+
} catch {
|
|
140
|
+
const len = inputEl.value.length;
|
|
141
|
+
inputEl.setSelectionRange(len, len);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function getNewCursorPosition(oldValue, newValue, oldPosition) {
|
|
145
|
+
const beforeCursor = oldValue.slice(0, oldPosition);
|
|
146
|
+
const afterCursor = oldValue.slice(oldPosition);
|
|
147
|
+
let prefixLength = 0;
|
|
148
|
+
const maxPrefixLength = Math.min(beforeCursor.length, newValue.length);
|
|
149
|
+
for (let i = 0; i < maxPrefixLength; i++) {
|
|
150
|
+
if (beforeCursor[i] === newValue[i]) {
|
|
151
|
+
prefixLength = i + 1;
|
|
152
|
+
} else {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
let suffixLength = 0;
|
|
157
|
+
const maxSuffixLength = Math.min(afterCursor.length, newValue.length - prefixLength);
|
|
158
|
+
for (let i = 0; i < maxSuffixLength; i++) {
|
|
159
|
+
const oldIndex = afterCursor.length - 1 - i;
|
|
160
|
+
const newIndex = newValue.length - 1 - i;
|
|
161
|
+
if (afterCursor[oldIndex] === newValue[newIndex]) {
|
|
162
|
+
suffixLength = i + 1;
|
|
163
|
+
} else {
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (prefixLength >= beforeCursor.length) {
|
|
168
|
+
return prefixLength;
|
|
169
|
+
}
|
|
170
|
+
if (suffixLength >= afterCursor.length) {
|
|
171
|
+
return newValue.length - suffixLength;
|
|
172
|
+
}
|
|
173
|
+
if (prefixLength > 0) {
|
|
174
|
+
return prefixLength;
|
|
175
|
+
}
|
|
176
|
+
if (suffixLength > 0) {
|
|
177
|
+
return newValue.length - suffixLength;
|
|
178
|
+
}
|
|
179
|
+
if (oldValue.length > 0) {
|
|
180
|
+
const ratio = oldPosition / oldValue.length;
|
|
181
|
+
return Math.round(ratio * newValue.length);
|
|
182
|
+
}
|
|
183
|
+
return newValue.length;
|
|
184
|
+
}
|
|
185
|
+
|
|
109
186
|
// src/number-input.connect.ts
|
|
110
187
|
function connect(service, normalize) {
|
|
111
188
|
const { state, send, prop, scope, computed } = service;
|
|
@@ -227,7 +304,8 @@ function connect(service, normalize) {
|
|
|
227
304
|
send({ type: "INPUT.BLUR" });
|
|
228
305
|
},
|
|
229
306
|
onInput(event) {
|
|
230
|
-
|
|
307
|
+
const selection = recordCursor(event.currentTarget, scope);
|
|
308
|
+
send({ type: "INPUT.CHANGE", target: event.currentTarget, hint: "set", selection });
|
|
231
309
|
},
|
|
232
310
|
onBeforeInput(event) {
|
|
233
311
|
try {
|
|
@@ -361,49 +439,6 @@ function connect(service, normalize) {
|
|
|
361
439
|
}
|
|
362
440
|
};
|
|
363
441
|
}
|
|
364
|
-
|
|
365
|
-
// src/cursor.ts
|
|
366
|
-
function recordCursor(inputEl, scope) {
|
|
367
|
-
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
368
|
-
try {
|
|
369
|
-
const { selectionStart: start, selectionEnd: end, value } = inputEl;
|
|
370
|
-
const beforeTxt = value.substring(0, start);
|
|
371
|
-
const afterTxt = value.substring(end);
|
|
372
|
-
return {
|
|
373
|
-
start,
|
|
374
|
-
end,
|
|
375
|
-
value,
|
|
376
|
-
beforeTxt,
|
|
377
|
-
afterTxt
|
|
378
|
-
};
|
|
379
|
-
} catch {
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
function restoreCursor(inputEl, selection, scope) {
|
|
383
|
-
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
384
|
-
if (!selection) {
|
|
385
|
-
inputEl.setSelectionRange(inputEl.value.length, inputEl.value.length);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
try {
|
|
389
|
-
const { value } = inputEl;
|
|
390
|
-
const { beforeTxt = "", afterTxt = "", start } = selection;
|
|
391
|
-
let startPos = value.length;
|
|
392
|
-
if (value.endsWith(afterTxt)) {
|
|
393
|
-
startPos = value.length - afterTxt.length;
|
|
394
|
-
} else if (value.startsWith(beforeTxt)) {
|
|
395
|
-
startPos = beforeTxt.length;
|
|
396
|
-
} else if (start != null) {
|
|
397
|
-
const beforeLastChar = beforeTxt[start - 1];
|
|
398
|
-
const newIndex = value.indexOf(beforeLastChar, start - 1);
|
|
399
|
-
if (newIndex !== -1) {
|
|
400
|
-
startPos = newIndex + 1;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
inputEl.setSelectionRange(startPos, startPos);
|
|
404
|
-
} catch {
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
442
|
var createFormatter = (locale, options = {}) => {
|
|
408
443
|
return new Intl.NumberFormat(locale, options);
|
|
409
444
|
};
|
|
@@ -815,7 +850,7 @@ var machine = createMachine({
|
|
|
815
850
|
syncInputElement({ context, event, computed, scope }) {
|
|
816
851
|
const value = event.type.endsWith("CHANGE") ? context.get("value") : computed("formattedValue");
|
|
817
852
|
const inputEl = getInputEl(scope);
|
|
818
|
-
const sel =
|
|
853
|
+
const sel = event.selection;
|
|
819
854
|
domQuery.raf(() => {
|
|
820
855
|
domQuery.setElementValue(inputEl, value);
|
|
821
856
|
restoreCursor(inputEl, sel, scope);
|
package/dist/index.mjs
CHANGED
|
@@ -104,6 +104,83 @@ var createVirtualCursor = (ctx, point) => {
|
|
|
104
104
|
doc.body.appendChild(el);
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
+
// src/cursor.ts
|
|
108
|
+
function recordCursor(inputEl, scope) {
|
|
109
|
+
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
110
|
+
try {
|
|
111
|
+
const { selectionStart: start, selectionEnd: end, value } = inputEl;
|
|
112
|
+
if (start == null || end == null) return void 0;
|
|
113
|
+
return { start, end, value };
|
|
114
|
+
} catch {
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function restoreCursor(inputEl, selection, scope) {
|
|
119
|
+
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
120
|
+
if (!selection) {
|
|
121
|
+
const len = inputEl.value.length;
|
|
122
|
+
inputEl.setSelectionRange(len, len);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const newValue = inputEl.value;
|
|
127
|
+
const { start, end, value: oldValue } = selection;
|
|
128
|
+
if (newValue === oldValue) {
|
|
129
|
+
inputEl.setSelectionRange(start, end);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const newStart = getNewCursorPosition(oldValue, newValue, start);
|
|
133
|
+
const newEnd = start === end ? newStart : getNewCursorPosition(oldValue, newValue, end);
|
|
134
|
+
const clampedStart = Math.max(0, Math.min(newStart, newValue.length));
|
|
135
|
+
const clampedEnd = Math.max(clampedStart, Math.min(newEnd, newValue.length));
|
|
136
|
+
inputEl.setSelectionRange(clampedStart, clampedEnd);
|
|
137
|
+
} catch {
|
|
138
|
+
const len = inputEl.value.length;
|
|
139
|
+
inputEl.setSelectionRange(len, len);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function getNewCursorPosition(oldValue, newValue, oldPosition) {
|
|
143
|
+
const beforeCursor = oldValue.slice(0, oldPosition);
|
|
144
|
+
const afterCursor = oldValue.slice(oldPosition);
|
|
145
|
+
let prefixLength = 0;
|
|
146
|
+
const maxPrefixLength = Math.min(beforeCursor.length, newValue.length);
|
|
147
|
+
for (let i = 0; i < maxPrefixLength; i++) {
|
|
148
|
+
if (beforeCursor[i] === newValue[i]) {
|
|
149
|
+
prefixLength = i + 1;
|
|
150
|
+
} else {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let suffixLength = 0;
|
|
155
|
+
const maxSuffixLength = Math.min(afterCursor.length, newValue.length - prefixLength);
|
|
156
|
+
for (let i = 0; i < maxSuffixLength; i++) {
|
|
157
|
+
const oldIndex = afterCursor.length - 1 - i;
|
|
158
|
+
const newIndex = newValue.length - 1 - i;
|
|
159
|
+
if (afterCursor[oldIndex] === newValue[newIndex]) {
|
|
160
|
+
suffixLength = i + 1;
|
|
161
|
+
} else {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (prefixLength >= beforeCursor.length) {
|
|
166
|
+
return prefixLength;
|
|
167
|
+
}
|
|
168
|
+
if (suffixLength >= afterCursor.length) {
|
|
169
|
+
return newValue.length - suffixLength;
|
|
170
|
+
}
|
|
171
|
+
if (prefixLength > 0) {
|
|
172
|
+
return prefixLength;
|
|
173
|
+
}
|
|
174
|
+
if (suffixLength > 0) {
|
|
175
|
+
return newValue.length - suffixLength;
|
|
176
|
+
}
|
|
177
|
+
if (oldValue.length > 0) {
|
|
178
|
+
const ratio = oldPosition / oldValue.length;
|
|
179
|
+
return Math.round(ratio * newValue.length);
|
|
180
|
+
}
|
|
181
|
+
return newValue.length;
|
|
182
|
+
}
|
|
183
|
+
|
|
107
184
|
// src/number-input.connect.ts
|
|
108
185
|
function connect(service, normalize) {
|
|
109
186
|
const { state, send, prop, scope, computed } = service;
|
|
@@ -225,7 +302,8 @@ function connect(service, normalize) {
|
|
|
225
302
|
send({ type: "INPUT.BLUR" });
|
|
226
303
|
},
|
|
227
304
|
onInput(event) {
|
|
228
|
-
|
|
305
|
+
const selection = recordCursor(event.currentTarget, scope);
|
|
306
|
+
send({ type: "INPUT.CHANGE", target: event.currentTarget, hint: "set", selection });
|
|
229
307
|
},
|
|
230
308
|
onBeforeInput(event) {
|
|
231
309
|
try {
|
|
@@ -359,49 +437,6 @@ function connect(service, normalize) {
|
|
|
359
437
|
}
|
|
360
438
|
};
|
|
361
439
|
}
|
|
362
|
-
|
|
363
|
-
// src/cursor.ts
|
|
364
|
-
function recordCursor(inputEl, scope) {
|
|
365
|
-
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
366
|
-
try {
|
|
367
|
-
const { selectionStart: start, selectionEnd: end, value } = inputEl;
|
|
368
|
-
const beforeTxt = value.substring(0, start);
|
|
369
|
-
const afterTxt = value.substring(end);
|
|
370
|
-
return {
|
|
371
|
-
start,
|
|
372
|
-
end,
|
|
373
|
-
value,
|
|
374
|
-
beforeTxt,
|
|
375
|
-
afterTxt
|
|
376
|
-
};
|
|
377
|
-
} catch {
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function restoreCursor(inputEl, selection, scope) {
|
|
381
|
-
if (!inputEl || !scope.isActiveElement(inputEl)) return;
|
|
382
|
-
if (!selection) {
|
|
383
|
-
inputEl.setSelectionRange(inputEl.value.length, inputEl.value.length);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
try {
|
|
387
|
-
const { value } = inputEl;
|
|
388
|
-
const { beforeTxt = "", afterTxt = "", start } = selection;
|
|
389
|
-
let startPos = value.length;
|
|
390
|
-
if (value.endsWith(afterTxt)) {
|
|
391
|
-
startPos = value.length - afterTxt.length;
|
|
392
|
-
} else if (value.startsWith(beforeTxt)) {
|
|
393
|
-
startPos = beforeTxt.length;
|
|
394
|
-
} else if (start != null) {
|
|
395
|
-
const beforeLastChar = beforeTxt[start - 1];
|
|
396
|
-
const newIndex = value.indexOf(beforeLastChar, start - 1);
|
|
397
|
-
if (newIndex !== -1) {
|
|
398
|
-
startPos = newIndex + 1;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
inputEl.setSelectionRange(startPos, startPos);
|
|
402
|
-
} catch {
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
440
|
var createFormatter = (locale, options = {}) => {
|
|
406
441
|
return new Intl.NumberFormat(locale, options);
|
|
407
442
|
};
|
|
@@ -813,7 +848,7 @@ var machine = createMachine({
|
|
|
813
848
|
syncInputElement({ context, event, computed, scope }) {
|
|
814
849
|
const value = event.type.endsWith("CHANGE") ? context.get("value") : computed("formattedValue");
|
|
815
850
|
const inputEl = getInputEl(scope);
|
|
816
|
-
const sel =
|
|
851
|
+
const sel = event.selection;
|
|
817
852
|
raf(() => {
|
|
818
853
|
setElementValue(inputEl, value);
|
|
819
854
|
restoreCursor(inputEl, sel, scope);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/number-input",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Core logic for the number-input widget implemented as a state machine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@internationalized/number": "3.6.5",
|
|
30
|
-
"@zag-js/anatomy": "1.
|
|
31
|
-
"@zag-js/core": "1.
|
|
32
|
-
"@zag-js/dom-query": "1.
|
|
33
|
-
"@zag-js/types": "1.
|
|
34
|
-
"@zag-js/utils": "1.
|
|
30
|
+
"@zag-js/anatomy": "1.25.0",
|
|
31
|
+
"@zag-js/core": "1.25.0",
|
|
32
|
+
"@zag-js/dom-query": "1.25.0",
|
|
33
|
+
"@zag-js/types": "1.25.0",
|
|
34
|
+
"@zag-js/utils": "1.25.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"clean-package": "2.2.0"
|