@zag-js/number-input 0.16.0 → 0.18.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.d.mts +64 -64
- package/dist/index.d.ts +64 -64
- package/dist/index.js +46 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -10
- package/src/index.ts +1 -1
- package/src/number-input.connect.ts +2 -2
- package/src/number-input.machine.ts +48 -47
- package/src/number-input.types.ts +62 -62
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/number-input",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Core logic for the number-input widget implemented as a state machine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -27,15 +27,14 @@
|
|
|
27
27
|
"url": "https://github.com/chakra-ui/zag/issues"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@zag-js/anatomy": "0.
|
|
31
|
-
"@zag-js/core": "0.
|
|
32
|
-
"@zag-js/dom-query": "0.
|
|
33
|
-
"@zag-js/dom-event": "0.
|
|
34
|
-
"@zag-js/
|
|
35
|
-
"@zag-js/
|
|
36
|
-
"@zag-js/
|
|
37
|
-
"@zag-js/
|
|
38
|
-
"@zag-js/types": "0.16.0"
|
|
30
|
+
"@zag-js/anatomy": "0.18.0",
|
|
31
|
+
"@zag-js/core": "0.18.0",
|
|
32
|
+
"@zag-js/dom-query": "0.18.0",
|
|
33
|
+
"@zag-js/dom-event": "0.18.0",
|
|
34
|
+
"@zag-js/mutation-observer": "0.18.0",
|
|
35
|
+
"@zag-js/number-utils": "0.18.0",
|
|
36
|
+
"@zag-js/utils": "0.18.0",
|
|
37
|
+
"@zag-js/types": "0.18.0"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
40
|
"clean-package": "2.2.0"
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { anatomy } from "./number-input.anatomy"
|
|
2
2
|
export { connect } from "./number-input.connect"
|
|
3
3
|
export { machine } from "./number-input.machine"
|
|
4
|
-
export type { UserDefinedContext as Context,
|
|
4
|
+
export type { UserDefinedContext as Context, MachineApi as Api } from "./number-input.types"
|
|
@@ -4,10 +4,10 @@ import { roundToDevicePixel } from "@zag-js/number-utils"
|
|
|
4
4
|
import type { NormalizeProps, PropTypes } from "@zag-js/types"
|
|
5
5
|
import { parts } from "./number-input.anatomy"
|
|
6
6
|
import { dom } from "./number-input.dom"
|
|
7
|
-
import type {
|
|
7
|
+
import type { MachineApi, Send, State } from "./number-input.types"
|
|
8
8
|
import { utils } from "./number-input.utils"
|
|
9
9
|
|
|
10
|
-
export function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>):
|
|
10
|
+
export function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {
|
|
11
11
|
const isFocused = state.hasTag("focus")
|
|
12
12
|
const isInvalid = state.context.isOutOfRange || !!state.context.invalid
|
|
13
13
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { choose, createMachine, guards } from "@zag-js/core"
|
|
2
2
|
import { addDomEvent, requestPointerLock } from "@zag-js/dom-event"
|
|
3
3
|
import { isSafari, raf } from "@zag-js/dom-query"
|
|
4
|
-
import { dispatchInputValueEvent } from "@zag-js/form-utils"
|
|
5
4
|
import { observeAttributes } from "@zag-js/mutation-observer"
|
|
6
5
|
import { isAtMax, isAtMin, isWithinRange, valueOf } from "@zag-js/number-utils"
|
|
7
6
|
import { callAll, compact } from "@zag-js/utils"
|
|
@@ -54,7 +53,7 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
54
53
|
},
|
|
55
54
|
|
|
56
55
|
watch: {
|
|
57
|
-
value: ["
|
|
56
|
+
value: ["syncInputElement"],
|
|
58
57
|
isOutOfRange: ["invokeOnInvalid"],
|
|
59
58
|
scrubberCursorPoint: ["setVirtualCursorPosition"],
|
|
60
59
|
},
|
|
@@ -62,15 +61,9 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
62
61
|
entry: ["syncInputValue"],
|
|
63
62
|
|
|
64
63
|
on: {
|
|
65
|
-
SET_VALUE:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
actions: ["setValue", "clampValue", "setHintToSet"],
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
actions: ["setValue", "setHintToSet"],
|
|
72
|
-
},
|
|
73
|
-
],
|
|
64
|
+
SET_VALUE: {
|
|
65
|
+
actions: ["setValue", "clampValue", "setHintToSet"],
|
|
66
|
+
},
|
|
74
67
|
CLEAR_VALUE: {
|
|
75
68
|
actions: ["clearValue"],
|
|
76
69
|
},
|
|
@@ -84,17 +77,19 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
84
77
|
|
|
85
78
|
states: {
|
|
86
79
|
idle: {
|
|
87
|
-
exit: "invokeOnFocus",
|
|
88
80
|
on: {
|
|
89
81
|
PRESS_DOWN: {
|
|
90
82
|
target: "before:spin",
|
|
91
|
-
actions: ["focusInput", "setHint"],
|
|
83
|
+
actions: ["focusInput", "invokeOnFocus", "setHint"],
|
|
92
84
|
},
|
|
93
85
|
PRESS_DOWN_SCRUBBER: {
|
|
94
86
|
target: "scrubbing",
|
|
95
|
-
actions: ["focusInput", "setHint", "setCursorPoint"],
|
|
87
|
+
actions: ["focusInput", "invokeOnFocus", "setHint", "setCursorPoint"],
|
|
88
|
+
},
|
|
89
|
+
FOCUS: {
|
|
90
|
+
target: "focused",
|
|
91
|
+
actions: ["focusInput", "invokeOnFocus"],
|
|
96
92
|
},
|
|
97
|
-
FOCUS: "focused",
|
|
98
93
|
},
|
|
99
94
|
},
|
|
100
95
|
|
|
@@ -290,35 +285,37 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
290
285
|
actions: {
|
|
291
286
|
focusInput(ctx) {
|
|
292
287
|
if (!ctx.focusInputOnChange) return
|
|
293
|
-
const
|
|
294
|
-
raf(() =>
|
|
288
|
+
const inputEl = dom.getInputEl(ctx)
|
|
289
|
+
raf(() => {
|
|
290
|
+
inputEl?.focus()
|
|
291
|
+
})
|
|
295
292
|
},
|
|
296
293
|
increment(ctx, evt) {
|
|
297
|
-
|
|
294
|
+
set.value(ctx, utils.increment(ctx, evt.step))
|
|
298
295
|
},
|
|
299
296
|
decrement(ctx, evt) {
|
|
300
|
-
|
|
297
|
+
set.value(ctx, utils.decrement(ctx, evt.step))
|
|
301
298
|
},
|
|
302
299
|
clampValue(ctx) {
|
|
303
|
-
|
|
300
|
+
set.value(ctx, utils.clamp(ctx))
|
|
304
301
|
},
|
|
305
302
|
roundValue(ctx) {
|
|
306
|
-
if (ctx.value
|
|
307
|
-
|
|
308
|
-
}
|
|
303
|
+
if (ctx.value === "") return
|
|
304
|
+
set.value(ctx, utils.round(ctx))
|
|
309
305
|
},
|
|
310
306
|
setValue(ctx, evt) {
|
|
311
|
-
|
|
312
|
-
|
|
307
|
+
let value = evt.target?.value ?? evt.value
|
|
308
|
+
value = utils.sanitize(ctx, utils.parse(ctx, value.toString()))
|
|
309
|
+
set.value(ctx, value)
|
|
313
310
|
},
|
|
314
311
|
clearValue(ctx) {
|
|
315
|
-
|
|
312
|
+
set.value(ctx, "")
|
|
316
313
|
},
|
|
317
314
|
setToMax(ctx) {
|
|
318
|
-
|
|
315
|
+
set.value(ctx, ctx.max.toString())
|
|
319
316
|
},
|
|
320
317
|
setToMin(ctx) {
|
|
321
|
-
|
|
318
|
+
set.value(ctx, ctx.min.toString())
|
|
322
319
|
},
|
|
323
320
|
setHint(ctx, evt) {
|
|
324
321
|
ctx.hint = evt.hint
|
|
@@ -329,12 +326,6 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
329
326
|
setHintToSet(ctx) {
|
|
330
327
|
ctx.hint = "set"
|
|
331
328
|
},
|
|
332
|
-
invokeOnChange(ctx) {
|
|
333
|
-
ctx.onChange?.({
|
|
334
|
-
value: ctx.value,
|
|
335
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
336
|
-
})
|
|
337
|
-
},
|
|
338
329
|
invokeOnFocus(ctx, evt) {
|
|
339
330
|
let srcElement: HTMLElement | null = null
|
|
340
331
|
|
|
@@ -353,10 +344,7 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
353
344
|
})
|
|
354
345
|
},
|
|
355
346
|
invokeOnBlur(ctx) {
|
|
356
|
-
ctx.onBlur?.({
|
|
357
|
-
value: ctx.value,
|
|
358
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
359
|
-
})
|
|
347
|
+
ctx.onBlur?.({ value: ctx.value, valueAsNumber: ctx.valueAsNumber })
|
|
360
348
|
},
|
|
361
349
|
invokeOnInvalid(ctx) {
|
|
362
350
|
if (!ctx.isOutOfRange) return
|
|
@@ -367,12 +355,16 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
367
355
|
valueAsNumber: ctx.valueAsNumber,
|
|
368
356
|
})
|
|
369
357
|
},
|
|
370
|
-
|
|
358
|
+
syncInputElement(ctx) {
|
|
359
|
+
const inputEl = dom.getInputEl(ctx)
|
|
360
|
+
dom.setValue(inputEl, ctx.formattedValue)
|
|
361
|
+
},
|
|
371
362
|
syncInputValue(ctx) {
|
|
372
|
-
const
|
|
373
|
-
if (!
|
|
374
|
-
|
|
375
|
-
|
|
363
|
+
const inputEl = dom.getInputEl(ctx)
|
|
364
|
+
if (!inputEl || inputEl.value == ctx.value) return
|
|
365
|
+
|
|
366
|
+
const value = utils.parse(ctx, inputEl.value)
|
|
367
|
+
set.value(ctx, utils.sanitize(ctx, value))
|
|
376
368
|
},
|
|
377
369
|
setCursorPoint(ctx, evt) {
|
|
378
370
|
ctx.scrubberCursorPoint = evt.point
|
|
@@ -386,11 +378,20 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
386
378
|
const { x, y } = ctx.scrubberCursorPoint
|
|
387
379
|
cursor.style.transform = `translate3d(${x}px, ${y}px, 0px)`
|
|
388
380
|
},
|
|
389
|
-
dispatchChangeEvent(ctx) {
|
|
390
|
-
const inputEl = dom.getInputEl(ctx)
|
|
391
|
-
dispatchInputValueEvent(inputEl, { value: ctx.formattedValue })
|
|
392
|
-
},
|
|
393
381
|
},
|
|
394
382
|
},
|
|
395
383
|
)
|
|
396
384
|
}
|
|
385
|
+
|
|
386
|
+
const invoke = {
|
|
387
|
+
onChange: (ctx: MachineContext) => {
|
|
388
|
+
ctx.onChange?.({ value: ctx.value, valueAsNumber: ctx.valueAsNumber })
|
|
389
|
+
},
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const set = {
|
|
393
|
+
value: (ctx: MachineContext, value: string) => {
|
|
394
|
+
ctx.value = value
|
|
395
|
+
invoke.onChange(ctx)
|
|
396
|
+
},
|
|
397
|
+
}
|
|
@@ -154,68 +154,6 @@ type PublicContext = DirectionProperty &
|
|
|
154
154
|
spinOnPress?: boolean
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
export type PublicApi<T extends PropTypes = PropTypes> = {
|
|
158
|
-
/**
|
|
159
|
-
* Whether the input is focused.
|
|
160
|
-
*/
|
|
161
|
-
isFocused: boolean
|
|
162
|
-
/**
|
|
163
|
-
* Whether the input is invalid.
|
|
164
|
-
*/
|
|
165
|
-
isInvalid: boolean
|
|
166
|
-
/**
|
|
167
|
-
* Whether the input value is empty.
|
|
168
|
-
*/
|
|
169
|
-
isValueEmpty: boolean
|
|
170
|
-
/**
|
|
171
|
-
* The formatted value of the input.
|
|
172
|
-
*/
|
|
173
|
-
value: string
|
|
174
|
-
/**
|
|
175
|
-
* The value of the input as a number.
|
|
176
|
-
*/
|
|
177
|
-
valueAsNumber: number
|
|
178
|
-
/**
|
|
179
|
-
* Function to set the value of the input.
|
|
180
|
-
*/
|
|
181
|
-
setValue(value: string | number): void
|
|
182
|
-
/**
|
|
183
|
-
* Function to clear the value of the input.
|
|
184
|
-
*/
|
|
185
|
-
clearValue(): void
|
|
186
|
-
/**
|
|
187
|
-
* Function to increment the value of the input by the step.
|
|
188
|
-
*/
|
|
189
|
-
increment(): void
|
|
190
|
-
/**
|
|
191
|
-
* Function to decrement the value of the input by the step.
|
|
192
|
-
*/
|
|
193
|
-
decrement(): void
|
|
194
|
-
/**
|
|
195
|
-
* Function to set the value of the input to the max.
|
|
196
|
-
*/
|
|
197
|
-
setToMax(): void
|
|
198
|
-
/**
|
|
199
|
-
* Function to set the value of the input to the min.
|
|
200
|
-
*/
|
|
201
|
-
setToMin(): void
|
|
202
|
-
/**
|
|
203
|
-
* Function to focus the input.
|
|
204
|
-
*/
|
|
205
|
-
focus(): void
|
|
206
|
-
/**
|
|
207
|
-
* Function to blur the input.
|
|
208
|
-
*/
|
|
209
|
-
blur(): void
|
|
210
|
-
rootProps: T["element"]
|
|
211
|
-
labelProps: T["label"]
|
|
212
|
-
controlProps: T["element"]
|
|
213
|
-
inputProps: T["input"]
|
|
214
|
-
decrementTriggerProps: T["button"]
|
|
215
|
-
incrementTriggerProps: T["button"]
|
|
216
|
-
scrubberProps: T["element"]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
157
|
export type UserDefinedContext = RequiredBy<PublicContext, "id">
|
|
220
158
|
|
|
221
159
|
type ComputedContext = Readonly<{
|
|
@@ -294,3 +232,65 @@ export type MachineState = {
|
|
|
294
232
|
export type State = S.State<MachineContext, MachineState>
|
|
295
233
|
|
|
296
234
|
export type Send = S.Send<S.AnyEventObject>
|
|
235
|
+
|
|
236
|
+
export type MachineApi<T extends PropTypes = PropTypes> = {
|
|
237
|
+
/**
|
|
238
|
+
* Whether the input is focused.
|
|
239
|
+
*/
|
|
240
|
+
isFocused: boolean
|
|
241
|
+
/**
|
|
242
|
+
* Whether the input is invalid.
|
|
243
|
+
*/
|
|
244
|
+
isInvalid: boolean
|
|
245
|
+
/**
|
|
246
|
+
* Whether the input value is empty.
|
|
247
|
+
*/
|
|
248
|
+
isValueEmpty: boolean
|
|
249
|
+
/**
|
|
250
|
+
* The formatted value of the input.
|
|
251
|
+
*/
|
|
252
|
+
value: string
|
|
253
|
+
/**
|
|
254
|
+
* The value of the input as a number.
|
|
255
|
+
*/
|
|
256
|
+
valueAsNumber: number
|
|
257
|
+
/**
|
|
258
|
+
* Function to set the value of the input.
|
|
259
|
+
*/
|
|
260
|
+
setValue(value: string | number): void
|
|
261
|
+
/**
|
|
262
|
+
* Function to clear the value of the input.
|
|
263
|
+
*/
|
|
264
|
+
clearValue(): void
|
|
265
|
+
/**
|
|
266
|
+
* Function to increment the value of the input by the step.
|
|
267
|
+
*/
|
|
268
|
+
increment(): void
|
|
269
|
+
/**
|
|
270
|
+
* Function to decrement the value of the input by the step.
|
|
271
|
+
*/
|
|
272
|
+
decrement(): void
|
|
273
|
+
/**
|
|
274
|
+
* Function to set the value of the input to the max.
|
|
275
|
+
*/
|
|
276
|
+
setToMax(): void
|
|
277
|
+
/**
|
|
278
|
+
* Function to set the value of the input to the min.
|
|
279
|
+
*/
|
|
280
|
+
setToMin(): void
|
|
281
|
+
/**
|
|
282
|
+
* Function to focus the input.
|
|
283
|
+
*/
|
|
284
|
+
focus(): void
|
|
285
|
+
/**
|
|
286
|
+
* Function to blur the input.
|
|
287
|
+
*/
|
|
288
|
+
blur(): void
|
|
289
|
+
rootProps: T["element"]
|
|
290
|
+
labelProps: T["label"]
|
|
291
|
+
controlProps: T["element"]
|
|
292
|
+
inputProps: T["input"]
|
|
293
|
+
decrementTriggerProps: T["button"]
|
|
294
|
+
incrementTriggerProps: T["button"]
|
|
295
|
+
scrubberProps: T["element"]
|
|
296
|
+
}
|