@react-aria/spinbutton 3.7.0 → 3.7.1
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/types.d.ts.map +1 -1
- package/dist/useSpinButton.main.js +39 -30
- package/dist/useSpinButton.main.js.map +1 -1
- package/dist/useSpinButton.mjs +39 -30
- package/dist/useSpinButton.module.js +39 -30
- package/dist/useSpinButton.module.js.map +1 -1
- package/package.json +6 -6
- package/src/useSpinButton.ts +43 -52
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;
|
|
1
|
+
{"mappings":";;AAwBA,gCAAiC,SAAQ,SAAS,EAAE,WAAW,MAAM,CAAC,EAAE,UAAU,MAAM,CAAC,EAAE,eAAe,MAAM,CAAC;IAC/G,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;CAC9B;AAED;IACE,eAAe,EAAE,aAAa,CAAC;IAC/B,oBAAoB,EAAE,eAAe,CAAC;IACtC,oBAAoB,EAAE,eAAe,CAAA;CACtC;AAED,8BACE,KAAK,EAAE,eAAe,GACrB,cAAc,CA+PhB","sources":["packages/@react-aria/spinbutton/src/packages/@react-aria/spinbutton/src/useSpinButton.ts","packages/@react-aria/spinbutton/src/packages/@react-aria/spinbutton/src/index.ts","packages/@react-aria/spinbutton/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport type {SpinButtonProps, SpinbuttonAria} from './useSpinButton';\nexport {useSpinButton} from './useSpinButton';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
|
@@ -29,6 +29,7 @@ $parcel$export(module.exports, "useSpinButton", () => $37bbd4c129023f61$export$e
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
const $37bbd4c129023f61$var$noop = ()=>{};
|
|
32
33
|
function $37bbd4c129023f61$export$e908e06f4b8e3402(props) {
|
|
33
34
|
const _async = (0, $2pZbw$react.useRef)(undefined);
|
|
34
35
|
let { value: value, textValue: textValue, minValue: minValue, maxValue: maxValue, isDisabled: isDisabled, isReadOnly: isReadOnly, isRequired: isRequired, onIncrement: onIncrement, onIncrementPage: onIncrementPage, onDecrement: onDecrement, onDecrementPage: onDecrementPage, onDecrementToMin: onDecrementToMin, onIncrementToMax: onIncrementToMax } = props;
|
|
@@ -115,23 +116,31 @@ function $37bbd4c129023f61$export$e908e06f4b8e3402(props) {
|
|
|
115
116
|
}, [
|
|
116
117
|
clearAsync
|
|
117
118
|
]);
|
|
118
|
-
const
|
|
119
|
+
const onIncrementEvent = (0, $2pZbw$reactariautils.useEffectEvent)(onIncrement !== null && onIncrement !== void 0 ? onIncrement : $37bbd4c129023f61$var$noop);
|
|
120
|
+
const onDecrementEvent = (0, $2pZbw$reactariautils.useEffectEvent)(onDecrement !== null && onDecrement !== void 0 ? onDecrement : $37bbd4c129023f61$var$noop);
|
|
121
|
+
const stepUpEvent = (0, $2pZbw$reactariautils.useEffectEvent)(()=>{
|
|
122
|
+
if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {
|
|
123
|
+
onIncrementEvent();
|
|
124
|
+
onIncrementPressStartEvent(60);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
const onIncrementPressStartEvent = (0, $2pZbw$reactariautils.useEffectEvent)((initialStepDelay)=>{
|
|
119
128
|
clearAsyncEvent();
|
|
120
129
|
isSpinning.current = true;
|
|
121
|
-
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
122
130
|
// Start spinning after initial delay
|
|
123
|
-
_async.current = window.setTimeout(
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
_async.current = window.setTimeout(stepUpEvent, initialStepDelay);
|
|
132
|
+
});
|
|
133
|
+
const stepDownEvent = (0, $2pZbw$reactariautils.useEffectEvent)(()=>{
|
|
134
|
+
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {
|
|
135
|
+
onDecrementEvent();
|
|
136
|
+
onDecrementPressStartEvent(60);
|
|
137
|
+
}
|
|
126
138
|
});
|
|
127
|
-
const
|
|
139
|
+
const onDecrementPressStartEvent = (0, $2pZbw$reactariautils.useEffectEvent)((initialStepDelay)=>{
|
|
128
140
|
clearAsyncEvent();
|
|
129
141
|
isSpinning.current = true;
|
|
130
|
-
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
131
142
|
// Start spinning after initial delay
|
|
132
|
-
_async.current = window.setTimeout(
|
|
133
|
-
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) onDecrementPressStart(60);
|
|
134
|
-
}, initialStepDelay);
|
|
143
|
+
_async.current = window.setTimeout(stepDownEvent, initialStepDelay);
|
|
135
144
|
});
|
|
136
145
|
let cancelContextMenu = (e)=>{
|
|
137
146
|
e.preventDefault();
|
|
@@ -144,15 +153,15 @@ function $37bbd4c129023f61$export$e908e06f4b8e3402(props) {
|
|
|
144
153
|
let isUp = (0, $2pZbw$react.useRef)(false);
|
|
145
154
|
let [isIncrementPressed, setIsIncrementPressed] = (0, $2pZbw$react.useState)(null);
|
|
146
155
|
(0, $2pZbw$react.useEffect)(()=>{
|
|
147
|
-
if (isIncrementPressed === 'touch')
|
|
148
|
-
else if (isIncrementPressed)
|
|
156
|
+
if (isIncrementPressed === 'touch') onIncrementPressStartEvent(600);
|
|
157
|
+
else if (isIncrementPressed) onIncrementPressStartEvent(400);
|
|
149
158
|
}, [
|
|
150
159
|
isIncrementPressed
|
|
151
160
|
]);
|
|
152
161
|
let [isDecrementPressed, setIsDecrementPressed] = (0, $2pZbw$react.useState)(null);
|
|
153
162
|
(0, $2pZbw$react.useEffect)(()=>{
|
|
154
|
-
if (isDecrementPressed === 'touch')
|
|
155
|
-
else if (isDecrementPressed)
|
|
163
|
+
if (isDecrementPressed === 'touch') onDecrementPressStartEvent(600);
|
|
164
|
+
else if (isDecrementPressed) onDecrementPressStartEvent(400);
|
|
156
165
|
}, [
|
|
157
166
|
isDecrementPressed
|
|
158
167
|
]);
|
|
@@ -172,32 +181,32 @@ function $37bbd4c129023f61$export$e908e06f4b8e3402(props) {
|
|
|
172
181
|
},
|
|
173
182
|
incrementButtonProps: {
|
|
174
183
|
onPressStart: (e)=>{
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
clearAsync();
|
|
185
|
+
if (e.pointerType !== 'touch') {
|
|
186
|
+
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
187
|
+
setIsIncrementPressed('mouse');
|
|
188
|
+
} else {
|
|
178
189
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
179
190
|
capture: true
|
|
180
191
|
});
|
|
181
192
|
isUp.current = false;
|
|
182
193
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
183
194
|
// the control isn't spinning.
|
|
184
|
-
|
|
185
|
-
setIsIncrementPressed('touch');
|
|
186
|
-
}, 600);
|
|
195
|
+
setIsIncrementPressed('touch');
|
|
187
196
|
}
|
|
188
197
|
addGlobalListener(window, 'contextmenu', cancelContextMenu);
|
|
189
198
|
},
|
|
190
199
|
onPressUp: (e)=>{
|
|
191
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
192
200
|
clearAsync();
|
|
201
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
193
202
|
removeAllGlobalListeners();
|
|
194
203
|
setIsIncrementPressed(null);
|
|
195
204
|
},
|
|
196
205
|
onPressEnd: (e)=>{
|
|
206
|
+
clearAsync();
|
|
197
207
|
if (e.pointerType === 'touch') {
|
|
198
208
|
if (!isSpinning.current && isUp.current) onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
199
209
|
}
|
|
200
|
-
clearAsync();
|
|
201
210
|
isUp.current = false;
|
|
202
211
|
setIsIncrementPressed(null);
|
|
203
212
|
},
|
|
@@ -206,31 +215,31 @@ function $37bbd4c129023f61$export$e908e06f4b8e3402(props) {
|
|
|
206
215
|
},
|
|
207
216
|
decrementButtonProps: {
|
|
208
217
|
onPressStart: (e)=>{
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
218
|
+
clearAsync();
|
|
219
|
+
if (e.pointerType !== 'touch') {
|
|
220
|
+
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
221
|
+
setIsDecrementPressed('mouse');
|
|
222
|
+
} else {
|
|
212
223
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
213
224
|
capture: true
|
|
214
225
|
});
|
|
215
226
|
isUp.current = false;
|
|
216
227
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
217
228
|
// the control isn't spinning.
|
|
218
|
-
|
|
219
|
-
setIsDecrementPressed('touch');
|
|
220
|
-
}, 600);
|
|
229
|
+
setIsDecrementPressed('touch');
|
|
221
230
|
}
|
|
222
231
|
},
|
|
223
232
|
onPressUp: (e)=>{
|
|
224
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
225
233
|
clearAsync();
|
|
234
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
226
235
|
removeAllGlobalListeners();
|
|
227
236
|
setIsDecrementPressed(null);
|
|
228
237
|
},
|
|
229
238
|
onPressEnd: (e)=>{
|
|
239
|
+
clearAsync();
|
|
230
240
|
if (e.pointerType === 'touch') {
|
|
231
241
|
if (!isSpinning.current && isUp.current) onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
232
242
|
}
|
|
233
|
-
clearAsync();
|
|
234
243
|
isUp.current = false;
|
|
235
244
|
setIsDecrementPressed(null);
|
|
236
245
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@react-aria/spinbutton/src/useSpinButton.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {announce, clearAnnouncer} from '@react-aria/live-announcer';\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMAttributes, InputBase, RangeInputBase, Validation, ValueBase} from '@react-types/shared';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useEffectEvent, useGlobalListeners} from '@react-aria/utils';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\n\nexport interface SpinButtonProps extends InputBase, Validation<number>, ValueBase<number>, RangeInputBase<number> {\n textValue?: string,\n onIncrement?: () => void,\n onIncrementPage?: () => void,\n onDecrement?: () => void,\n onDecrementPage?: () => void,\n onDecrementToMin?: () => void,\n onIncrementToMax?: () => void\n}\n\nexport interface SpinbuttonAria {\n spinButtonProps: DOMAttributes,\n incrementButtonProps: AriaButtonProps,\n decrementButtonProps: AriaButtonProps\n}\n\nexport function useSpinButton(\n props: SpinButtonProps\n): SpinbuttonAria {\n const _async = useRef<number>(undefined);\n let {\n value,\n textValue,\n minValue,\n maxValue,\n isDisabled,\n isReadOnly,\n isRequired,\n onIncrement,\n onIncrementPage,\n onDecrement,\n onDecrementPage,\n onDecrementToMin,\n onIncrementToMax\n } = props;\n const stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/spinbutton');\n\n let isSpinning = useRef(false);\n const clearAsync = useCallback(() => {\n clearTimeout(_async.current);\n isSpinning.current = false;\n }, []);\n const clearAsyncEvent = useEffectEvent(() => {\n clearAsync();\n });\n\n useEffect(() => {\n return () => clearAsyncEvent();\n }, []);\n\n let onKeyDown = (e) => {\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || isReadOnly || e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'PageUp':\n if (onIncrementPage) {\n e.preventDefault();\n onIncrementPage?.();\n break;\n }\n // fallthrough!\n case 'ArrowUp':\n case 'Up':\n if (onIncrement) {\n e.preventDefault();\n onIncrement?.();\n }\n break;\n case 'PageDown':\n if (onDecrementPage) {\n e.preventDefault();\n onDecrementPage?.();\n break;\n }\n // fallthrough\n case 'ArrowDown':\n case 'Down':\n if (onDecrement) {\n e.preventDefault();\n onDecrement?.();\n }\n break;\n case 'Home':\n if (onDecrementToMin) {\n e.preventDefault();\n onDecrementToMin?.();\n }\n break;\n case 'End':\n if (onIncrementToMax) {\n e.preventDefault();\n onIncrementToMax?.();\n }\n break;\n }\n };\n\n let isFocused = useRef(false);\n let onFocus = () => {\n isFocused.current = true;\n };\n\n let onBlur = () => {\n isFocused.current = false;\n };\n\n // Replace Unicode hyphen-minus (U+002D) with minus sign (U+2212).\n // This ensures that macOS VoiceOver announces it as \"minus\" even with other characters between the minus sign\n // and the number (e.g. currency symbol). Otherwise it announces nothing because it assumes the character is a hyphen.\n // In addition, replace the empty string with the word \"Empty\" so that iOS VoiceOver does not read \"50%\" for an empty field.\n let ariaTextValue = textValue === '' ? stringFormatter.format('Empty') : (textValue || `${value}`).replace('-', '\\u2212');\n\n useEffect(() => {\n if (isFocused.current) {\n clearAnnouncer('assertive');\n announce(ariaTextValue, 'assertive');\n }\n }, [ariaTextValue]);\n\n // For touch users, if they move their finger like they're scrolling, we don't want to trigger a spin.\n let onPointerCancel = useCallback(() => {\n clearAsync();\n }, [clearAsync]);\n\n const onIncrementPressStart = useEffectEvent(\n (initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n onIncrement?.();\n // Start spinning after initial delay\n _async.current = window.setTimeout(\n () => {\n if ((maxValue === undefined || isNaN(maxValue)) || (value === undefined || isNaN(value)) || value < maxValue) {\n onIncrementPressStart(60);\n }\n },\n initialStepDelay\n );\n }\n );\n\n const onDecrementPressStart = useEffectEvent(\n (initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n onDecrement?.();\n // Start spinning after initial delay\n _async.current = window.setTimeout(\n () => {\n if ((minValue === undefined || isNaN(minValue)) || (value === undefined || isNaN(value)) || value > minValue) {\n onDecrementPressStart(60);\n }\n },\n initialStepDelay\n );\n }\n );\n\n let cancelContextMenu = (e) => {\n e.preventDefault();\n };\n\n let {addGlobalListener, removeAllGlobalListeners} = useGlobalListeners();\n\n // Tracks in touch if the press end event was preceded by a press up.\n // If it wasn't, then we know the finger left the button while still in contact with the screen.\n // This means that the user is trying to scroll or interact in some way that shouldn't trigger\n // an increment or decrement.\n let isUp = useRef(false);\n\n let [isIncrementPressed, setIsIncrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isIncrementPressed === 'touch') {\n onIncrementPressStart(60);\n } else if (isIncrementPressed) {\n onIncrementPressStart(400);\n }\n }, [isIncrementPressed]);\n\n let [isDecrementPressed, setIsDecrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isDecrementPressed === 'touch') {\n onDecrementPressStart(60);\n } else if (isDecrementPressed) {\n onDecrementPressStart(400);\n }\n }, [isDecrementPressed]);\n\n return {\n spinButtonProps: {\n role: 'spinbutton',\n 'aria-valuenow': value !== undefined && !isNaN(value) ? value : undefined,\n 'aria-valuetext': ariaTextValue,\n 'aria-valuemin': minValue,\n 'aria-valuemax': maxValue,\n 'aria-disabled': isDisabled || undefined,\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n onKeyDown,\n onFocus,\n onBlur\n },\n incrementButtonProps: {\n onPressStart: (e) => {\n if (e.pointerType !== 'touch') {\n setIsIncrementPressed('mouse');\n } else {\n if (_async.current) {\n clearAsync();\n }\n\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n _async.current = window.setTimeout(() => {\n setIsIncrementPressed('touch');\n }, 600);\n }\n addGlobalListener(window, 'contextmenu', cancelContextMenu);\n },\n onPressUp: (e) => {\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n clearAsync();\n removeAllGlobalListeners();\n setIsIncrementPressed(null);\n },\n onPressEnd: (e) => {\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onIncrement?.();\n }\n }\n clearAsync();\n isUp.current = false;\n setIsIncrementPressed(null);\n },\n onFocus,\n onBlur\n },\n decrementButtonProps: {\n onPressStart: (e) => {\n if (e.pointerType !== 'touch') {\n setIsDecrementPressed('mouse');\n } else {\n if (_async.current) {\n clearAsync();\n }\n\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n _async.current = window.setTimeout(() => {\n setIsDecrementPressed('touch');\n }, 600);\n }\n },\n onPressUp: (e) => {\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n clearAsync();\n removeAllGlobalListeners();\n setIsDecrementPressed(null);\n },\n onPressEnd: (e) => {\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onDecrement?.();\n }\n }\n clearAsync();\n isUp.current = false;\n setIsDecrementPressed(null);\n },\n onFocus,\n onBlur\n }\n };\n}\n"],"names":[],"version":3,"file":"useSpinButton.main.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/spinbutton/src/useSpinButton.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {announce, clearAnnouncer} from '@react-aria/live-announcer';\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMAttributes, InputBase, RangeInputBase, Validation, ValueBase} from '@react-types/shared';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useEffectEvent, useGlobalListeners} from '@react-aria/utils';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\n\nconst noop = () => {};\n\nexport interface SpinButtonProps extends InputBase, Validation<number>, ValueBase<number>, RangeInputBase<number> {\n textValue?: string,\n onIncrement?: () => void,\n onIncrementPage?: () => void,\n onDecrement?: () => void,\n onDecrementPage?: () => void,\n onDecrementToMin?: () => void,\n onIncrementToMax?: () => void\n}\n\nexport interface SpinbuttonAria {\n spinButtonProps: DOMAttributes,\n incrementButtonProps: AriaButtonProps,\n decrementButtonProps: AriaButtonProps\n}\n\nexport function useSpinButton(\n props: SpinButtonProps\n): SpinbuttonAria {\n const _async = useRef<number>(undefined);\n let {\n value,\n textValue,\n minValue,\n maxValue,\n isDisabled,\n isReadOnly,\n isRequired,\n onIncrement,\n onIncrementPage,\n onDecrement,\n onDecrementPage,\n onDecrementToMin,\n onIncrementToMax\n } = props;\n const stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/spinbutton');\n\n let isSpinning = useRef(false);\n const clearAsync = useCallback(() => {\n clearTimeout(_async.current);\n isSpinning.current = false;\n }, []);\n const clearAsyncEvent = useEffectEvent(() => {\n clearAsync();\n });\n\n useEffect(() => {\n return () => clearAsyncEvent();\n }, []);\n\n let onKeyDown = (e) => {\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || isReadOnly || e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'PageUp':\n if (onIncrementPage) {\n e.preventDefault();\n onIncrementPage?.();\n break;\n }\n // fallthrough!\n case 'ArrowUp':\n case 'Up':\n if (onIncrement) {\n e.preventDefault();\n onIncrement?.();\n }\n break;\n case 'PageDown':\n if (onDecrementPage) {\n e.preventDefault();\n onDecrementPage?.();\n break;\n }\n // fallthrough\n case 'ArrowDown':\n case 'Down':\n if (onDecrement) {\n e.preventDefault();\n onDecrement?.();\n }\n break;\n case 'Home':\n if (onDecrementToMin) {\n e.preventDefault();\n onDecrementToMin?.();\n }\n break;\n case 'End':\n if (onIncrementToMax) {\n e.preventDefault();\n onIncrementToMax?.();\n }\n break;\n }\n };\n\n let isFocused = useRef(false);\n let onFocus = () => {\n isFocused.current = true;\n };\n\n let onBlur = () => {\n isFocused.current = false;\n };\n\n // Replace Unicode hyphen-minus (U+002D) with minus sign (U+2212).\n // This ensures that macOS VoiceOver announces it as \"minus\" even with other characters between the minus sign\n // and the number (e.g. currency symbol). Otherwise it announces nothing because it assumes the character is a hyphen.\n // In addition, replace the empty string with the word \"Empty\" so that iOS VoiceOver does not read \"50%\" for an empty field.\n let ariaTextValue = textValue === '' ? stringFormatter.format('Empty') : (textValue || `${value}`).replace('-', '\\u2212');\n\n useEffect(() => {\n if (isFocused.current) {\n clearAnnouncer('assertive');\n announce(ariaTextValue, 'assertive');\n }\n }, [ariaTextValue]);\n\n // For touch users, if they move their finger like they're scrolling, we don't want to trigger a spin.\n let onPointerCancel = useCallback(() => {\n clearAsync();\n }, [clearAsync]);\n\n const onIncrementEvent = useEffectEvent(onIncrement ?? noop);\n const onDecrementEvent = useEffectEvent(onDecrement ?? noop);\n\n const stepUpEvent = useEffectEvent(() => {\n if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {\n onIncrementEvent();\n onIncrementPressStartEvent(60);\n }\n });\n\n const onIncrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n // Start spinning after initial delay\n _async.current = window.setTimeout(stepUpEvent, initialStepDelay);\n });\n\n const stepDownEvent = useEffectEvent(() => {\n if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {\n onDecrementEvent();\n onDecrementPressStartEvent(60);\n }\n });\n\n const onDecrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n // Start spinning after initial delay\n _async.current = window.setTimeout(stepDownEvent, initialStepDelay);\n });\n\n let cancelContextMenu = (e) => {\n e.preventDefault();\n };\n\n let {addGlobalListener, removeAllGlobalListeners} = useGlobalListeners();\n\n // Tracks in touch if the press end event was preceded by a press up.\n // If it wasn't, then we know the finger left the button while still in contact with the screen.\n // This means that the user is trying to scroll or interact in some way that shouldn't trigger\n // an increment or decrement.\n let isUp = useRef(false);\n\n let [isIncrementPressed, setIsIncrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isIncrementPressed === 'touch') {\n onIncrementPressStartEvent(600);\n } else if (isIncrementPressed) {\n onIncrementPressStartEvent(400);\n }\n }, [isIncrementPressed]);\n\n let [isDecrementPressed, setIsDecrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isDecrementPressed === 'touch') {\n onDecrementPressStartEvent(600);\n } else if (isDecrementPressed) {\n onDecrementPressStartEvent(400);\n }\n }, [isDecrementPressed]);\n\n return {\n spinButtonProps: {\n role: 'spinbutton',\n 'aria-valuenow': value !== undefined && !isNaN(value) ? value : undefined,\n 'aria-valuetext': ariaTextValue,\n 'aria-valuemin': minValue,\n 'aria-valuemax': maxValue,\n 'aria-disabled': isDisabled || undefined,\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n onKeyDown,\n onFocus,\n onBlur\n },\n incrementButtonProps: {\n onPressStart: (e) => {\n clearAsync();\n if (e.pointerType !== 'touch') {\n onIncrement?.();\n setIsIncrementPressed('mouse');\n } else {\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n setIsIncrementPressed('touch');\n }\n addGlobalListener(window, 'contextmenu', cancelContextMenu);\n },\n onPressUp: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n removeAllGlobalListeners();\n setIsIncrementPressed(null);\n },\n onPressEnd: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onIncrement?.();\n }\n }\n isUp.current = false;\n setIsIncrementPressed(null);\n },\n onFocus,\n onBlur\n },\n decrementButtonProps: {\n onPressStart: (e) => {\n clearAsync();\n if (e.pointerType !== 'touch') {\n onDecrement?.();\n setIsDecrementPressed('mouse');\n } else {\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n setIsDecrementPressed('touch');\n }\n },\n onPressUp: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n removeAllGlobalListeners();\n setIsDecrementPressed(null);\n },\n onPressEnd: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onDecrement?.();\n }\n }\n isUp.current = false;\n setIsDecrementPressed(null);\n },\n onFocus,\n onBlur\n }\n };\n}\n"],"names":[],"version":3,"file":"useSpinButton.main.js.map"}
|
package/dist/useSpinButton.mjs
CHANGED
|
@@ -23,6 +23,7 @@ function $parcel$interopDefault(a) {
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
const $d2e8511e6f209edf$var$noop = ()=>{};
|
|
26
27
|
function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
27
28
|
const _async = (0, $5rwhf$useRef)(undefined);
|
|
28
29
|
let { value: value, textValue: textValue, minValue: minValue, maxValue: maxValue, isDisabled: isDisabled, isReadOnly: isReadOnly, isRequired: isRequired, onIncrement: onIncrement, onIncrementPage: onIncrementPage, onDecrement: onDecrement, onDecrementPage: onDecrementPage, onDecrementToMin: onDecrementToMin, onIncrementToMax: onIncrementToMax } = props;
|
|
@@ -109,23 +110,31 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
109
110
|
}, [
|
|
110
111
|
clearAsync
|
|
111
112
|
]);
|
|
112
|
-
const
|
|
113
|
+
const onIncrementEvent = (0, $5rwhf$useEffectEvent)(onIncrement !== null && onIncrement !== void 0 ? onIncrement : $d2e8511e6f209edf$var$noop);
|
|
114
|
+
const onDecrementEvent = (0, $5rwhf$useEffectEvent)(onDecrement !== null && onDecrement !== void 0 ? onDecrement : $d2e8511e6f209edf$var$noop);
|
|
115
|
+
const stepUpEvent = (0, $5rwhf$useEffectEvent)(()=>{
|
|
116
|
+
if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {
|
|
117
|
+
onIncrementEvent();
|
|
118
|
+
onIncrementPressStartEvent(60);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
const onIncrementPressStartEvent = (0, $5rwhf$useEffectEvent)((initialStepDelay)=>{
|
|
113
122
|
clearAsyncEvent();
|
|
114
123
|
isSpinning.current = true;
|
|
115
|
-
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
116
124
|
// Start spinning after initial delay
|
|
117
|
-
_async.current = window.setTimeout(
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
_async.current = window.setTimeout(stepUpEvent, initialStepDelay);
|
|
126
|
+
});
|
|
127
|
+
const stepDownEvent = (0, $5rwhf$useEffectEvent)(()=>{
|
|
128
|
+
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {
|
|
129
|
+
onDecrementEvent();
|
|
130
|
+
onDecrementPressStartEvent(60);
|
|
131
|
+
}
|
|
120
132
|
});
|
|
121
|
-
const
|
|
133
|
+
const onDecrementPressStartEvent = (0, $5rwhf$useEffectEvent)((initialStepDelay)=>{
|
|
122
134
|
clearAsyncEvent();
|
|
123
135
|
isSpinning.current = true;
|
|
124
|
-
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
125
136
|
// Start spinning after initial delay
|
|
126
|
-
_async.current = window.setTimeout(
|
|
127
|
-
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) onDecrementPressStart(60);
|
|
128
|
-
}, initialStepDelay);
|
|
137
|
+
_async.current = window.setTimeout(stepDownEvent, initialStepDelay);
|
|
129
138
|
});
|
|
130
139
|
let cancelContextMenu = (e)=>{
|
|
131
140
|
e.preventDefault();
|
|
@@ -138,15 +147,15 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
138
147
|
let isUp = (0, $5rwhf$useRef)(false);
|
|
139
148
|
let [isIncrementPressed, setIsIncrementPressed] = (0, $5rwhf$useState)(null);
|
|
140
149
|
(0, $5rwhf$useEffect)(()=>{
|
|
141
|
-
if (isIncrementPressed === 'touch')
|
|
142
|
-
else if (isIncrementPressed)
|
|
150
|
+
if (isIncrementPressed === 'touch') onIncrementPressStartEvent(600);
|
|
151
|
+
else if (isIncrementPressed) onIncrementPressStartEvent(400);
|
|
143
152
|
}, [
|
|
144
153
|
isIncrementPressed
|
|
145
154
|
]);
|
|
146
155
|
let [isDecrementPressed, setIsDecrementPressed] = (0, $5rwhf$useState)(null);
|
|
147
156
|
(0, $5rwhf$useEffect)(()=>{
|
|
148
|
-
if (isDecrementPressed === 'touch')
|
|
149
|
-
else if (isDecrementPressed)
|
|
157
|
+
if (isDecrementPressed === 'touch') onDecrementPressStartEvent(600);
|
|
158
|
+
else if (isDecrementPressed) onDecrementPressStartEvent(400);
|
|
150
159
|
}, [
|
|
151
160
|
isDecrementPressed
|
|
152
161
|
]);
|
|
@@ -166,32 +175,32 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
166
175
|
},
|
|
167
176
|
incrementButtonProps: {
|
|
168
177
|
onPressStart: (e)=>{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
clearAsync();
|
|
179
|
+
if (e.pointerType !== 'touch') {
|
|
180
|
+
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
181
|
+
setIsIncrementPressed('mouse');
|
|
182
|
+
} else {
|
|
172
183
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
173
184
|
capture: true
|
|
174
185
|
});
|
|
175
186
|
isUp.current = false;
|
|
176
187
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
177
188
|
// the control isn't spinning.
|
|
178
|
-
|
|
179
|
-
setIsIncrementPressed('touch');
|
|
180
|
-
}, 600);
|
|
189
|
+
setIsIncrementPressed('touch');
|
|
181
190
|
}
|
|
182
191
|
addGlobalListener(window, 'contextmenu', cancelContextMenu);
|
|
183
192
|
},
|
|
184
193
|
onPressUp: (e)=>{
|
|
185
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
186
194
|
clearAsync();
|
|
195
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
187
196
|
removeAllGlobalListeners();
|
|
188
197
|
setIsIncrementPressed(null);
|
|
189
198
|
},
|
|
190
199
|
onPressEnd: (e)=>{
|
|
200
|
+
clearAsync();
|
|
191
201
|
if (e.pointerType === 'touch') {
|
|
192
202
|
if (!isSpinning.current && isUp.current) onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
193
203
|
}
|
|
194
|
-
clearAsync();
|
|
195
204
|
isUp.current = false;
|
|
196
205
|
setIsIncrementPressed(null);
|
|
197
206
|
},
|
|
@@ -200,31 +209,31 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
200
209
|
},
|
|
201
210
|
decrementButtonProps: {
|
|
202
211
|
onPressStart: (e)=>{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
212
|
+
clearAsync();
|
|
213
|
+
if (e.pointerType !== 'touch') {
|
|
214
|
+
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
215
|
+
setIsDecrementPressed('mouse');
|
|
216
|
+
} else {
|
|
206
217
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
207
218
|
capture: true
|
|
208
219
|
});
|
|
209
220
|
isUp.current = false;
|
|
210
221
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
211
222
|
// the control isn't spinning.
|
|
212
|
-
|
|
213
|
-
setIsDecrementPressed('touch');
|
|
214
|
-
}, 600);
|
|
223
|
+
setIsDecrementPressed('touch');
|
|
215
224
|
}
|
|
216
225
|
},
|
|
217
226
|
onPressUp: (e)=>{
|
|
218
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
219
227
|
clearAsync();
|
|
228
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
220
229
|
removeAllGlobalListeners();
|
|
221
230
|
setIsDecrementPressed(null);
|
|
222
231
|
},
|
|
223
232
|
onPressEnd: (e)=>{
|
|
233
|
+
clearAsync();
|
|
224
234
|
if (e.pointerType === 'touch') {
|
|
225
235
|
if (!isSpinning.current && isUp.current) onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
226
236
|
}
|
|
227
|
-
clearAsync();
|
|
228
237
|
isUp.current = false;
|
|
229
238
|
setIsDecrementPressed(null);
|
|
230
239
|
},
|
|
@@ -23,6 +23,7 @@ function $parcel$interopDefault(a) {
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
const $d2e8511e6f209edf$var$noop = ()=>{};
|
|
26
27
|
function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
27
28
|
const _async = (0, $5rwhf$useRef)(undefined);
|
|
28
29
|
let { value: value, textValue: textValue, minValue: minValue, maxValue: maxValue, isDisabled: isDisabled, isReadOnly: isReadOnly, isRequired: isRequired, onIncrement: onIncrement, onIncrementPage: onIncrementPage, onDecrement: onDecrement, onDecrementPage: onDecrementPage, onDecrementToMin: onDecrementToMin, onIncrementToMax: onIncrementToMax } = props;
|
|
@@ -109,23 +110,31 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
109
110
|
}, [
|
|
110
111
|
clearAsync
|
|
111
112
|
]);
|
|
112
|
-
const
|
|
113
|
+
const onIncrementEvent = (0, $5rwhf$useEffectEvent)(onIncrement !== null && onIncrement !== void 0 ? onIncrement : $d2e8511e6f209edf$var$noop);
|
|
114
|
+
const onDecrementEvent = (0, $5rwhf$useEffectEvent)(onDecrement !== null && onDecrement !== void 0 ? onDecrement : $d2e8511e6f209edf$var$noop);
|
|
115
|
+
const stepUpEvent = (0, $5rwhf$useEffectEvent)(()=>{
|
|
116
|
+
if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {
|
|
117
|
+
onIncrementEvent();
|
|
118
|
+
onIncrementPressStartEvent(60);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
const onIncrementPressStartEvent = (0, $5rwhf$useEffectEvent)((initialStepDelay)=>{
|
|
113
122
|
clearAsyncEvent();
|
|
114
123
|
isSpinning.current = true;
|
|
115
|
-
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
116
124
|
// Start spinning after initial delay
|
|
117
|
-
_async.current = window.setTimeout(
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
_async.current = window.setTimeout(stepUpEvent, initialStepDelay);
|
|
126
|
+
});
|
|
127
|
+
const stepDownEvent = (0, $5rwhf$useEffectEvent)(()=>{
|
|
128
|
+
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {
|
|
129
|
+
onDecrementEvent();
|
|
130
|
+
onDecrementPressStartEvent(60);
|
|
131
|
+
}
|
|
120
132
|
});
|
|
121
|
-
const
|
|
133
|
+
const onDecrementPressStartEvent = (0, $5rwhf$useEffectEvent)((initialStepDelay)=>{
|
|
122
134
|
clearAsyncEvent();
|
|
123
135
|
isSpinning.current = true;
|
|
124
|
-
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
125
136
|
// Start spinning after initial delay
|
|
126
|
-
_async.current = window.setTimeout(
|
|
127
|
-
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) onDecrementPressStart(60);
|
|
128
|
-
}, initialStepDelay);
|
|
137
|
+
_async.current = window.setTimeout(stepDownEvent, initialStepDelay);
|
|
129
138
|
});
|
|
130
139
|
let cancelContextMenu = (e)=>{
|
|
131
140
|
e.preventDefault();
|
|
@@ -138,15 +147,15 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
138
147
|
let isUp = (0, $5rwhf$useRef)(false);
|
|
139
148
|
let [isIncrementPressed, setIsIncrementPressed] = (0, $5rwhf$useState)(null);
|
|
140
149
|
(0, $5rwhf$useEffect)(()=>{
|
|
141
|
-
if (isIncrementPressed === 'touch')
|
|
142
|
-
else if (isIncrementPressed)
|
|
150
|
+
if (isIncrementPressed === 'touch') onIncrementPressStartEvent(600);
|
|
151
|
+
else if (isIncrementPressed) onIncrementPressStartEvent(400);
|
|
143
152
|
}, [
|
|
144
153
|
isIncrementPressed
|
|
145
154
|
]);
|
|
146
155
|
let [isDecrementPressed, setIsDecrementPressed] = (0, $5rwhf$useState)(null);
|
|
147
156
|
(0, $5rwhf$useEffect)(()=>{
|
|
148
|
-
if (isDecrementPressed === 'touch')
|
|
149
|
-
else if (isDecrementPressed)
|
|
157
|
+
if (isDecrementPressed === 'touch') onDecrementPressStartEvent(600);
|
|
158
|
+
else if (isDecrementPressed) onDecrementPressStartEvent(400);
|
|
150
159
|
}, [
|
|
151
160
|
isDecrementPressed
|
|
152
161
|
]);
|
|
@@ -166,32 +175,32 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
166
175
|
},
|
|
167
176
|
incrementButtonProps: {
|
|
168
177
|
onPressStart: (e)=>{
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
clearAsync();
|
|
179
|
+
if (e.pointerType !== 'touch') {
|
|
180
|
+
onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
181
|
+
setIsIncrementPressed('mouse');
|
|
182
|
+
} else {
|
|
172
183
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
173
184
|
capture: true
|
|
174
185
|
});
|
|
175
186
|
isUp.current = false;
|
|
176
187
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
177
188
|
// the control isn't spinning.
|
|
178
|
-
|
|
179
|
-
setIsIncrementPressed('touch');
|
|
180
|
-
}, 600);
|
|
189
|
+
setIsIncrementPressed('touch');
|
|
181
190
|
}
|
|
182
191
|
addGlobalListener(window, 'contextmenu', cancelContextMenu);
|
|
183
192
|
},
|
|
184
193
|
onPressUp: (e)=>{
|
|
185
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
186
194
|
clearAsync();
|
|
195
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
187
196
|
removeAllGlobalListeners();
|
|
188
197
|
setIsIncrementPressed(null);
|
|
189
198
|
},
|
|
190
199
|
onPressEnd: (e)=>{
|
|
200
|
+
clearAsync();
|
|
191
201
|
if (e.pointerType === 'touch') {
|
|
192
202
|
if (!isSpinning.current && isUp.current) onIncrement === null || onIncrement === void 0 ? void 0 : onIncrement();
|
|
193
203
|
}
|
|
194
|
-
clearAsync();
|
|
195
204
|
isUp.current = false;
|
|
196
205
|
setIsIncrementPressed(null);
|
|
197
206
|
},
|
|
@@ -200,31 +209,31 @@ function $d2e8511e6f209edf$export$e908e06f4b8e3402(props) {
|
|
|
200
209
|
},
|
|
201
210
|
decrementButtonProps: {
|
|
202
211
|
onPressStart: (e)=>{
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
212
|
+
clearAsync();
|
|
213
|
+
if (e.pointerType !== 'touch') {
|
|
214
|
+
onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
215
|
+
setIsDecrementPressed('mouse');
|
|
216
|
+
} else {
|
|
206
217
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {
|
|
207
218
|
capture: true
|
|
208
219
|
});
|
|
209
220
|
isUp.current = false;
|
|
210
221
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
211
222
|
// the control isn't spinning.
|
|
212
|
-
|
|
213
|
-
setIsDecrementPressed('touch');
|
|
214
|
-
}, 600);
|
|
223
|
+
setIsDecrementPressed('touch');
|
|
215
224
|
}
|
|
216
225
|
},
|
|
217
226
|
onPressUp: (e)=>{
|
|
218
|
-
if (e.pointerType === 'touch') isUp.current = true;
|
|
219
227
|
clearAsync();
|
|
228
|
+
if (e.pointerType === 'touch') isUp.current = true;
|
|
220
229
|
removeAllGlobalListeners();
|
|
221
230
|
setIsDecrementPressed(null);
|
|
222
231
|
},
|
|
223
232
|
onPressEnd: (e)=>{
|
|
233
|
+
clearAsync();
|
|
224
234
|
if (e.pointerType === 'touch') {
|
|
225
235
|
if (!isSpinning.current && isUp.current) onDecrement === null || onDecrement === void 0 ? void 0 : onDecrement();
|
|
226
236
|
}
|
|
227
|
-
clearAsync();
|
|
228
237
|
isUp.current = false;
|
|
229
238
|
setIsDecrementPressed(null);
|
|
230
239
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@react-aria/spinbutton/src/useSpinButton.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {announce, clearAnnouncer} from '@react-aria/live-announcer';\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMAttributes, InputBase, RangeInputBase, Validation, ValueBase} from '@react-types/shared';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useEffectEvent, useGlobalListeners} from '@react-aria/utils';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\n\nexport interface SpinButtonProps extends InputBase, Validation<number>, ValueBase<number>, RangeInputBase<number> {\n textValue?: string,\n onIncrement?: () => void,\n onIncrementPage?: () => void,\n onDecrement?: () => void,\n onDecrementPage?: () => void,\n onDecrementToMin?: () => void,\n onIncrementToMax?: () => void\n}\n\nexport interface SpinbuttonAria {\n spinButtonProps: DOMAttributes,\n incrementButtonProps: AriaButtonProps,\n decrementButtonProps: AriaButtonProps\n}\n\nexport function useSpinButton(\n props: SpinButtonProps\n): SpinbuttonAria {\n const _async = useRef<number>(undefined);\n let {\n value,\n textValue,\n minValue,\n maxValue,\n isDisabled,\n isReadOnly,\n isRequired,\n onIncrement,\n onIncrementPage,\n onDecrement,\n onDecrementPage,\n onDecrementToMin,\n onIncrementToMax\n } = props;\n const stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/spinbutton');\n\n let isSpinning = useRef(false);\n const clearAsync = useCallback(() => {\n clearTimeout(_async.current);\n isSpinning.current = false;\n }, []);\n const clearAsyncEvent = useEffectEvent(() => {\n clearAsync();\n });\n\n useEffect(() => {\n return () => clearAsyncEvent();\n }, []);\n\n let onKeyDown = (e) => {\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || isReadOnly || e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'PageUp':\n if (onIncrementPage) {\n e.preventDefault();\n onIncrementPage?.();\n break;\n }\n // fallthrough!\n case 'ArrowUp':\n case 'Up':\n if (onIncrement) {\n e.preventDefault();\n onIncrement?.();\n }\n break;\n case 'PageDown':\n if (onDecrementPage) {\n e.preventDefault();\n onDecrementPage?.();\n break;\n }\n // fallthrough\n case 'ArrowDown':\n case 'Down':\n if (onDecrement) {\n e.preventDefault();\n onDecrement?.();\n }\n break;\n case 'Home':\n if (onDecrementToMin) {\n e.preventDefault();\n onDecrementToMin?.();\n }\n break;\n case 'End':\n if (onIncrementToMax) {\n e.preventDefault();\n onIncrementToMax?.();\n }\n break;\n }\n };\n\n let isFocused = useRef(false);\n let onFocus = () => {\n isFocused.current = true;\n };\n\n let onBlur = () => {\n isFocused.current = false;\n };\n\n // Replace Unicode hyphen-minus (U+002D) with minus sign (U+2212).\n // This ensures that macOS VoiceOver announces it as \"minus\" even with other characters between the minus sign\n // and the number (e.g. currency symbol). Otherwise it announces nothing because it assumes the character is a hyphen.\n // In addition, replace the empty string with the word \"Empty\" so that iOS VoiceOver does not read \"50%\" for an empty field.\n let ariaTextValue = textValue === '' ? stringFormatter.format('Empty') : (textValue || `${value}`).replace('-', '\\u2212');\n\n useEffect(() => {\n if (isFocused.current) {\n clearAnnouncer('assertive');\n announce(ariaTextValue, 'assertive');\n }\n }, [ariaTextValue]);\n\n // For touch users, if they move their finger like they're scrolling, we don't want to trigger a spin.\n let onPointerCancel = useCallback(() => {\n clearAsync();\n }, [clearAsync]);\n\n const onIncrementPressStart = useEffectEvent(\n (initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n onIncrement?.();\n // Start spinning after initial delay\n _async.current = window.setTimeout(\n () => {\n if ((maxValue === undefined || isNaN(maxValue)) || (value === undefined || isNaN(value)) || value < maxValue) {\n onIncrementPressStart(60);\n }\n },\n initialStepDelay\n );\n }\n );\n\n const onDecrementPressStart = useEffectEvent(\n (initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n onDecrement?.();\n // Start spinning after initial delay\n _async.current = window.setTimeout(\n () => {\n if ((minValue === undefined || isNaN(minValue)) || (value === undefined || isNaN(value)) || value > minValue) {\n onDecrementPressStart(60);\n }\n },\n initialStepDelay\n );\n }\n );\n\n let cancelContextMenu = (e) => {\n e.preventDefault();\n };\n\n let {addGlobalListener, removeAllGlobalListeners} = useGlobalListeners();\n\n // Tracks in touch if the press end event was preceded by a press up.\n // If it wasn't, then we know the finger left the button while still in contact with the screen.\n // This means that the user is trying to scroll or interact in some way that shouldn't trigger\n // an increment or decrement.\n let isUp = useRef(false);\n\n let [isIncrementPressed, setIsIncrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isIncrementPressed === 'touch') {\n onIncrementPressStart(60);\n } else if (isIncrementPressed) {\n onIncrementPressStart(400);\n }\n }, [isIncrementPressed]);\n\n let [isDecrementPressed, setIsDecrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isDecrementPressed === 'touch') {\n onDecrementPressStart(60);\n } else if (isDecrementPressed) {\n onDecrementPressStart(400);\n }\n }, [isDecrementPressed]);\n\n return {\n spinButtonProps: {\n role: 'spinbutton',\n 'aria-valuenow': value !== undefined && !isNaN(value) ? value : undefined,\n 'aria-valuetext': ariaTextValue,\n 'aria-valuemin': minValue,\n 'aria-valuemax': maxValue,\n 'aria-disabled': isDisabled || undefined,\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n onKeyDown,\n onFocus,\n onBlur\n },\n incrementButtonProps: {\n onPressStart: (e) => {\n if (e.pointerType !== 'touch') {\n setIsIncrementPressed('mouse');\n } else {\n if (_async.current) {\n clearAsync();\n }\n\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n _async.current = window.setTimeout(() => {\n setIsIncrementPressed('touch');\n }, 600);\n }\n addGlobalListener(window, 'contextmenu', cancelContextMenu);\n },\n onPressUp: (e) => {\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n clearAsync();\n removeAllGlobalListeners();\n setIsIncrementPressed(null);\n },\n onPressEnd: (e) => {\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onIncrement?.();\n }\n }\n clearAsync();\n isUp.current = false;\n setIsIncrementPressed(null);\n },\n onFocus,\n onBlur\n },\n decrementButtonProps: {\n onPressStart: (e) => {\n if (e.pointerType !== 'touch') {\n setIsDecrementPressed('mouse');\n } else {\n if (_async.current) {\n clearAsync();\n }\n\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n _async.current = window.setTimeout(() => {\n setIsDecrementPressed('touch');\n }, 600);\n }\n },\n onPressUp: (e) => {\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n clearAsync();\n removeAllGlobalListeners();\n setIsDecrementPressed(null);\n },\n onPressEnd: (e) => {\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onDecrement?.();\n }\n }\n clearAsync();\n isUp.current = false;\n setIsDecrementPressed(null);\n },\n onFocus,\n onBlur\n }\n };\n}\n"],"names":[],"version":3,"file":"useSpinButton.module.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/spinbutton/src/useSpinButton.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {announce, clearAnnouncer} from '@react-aria/live-announcer';\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMAttributes, InputBase, RangeInputBase, Validation, ValueBase} from '@react-types/shared';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useEffectEvent, useGlobalListeners} from '@react-aria/utils';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\n\nconst noop = () => {};\n\nexport interface SpinButtonProps extends InputBase, Validation<number>, ValueBase<number>, RangeInputBase<number> {\n textValue?: string,\n onIncrement?: () => void,\n onIncrementPage?: () => void,\n onDecrement?: () => void,\n onDecrementPage?: () => void,\n onDecrementToMin?: () => void,\n onIncrementToMax?: () => void\n}\n\nexport interface SpinbuttonAria {\n spinButtonProps: DOMAttributes,\n incrementButtonProps: AriaButtonProps,\n decrementButtonProps: AriaButtonProps\n}\n\nexport function useSpinButton(\n props: SpinButtonProps\n): SpinbuttonAria {\n const _async = useRef<number>(undefined);\n let {\n value,\n textValue,\n minValue,\n maxValue,\n isDisabled,\n isReadOnly,\n isRequired,\n onIncrement,\n onIncrementPage,\n onDecrement,\n onDecrementPage,\n onDecrementToMin,\n onIncrementToMax\n } = props;\n const stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/spinbutton');\n\n let isSpinning = useRef(false);\n const clearAsync = useCallback(() => {\n clearTimeout(_async.current);\n isSpinning.current = false;\n }, []);\n const clearAsyncEvent = useEffectEvent(() => {\n clearAsync();\n });\n\n useEffect(() => {\n return () => clearAsyncEvent();\n }, []);\n\n let onKeyDown = (e) => {\n if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || isReadOnly || e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'PageUp':\n if (onIncrementPage) {\n e.preventDefault();\n onIncrementPage?.();\n break;\n }\n // fallthrough!\n case 'ArrowUp':\n case 'Up':\n if (onIncrement) {\n e.preventDefault();\n onIncrement?.();\n }\n break;\n case 'PageDown':\n if (onDecrementPage) {\n e.preventDefault();\n onDecrementPage?.();\n break;\n }\n // fallthrough\n case 'ArrowDown':\n case 'Down':\n if (onDecrement) {\n e.preventDefault();\n onDecrement?.();\n }\n break;\n case 'Home':\n if (onDecrementToMin) {\n e.preventDefault();\n onDecrementToMin?.();\n }\n break;\n case 'End':\n if (onIncrementToMax) {\n e.preventDefault();\n onIncrementToMax?.();\n }\n break;\n }\n };\n\n let isFocused = useRef(false);\n let onFocus = () => {\n isFocused.current = true;\n };\n\n let onBlur = () => {\n isFocused.current = false;\n };\n\n // Replace Unicode hyphen-minus (U+002D) with minus sign (U+2212).\n // This ensures that macOS VoiceOver announces it as \"minus\" even with other characters between the minus sign\n // and the number (e.g. currency symbol). Otherwise it announces nothing because it assumes the character is a hyphen.\n // In addition, replace the empty string with the word \"Empty\" so that iOS VoiceOver does not read \"50%\" for an empty field.\n let ariaTextValue = textValue === '' ? stringFormatter.format('Empty') : (textValue || `${value}`).replace('-', '\\u2212');\n\n useEffect(() => {\n if (isFocused.current) {\n clearAnnouncer('assertive');\n announce(ariaTextValue, 'assertive');\n }\n }, [ariaTextValue]);\n\n // For touch users, if they move their finger like they're scrolling, we don't want to trigger a spin.\n let onPointerCancel = useCallback(() => {\n clearAsync();\n }, [clearAsync]);\n\n const onIncrementEvent = useEffectEvent(onIncrement ?? noop);\n const onDecrementEvent = useEffectEvent(onDecrement ?? noop);\n\n const stepUpEvent = useEffectEvent(() => {\n if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {\n onIncrementEvent();\n onIncrementPressStartEvent(60);\n }\n });\n\n const onIncrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n // Start spinning after initial delay\n _async.current = window.setTimeout(stepUpEvent, initialStepDelay);\n });\n\n const stepDownEvent = useEffectEvent(() => {\n if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {\n onDecrementEvent();\n onDecrementPressStartEvent(60);\n }\n });\n\n const onDecrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {\n clearAsyncEvent();\n isSpinning.current = true;\n // Start spinning after initial delay\n _async.current = window.setTimeout(stepDownEvent, initialStepDelay);\n });\n\n let cancelContextMenu = (e) => {\n e.preventDefault();\n };\n\n let {addGlobalListener, removeAllGlobalListeners} = useGlobalListeners();\n\n // Tracks in touch if the press end event was preceded by a press up.\n // If it wasn't, then we know the finger left the button while still in contact with the screen.\n // This means that the user is trying to scroll or interact in some way that shouldn't trigger\n // an increment or decrement.\n let isUp = useRef(false);\n\n let [isIncrementPressed, setIsIncrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isIncrementPressed === 'touch') {\n onIncrementPressStartEvent(600);\n } else if (isIncrementPressed) {\n onIncrementPressStartEvent(400);\n }\n }, [isIncrementPressed]);\n\n let [isDecrementPressed, setIsDecrementPressed] = useState<'touch' | 'mouse' | null>(null);\n useEffect(() => {\n if (isDecrementPressed === 'touch') {\n onDecrementPressStartEvent(600);\n } else if (isDecrementPressed) {\n onDecrementPressStartEvent(400);\n }\n }, [isDecrementPressed]);\n\n return {\n spinButtonProps: {\n role: 'spinbutton',\n 'aria-valuenow': value !== undefined && !isNaN(value) ? value : undefined,\n 'aria-valuetext': ariaTextValue,\n 'aria-valuemin': minValue,\n 'aria-valuemax': maxValue,\n 'aria-disabled': isDisabled || undefined,\n 'aria-readonly': isReadOnly || undefined,\n 'aria-required': isRequired || undefined,\n onKeyDown,\n onFocus,\n onBlur\n },\n incrementButtonProps: {\n onPressStart: (e) => {\n clearAsync();\n if (e.pointerType !== 'touch') {\n onIncrement?.();\n setIsIncrementPressed('mouse');\n } else {\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n setIsIncrementPressed('touch');\n }\n addGlobalListener(window, 'contextmenu', cancelContextMenu);\n },\n onPressUp: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n removeAllGlobalListeners();\n setIsIncrementPressed(null);\n },\n onPressEnd: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onIncrement?.();\n }\n }\n isUp.current = false;\n setIsIncrementPressed(null);\n },\n onFocus,\n onBlur\n },\n decrementButtonProps: {\n onPressStart: (e) => {\n clearAsync();\n if (e.pointerType !== 'touch') {\n onDecrement?.();\n setIsDecrementPressed('mouse');\n } else {\n addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});\n isUp.current = false;\n // For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if\n // the control isn't spinning.\n setIsDecrementPressed('touch');\n }\n },\n onPressUp: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n isUp.current = true;\n }\n removeAllGlobalListeners();\n setIsDecrementPressed(null);\n },\n onPressEnd: (e) => {\n clearAsync();\n if (e.pointerType === 'touch') {\n if (!isSpinning.current && isUp.current) {\n onDecrement?.();\n }\n }\n isUp.current = false;\n setIsDecrementPressed(null);\n },\n onFocus,\n onBlur\n }\n };\n}\n"],"names":[],"version":3,"file":"useSpinButton.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/spinbutton",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.1",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"url": "https://github.com/adobe/react-spectrum"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@react-aria/i18n": "^3.12.
|
|
29
|
+
"@react-aria/i18n": "^3.12.15",
|
|
30
30
|
"@react-aria/live-announcer": "^3.4.4",
|
|
31
|
-
"@react-aria/utils": "^3.
|
|
32
|
-
"@react-types/button": "^3.
|
|
33
|
-
"@react-types/shared": "^3.
|
|
31
|
+
"@react-aria/utils": "^3.33.0",
|
|
32
|
+
"@react-types/button": "^3.15.0",
|
|
33
|
+
"@react-types/shared": "^3.33.0",
|
|
34
34
|
"@swc/helpers": "^0.5.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "66e51757606b43a89ed02c574ca24517323a2ab9"
|
|
44
44
|
}
|
package/src/useSpinButton.ts
CHANGED
|
@@ -20,6 +20,8 @@ import {useEffectEvent, useGlobalListeners} from '@react-aria/utils';
|
|
|
20
20
|
import {useLocalizedStringFormatter} from '@react-aria/i18n';
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
const noop = () => {};
|
|
24
|
+
|
|
23
25
|
export interface SpinButtonProps extends InputBase, Validation<number>, ValueBase<number>, RangeInputBase<number> {
|
|
24
26
|
textValue?: string,
|
|
25
27
|
onIncrement?: () => void,
|
|
@@ -146,39 +148,36 @@ export function useSpinButton(
|
|
|
146
148
|
clearAsync();
|
|
147
149
|
}, [clearAsync]);
|
|
148
150
|
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
() => {
|
|
157
|
-
if ((maxValue === undefined || isNaN(maxValue)) || (value === undefined || isNaN(value)) || value < maxValue) {
|
|
158
|
-
onIncrementPressStart(60);
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
initialStepDelay
|
|
162
|
-
);
|
|
151
|
+
const onIncrementEvent = useEffectEvent(onIncrement ?? noop);
|
|
152
|
+
const onDecrementEvent = useEffectEvent(onDecrement ?? noop);
|
|
153
|
+
|
|
154
|
+
const stepUpEvent = useEffectEvent(() => {
|
|
155
|
+
if (maxValue === undefined || isNaN(maxValue) || value === undefined || isNaN(value) || value < maxValue) {
|
|
156
|
+
onIncrementEvent();
|
|
157
|
+
onIncrementPressStartEvent(60);
|
|
163
158
|
}
|
|
164
|
-
);
|
|
159
|
+
});
|
|
165
160
|
|
|
166
|
-
const
|
|
167
|
-
(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
},
|
|
178
|
-
initialStepDelay
|
|
179
|
-
);
|
|
161
|
+
const onIncrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {
|
|
162
|
+
clearAsyncEvent();
|
|
163
|
+
isSpinning.current = true;
|
|
164
|
+
// Start spinning after initial delay
|
|
165
|
+
_async.current = window.setTimeout(stepUpEvent, initialStepDelay);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const stepDownEvent = useEffectEvent(() => {
|
|
169
|
+
if (minValue === undefined || isNaN(minValue) || value === undefined || isNaN(value) || value > minValue) {
|
|
170
|
+
onDecrementEvent();
|
|
171
|
+
onDecrementPressStartEvent(60);
|
|
180
172
|
}
|
|
181
|
-
);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const onDecrementPressStartEvent = useEffectEvent((initialStepDelay: number) => {
|
|
176
|
+
clearAsyncEvent();
|
|
177
|
+
isSpinning.current = true;
|
|
178
|
+
// Start spinning after initial delay
|
|
179
|
+
_async.current = window.setTimeout(stepDownEvent, initialStepDelay);
|
|
180
|
+
});
|
|
182
181
|
|
|
183
182
|
let cancelContextMenu = (e) => {
|
|
184
183
|
e.preventDefault();
|
|
@@ -195,18 +194,18 @@ export function useSpinButton(
|
|
|
195
194
|
let [isIncrementPressed, setIsIncrementPressed] = useState<'touch' | 'mouse' | null>(null);
|
|
196
195
|
useEffect(() => {
|
|
197
196
|
if (isIncrementPressed === 'touch') {
|
|
198
|
-
|
|
197
|
+
onIncrementPressStartEvent(600);
|
|
199
198
|
} else if (isIncrementPressed) {
|
|
200
|
-
|
|
199
|
+
onIncrementPressStartEvent(400);
|
|
201
200
|
}
|
|
202
201
|
}, [isIncrementPressed]);
|
|
203
202
|
|
|
204
203
|
let [isDecrementPressed, setIsDecrementPressed] = useState<'touch' | 'mouse' | null>(null);
|
|
205
204
|
useEffect(() => {
|
|
206
205
|
if (isDecrementPressed === 'touch') {
|
|
207
|
-
|
|
206
|
+
onDecrementPressStartEvent(600);
|
|
208
207
|
} else if (isDecrementPressed) {
|
|
209
|
-
|
|
208
|
+
onDecrementPressStartEvent(400);
|
|
210
209
|
}
|
|
211
210
|
}, [isDecrementPressed]);
|
|
212
211
|
|
|
@@ -226,38 +225,34 @@ export function useSpinButton(
|
|
|
226
225
|
},
|
|
227
226
|
incrementButtonProps: {
|
|
228
227
|
onPressStart: (e) => {
|
|
228
|
+
clearAsync();
|
|
229
229
|
if (e.pointerType !== 'touch') {
|
|
230
|
+
onIncrement?.();
|
|
230
231
|
setIsIncrementPressed('mouse');
|
|
231
232
|
} else {
|
|
232
|
-
if (_async.current) {
|
|
233
|
-
clearAsync();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
233
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});
|
|
237
234
|
isUp.current = false;
|
|
238
235
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
239
236
|
// the control isn't spinning.
|
|
240
|
-
|
|
241
|
-
setIsIncrementPressed('touch');
|
|
242
|
-
}, 600);
|
|
237
|
+
setIsIncrementPressed('touch');
|
|
243
238
|
}
|
|
244
239
|
addGlobalListener(window, 'contextmenu', cancelContextMenu);
|
|
245
240
|
},
|
|
246
241
|
onPressUp: (e) => {
|
|
242
|
+
clearAsync();
|
|
247
243
|
if (e.pointerType === 'touch') {
|
|
248
244
|
isUp.current = true;
|
|
249
245
|
}
|
|
250
|
-
clearAsync();
|
|
251
246
|
removeAllGlobalListeners();
|
|
252
247
|
setIsIncrementPressed(null);
|
|
253
248
|
},
|
|
254
249
|
onPressEnd: (e) => {
|
|
250
|
+
clearAsync();
|
|
255
251
|
if (e.pointerType === 'touch') {
|
|
256
252
|
if (!isSpinning.current && isUp.current) {
|
|
257
253
|
onIncrement?.();
|
|
258
254
|
}
|
|
259
255
|
}
|
|
260
|
-
clearAsync();
|
|
261
256
|
isUp.current = false;
|
|
262
257
|
setIsIncrementPressed(null);
|
|
263
258
|
},
|
|
@@ -266,37 +261,33 @@ export function useSpinButton(
|
|
|
266
261
|
},
|
|
267
262
|
decrementButtonProps: {
|
|
268
263
|
onPressStart: (e) => {
|
|
264
|
+
clearAsync();
|
|
269
265
|
if (e.pointerType !== 'touch') {
|
|
266
|
+
onDecrement?.();
|
|
270
267
|
setIsDecrementPressed('mouse');
|
|
271
268
|
} else {
|
|
272
|
-
if (_async.current) {
|
|
273
|
-
clearAsync();
|
|
274
|
-
}
|
|
275
|
-
|
|
276
269
|
addGlobalListener(window, 'pointercancel', onPointerCancel, {capture: true});
|
|
277
270
|
isUp.current = false;
|
|
278
271
|
// For touch users, don't trigger a decrement on press start, we'll wait for the press end to trigger it if
|
|
279
272
|
// the control isn't spinning.
|
|
280
|
-
|
|
281
|
-
setIsDecrementPressed('touch');
|
|
282
|
-
}, 600);
|
|
273
|
+
setIsDecrementPressed('touch');
|
|
283
274
|
}
|
|
284
275
|
},
|
|
285
276
|
onPressUp: (e) => {
|
|
277
|
+
clearAsync();
|
|
286
278
|
if (e.pointerType === 'touch') {
|
|
287
279
|
isUp.current = true;
|
|
288
280
|
}
|
|
289
|
-
clearAsync();
|
|
290
281
|
removeAllGlobalListeners();
|
|
291
282
|
setIsDecrementPressed(null);
|
|
292
283
|
},
|
|
293
284
|
onPressEnd: (e) => {
|
|
285
|
+
clearAsync();
|
|
294
286
|
if (e.pointerType === 'touch') {
|
|
295
287
|
if (!isSpinning.current && isUp.current) {
|
|
296
288
|
onDecrement?.();
|
|
297
289
|
}
|
|
298
290
|
}
|
|
299
|
-
clearAsync();
|
|
300
291
|
isUp.current = false;
|
|
301
292
|
setIsDecrementPressed(null);
|
|
302
293
|
},
|