@zag-js/number-input 0.10.4 → 0.11.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.mjs CHANGED
@@ -1,3 +1,771 @@
1
- export { anatomy } from './number-input.anatomy.mjs';
2
- export { connect } from './number-input.connect.mjs';
3
- export { machine } from './number-input.machine.mjs';
1
+ // src/number-input.anatomy.ts
2
+ import { createAnatomy } from "@zag-js/anatomy";
3
+ var anatomy = createAnatomy("numberInput").parts(
4
+ "root",
5
+ "label",
6
+ "input",
7
+ "control",
8
+ "incrementTrigger",
9
+ "decrementTrigger",
10
+ "scrubber"
11
+ );
12
+ var parts = anatomy.build();
13
+
14
+ // src/number-input.connect.ts
15
+ import { getEventPoint, getEventStep, getNativeEvent, isLeftClick } from "@zag-js/dom-event";
16
+ import { ariaAttr, dataAttr } from "@zag-js/dom-query";
17
+ import { roundToDevicePixel as roundToDevicePixel2 } from "@zag-js/number-utils";
18
+
19
+ // src/number-input.dom.ts
20
+ import { createScope, isSafari, MAX_Z_INDEX } from "@zag-js/dom-query";
21
+ import { roundToDevicePixel, wrap } from "@zag-js/number-utils";
22
+ var dom = createScope({
23
+ getRootId: (ctx) => ctx.ids?.root ?? `number-input:${ctx.id}`,
24
+ getInputId: (ctx) => ctx.ids?.input ?? `number-input:${ctx.id}:input`,
25
+ getIncrementTriggerId: (ctx) => ctx.ids?.incrementTrigger ?? `number-input:${ctx.id}:inc`,
26
+ getDecrementTriggerId: (ctx) => ctx.ids?.decrementTrigger ?? `number-input:${ctx.id}:dec`,
27
+ getScrubberId: (ctx) => ctx.ids?.scrubber ?? `number-input:${ctx.id}:scrubber`,
28
+ getCursorId: (ctx) => `number-input:${ctx.id}:cursor`,
29
+ getLabelId: (ctx) => ctx.ids?.label ?? `number-input:${ctx.id}:label`,
30
+ getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
31
+ getIncrementTriggerEl: (ctx) => dom.getById(ctx, dom.getIncrementTriggerId(ctx)),
32
+ getDecrementTriggerEl: (ctx) => dom.getById(ctx, dom.getDecrementTriggerId(ctx)),
33
+ getScrubberEl: (ctx) => dom.getById(ctx, dom.getScrubberId(ctx)),
34
+ getCursorEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
35
+ getPressedTriggerEl: (ctx, hint = ctx.hint) => {
36
+ let btnEl = null;
37
+ if (hint === "increment") {
38
+ btnEl = dom.getIncrementTriggerEl(ctx);
39
+ }
40
+ if (hint === "decrement") {
41
+ btnEl = dom.getDecrementTriggerEl(ctx);
42
+ }
43
+ return btnEl;
44
+ },
45
+ setupVirtualCursor(ctx) {
46
+ if (isSafari())
47
+ return;
48
+ dom.createVirtualCursor(ctx);
49
+ return () => {
50
+ dom.getCursorEl(ctx)?.remove();
51
+ };
52
+ },
53
+ preventTextSelection(ctx) {
54
+ const doc = dom.getDoc(ctx);
55
+ const html = doc.documentElement;
56
+ const body = doc.body;
57
+ body.style.pointerEvents = "none";
58
+ html.style.userSelect = "none";
59
+ html.style.cursor = "ew-resize";
60
+ return () => {
61
+ body.style.pointerEvents = "";
62
+ html.style.userSelect = "";
63
+ html.style.cursor = "";
64
+ if (!html.style.length) {
65
+ html.removeAttribute("style");
66
+ }
67
+ if (!body.style.length) {
68
+ body.removeAttribute("style");
69
+ }
70
+ };
71
+ },
72
+ getMousementValue(ctx, event) {
73
+ const x = roundToDevicePixel(event.movementX);
74
+ const y = roundToDevicePixel(event.movementY);
75
+ let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null;
76
+ if (ctx.isRtl && hint === "increment")
77
+ hint = "decrement";
78
+ if (ctx.isRtl && hint === "decrement")
79
+ hint = "increment";
80
+ const point = {
81
+ x: ctx.scrubberCursorPoint.x + x,
82
+ y: ctx.scrubberCursorPoint.y + y
83
+ };
84
+ const win = dom.getWin(ctx);
85
+ const width = win.innerWidth;
86
+ const half = roundToDevicePixel(7.5);
87
+ point.x = wrap(point.x + half, width) - half;
88
+ return { hint, point };
89
+ },
90
+ createVirtualCursor(ctx) {
91
+ const doc = dom.getDoc(ctx);
92
+ const el = doc.createElement("div");
93
+ el.className = "scrubber--cursor";
94
+ el.id = dom.getCursorId(ctx);
95
+ Object.assign(el.style, {
96
+ width: "15px",
97
+ height: "15px",
98
+ position: "fixed",
99
+ pointerEvents: "none",
100
+ left: "0px",
101
+ top: "0px",
102
+ zIndex: MAX_Z_INDEX,
103
+ transform: ctx.scrubberCursorPoint ? `translate3d(${ctx.scrubberCursorPoint.x}px, ${ctx.scrubberCursorPoint.y}px, 0px)` : void 0,
104
+ willChange: "transform"
105
+ });
106
+ el.innerHTML = `
107
+ <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);">
108
+ <g transform="translate(2 3)">
109
+ <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>
110
+ <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>
111
+ </g>
112
+ </svg>`;
113
+ doc.body.appendChild(el);
114
+ }
115
+ });
116
+
117
+ // src/number-input.utils.ts
118
+ import { isModifiedEvent } from "@zag-js/dom-event";
119
+ import { clamp, decrement, formatDecimal, increment } from "@zag-js/number-utils";
120
+ var utils = {
121
+ isValidNumericEvent: (ctx, event) => {
122
+ if (event.key == null)
123
+ return true;
124
+ const isModifier = isModifiedEvent(event);
125
+ const isSingleKey = event.key.length === 1;
126
+ if (isModifier || !isSingleKey)
127
+ return true;
128
+ return ctx.validateCharacter?.(event.key) ?? utils.isFloatingPoint(event.key);
129
+ },
130
+ isFloatingPoint: (v) => /^[0-9+\-.]$/.test(v),
131
+ sanitize: (ctx, value) => {
132
+ return value.split("").filter(ctx.validateCharacter ?? utils.isFloatingPoint).join("");
133
+ },
134
+ increment: (ctx, step) => {
135
+ const value = increment(ctx.value, step ?? ctx.step);
136
+ return formatDecimal(clamp(value, ctx), ctx);
137
+ },
138
+ decrement: (ctx, step) => {
139
+ const value = decrement(ctx.value, step ?? ctx.step);
140
+ return formatDecimal(clamp(value, ctx), ctx);
141
+ },
142
+ clamp: (ctx) => {
143
+ return formatDecimal(clamp(ctx.value, ctx), ctx);
144
+ },
145
+ parse: (ctx, value) => {
146
+ return ctx.parse?.(value) ?? value;
147
+ },
148
+ format: (ctx, value) => {
149
+ const _val = value.toString();
150
+ return ctx.format?.(_val) ?? _val;
151
+ },
152
+ round: (ctx) => {
153
+ return formatDecimal(ctx.value, ctx);
154
+ }
155
+ };
156
+
157
+ // src/number-input.connect.ts
158
+ function connect(state, send, normalize) {
159
+ const isFocused = state.hasTag("focus");
160
+ const isInvalid = state.context.isOutOfRange || !!state.context.invalid;
161
+ const isDisabled = !!state.context.disabled;
162
+ const isValueEmpty = state.context.isValueEmpty;
163
+ const isIncrementDisabled = isDisabled || !state.context.canIncrement;
164
+ const isDecrementDisabled = isDisabled || !state.context.canDecrement;
165
+ const translations = state.context.translations;
166
+ return {
167
+ /**
168
+ * Whether the input is focused.
169
+ */
170
+ isFocused,
171
+ /**
172
+ * Whether the input is invalid.
173
+ */
174
+ isInvalid,
175
+ /**
176
+ * Whether the input value is empty.
177
+ */
178
+ isValueEmpty,
179
+ /**
180
+ * The formatted value of the input.
181
+ */
182
+ value: state.context.formattedValue,
183
+ /**
184
+ * The value of the input as a number.
185
+ */
186
+ valueAsNumber: state.context.valueAsNumber,
187
+ /**
188
+ * Function to set the value of the input.
189
+ */
190
+ setValue(value) {
191
+ send({ type: "SET_VALUE", value: value.toString() });
192
+ },
193
+ /**
194
+ * Function to clear the value of the input.
195
+ */
196
+ clearValue() {
197
+ send("CLEAR_VALUE");
198
+ },
199
+ /**
200
+ * Function to increment the value of the input by the step.
201
+ */
202
+ increment() {
203
+ send("INCREMENT");
204
+ },
205
+ /**
206
+ * Function to decrement the value of the input by the step.
207
+ */
208
+ decrement() {
209
+ send("DECREMENT");
210
+ },
211
+ /**
212
+ * Function to set the value of the input to the max.
213
+ */
214
+ setToMax() {
215
+ send({ type: "SET_VALUE", value: state.context.max });
216
+ },
217
+ /**
218
+ * Function to set the value of the input to the min.
219
+ */
220
+ setToMin() {
221
+ send({ type: "SET_VALUE", value: state.context.min });
222
+ },
223
+ /**
224
+ * Function to focus the input.
225
+ */
226
+ focus() {
227
+ dom.getInputEl(state.context)?.focus();
228
+ },
229
+ /**
230
+ * Function to blur the input.
231
+ */
232
+ blur() {
233
+ dom.getInputEl(state.context)?.blur();
234
+ },
235
+ rootProps: normalize.element({
236
+ id: dom.getRootId(state.context),
237
+ ...parts.root.attrs,
238
+ "data-disabled": dataAttr(isDisabled)
239
+ }),
240
+ labelProps: normalize.label({
241
+ ...parts.label.attrs,
242
+ "data-disabled": dataAttr(isDisabled),
243
+ "data-invalid": dataAttr(isInvalid),
244
+ id: dom.getLabelId(state.context),
245
+ htmlFor: dom.getInputId(state.context)
246
+ }),
247
+ controlProps: normalize.element({
248
+ ...parts.control.attrs,
249
+ role: "group",
250
+ "aria-disabled": isDisabled,
251
+ "data-disabled": dataAttr(isDisabled),
252
+ "data-invalid": dataAttr(isInvalid),
253
+ "aria-invalid": ariaAttr(state.context.invalid)
254
+ }),
255
+ inputProps: normalize.input({
256
+ ...parts.input.attrs,
257
+ name: state.context.name,
258
+ form: state.context.form,
259
+ id: dom.getInputId(state.context),
260
+ role: "spinbutton",
261
+ defaultValue: state.context.formattedValue,
262
+ pattern: state.context.pattern,
263
+ inputMode: state.context.inputMode,
264
+ "aria-invalid": ariaAttr(isInvalid),
265
+ "data-invalid": dataAttr(isInvalid),
266
+ disabled: isDisabled,
267
+ "data-disabled": dataAttr(isDisabled),
268
+ readOnly: !!state.context.readOnly,
269
+ autoComplete: "off",
270
+ autoCorrect: "off",
271
+ spellCheck: "false",
272
+ type: "text",
273
+ "aria-roledescription": "numberfield",
274
+ "aria-valuemin": state.context.min,
275
+ "aria-valuemax": state.context.max,
276
+ "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
277
+ "aria-valuetext": state.context.valueText,
278
+ onFocus() {
279
+ send("FOCUS");
280
+ },
281
+ onBlur() {
282
+ send("BLUR");
283
+ },
284
+ onChange(event) {
285
+ send({ type: "CHANGE", target: event.currentTarget, hint: "set" });
286
+ },
287
+ onKeyDown(event) {
288
+ const evt = getNativeEvent(event);
289
+ if (evt.isComposing)
290
+ return;
291
+ if (!utils.isValidNumericEvent(state.context, event)) {
292
+ event.preventDefault();
293
+ }
294
+ const step = getEventStep(event) * state.context.step;
295
+ const keyMap = {
296
+ ArrowUp() {
297
+ send({ type: "ARROW_UP", step });
298
+ },
299
+ ArrowDown() {
300
+ send({ type: "ARROW_DOWN", step });
301
+ },
302
+ Home() {
303
+ send("HOME");
304
+ },
305
+ End() {
306
+ send("END");
307
+ }
308
+ };
309
+ const exec = keyMap[event.key];
310
+ if (exec) {
311
+ exec(event);
312
+ event.preventDefault();
313
+ }
314
+ }
315
+ }),
316
+ decrementTriggerProps: normalize.button({
317
+ ...parts.decrementTrigger.attrs,
318
+ id: dom.getDecrementTriggerId(state.context),
319
+ disabled: isDecrementDisabled,
320
+ "data-disabled": dataAttr(isDecrementDisabled),
321
+ "aria-label": translations.decrementLabel,
322
+ type: "button",
323
+ tabIndex: -1,
324
+ "aria-controls": dom.getInputId(state.context),
325
+ onPointerDown(event) {
326
+ if (isDecrementDisabled)
327
+ return;
328
+ send(isLeftClick(event) ? { type: "PRESS_DOWN", hint: "decrement" } : { type: "FOCUS" });
329
+ event.preventDefault();
330
+ },
331
+ onPointerUp() {
332
+ send({ type: "PRESS_UP", hint: "decrement" });
333
+ },
334
+ onPointerLeave() {
335
+ if (isDecrementDisabled)
336
+ return;
337
+ send({ type: "PRESS_UP", hint: "decrement" });
338
+ }
339
+ }),
340
+ incrementTriggerProps: normalize.button({
341
+ ...parts.incrementTrigger.attrs,
342
+ id: dom.getIncrementTriggerId(state.context),
343
+ disabled: isIncrementDisabled,
344
+ "data-disabled": dataAttr(isIncrementDisabled),
345
+ "aria-label": translations.incrementLabel,
346
+ type: "button",
347
+ tabIndex: -1,
348
+ "aria-controls": dom.getInputId(state.context),
349
+ onPointerDown(event) {
350
+ if (isIncrementDisabled)
351
+ return;
352
+ send(isLeftClick(event) ? { type: "PRESS_DOWN", hint: "increment" } : { type: "FOCUS" });
353
+ event.preventDefault();
354
+ },
355
+ onPointerUp() {
356
+ send({ type: "PRESS_UP", hint: "increment" });
357
+ },
358
+ onPointerLeave() {
359
+ send({ type: "PRESS_UP", hint: "increment" });
360
+ }
361
+ }),
362
+ scrubberProps: normalize.element({
363
+ ...parts.scrubber.attrs,
364
+ "data-disabled": dataAttr(isDisabled),
365
+ id: dom.getScrubberId(state.context),
366
+ role: "presentation",
367
+ onMouseDown(event) {
368
+ if (isDisabled)
369
+ return;
370
+ const evt = getNativeEvent(event);
371
+ const point = getEventPoint(evt);
372
+ point.x = point.x - roundToDevicePixel2(7.5);
373
+ point.y = point.y - roundToDevicePixel2(7.5);
374
+ send({ type: "PRESS_DOWN_SCRUBBER", point });
375
+ event.preventDefault();
376
+ },
377
+ style: {
378
+ cursor: isDisabled ? void 0 : "ew-resize"
379
+ }
380
+ })
381
+ };
382
+ }
383
+
384
+ // src/number-input.machine.ts
385
+ import { choose, createMachine, guards } from "@zag-js/core";
386
+ import { addDomEvent, requestPointerLock } from "@zag-js/dom-event";
387
+ import { isSafari as isSafari2, raf } from "@zag-js/dom-query";
388
+ import { dispatchInputValueEvent } from "@zag-js/form-utils";
389
+ import { observeAttributes } from "@zag-js/mutation-observer";
390
+ import { isAtMax, isAtMin, isWithinRange, valueOf } from "@zag-js/number-utils";
391
+ import { callAll, compact } from "@zag-js/utils";
392
+ var { not, and } = guards;
393
+ function machine(userContext) {
394
+ const ctx = compact(userContext);
395
+ return createMachine(
396
+ {
397
+ id: "number-input",
398
+ initial: "idle",
399
+ context: {
400
+ dir: "ltr",
401
+ focusInputOnChange: true,
402
+ clampValueOnBlur: true,
403
+ allowOverflow: false,
404
+ inputMode: "decimal",
405
+ pattern: "[0-9]*(.[0-9]+)?",
406
+ hint: null,
407
+ value: "",
408
+ step: 1,
409
+ min: Number.MIN_SAFE_INTEGER,
410
+ max: Number.MAX_SAFE_INTEGER,
411
+ scrubberCursorPoint: null,
412
+ invalid: false,
413
+ spinOnPress: true,
414
+ ...ctx,
415
+ translations: {
416
+ incrementLabel: "increment value",
417
+ decrementLabel: "decrease value",
418
+ ...ctx.translations
419
+ }
420
+ },
421
+ computed: {
422
+ isRtl: (ctx2) => ctx2.dir === "rtl",
423
+ valueAsNumber: (ctx2) => valueOf(ctx2.value),
424
+ isAtMin: (ctx2) => isAtMin(ctx2.value, ctx2),
425
+ isAtMax: (ctx2) => isAtMax(ctx2.value, ctx2),
426
+ isOutOfRange: (ctx2) => !isWithinRange(ctx2.value, ctx2),
427
+ isValueEmpty: (ctx2) => ctx2.value === "",
428
+ canIncrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMax,
429
+ canDecrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMin,
430
+ valueText: (ctx2) => ctx2.translations.valueText?.(ctx2.value),
431
+ formattedValue: (ctx2) => ctx2.format?.(ctx2.value).toString() ?? ctx2.value
432
+ },
433
+ watch: {
434
+ value: ["invokeOnChange", "dispatchChangeEvent"],
435
+ isOutOfRange: ["invokeOnInvalid"],
436
+ scrubberCursorPoint: ["setVirtualCursorPosition"]
437
+ },
438
+ entry: ["syncInputValue"],
439
+ on: {
440
+ SET_VALUE: [
441
+ {
442
+ guard: "clampOnBlur",
443
+ actions: ["setValue", "clampValue", "setHintToSet"]
444
+ },
445
+ {
446
+ actions: ["setValue", "setHintToSet"]
447
+ }
448
+ ],
449
+ CLEAR_VALUE: {
450
+ actions: ["clearValue"]
451
+ },
452
+ INCREMENT: {
453
+ actions: ["increment"]
454
+ },
455
+ DECREMENT: {
456
+ actions: ["decrement"]
457
+ }
458
+ },
459
+ states: {
460
+ idle: {
461
+ exit: "invokeOnFocus",
462
+ on: {
463
+ PRESS_DOWN: {
464
+ target: "before:spin",
465
+ actions: ["focusInput", "setHint"]
466
+ },
467
+ PRESS_DOWN_SCRUBBER: {
468
+ target: "scrubbing",
469
+ actions: ["focusInput", "setHint", "setCursorPoint"]
470
+ },
471
+ FOCUS: "focused"
472
+ }
473
+ },
474
+ focused: {
475
+ tags: "focus",
476
+ entry: "focusInput",
477
+ activities: "attachWheelListener",
478
+ on: {
479
+ PRESS_DOWN: {
480
+ target: "before:spin",
481
+ actions: ["focusInput", "setHint"]
482
+ },
483
+ PRESS_DOWN_SCRUBBER: {
484
+ target: "scrubbing",
485
+ actions: ["focusInput", "setHint", "setCursorPoint"]
486
+ },
487
+ ARROW_UP: {
488
+ actions: "increment"
489
+ },
490
+ ARROW_DOWN: {
491
+ actions: "decrement"
492
+ },
493
+ HOME: {
494
+ actions: "setToMin"
495
+ },
496
+ END: {
497
+ actions: "setToMax"
498
+ },
499
+ CHANGE: {
500
+ actions: ["setValue", "setHint"]
501
+ },
502
+ BLUR: [
503
+ {
504
+ guard: "isInvalidExponential",
505
+ target: "idle",
506
+ actions: ["clearValue", "clearHint", "invokeOnBlur"]
507
+ },
508
+ {
509
+ guard: and("clampOnBlur", not("isInRange"), not("isEmptyValue")),
510
+ target: "idle",
511
+ actions: ["clampValue", "clearHint", "invokeOnBlur"]
512
+ },
513
+ {
514
+ target: "idle",
515
+ actions: ["roundValue", "invokeOnBlur"]
516
+ }
517
+ ]
518
+ }
519
+ },
520
+ "before:spin": {
521
+ tags: "focus",
522
+ activities: "trackButtonDisabled",
523
+ entry: choose([
524
+ { guard: "isIncrementHint", actions: "increment" },
525
+ { guard: "isDecrementHint", actions: "decrement" }
526
+ ]),
527
+ after: {
528
+ CHANGE_DELAY: {
529
+ target: "spinning",
530
+ guard: and("isInRange", "spinOnPress")
531
+ }
532
+ },
533
+ on: {
534
+ PRESS_UP: {
535
+ target: "focused",
536
+ actions: "clearHint"
537
+ }
538
+ }
539
+ },
540
+ spinning: {
541
+ tags: "focus",
542
+ activities: "trackButtonDisabled",
543
+ every: [
544
+ {
545
+ delay: "CHANGE_INTERVAL",
546
+ guard: and(not("isAtMin"), "isIncrementHint"),
547
+ actions: "increment"
548
+ },
549
+ {
550
+ delay: "CHANGE_INTERVAL",
551
+ guard: and(not("isAtMax"), "isDecrementHint"),
552
+ actions: "decrement"
553
+ }
554
+ ],
555
+ on: {
556
+ PRESS_UP: {
557
+ target: "focused",
558
+ actions: "clearHint"
559
+ }
560
+ }
561
+ },
562
+ scrubbing: {
563
+ tags: "focus",
564
+ exit: "clearCursorPoint",
565
+ activities: ["activatePointerLock", "trackMousemove", "setupVirtualCursor", "preventTextSelection"],
566
+ on: {
567
+ POINTER_UP_SCRUBBER: "focused",
568
+ POINTER_MOVE_SCRUBBER: [
569
+ {
570
+ guard: "isIncrementHint",
571
+ actions: ["increment", "setCursorPoint"]
572
+ },
573
+ {
574
+ guard: "isDecrementHint",
575
+ actions: ["decrement", "setCursorPoint"]
576
+ }
577
+ ]
578
+ }
579
+ }
580
+ }
581
+ },
582
+ {
583
+ delays: {
584
+ CHANGE_INTERVAL: 50,
585
+ CHANGE_DELAY: 300
586
+ },
587
+ guards: {
588
+ clampOnBlur: (ctx2) => !!ctx2.clampValueOnBlur,
589
+ isAtMin: (ctx2) => ctx2.isAtMin,
590
+ spinOnPress: (ctx2) => !!ctx2.spinOnPress,
591
+ isAtMax: (ctx2) => ctx2.isAtMax,
592
+ isInRange: (ctx2) => !ctx2.isOutOfRange,
593
+ isDecrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "decrement",
594
+ isEmptyValue: (ctx2) => ctx2.isValueEmpty,
595
+ isIncrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "increment",
596
+ isInvalidExponential: (ctx2) => ctx2.value.toString().startsWith("e")
597
+ },
598
+ activities: {
599
+ setupVirtualCursor(ctx2) {
600
+ return dom.setupVirtualCursor(ctx2);
601
+ },
602
+ preventTextSelection(ctx2) {
603
+ return dom.preventTextSelection(ctx2);
604
+ },
605
+ trackButtonDisabled(ctx2, _evt, { send }) {
606
+ const btn = dom.getPressedTriggerEl(ctx2, ctx2.hint);
607
+ return observeAttributes(btn, ["disabled"], () => {
608
+ send("PRESS_UP");
609
+ });
610
+ },
611
+ attachWheelListener(ctx2, _evt, { send }) {
612
+ const input = dom.getInputEl(ctx2);
613
+ if (!input)
614
+ return;
615
+ function onWheel(event) {
616
+ const isInputFocused = dom.getDoc(ctx2).activeElement === input;
617
+ if (!ctx2.allowMouseWheel || !isInputFocused)
618
+ return;
619
+ event.preventDefault();
620
+ const dir = Math.sign(event.deltaY) * -1;
621
+ if (dir === 1) {
622
+ send("INCREMENT");
623
+ } else if (dir === -1) {
624
+ send("DECREMENT");
625
+ }
626
+ }
627
+ return addDomEvent(input, "wheel", onWheel, { passive: false });
628
+ },
629
+ activatePointerLock(ctx2) {
630
+ if (isSafari2())
631
+ return;
632
+ return requestPointerLock(dom.getDoc(ctx2));
633
+ },
634
+ trackMousemove(ctx2, _evt, { send }) {
635
+ const doc = dom.getDoc(ctx2);
636
+ function onMousemove(event) {
637
+ if (!ctx2.scrubberCursorPoint)
638
+ return;
639
+ const value = dom.getMousementValue(ctx2, event);
640
+ if (!value.hint)
641
+ return;
642
+ send({
643
+ type: "POINTER_MOVE_SCRUBBER",
644
+ hint: value.hint,
645
+ point: value.point
646
+ });
647
+ }
648
+ function onMouseup() {
649
+ send("POINTER_UP_SCRUBBER");
650
+ }
651
+ return callAll(
652
+ addDomEvent(doc, "mousemove", onMousemove, false),
653
+ addDomEvent(doc, "mouseup", onMouseup, false)
654
+ );
655
+ }
656
+ },
657
+ actions: {
658
+ focusInput(ctx2) {
659
+ if (!ctx2.focusInputOnChange)
660
+ return;
661
+ const input = dom.getInputEl(ctx2);
662
+ raf(() => input?.focus());
663
+ },
664
+ increment(ctx2, evt) {
665
+ ctx2.value = utils.increment(ctx2, evt.step);
666
+ },
667
+ decrement(ctx2, evt) {
668
+ ctx2.value = utils.decrement(ctx2, evt.step);
669
+ },
670
+ clampValue(ctx2) {
671
+ ctx2.value = utils.clamp(ctx2);
672
+ },
673
+ roundValue(ctx2) {
674
+ if (ctx2.value !== "") {
675
+ ctx2.value = utils.round(ctx2);
676
+ }
677
+ },
678
+ setValue(ctx2, evt) {
679
+ const value = evt.target?.value ?? evt.value;
680
+ ctx2.value = utils.sanitize(ctx2, utils.parse(ctx2, value.toString()));
681
+ },
682
+ clearValue(ctx2) {
683
+ ctx2.value = "";
684
+ },
685
+ setToMax(ctx2) {
686
+ ctx2.value = ctx2.max.toString();
687
+ },
688
+ setToMin(ctx2) {
689
+ ctx2.value = ctx2.min.toString();
690
+ },
691
+ setHint(ctx2, evt) {
692
+ ctx2.hint = evt.hint;
693
+ },
694
+ clearHint(ctx2) {
695
+ ctx2.hint = null;
696
+ },
697
+ setHintToSet(ctx2) {
698
+ ctx2.hint = "set";
699
+ },
700
+ invokeOnChange(ctx2) {
701
+ ctx2.onChange?.({
702
+ value: ctx2.value,
703
+ valueAsNumber: ctx2.valueAsNumber
704
+ });
705
+ },
706
+ invokeOnFocus(ctx2, evt) {
707
+ let srcElement = null;
708
+ if (evt.type === "PRESS_DOWN") {
709
+ srcElement = dom.getPressedTriggerEl(ctx2, evt.hint);
710
+ } else if (evt.type === "FOCUS") {
711
+ srcElement = dom.getInputEl(ctx2);
712
+ } else if (evt.type === "PRESS_DOWN_SCRUBBER") {
713
+ srcElement = dom.getScrubberEl(ctx2);
714
+ }
715
+ ctx2.onFocus?.({
716
+ value: ctx2.value,
717
+ valueAsNumber: ctx2.valueAsNumber,
718
+ srcElement
719
+ });
720
+ },
721
+ invokeOnBlur(ctx2) {
722
+ ctx2.onBlur?.({
723
+ value: ctx2.value,
724
+ valueAsNumber: ctx2.valueAsNumber
725
+ });
726
+ },
727
+ invokeOnInvalid(ctx2) {
728
+ if (!ctx2.isOutOfRange)
729
+ return;
730
+ const reason = ctx2.valueAsNumber > ctx2.max ? "rangeOverflow" : "rangeUnderflow";
731
+ ctx2.onInvalid?.({
732
+ reason,
733
+ value: ctx2.formattedValue,
734
+ valueAsNumber: ctx2.valueAsNumber
735
+ });
736
+ },
737
+ // sync input value, in event it was set from form libraries via `ref`, `bind:this`, etc.
738
+ syncInputValue(ctx2) {
739
+ const input = dom.getInputEl(ctx2);
740
+ if (!input || input.value == ctx2.value)
741
+ return;
742
+ const value = utils.parse(ctx2, input.value);
743
+ ctx2.value = utils.sanitize(ctx2, value);
744
+ },
745
+ setCursorPoint(ctx2, evt) {
746
+ ctx2.scrubberCursorPoint = evt.point;
747
+ },
748
+ clearCursorPoint(ctx2) {
749
+ ctx2.scrubberCursorPoint = null;
750
+ },
751
+ setVirtualCursorPosition(ctx2) {
752
+ const cursor = dom.getCursorEl(ctx2);
753
+ if (!cursor || !ctx2.scrubberCursorPoint)
754
+ return;
755
+ const { x, y } = ctx2.scrubberCursorPoint;
756
+ cursor.style.transform = `translate3d(${x}px, ${y}px, 0px)`;
757
+ },
758
+ dispatchChangeEvent(ctx2) {
759
+ const inputEl = dom.getInputEl(ctx2);
760
+ dispatchInputValueEvent(inputEl, { value: ctx2.formattedValue });
761
+ }
762
+ }
763
+ }
764
+ );
765
+ }
766
+ export {
767
+ anatomy,
768
+ connect,
769
+ machine
770
+ };
771
+ //# sourceMappingURL=index.mjs.map