@zag-js/number-input 0.70.0 → 0.71.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 +75 -117
- package/dist/index.mjs +14 -31
- package/package.json +10 -11
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/src/cursor.ts +0 -57
- package/src/index.ts +0 -13
- package/src/number-input.anatomy.ts +0 -14
- package/src/number-input.connect.ts +0 -265
- package/src/number-input.dom.ts +0 -113
- package/src/number-input.machine.ts +0 -445
- package/src/number-input.props.ts +0 -34
- package/src/number-input.types.ts +0 -324
- package/src/number-input.utils.ts +0 -22
package/src/number-input.dom.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { createScope, isSafari, MAX_Z_INDEX } from "@zag-js/dom-query"
|
|
2
|
-
import { roundToDevicePixel, wrap } from "@zag-js/number-utils"
|
|
3
|
-
import type { MachineContext as Ctx } from "./number-input.types"
|
|
4
|
-
|
|
5
|
-
export const dom = createScope({
|
|
6
|
-
getRootId: (ctx: Ctx) => ctx.ids?.root ?? `number-input:${ctx.id}`,
|
|
7
|
-
getInputId: (ctx: Ctx) => ctx.ids?.input ?? `number-input:${ctx.id}:input`,
|
|
8
|
-
getIncrementTriggerId: (ctx: Ctx) => ctx.ids?.incrementTrigger ?? `number-input:${ctx.id}:inc`,
|
|
9
|
-
getDecrementTriggerId: (ctx: Ctx) => ctx.ids?.decrementTrigger ?? `number-input:${ctx.id}:dec`,
|
|
10
|
-
getScrubberId: (ctx: Ctx) => ctx.ids?.scrubber ?? `number-input:${ctx.id}:scrubber`,
|
|
11
|
-
getCursorId: (ctx: Ctx) => `number-input:${ctx.id}:cursor`,
|
|
12
|
-
getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `number-input:${ctx.id}:label`,
|
|
13
|
-
|
|
14
|
-
getInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getInputId(ctx)),
|
|
15
|
-
getIncrementTriggerEl: (ctx: Ctx) => dom.getById<HTMLButtonElement>(ctx, dom.getIncrementTriggerId(ctx)),
|
|
16
|
-
getDecrementTriggerEl: (ctx: Ctx) => dom.getById<HTMLButtonElement>(ctx, dom.getDecrementTriggerId(ctx)),
|
|
17
|
-
getScrubberEl: (ctx: Ctx) => dom.getById(ctx, dom.getScrubberId(ctx)),
|
|
18
|
-
getCursorEl: (ctx: Ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
|
|
19
|
-
|
|
20
|
-
getPressedTriggerEl: (ctx: Ctx, hint = ctx.hint) => {
|
|
21
|
-
let btnEl: HTMLButtonElement | null = null
|
|
22
|
-
if (hint === "increment") {
|
|
23
|
-
btnEl = dom.getIncrementTriggerEl(ctx)
|
|
24
|
-
}
|
|
25
|
-
if (hint === "decrement") {
|
|
26
|
-
btnEl = dom.getDecrementTriggerEl(ctx)
|
|
27
|
-
}
|
|
28
|
-
return btnEl
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
setupVirtualCursor(ctx: Ctx) {
|
|
32
|
-
if (isSafari()) return
|
|
33
|
-
dom.createVirtualCursor(ctx)
|
|
34
|
-
return () => {
|
|
35
|
-
dom.getCursorEl(ctx)?.remove()
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
preventTextSelection(ctx: Ctx) {
|
|
40
|
-
const doc = dom.getDoc(ctx)
|
|
41
|
-
const html = doc.documentElement
|
|
42
|
-
const body = doc.body
|
|
43
|
-
|
|
44
|
-
body.style.pointerEvents = "none"
|
|
45
|
-
html.style.userSelect = "none"
|
|
46
|
-
html.style.cursor = "ew-resize"
|
|
47
|
-
|
|
48
|
-
return () => {
|
|
49
|
-
body.style.pointerEvents = ""
|
|
50
|
-
html.style.userSelect = ""
|
|
51
|
-
html.style.cursor = ""
|
|
52
|
-
if (!html.style.length) {
|
|
53
|
-
html.removeAttribute("style")
|
|
54
|
-
}
|
|
55
|
-
if (!body.style.length) {
|
|
56
|
-
body.removeAttribute("style")
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
getMousementValue(ctx: Ctx, event: MouseEvent) {
|
|
62
|
-
const x = roundToDevicePixel(event.movementX)
|
|
63
|
-
const y = roundToDevicePixel(event.movementY)
|
|
64
|
-
|
|
65
|
-
let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null
|
|
66
|
-
|
|
67
|
-
if (ctx.isRtl && hint === "increment") hint = "decrement"
|
|
68
|
-
if (ctx.isRtl && hint === "decrement") hint = "increment"
|
|
69
|
-
|
|
70
|
-
const point = {
|
|
71
|
-
x: ctx.scrubberCursorPoint!.x + x,
|
|
72
|
-
y: ctx.scrubberCursorPoint!.y + y,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const win = dom.getWin(ctx)
|
|
76
|
-
const width = win.innerWidth
|
|
77
|
-
const half = roundToDevicePixel(7.5)
|
|
78
|
-
point.x = wrap(point.x + half, width) - half
|
|
79
|
-
|
|
80
|
-
return { hint, point }
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
createVirtualCursor(ctx: Ctx) {
|
|
84
|
-
const doc = dom.getDoc(ctx)
|
|
85
|
-
const el = doc.createElement("div")
|
|
86
|
-
el.className = "scrubber--cursor"
|
|
87
|
-
el.id = dom.getCursorId(ctx)
|
|
88
|
-
|
|
89
|
-
Object.assign(el.style, {
|
|
90
|
-
width: "15px",
|
|
91
|
-
height: "15px",
|
|
92
|
-
position: "fixed",
|
|
93
|
-
pointerEvents: "none",
|
|
94
|
-
left: "0px",
|
|
95
|
-
top: "0px",
|
|
96
|
-
zIndex: MAX_Z_INDEX,
|
|
97
|
-
transform: ctx.scrubberCursorPoint
|
|
98
|
-
? `translate3d(${ctx.scrubberCursorPoint.x}px, ${ctx.scrubberCursorPoint.y}px, 0px)`
|
|
99
|
-
: undefined,
|
|
100
|
-
willChange: "transform",
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
el.innerHTML = `
|
|
104
|
-
<svg width="46" height="15" style="left: -15.5px; position: absolute; top: 0; filter: drop-shadow(rgba(0, 0, 0, 0.4) 0px 1px 1.1px);">
|
|
105
|
-
<g transform="translate(2 3)">
|
|
106
|
-
<path fill-rule="evenodd" d="M 15 4.5L 15 2L 11.5 5.5L 15 9L 15 6.5L 31 6.5L 31 9L 34.5 5.5L 31 2L 31 4.5Z" style="stroke-width: 2px; stroke: white;"></path>
|
|
107
|
-
<path fill-rule="evenodd" d="M 15 4.5L 15 2L 11.5 5.5L 15 9L 15 6.5L 31 6.5L 31 9L 34.5 5.5L 31 2L 31 4.5Z"></path>
|
|
108
|
-
</g>
|
|
109
|
-
</svg>`
|
|
110
|
-
|
|
111
|
-
doc.body.appendChild(el)
|
|
112
|
-
},
|
|
113
|
-
})
|
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { choose, createMachine, guards } from "@zag-js/core"
|
|
2
|
-
import { addDomEvent, requestPointerLock } from "@zag-js/dom-event"
|
|
3
|
-
import { isSafari, observeAttributes, raf } from "@zag-js/dom-query"
|
|
4
|
-
import { trackFormControl } from "@zag-js/form-utils"
|
|
5
|
-
import { clamp, decrement, increment, isAtMax, isAtMin, isWithinRange } from "@zag-js/number-utils"
|
|
6
|
-
import { callAll, compact, isEqual } from "@zag-js/utils"
|
|
7
|
-
import { recordCursor, restoreCursor } from "./cursor"
|
|
8
|
-
import { dom } from "./number-input.dom"
|
|
9
|
-
import type { MachineContext, MachineState, UserDefinedContext } from "./number-input.types"
|
|
10
|
-
import { createFormatter, createParser, formatValue, parseValue } from "./number-input.utils"
|
|
11
|
-
|
|
12
|
-
const { not, and } = guards
|
|
13
|
-
|
|
14
|
-
export function machine(userContext: UserDefinedContext) {
|
|
15
|
-
const ctx = compact(userContext)
|
|
16
|
-
return createMachine<MachineContext, MachineState>(
|
|
17
|
-
{
|
|
18
|
-
id: "number-input",
|
|
19
|
-
initial: "idle",
|
|
20
|
-
context: {
|
|
21
|
-
dir: "ltr",
|
|
22
|
-
locale: "en-US",
|
|
23
|
-
focusInputOnChange: true,
|
|
24
|
-
clampValueOnBlur: true,
|
|
25
|
-
allowOverflow: false,
|
|
26
|
-
inputMode: "decimal",
|
|
27
|
-
pattern: "[0-9]*(.[0-9]+)?",
|
|
28
|
-
value: "",
|
|
29
|
-
step: 1,
|
|
30
|
-
min: Number.MIN_SAFE_INTEGER,
|
|
31
|
-
max: Number.MAX_SAFE_INTEGER,
|
|
32
|
-
invalid: false,
|
|
33
|
-
spinOnPress: true,
|
|
34
|
-
disabled: false,
|
|
35
|
-
readOnly: false,
|
|
36
|
-
...ctx,
|
|
37
|
-
hint: null,
|
|
38
|
-
scrubberCursorPoint: null,
|
|
39
|
-
fieldsetDisabled: false,
|
|
40
|
-
formatter: createFormatter(ctx.locale || "en-US", ctx.formatOptions),
|
|
41
|
-
parser: createParser(ctx.locale || "en-US", ctx.formatOptions),
|
|
42
|
-
translations: {
|
|
43
|
-
incrementLabel: "increment value",
|
|
44
|
-
decrementLabel: "decrease value",
|
|
45
|
-
...ctx.translations,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
computed: {
|
|
50
|
-
isRtl: (ctx) => ctx.dir === "rtl",
|
|
51
|
-
valueAsNumber: (ctx) => parseValue(ctx, ctx.value),
|
|
52
|
-
formattedValue: (ctx) => formatValue(ctx, ctx.valueAsNumber),
|
|
53
|
-
isAtMin: (ctx) => isAtMin(ctx.valueAsNumber, ctx),
|
|
54
|
-
isAtMax: (ctx) => isAtMax(ctx.valueAsNumber, ctx),
|
|
55
|
-
isOutOfRange: (ctx) => !isWithinRange(ctx.valueAsNumber, ctx),
|
|
56
|
-
isValueEmpty: (ctx) => ctx.value === "",
|
|
57
|
-
isDisabled: (ctx) => !!ctx.disabled || ctx.fieldsetDisabled,
|
|
58
|
-
canIncrement: (ctx) => ctx.allowOverflow || !ctx.isAtMax,
|
|
59
|
-
canDecrement: (ctx) => ctx.allowOverflow || !ctx.isAtMin,
|
|
60
|
-
valueText: (ctx) => ctx.translations.valueText?.(ctx.value),
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
watch: {
|
|
64
|
-
formatOptions: ["setFormatterAndParser", "syncInputElement"],
|
|
65
|
-
locale: ["setFormatterAndParser", "syncInputElement"],
|
|
66
|
-
value: ["syncInputElement"],
|
|
67
|
-
isOutOfRange: ["invokeOnInvalid"],
|
|
68
|
-
scrubberCursorPoint: ["setVirtualCursorPosition"],
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
activities: ["trackFormControl"],
|
|
72
|
-
|
|
73
|
-
on: {
|
|
74
|
-
"VALUE.SET": {
|
|
75
|
-
actions: ["setRawValue", "setHintToSet"],
|
|
76
|
-
},
|
|
77
|
-
"VALUE.CLEAR": {
|
|
78
|
-
actions: ["clearValue"],
|
|
79
|
-
},
|
|
80
|
-
"VALUE.INCREMENT": {
|
|
81
|
-
actions: ["increment"],
|
|
82
|
-
},
|
|
83
|
-
"VALUE.DECREMENT": {
|
|
84
|
-
actions: ["decrement"],
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
states: {
|
|
89
|
-
idle: {
|
|
90
|
-
on: {
|
|
91
|
-
"TRIGGER.PRESS_DOWN": [
|
|
92
|
-
{ guard: "isTouchPointer", target: "before:spin", actions: ["setHint"] },
|
|
93
|
-
{
|
|
94
|
-
target: "before:spin",
|
|
95
|
-
actions: ["focusInput", "invokeOnFocus", "setHint"],
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
"SCRUBBER.PRESS_DOWN": {
|
|
99
|
-
target: "scrubbing",
|
|
100
|
-
actions: ["focusInput", "invokeOnFocus", "setHint", "setCursorPoint"],
|
|
101
|
-
},
|
|
102
|
-
"INPUT.FOCUS": {
|
|
103
|
-
target: "focused",
|
|
104
|
-
actions: ["focusInput", "invokeOnFocus"],
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
focused: {
|
|
110
|
-
tags: "focus",
|
|
111
|
-
activities: "attachWheelListener",
|
|
112
|
-
on: {
|
|
113
|
-
"TRIGGER.PRESS_DOWN": [
|
|
114
|
-
{ guard: "isTouchPointer", target: "before:spin", actions: ["setHint"] },
|
|
115
|
-
{ target: "before:spin", actions: ["focusInput", "setHint"] },
|
|
116
|
-
],
|
|
117
|
-
"SCRUBBER.PRESS_DOWN": {
|
|
118
|
-
target: "scrubbing",
|
|
119
|
-
actions: ["focusInput", "setHint", "setCursorPoint"],
|
|
120
|
-
},
|
|
121
|
-
"INPUT.ARROW_UP": {
|
|
122
|
-
actions: "increment",
|
|
123
|
-
},
|
|
124
|
-
"INPUT.ARROW_DOWN": {
|
|
125
|
-
actions: "decrement",
|
|
126
|
-
},
|
|
127
|
-
"INPUT.HOME": {
|
|
128
|
-
actions: "decrementToMin",
|
|
129
|
-
},
|
|
130
|
-
"INPUT.END": {
|
|
131
|
-
actions: "incrementToMax",
|
|
132
|
-
},
|
|
133
|
-
"INPUT.CHANGE": {
|
|
134
|
-
actions: ["setValue", "setHint"],
|
|
135
|
-
},
|
|
136
|
-
"INPUT.BLUR": [
|
|
137
|
-
{
|
|
138
|
-
guard: and("clampValueOnBlur", not("isInRange")),
|
|
139
|
-
target: "idle",
|
|
140
|
-
actions: ["setClampedValue", "clearHint", "invokeOnBlur"],
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
target: "idle",
|
|
144
|
-
actions: ["setFormattedValue", "clearHint", "invokeOnBlur"],
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
"INPUT.ENTER": {
|
|
148
|
-
actions: ["setFormattedValue", "clearHint", "invokeOnBlur"],
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
"before:spin": {
|
|
154
|
-
tags: "focus",
|
|
155
|
-
activities: "trackButtonDisabled",
|
|
156
|
-
entry: choose([
|
|
157
|
-
{ guard: "isIncrementHint", actions: "increment" },
|
|
158
|
-
{ guard: "isDecrementHint", actions: "decrement" },
|
|
159
|
-
]),
|
|
160
|
-
after: {
|
|
161
|
-
CHANGE_DELAY: {
|
|
162
|
-
target: "spinning",
|
|
163
|
-
guard: and("isInRange", "spinOnPress"),
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
on: {
|
|
167
|
-
"TRIGGER.PRESS_UP": [
|
|
168
|
-
{ guard: "isTouchPointer", target: "focused", actions: "clearHint" },
|
|
169
|
-
{ target: "focused", actions: ["focusInput", "clearHint"] },
|
|
170
|
-
],
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
spinning: {
|
|
175
|
-
tags: "focus",
|
|
176
|
-
activities: "trackButtonDisabled",
|
|
177
|
-
every: [
|
|
178
|
-
{
|
|
179
|
-
delay: "CHANGE_INTERVAL",
|
|
180
|
-
guard: and(not("isAtMin"), "isIncrementHint"),
|
|
181
|
-
actions: "increment",
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
delay: "CHANGE_INTERVAL",
|
|
185
|
-
guard: and(not("isAtMax"), "isDecrementHint"),
|
|
186
|
-
actions: "decrement",
|
|
187
|
-
},
|
|
188
|
-
],
|
|
189
|
-
on: {
|
|
190
|
-
"TRIGGER.PRESS_UP": {
|
|
191
|
-
target: "focused",
|
|
192
|
-
actions: ["focusInput", "clearHint"],
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
scrubbing: {
|
|
198
|
-
tags: "focus",
|
|
199
|
-
activities: ["activatePointerLock", "trackMousemove", "setupVirtualCursor", "preventTextSelection"],
|
|
200
|
-
on: {
|
|
201
|
-
"SCRUBBER.POINTER_UP": {
|
|
202
|
-
target: "focused",
|
|
203
|
-
actions: ["focusInput", "clearCursorPoint"],
|
|
204
|
-
},
|
|
205
|
-
"SCRUBBER.POINTER_MOVE": [
|
|
206
|
-
{
|
|
207
|
-
guard: "isIncrementHint",
|
|
208
|
-
actions: ["increment", "setCursorPoint"],
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
guard: "isDecrementHint",
|
|
212
|
-
actions: ["decrement", "setCursorPoint"],
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
delays: {
|
|
221
|
-
CHANGE_INTERVAL: 50,
|
|
222
|
-
CHANGE_DELAY: 300,
|
|
223
|
-
},
|
|
224
|
-
|
|
225
|
-
guards: {
|
|
226
|
-
clampValueOnBlur: (ctx) => ctx.clampValueOnBlur,
|
|
227
|
-
isAtMin: (ctx) => ctx.isAtMin,
|
|
228
|
-
spinOnPress: (ctx) => !!ctx.spinOnPress,
|
|
229
|
-
isAtMax: (ctx) => ctx.isAtMax,
|
|
230
|
-
isInRange: (ctx) => !ctx.isOutOfRange,
|
|
231
|
-
isDecrementHint: (ctx, evt) => (evt.hint ?? ctx.hint) === "decrement",
|
|
232
|
-
isIncrementHint: (ctx, evt) => (evt.hint ?? ctx.hint) === "increment",
|
|
233
|
-
isTouchPointer: (_ctx, evt) => evt.pointerType === "touch",
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
activities: {
|
|
237
|
-
trackFormControl(ctx, _evt, { initialContext }) {
|
|
238
|
-
const inputEl = dom.getInputEl(ctx)
|
|
239
|
-
return trackFormControl(inputEl, {
|
|
240
|
-
onFieldsetDisabledChange(disabled) {
|
|
241
|
-
ctx.fieldsetDisabled = disabled
|
|
242
|
-
},
|
|
243
|
-
onFormReset() {
|
|
244
|
-
set.value(ctx, initialContext.value)
|
|
245
|
-
},
|
|
246
|
-
})
|
|
247
|
-
},
|
|
248
|
-
setupVirtualCursor(ctx) {
|
|
249
|
-
return dom.setupVirtualCursor(ctx)
|
|
250
|
-
},
|
|
251
|
-
preventTextSelection(ctx) {
|
|
252
|
-
return dom.preventTextSelection(ctx)
|
|
253
|
-
},
|
|
254
|
-
trackButtonDisabled(ctx, _evt, { send }) {
|
|
255
|
-
const btn = dom.getPressedTriggerEl(ctx, ctx.hint)
|
|
256
|
-
return observeAttributes(btn, {
|
|
257
|
-
attributes: ["disabled"],
|
|
258
|
-
callback() {
|
|
259
|
-
send({ type: "TRIGGER.PRESS_UP", src: "attr" })
|
|
260
|
-
},
|
|
261
|
-
})
|
|
262
|
-
},
|
|
263
|
-
attachWheelListener(ctx, _evt, { send }) {
|
|
264
|
-
const inputEl = dom.getInputEl(ctx)
|
|
265
|
-
if (!inputEl || !dom.isActiveElement(ctx, inputEl) || !ctx.allowMouseWheel) return
|
|
266
|
-
|
|
267
|
-
function onWheel(event: WheelEvent) {
|
|
268
|
-
event.preventDefault()
|
|
269
|
-
const dir = Math.sign(event.deltaY) * -1
|
|
270
|
-
if (dir === 1) {
|
|
271
|
-
send("VALUE.INCREMENT")
|
|
272
|
-
} else if (dir === -1) {
|
|
273
|
-
send("VALUE.DECREMENT")
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return addDomEvent(inputEl, "wheel", onWheel, { passive: false })
|
|
278
|
-
},
|
|
279
|
-
activatePointerLock(ctx) {
|
|
280
|
-
if (isSafari()) return
|
|
281
|
-
return requestPointerLock(dom.getDoc(ctx))
|
|
282
|
-
},
|
|
283
|
-
trackMousemove(ctx, _evt, { send }) {
|
|
284
|
-
const doc = dom.getDoc(ctx)
|
|
285
|
-
|
|
286
|
-
function onMousemove(event: MouseEvent) {
|
|
287
|
-
if (!ctx.scrubberCursorPoint) return
|
|
288
|
-
const value = dom.getMousementValue(ctx, event)
|
|
289
|
-
if (!value.hint) return
|
|
290
|
-
send({
|
|
291
|
-
type: "SCRUBBER.POINTER_MOVE",
|
|
292
|
-
hint: value.hint,
|
|
293
|
-
point: value.point,
|
|
294
|
-
})
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function onMouseup() {
|
|
298
|
-
send("SCRUBBER.POINTER_UP")
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return callAll(
|
|
302
|
-
addDomEvent(doc, "mousemove", onMousemove, false),
|
|
303
|
-
addDomEvent(doc, "mouseup", onMouseup, false),
|
|
304
|
-
)
|
|
305
|
-
},
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
actions: {
|
|
309
|
-
focusInput(ctx) {
|
|
310
|
-
if (!ctx.focusInputOnChange) return
|
|
311
|
-
const inputEl = dom.getInputEl(ctx)
|
|
312
|
-
if (dom.isActiveElement(ctx, inputEl)) return
|
|
313
|
-
raf(() => inputEl?.focus({ preventScroll: true }))
|
|
314
|
-
},
|
|
315
|
-
increment(ctx, evt) {
|
|
316
|
-
const nextValue = increment(ctx.valueAsNumber, evt.step ?? ctx.step)
|
|
317
|
-
const value = formatValue(ctx, clamp(nextValue, ctx))
|
|
318
|
-
set.value(ctx, value)
|
|
319
|
-
},
|
|
320
|
-
decrement(ctx, evt) {
|
|
321
|
-
const nextValue = decrement(ctx.valueAsNumber, evt.step ?? ctx.step)
|
|
322
|
-
const value = formatValue(ctx, clamp(nextValue, ctx))
|
|
323
|
-
set.value(ctx, value)
|
|
324
|
-
},
|
|
325
|
-
setClampedValue(ctx) {
|
|
326
|
-
const nextValue = clamp(ctx.valueAsNumber, ctx)
|
|
327
|
-
set.value(ctx, formatValue(ctx, nextValue))
|
|
328
|
-
},
|
|
329
|
-
setRawValue(ctx, evt) {
|
|
330
|
-
const parsedValue = parseValue(ctx, evt.value)
|
|
331
|
-
const value = formatValue(ctx, clamp(parsedValue, ctx))
|
|
332
|
-
set.value(ctx, value)
|
|
333
|
-
},
|
|
334
|
-
setValue(ctx, evt) {
|
|
335
|
-
const value = evt.target?.value ?? evt.value
|
|
336
|
-
set.value(ctx, value)
|
|
337
|
-
},
|
|
338
|
-
clearValue(ctx) {
|
|
339
|
-
set.value(ctx, "")
|
|
340
|
-
},
|
|
341
|
-
incrementToMax(ctx) {
|
|
342
|
-
const value = formatValue(ctx, ctx.max)
|
|
343
|
-
set.value(ctx, value)
|
|
344
|
-
},
|
|
345
|
-
decrementToMin(ctx) {
|
|
346
|
-
const value = formatValue(ctx, ctx.min)
|
|
347
|
-
set.value(ctx, value)
|
|
348
|
-
},
|
|
349
|
-
setHint(ctx, evt) {
|
|
350
|
-
ctx.hint = evt.hint
|
|
351
|
-
},
|
|
352
|
-
clearHint(ctx) {
|
|
353
|
-
ctx.hint = null
|
|
354
|
-
},
|
|
355
|
-
setHintToSet(ctx) {
|
|
356
|
-
ctx.hint = "set"
|
|
357
|
-
},
|
|
358
|
-
invokeOnFocus(ctx) {
|
|
359
|
-
ctx.onFocusChange?.({
|
|
360
|
-
focused: true,
|
|
361
|
-
value: ctx.formattedValue,
|
|
362
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
363
|
-
})
|
|
364
|
-
},
|
|
365
|
-
invokeOnBlur(ctx) {
|
|
366
|
-
ctx.onFocusChange?.({
|
|
367
|
-
focused: false,
|
|
368
|
-
value: ctx.formattedValue,
|
|
369
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
370
|
-
})
|
|
371
|
-
},
|
|
372
|
-
invokeOnInvalid(ctx) {
|
|
373
|
-
if (!ctx.isOutOfRange) return
|
|
374
|
-
const reason = ctx.valueAsNumber > ctx.max ? "rangeOverflow" : "rangeUnderflow"
|
|
375
|
-
ctx.onValueInvalid?.({
|
|
376
|
-
reason,
|
|
377
|
-
value: ctx.formattedValue,
|
|
378
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
379
|
-
})
|
|
380
|
-
},
|
|
381
|
-
syncInputElement(ctx, evt) {
|
|
382
|
-
const value = evt.type.endsWith("CHANGE") ? ctx.value : ctx.formattedValue
|
|
383
|
-
sync.input(ctx, value)
|
|
384
|
-
},
|
|
385
|
-
setFormattedValue(ctx) {
|
|
386
|
-
set.value(ctx, ctx.formattedValue)
|
|
387
|
-
},
|
|
388
|
-
setCursorPoint(ctx, evt) {
|
|
389
|
-
ctx.scrubberCursorPoint = evt.point
|
|
390
|
-
},
|
|
391
|
-
clearCursorPoint(ctx) {
|
|
392
|
-
ctx.scrubberCursorPoint = null
|
|
393
|
-
},
|
|
394
|
-
setVirtualCursorPosition(ctx) {
|
|
395
|
-
const cursorEl = dom.getCursorEl(ctx)
|
|
396
|
-
if (!cursorEl || !ctx.scrubberCursorPoint) return
|
|
397
|
-
const { x, y } = ctx.scrubberCursorPoint
|
|
398
|
-
cursorEl.style.transform = `translate3d(${x}px, ${y}px, 0px)`
|
|
399
|
-
},
|
|
400
|
-
setFormatterAndParser(ctx) {
|
|
401
|
-
if (!ctx.locale) return
|
|
402
|
-
ctx.formatter = createFormatter(ctx.locale, ctx.formatOptions)
|
|
403
|
-
ctx.parser = createParser(ctx.locale, ctx.formatOptions)
|
|
404
|
-
},
|
|
405
|
-
},
|
|
406
|
-
compareFns: {
|
|
407
|
-
formatOptions: (a, b) => isEqual(a, b),
|
|
408
|
-
scrubberCursorPoint: (a, b) => isEqual(a, b),
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
)
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const sync = {
|
|
415
|
-
input(ctx: MachineContext, value: string) {
|
|
416
|
-
const inputEl = dom.getInputEl(ctx)
|
|
417
|
-
if (!inputEl) return
|
|
418
|
-
|
|
419
|
-
// record cursor position before updating input value
|
|
420
|
-
const sel = recordCursor(inputEl)
|
|
421
|
-
|
|
422
|
-
// restore cursor position after updating input value
|
|
423
|
-
raf(() => {
|
|
424
|
-
dom.setValue(inputEl, value)
|
|
425
|
-
restoreCursor(inputEl, sel)
|
|
426
|
-
})
|
|
427
|
-
},
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
const invoke = {
|
|
431
|
-
onChange: (ctx: MachineContext) => {
|
|
432
|
-
ctx.onValueChange?.({
|
|
433
|
-
value: ctx.value,
|
|
434
|
-
valueAsNumber: ctx.valueAsNumber,
|
|
435
|
-
})
|
|
436
|
-
},
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const set = {
|
|
440
|
-
value: (ctx: MachineContext, value: string) => {
|
|
441
|
-
if (isEqual(ctx.value, value)) return
|
|
442
|
-
ctx.value = value
|
|
443
|
-
invoke.onChange(ctx)
|
|
444
|
-
},
|
|
445
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { createProps } from "@zag-js/types"
|
|
2
|
-
import { createSplitProps } from "@zag-js/utils"
|
|
3
|
-
import type { UserDefinedContext } from "./number-input.types"
|
|
4
|
-
|
|
5
|
-
export const props = createProps<UserDefinedContext>()([
|
|
6
|
-
"allowMouseWheel",
|
|
7
|
-
"allowOverflow",
|
|
8
|
-
"clampValueOnBlur",
|
|
9
|
-
"dir",
|
|
10
|
-
"disabled",
|
|
11
|
-
"focusInputOnChange",
|
|
12
|
-
"form",
|
|
13
|
-
"formatOptions",
|
|
14
|
-
"getRootNode",
|
|
15
|
-
"id",
|
|
16
|
-
"ids",
|
|
17
|
-
"inputMode",
|
|
18
|
-
"invalid",
|
|
19
|
-
"locale",
|
|
20
|
-
"max",
|
|
21
|
-
"min",
|
|
22
|
-
"name",
|
|
23
|
-
"onFocusChange",
|
|
24
|
-
"onValueChange",
|
|
25
|
-
"onValueInvalid",
|
|
26
|
-
"pattern",
|
|
27
|
-
"required",
|
|
28
|
-
"readOnly",
|
|
29
|
-
"spinOnPress",
|
|
30
|
-
"step",
|
|
31
|
-
"translations",
|
|
32
|
-
"value",
|
|
33
|
-
])
|
|
34
|
-
export const splitProps = createSplitProps<Partial<UserDefinedContext>>(props)
|