@zag-js/number-input 0.10.2 → 0.10.4

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.
@@ -1,243 +0,0 @@
1
- import {
2
- parts
3
- } from "./chunk-XHRILSH3.mjs";
4
- import {
5
- dom
6
- } from "./chunk-QYY4CWRS.mjs";
7
- import {
8
- utils
9
- } from "./chunk-AXXDGYUW.mjs";
10
-
11
- // src/number-input.connect.ts
12
- import { getEventPoint, getEventStep, getNativeEvent, isLeftClick } from "@zag-js/dom-event";
13
- import { ariaAttr, dataAttr } from "@zag-js/dom-query";
14
- import { roundToDevicePixel } from "@zag-js/number-utils";
15
- function connect(state, send, normalize) {
16
- const isFocused = state.hasTag("focus");
17
- const isInvalid = state.context.isOutOfRange || !!state.context.invalid;
18
- const isDisabled = !!state.context.disabled;
19
- const isValueEmpty = state.context.isValueEmpty;
20
- const isIncrementDisabled = isDisabled || !state.context.canIncrement;
21
- const isDecrementDisabled = isDisabled || !state.context.canDecrement;
22
- const translations = state.context.translations;
23
- return {
24
- /**
25
- * Whether the input is focused.
26
- */
27
- isFocused,
28
- /**
29
- * Whether the input is invalid.
30
- */
31
- isInvalid,
32
- /**
33
- * Whether the input value is empty.
34
- */
35
- isValueEmpty,
36
- /**
37
- * The formatted value of the input.
38
- */
39
- value: state.context.formattedValue,
40
- /**
41
- * The value of the input as a number.
42
- */
43
- valueAsNumber: state.context.valueAsNumber,
44
- /**
45
- * Function to set the value of the input.
46
- */
47
- setValue(value) {
48
- send({ type: "SET_VALUE", value: value.toString() });
49
- },
50
- /**
51
- * Function to clear the value of the input.
52
- */
53
- clearValue() {
54
- send("CLEAR_VALUE");
55
- },
56
- /**
57
- * Function to increment the value of the input by the step.
58
- */
59
- increment() {
60
- send("INCREMENT");
61
- },
62
- /**
63
- * Function to decrement the value of the input by the step.
64
- */
65
- decrement() {
66
- send("DECREMENT");
67
- },
68
- /**
69
- * Function to set the value of the input to the max.
70
- */
71
- setToMax() {
72
- send({ type: "SET_VALUE", value: state.context.max });
73
- },
74
- /**
75
- * Function to set the value of the input to the min.
76
- */
77
- setToMin() {
78
- send({ type: "SET_VALUE", value: state.context.min });
79
- },
80
- /**
81
- * Function to focus the input.
82
- */
83
- focus() {
84
- dom.getInputEl(state.context)?.focus();
85
- },
86
- /**
87
- * Function to blur the input.
88
- */
89
- blur() {
90
- dom.getInputEl(state.context)?.blur();
91
- },
92
- rootProps: normalize.element({
93
- id: dom.getRootId(state.context),
94
- ...parts.root.attrs,
95
- "data-disabled": dataAttr(isDisabled)
96
- }),
97
- labelProps: normalize.label({
98
- ...parts.label.attrs,
99
- "data-disabled": dataAttr(isDisabled),
100
- "data-invalid": dataAttr(isInvalid),
101
- id: dom.getLabelId(state.context),
102
- htmlFor: dom.getInputId(state.context)
103
- }),
104
- controlProps: normalize.element({
105
- ...parts.control.attrs,
106
- role: "group",
107
- "aria-disabled": isDisabled,
108
- "data-disabled": dataAttr(isDisabled),
109
- "data-invalid": dataAttr(isInvalid),
110
- "aria-invalid": ariaAttr(state.context.invalid)
111
- }),
112
- inputProps: normalize.input({
113
- ...parts.input.attrs,
114
- name: state.context.name,
115
- form: state.context.form,
116
- id: dom.getInputId(state.context),
117
- role: "spinbutton",
118
- defaultValue: state.context.formattedValue,
119
- pattern: state.context.pattern,
120
- inputMode: state.context.inputMode,
121
- "aria-invalid": ariaAttr(isInvalid),
122
- "data-invalid": dataAttr(isInvalid),
123
- disabled: isDisabled,
124
- "data-disabled": dataAttr(isDisabled),
125
- readOnly: !!state.context.readOnly,
126
- autoComplete: "off",
127
- autoCorrect: "off",
128
- spellCheck: "false",
129
- type: "text",
130
- "aria-roledescription": "numberfield",
131
- "aria-valuemin": state.context.min,
132
- "aria-valuemax": state.context.max,
133
- "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
134
- "aria-valuetext": state.context.valueText,
135
- onFocus() {
136
- send("FOCUS");
137
- },
138
- onBlur() {
139
- send("BLUR");
140
- },
141
- onChange(event) {
142
- send({ type: "CHANGE", target: event.currentTarget, hint: "set" });
143
- },
144
- onKeyDown(event) {
145
- const evt = getNativeEvent(event);
146
- if (evt.isComposing)
147
- return;
148
- if (!utils.isValidNumericEvent(state.context, event)) {
149
- event.preventDefault();
150
- }
151
- const step = getEventStep(event) * state.context.step;
152
- const keyMap = {
153
- ArrowUp() {
154
- send({ type: "ARROW_UP", step });
155
- },
156
- ArrowDown() {
157
- send({ type: "ARROW_DOWN", step });
158
- },
159
- Home() {
160
- send("HOME");
161
- },
162
- End() {
163
- send("END");
164
- }
165
- };
166
- const exec = keyMap[event.key];
167
- if (exec) {
168
- exec(event);
169
- event.preventDefault();
170
- }
171
- }
172
- }),
173
- decrementTriggerProps: normalize.button({
174
- ...parts.decrementTrigger.attrs,
175
- id: dom.getDecrementTriggerId(state.context),
176
- disabled: isDecrementDisabled,
177
- "data-disabled": dataAttr(isDecrementDisabled),
178
- "aria-label": translations.decrementLabel,
179
- type: "button",
180
- tabIndex: -1,
181
- "aria-controls": dom.getInputId(state.context),
182
- onPointerDown(event) {
183
- if (isDecrementDisabled)
184
- return;
185
- send(isLeftClick(event) ? { type: "PRESS_DOWN", hint: "decrement" } : { type: "FOCUS" });
186
- event.preventDefault();
187
- },
188
- onPointerUp() {
189
- send({ type: "PRESS_UP", hint: "decrement" });
190
- },
191
- onPointerLeave() {
192
- if (isDecrementDisabled)
193
- return;
194
- send({ type: "PRESS_UP", hint: "decrement" });
195
- }
196
- }),
197
- incrementTriggerProps: normalize.button({
198
- ...parts.incrementTrigger.attrs,
199
- id: dom.getIncrementTriggerId(state.context),
200
- disabled: isIncrementDisabled,
201
- "data-disabled": dataAttr(isIncrementDisabled),
202
- "aria-label": translations.incrementLabel,
203
- type: "button",
204
- tabIndex: -1,
205
- "aria-controls": dom.getInputId(state.context),
206
- onPointerDown(event) {
207
- if (isIncrementDisabled)
208
- return;
209
- send(isLeftClick(event) ? { type: "PRESS_DOWN", hint: "increment" } : { type: "FOCUS" });
210
- event.preventDefault();
211
- },
212
- onPointerUp() {
213
- send({ type: "PRESS_UP", hint: "increment" });
214
- },
215
- onPointerLeave() {
216
- send({ type: "PRESS_UP", hint: "increment" });
217
- }
218
- }),
219
- scrubberProps: normalize.element({
220
- ...parts.scrubber.attrs,
221
- "data-disabled": dataAttr(isDisabled),
222
- id: dom.getScrubberId(state.context),
223
- role: "presentation",
224
- onMouseDown(event) {
225
- if (isDisabled)
226
- return;
227
- const evt = getNativeEvent(event);
228
- const point = getEventPoint(evt);
229
- point.x = point.x - roundToDevicePixel(7.5);
230
- point.y = point.y - roundToDevicePixel(7.5);
231
- send({ type: "PRESS_DOWN_SCRUBBER", point });
232
- event.preventDefault();
233
- },
234
- style: {
235
- cursor: isDisabled ? void 0 : "ew-resize"
236
- }
237
- })
238
- };
239
- }
240
-
241
- export {
242
- connect
243
- };
@@ -1,43 +0,0 @@
1
- // src/number-input.utils.ts
2
- import { isModifiedEvent } from "@zag-js/dom-event";
3
- import { clamp, decrement, formatDecimal, increment } from "@zag-js/number-utils";
4
- var utils = {
5
- isValidNumericEvent: (ctx, event) => {
6
- if (event.key == null)
7
- return true;
8
- const isModifier = isModifiedEvent(event);
9
- const isSingleKey = event.key.length === 1;
10
- if (isModifier || !isSingleKey)
11
- return true;
12
- return ctx.validateCharacter?.(event.key) ?? utils.isFloatingPoint(event.key);
13
- },
14
- isFloatingPoint: (v) => /^[0-9+\-.]$/.test(v),
15
- sanitize: (ctx, value) => {
16
- return value.split("").filter(ctx.validateCharacter ?? utils.isFloatingPoint).join("");
17
- },
18
- increment: (ctx, step) => {
19
- const value = increment(ctx.value, step ?? ctx.step);
20
- return formatDecimal(clamp(value, ctx), ctx);
21
- },
22
- decrement: (ctx, step) => {
23
- const value = decrement(ctx.value, step ?? ctx.step);
24
- return formatDecimal(clamp(value, ctx), ctx);
25
- },
26
- clamp: (ctx) => {
27
- return formatDecimal(clamp(ctx.value, ctx), ctx);
28
- },
29
- parse: (ctx, value) => {
30
- return ctx.parse?.(value) ?? value;
31
- },
32
- format: (ctx, value) => {
33
- const _val = value.toString();
34
- return ctx.format?.(_val) ?? _val;
35
- },
36
- round: (ctx) => {
37
- return formatDecimal(ctx.value, ctx);
38
- }
39
- };
40
-
41
- export {
42
- utils
43
- };
@@ -1,101 +0,0 @@
1
- // src/number-input.dom.ts
2
- import { createScope, isSafari, MAX_Z_INDEX } from "@zag-js/dom-query";
3
- import { roundToDevicePixel, wrap } from "@zag-js/number-utils";
4
- var dom = createScope({
5
- getRootId: (ctx) => ctx.ids?.root ?? `number-input:${ctx.id}`,
6
- getInputId: (ctx) => ctx.ids?.input ?? `number-input:${ctx.id}:input`,
7
- getIncrementTriggerId: (ctx) => ctx.ids?.incrementTrigger ?? `number-input:${ctx.id}:inc`,
8
- getDecrementTriggerId: (ctx) => ctx.ids?.decrementTrigger ?? `number-input:${ctx.id}:dec`,
9
- getScrubberId: (ctx) => ctx.ids?.scrubber ?? `number-input:${ctx.id}:scrubber`,
10
- getCursorId: (ctx) => `number-input:${ctx.id}:cursor`,
11
- getLabelId: (ctx) => ctx.ids?.label ?? `number-input:${ctx.id}:label`,
12
- getInputEl: (ctx) => dom.getById(ctx, dom.getInputId(ctx)),
13
- getIncrementTriggerEl: (ctx) => dom.getById(ctx, dom.getIncrementTriggerId(ctx)),
14
- getDecrementTriggerEl: (ctx) => dom.getById(ctx, dom.getDecrementTriggerId(ctx)),
15
- getScrubberEl: (ctx) => dom.getById(ctx, dom.getScrubberId(ctx)),
16
- getCursorEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
17
- getPressedTriggerEl: (ctx, hint = ctx.hint) => {
18
- let btnEl = null;
19
- if (hint === "increment") {
20
- btnEl = dom.getIncrementTriggerEl(ctx);
21
- }
22
- if (hint === "decrement") {
23
- btnEl = dom.getDecrementTriggerEl(ctx);
24
- }
25
- return btnEl;
26
- },
27
- setupVirtualCursor(ctx) {
28
- if (isSafari())
29
- return;
30
- dom.createVirtualCursor(ctx);
31
- return () => {
32
- dom.getCursorEl(ctx)?.remove();
33
- };
34
- },
35
- preventTextSelection(ctx) {
36
- const doc = dom.getDoc(ctx);
37
- const html = doc.documentElement;
38
- const body = doc.body;
39
- body.style.pointerEvents = "none";
40
- html.style.userSelect = "none";
41
- html.style.cursor = "ew-resize";
42
- return () => {
43
- body.style.pointerEvents = "";
44
- html.style.userSelect = "";
45
- html.style.cursor = "";
46
- if (!html.style.length) {
47
- html.removeAttribute("style");
48
- }
49
- if (!body.style.length) {
50
- body.removeAttribute("style");
51
- }
52
- };
53
- },
54
- getMousementValue(ctx, event) {
55
- const x = roundToDevicePixel(event.movementX);
56
- const y = roundToDevicePixel(event.movementY);
57
- let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null;
58
- if (ctx.isRtl && hint === "increment")
59
- hint = "decrement";
60
- if (ctx.isRtl && hint === "decrement")
61
- hint = "increment";
62
- const point = {
63
- x: ctx.scrubberCursorPoint.x + x,
64
- y: ctx.scrubberCursorPoint.y + y
65
- };
66
- const win = dom.getWin(ctx);
67
- const width = win.innerWidth;
68
- const half = roundToDevicePixel(7.5);
69
- point.x = wrap(point.x + half, width) - half;
70
- return { hint, point };
71
- },
72
- createVirtualCursor(ctx) {
73
- const doc = dom.getDoc(ctx);
74
- const el = doc.createElement("div");
75
- el.className = "scrubber--cursor";
76
- el.id = dom.getCursorId(ctx);
77
- Object.assign(el.style, {
78
- width: "15px",
79
- height: "15px",
80
- position: "fixed",
81
- pointerEvents: "none",
82
- left: "0px",
83
- top: "0px",
84
- zIndex: MAX_Z_INDEX,
85
- transform: ctx.scrubberCursorPoint ? `translate3d(${ctx.scrubberCursorPoint.x}px, ${ctx.scrubberCursorPoint.y}px, 0px)` : void 0,
86
- willChange: "transform"
87
- });
88
- el.innerHTML = `
89
- <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);">
90
- <g transform="translate(2 3)">
91
- <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>
92
- <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>
93
- </g>
94
- </svg>`;
95
- doc.body.appendChild(el);
96
- }
97
- });
98
-
99
- export {
100
- dom
101
- };