@react-aria/numberfield
Advanced tools
Comparing version 3.0.0-nightly.992 to 3.0.0-nightly.994
178
dist/main.js
var { | ||
useTextField | ||
} = require("@react-aria/textfield"); | ||
var { | ||
useSpinButton | ||
@@ -15,4 +11,9 @@ } = require("@react-aria/spinbutton"); | ||
var { | ||
useFormattedTextField | ||
} = require("@react-aria/textfield"); | ||
var { | ||
useFocus, | ||
useFocusWithin | ||
useFocusWithin, | ||
useScrollWheel | ||
} = require("@react-aria/interactions"); | ||
@@ -30,5 +31,3 @@ | ||
useCallback, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
useState | ||
@@ -185,6 +184,2 @@ } = require("react"); | ||
function $ebb253b0ca493f114f41772a028a$var$supportsNativeBeforeInputEvent() { | ||
return typeof window !== 'undefined' && window.InputEvent && // @ts-ignore | ||
typeof InputEvent.prototype.getTargetRanges === 'function'; | ||
} | ||
/** | ||
@@ -194,4 +189,2 @@ * Provides the behavior and accessibility implementation for a number field component. | ||
*/ | ||
function useNumberField(props, state, inputRef) { | ||
@@ -255,10 +248,2 @@ let { | ||
let onWheel = useCallback(e => { | ||
// If the ctrlKey is pressed, this is a zoom event, do nothing. | ||
if (e.ctrlKey) { | ||
return; | ||
} // stop scrolling the page | ||
e.preventDefault(); | ||
if (e.deltaY > 0) { | ||
@@ -272,5 +257,4 @@ increment(); | ||
let scrollingDisabled = isDisabled || isReadOnly || !focusWithin; | ||
$ebb253b0ca493f114f41772a028a$var$useScrollWheel({ | ||
useScrollWheel({ | ||
onScroll: onWheel, | ||
capture: false, | ||
isDisabled: scrollingDisabled | ||
@@ -307,77 +291,2 @@ }, inputRef); // The inputMode attribute influences the software keyboard that is shown on touch devices. | ||
let stateRef = useRef(state); | ||
stateRef.current = state; // All browsers implement the 'beforeinput' event natively except Firefox | ||
// (currently behind a flag as of Firefox 84). React's polyfill does not | ||
// run in all cases that the native event fires, e.g. when deleting text. | ||
// Use the native event if available so that we can prevent invalid deletions. | ||
// We do not attempt to polyfill this in Firefox since it would be very complicated, | ||
// the benefit of doing so is fairly minor, and it's going to be natively supported soon. | ||
useEffect(() => { | ||
if (!$ebb253b0ca493f114f41772a028a$var$supportsNativeBeforeInputEvent()) { | ||
return; | ||
} | ||
let input = inputRef.current; | ||
let onBeforeInput = e => { | ||
let state = stateRef.current; // Compute the next value of the input if the event is allowed to proceed. | ||
// See https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes for a full list of input types. | ||
let nextValue; | ||
switch (e.inputType) { | ||
case 'historyUndo': | ||
case 'historyRedo': | ||
// Explicitly allow undo/redo. e.data is null in this case, but there's no need to validate, | ||
// because presumably the input would have already been validated previously. | ||
return; | ||
case 'deleteContent': | ||
case 'deleteByCut': | ||
case 'deleteByDrag': | ||
nextValue = input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentForward': | ||
// This is potentially incorrect, since the browser may actually delete more than a single UTF-16 | ||
// character. In reality, a full Unicode grapheme cluster consisting of multiple UTF-16 characters | ||
// or code points may be deleted. However, in our currently supported locales, there are no such cases. | ||
// If we support additional locales in the future, this may need to change. | ||
nextValue = input.selectionEnd === input.selectionStart ? input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd + 1) : input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentBackward': | ||
nextValue = input.selectionEnd === input.selectionStart ? input.value.slice(0, input.selectionStart - 1) + input.value.slice(input.selectionStart) : input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
default: | ||
if (e.data != null) { | ||
nextValue = input.value.slice(0, input.selectionStart) + e.data + input.value.slice(input.selectionEnd); | ||
} | ||
break; | ||
} // If we did not compute a value, or the new value is invalid, prevent the event | ||
// so that the browser does not update the input text, move the selection, or add to | ||
// the undo/redo stack. | ||
if (nextValue == null || !state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
}; | ||
input.addEventListener('beforeinput', onBeforeInput, false); | ||
return () => { | ||
input.removeEventListener('beforeinput', onBeforeInput, false); | ||
}; | ||
}, [inputRef, stateRef]); | ||
let onBeforeInput = !$ebb253b0ca493f114f41772a028a$var$supportsNativeBeforeInputEvent() ? e => { | ||
let nextValue = e.target.value.slice(0, e.target.selectionStart) + e.data + e.target.value.slice(e.target.selectionEnd); | ||
if (!state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
} : null; | ||
let onChange = value => { | ||
@@ -387,7 +296,6 @@ state.setInputValue(value); | ||
let compositionStartState = useRef(null); | ||
let { | ||
labelProps, | ||
inputProps: textFieldProps | ||
} = useTextField({ | ||
} = useFormattedTextField({ | ||
label, | ||
@@ -407,46 +315,4 @@ autoFocus, | ||
inputMode, | ||
onChange, | ||
onBeforeInput, | ||
onCompositionStart() { | ||
// Chrome does not implement Input Events Level 2, which specifies the insertFromComposition | ||
// and deleteByComposition inputType values for the beforeinput event. These are meant to occur | ||
// at the end of a composition (e.g. Pinyin IME, Android auto correct, etc.), and crucially, are | ||
// cancelable. The insertCompositionText and deleteCompositionText input types are not cancelable, | ||
// nor would we want to cancel them because the input from the user is incomplete at that point. | ||
// In Safari, insertFromComposition/deleteFromComposition will fire, however, allowing us to cancel | ||
// the final composition result if it is invalid. As a fallback for Chrome and Firefox, which either | ||
// don't support Input Events Level 2, or beforeinput at all, we store the state of the input when | ||
// the compositionstart event fires, and undo the changes in compositionend (below) if it is invalid. | ||
// Unfortunately, this messes up the undo/redo stack, but until insertFromComposition/deleteByComposition | ||
// are implemented, there is no other way to prevent composed input. | ||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1022204 | ||
let { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
} = inputRef.current; | ||
compositionStartState.current = { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
}; | ||
}, | ||
onCompositionEnd() { | ||
if (!state.validate(inputRef.current.value)) { | ||
// Restore the input value in the DOM immediately so we can synchronously update the selection position. | ||
// But also update the value in React state as well so it is correct for future updates. | ||
let { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
} = compositionStartState.current; | ||
inputRef.current.value = value; | ||
inputRef.current.setSelectionRange(selectionStart, selectionEnd); | ||
state.setInputValue(value); | ||
} | ||
} | ||
}, inputRef); | ||
onChange | ||
}, state, inputRef); | ||
let inputProps = mergeProps(spinButtonProps, textFieldProps, focusProps, { | ||
@@ -536,27 +402,5 @@ // override the spinbutton role, we can't focus a spin button with VO | ||
}; | ||
} // scroll wheel needs to be added not passively so it's cancelable, small helper hook to remember that | ||
} | ||
exports.useNumberField = useNumberField; | ||
function $ebb253b0ca493f114f41772a028a$var$useScrollWheel(_ref, ref) { | ||
let { | ||
onScroll, | ||
capture, | ||
isDisabled | ||
} = _ref; | ||
useEffect(() => { | ||
let elem = ref.current; | ||
if (!isDisabled) { | ||
elem.addEventListener('wheel', onScroll, capture); | ||
} | ||
return () => { | ||
if (!isDisabled) { | ||
elem.removeEventListener('wheel', onScroll, capture); | ||
} | ||
}; | ||
}, [onScroll, ref, capture, isDisabled]); | ||
} | ||
//# sourceMappingURL=main.js.map |
@@ -1,7 +0,7 @@ | ||
import { useTextField } from "@react-aria/textfield"; | ||
import { useSpinButton } from "@react-aria/spinbutton"; | ||
import { useMessageFormatter, useNumberFormatter } from "@react-aria/i18n"; | ||
import { useFocus, useFocusWithin } from "@react-aria/interactions"; | ||
import { useFormattedTextField } from "@react-aria/textfield"; | ||
import { useFocus, useFocusWithin, useScrollWheel } from "@react-aria/interactions"; | ||
import { isAndroid, isIOS, isIPhone, mergeProps, useId } from "@react-aria/utils"; | ||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; | ||
import { useCallback, useMemo, useState } from "react"; | ||
import _babelRuntimeHelpersEsmInteropRequireDefault from "@babel/runtime/helpers/esm/interopRequireDefault"; | ||
@@ -149,6 +149,2 @@ import _babelRuntimeHelpersEsmExtends from "@babel/runtime/helpers/esm/extends"; | ||
function $b40e566e8b7705a138eb78aae622eee$var$supportsNativeBeforeInputEvent() { | ||
return typeof window !== 'undefined' && window.InputEvent && // @ts-ignore | ||
typeof InputEvent.prototype.getTargetRanges === 'function'; | ||
} | ||
/** | ||
@@ -158,4 +154,2 @@ * Provides the behavior and accessibility implementation for a number field component. | ||
*/ | ||
export function useNumberField(props, state, inputRef) { | ||
@@ -219,10 +213,2 @@ let { | ||
let onWheel = useCallback(e => { | ||
// If the ctrlKey is pressed, this is a zoom event, do nothing. | ||
if (e.ctrlKey) { | ||
return; | ||
} // stop scrolling the page | ||
e.preventDefault(); | ||
if (e.deltaY > 0) { | ||
@@ -236,5 +222,4 @@ increment(); | ||
let scrollingDisabled = isDisabled || isReadOnly || !focusWithin; | ||
$b40e566e8b7705a138eb78aae622eee$var$useScrollWheel({ | ||
useScrollWheel({ | ||
onScroll: onWheel, | ||
capture: false, | ||
isDisabled: scrollingDisabled | ||
@@ -271,77 +256,2 @@ }, inputRef); // The inputMode attribute influences the software keyboard that is shown on touch devices. | ||
let stateRef = useRef(state); | ||
stateRef.current = state; // All browsers implement the 'beforeinput' event natively except Firefox | ||
// (currently behind a flag as of Firefox 84). React's polyfill does not | ||
// run in all cases that the native event fires, e.g. when deleting text. | ||
// Use the native event if available so that we can prevent invalid deletions. | ||
// We do not attempt to polyfill this in Firefox since it would be very complicated, | ||
// the benefit of doing so is fairly minor, and it's going to be natively supported soon. | ||
useEffect(() => { | ||
if (!$b40e566e8b7705a138eb78aae622eee$var$supportsNativeBeforeInputEvent()) { | ||
return; | ||
} | ||
let input = inputRef.current; | ||
let onBeforeInput = e => { | ||
let state = stateRef.current; // Compute the next value of the input if the event is allowed to proceed. | ||
// See https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes for a full list of input types. | ||
let nextValue; | ||
switch (e.inputType) { | ||
case 'historyUndo': | ||
case 'historyRedo': | ||
// Explicitly allow undo/redo. e.data is null in this case, but there's no need to validate, | ||
// because presumably the input would have already been validated previously. | ||
return; | ||
case 'deleteContent': | ||
case 'deleteByCut': | ||
case 'deleteByDrag': | ||
nextValue = input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentForward': | ||
// This is potentially incorrect, since the browser may actually delete more than a single UTF-16 | ||
// character. In reality, a full Unicode grapheme cluster consisting of multiple UTF-16 characters | ||
// or code points may be deleted. However, in our currently supported locales, there are no such cases. | ||
// If we support additional locales in the future, this may need to change. | ||
nextValue = input.selectionEnd === input.selectionStart ? input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd + 1) : input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentBackward': | ||
nextValue = input.selectionEnd === input.selectionStart ? input.value.slice(0, input.selectionStart - 1) + input.value.slice(input.selectionStart) : input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
default: | ||
if (e.data != null) { | ||
nextValue = input.value.slice(0, input.selectionStart) + e.data + input.value.slice(input.selectionEnd); | ||
} | ||
break; | ||
} // If we did not compute a value, or the new value is invalid, prevent the event | ||
// so that the browser does not update the input text, move the selection, or add to | ||
// the undo/redo stack. | ||
if (nextValue == null || !state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
}; | ||
input.addEventListener('beforeinput', onBeforeInput, false); | ||
return () => { | ||
input.removeEventListener('beforeinput', onBeforeInput, false); | ||
}; | ||
}, [inputRef, stateRef]); | ||
let onBeforeInput = !$b40e566e8b7705a138eb78aae622eee$var$supportsNativeBeforeInputEvent() ? e => { | ||
let nextValue = e.target.value.slice(0, e.target.selectionStart) + e.data + e.target.value.slice(e.target.selectionEnd); | ||
if (!state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
} : null; | ||
let onChange = value => { | ||
@@ -351,7 +261,6 @@ state.setInputValue(value); | ||
let compositionStartState = useRef(null); | ||
let { | ||
labelProps, | ||
inputProps: textFieldProps | ||
} = useTextField({ | ||
} = useFormattedTextField({ | ||
label, | ||
@@ -371,46 +280,4 @@ autoFocus, | ||
inputMode, | ||
onChange, | ||
onBeforeInput, | ||
onCompositionStart() { | ||
// Chrome does not implement Input Events Level 2, which specifies the insertFromComposition | ||
// and deleteByComposition inputType values for the beforeinput event. These are meant to occur | ||
// at the end of a composition (e.g. Pinyin IME, Android auto correct, etc.), and crucially, are | ||
// cancelable. The insertCompositionText and deleteCompositionText input types are not cancelable, | ||
// nor would we want to cancel them because the input from the user is incomplete at that point. | ||
// In Safari, insertFromComposition/deleteFromComposition will fire, however, allowing us to cancel | ||
// the final composition result if it is invalid. As a fallback for Chrome and Firefox, which either | ||
// don't support Input Events Level 2, or beforeinput at all, we store the state of the input when | ||
// the compositionstart event fires, and undo the changes in compositionend (below) if it is invalid. | ||
// Unfortunately, this messes up the undo/redo stack, but until insertFromComposition/deleteByComposition | ||
// are implemented, there is no other way to prevent composed input. | ||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1022204 | ||
let { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
} = inputRef.current; | ||
compositionStartState.current = { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
}; | ||
}, | ||
onCompositionEnd() { | ||
if (!state.validate(inputRef.current.value)) { | ||
// Restore the input value in the DOM immediately so we can synchronously update the selection position. | ||
// But also update the value in React state as well so it is correct for future updates. | ||
let { | ||
value, | ||
selectionStart, | ||
selectionEnd | ||
} = compositionStartState.current; | ||
inputRef.current.value = value; | ||
inputRef.current.setSelectionRange(selectionStart, selectionEnd); | ||
state.setInputValue(value); | ||
} | ||
} | ||
}, inputRef); | ||
onChange | ||
}, state, inputRef); | ||
let inputProps = mergeProps(spinButtonProps, textFieldProps, focusProps, { | ||
@@ -500,24 +367,3 @@ // override the spinbutton role, we can't focus a spin button with VO | ||
}; | ||
} // scroll wheel needs to be added not passively so it's cancelable, small helper hook to remember that | ||
function $b40e566e8b7705a138eb78aae622eee$var$useScrollWheel(_ref, ref) { | ||
let { | ||
onScroll, | ||
capture, | ||
isDisabled | ||
} = _ref; | ||
useEffect(() => { | ||
let elem = ref.current; | ||
if (!isDisabled) { | ||
elem.addEventListener('wheel', onScroll, capture); | ||
} | ||
return () => { | ||
if (!isDisabled) { | ||
elem.removeEventListener('wheel', onScroll, capture); | ||
} | ||
}; | ||
}, [onScroll, ref, capture, isDisabled]); | ||
} | ||
//# sourceMappingURL=module.js.map |
{ | ||
"name": "@react-aria/numberfield", | ||
"version": "3.0.0-nightly.992+d1844573", | ||
"version": "3.0.0-nightly.994+faa93480", | ||
"description": "Spectrum UI components in React", | ||
@@ -21,13 +21,13 @@ "license": "Apache-2.0", | ||
"@babel/runtime": "^7.6.2", | ||
"@react-aria/i18n": "3.0.0-nightly.992+d1844573", | ||
"@react-aria/interactions": "3.0.0-nightly.992+d1844573", | ||
"@react-aria/live-announcer": "3.0.0-nightly.992+d1844573", | ||
"@react-aria/spinbutton": "3.0.0-nightly.992+d1844573", | ||
"@react-aria/textfield": "3.0.0-nightly.992+d1844573", | ||
"@react-aria/utils": "3.0.0-nightly.992+d1844573", | ||
"@react-stately/numberfield": "3.0.0-nightly.992+d1844573", | ||
"@react-types/button": "3.3.2-nightly.2672+d1844573", | ||
"@react-types/numberfield": "3.0.0-nightly.2672+d1844573", | ||
"@react-types/shared": "3.0.0-nightly.992+d1844573", | ||
"@react-types/textfield": "3.0.0-nightly.992+d1844573" | ||
"@react-aria/i18n": "3.0.0-nightly.994+faa93480", | ||
"@react-aria/interactions": "3.0.0-nightly.994+faa93480", | ||
"@react-aria/live-announcer": "3.0.0-nightly.994+faa93480", | ||
"@react-aria/spinbutton": "3.0.0-nightly.994+faa93480", | ||
"@react-aria/textfield": "3.0.0-nightly.994+faa93480", | ||
"@react-aria/utils": "3.0.0-nightly.994+faa93480", | ||
"@react-stately/numberfield": "3.0.0-nightly.994+faa93480", | ||
"@react-types/button": "3.3.2-nightly.2674+faa93480", | ||
"@react-types/numberfield": "3.0.0-nightly.2674+faa93480", | ||
"@react-types/shared": "3.0.0-nightly.994+faa93480", | ||
"@react-types/textfield": "3.0.0-nightly.994+faa93480" | ||
}, | ||
@@ -40,3 +40,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "d1844573fa992f7a34285ebafdc08cb407829095" | ||
"gitHead": "faa9348097bf62403e37e32daf897cdad5512e09" | ||
} |
@@ -21,5 +21,3 @@ /* | ||
useCallback, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
useState | ||
@@ -33,2 +31,3 @@ } from 'react'; | ||
import {useFocus, useFocusWithin} from '@react-aria/interactions'; | ||
import {useFormattedTextField} from '@react-aria/textfield'; | ||
import { | ||
@@ -38,4 +37,4 @@ useMessageFormatter, | ||
} from '@react-aria/i18n'; | ||
import {useScrollWheel} from '@react-aria/interactions'; | ||
import {useSpinButton} from '@react-aria/spinbutton'; | ||
import {useTextField} from '@react-aria/textfield'; | ||
@@ -55,9 +54,2 @@ interface NumberFieldAria { | ||
function supportsNativeBeforeInputEvent() { | ||
return typeof window !== 'undefined' && | ||
window.InputEvent && | ||
// @ts-ignore | ||
typeof InputEvent.prototype.getTargetRanges === 'function'; | ||
} | ||
/** | ||
@@ -127,10 +119,2 @@ * Provides the behavior and accessibility implementation for a number field component. | ||
let onWheel = useCallback((e) => { | ||
// If the ctrlKey is pressed, this is a zoom event, do nothing. | ||
if (e.ctrlKey) { | ||
return; | ||
} | ||
// stop scrolling the page | ||
e.preventDefault(); | ||
if (e.deltaY > 0) { | ||
@@ -144,3 +128,3 @@ increment(); | ||
let scrollingDisabled = isDisabled || isReadOnly || !focusWithin; | ||
useScrollWheel({onScroll: onWheel, capture: false, isDisabled: scrollingDisabled}, inputRef); | ||
useScrollWheel({onScroll: onWheel, isDisabled: scrollingDisabled}, inputRef); | ||
@@ -175,86 +159,2 @@ // The inputMode attribute influences the software keyboard that is shown on touch devices. | ||
let stateRef = useRef(state); | ||
stateRef.current = state; | ||
// All browsers implement the 'beforeinput' event natively except Firefox | ||
// (currently behind a flag as of Firefox 84). React's polyfill does not | ||
// run in all cases that the native event fires, e.g. when deleting text. | ||
// Use the native event if available so that we can prevent invalid deletions. | ||
// We do not attempt to polyfill this in Firefox since it would be very complicated, | ||
// the benefit of doing so is fairly minor, and it's going to be natively supported soon. | ||
useEffect(() => { | ||
if (!supportsNativeBeforeInputEvent()) { | ||
return; | ||
} | ||
let input = inputRef.current; | ||
let onBeforeInput = (e: InputEvent) => { | ||
let state = stateRef.current; | ||
// Compute the next value of the input if the event is allowed to proceed. | ||
// See https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes for a full list of input types. | ||
let nextValue: string; | ||
switch (e.inputType) { | ||
case 'historyUndo': | ||
case 'historyRedo': | ||
// Explicitly allow undo/redo. e.data is null in this case, but there's no need to validate, | ||
// because presumably the input would have already been validated previously. | ||
return; | ||
case 'deleteContent': | ||
case 'deleteByCut': | ||
case 'deleteByDrag': | ||
nextValue = input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentForward': | ||
// This is potentially incorrect, since the browser may actually delete more than a single UTF-16 | ||
// character. In reality, a full Unicode grapheme cluster consisting of multiple UTF-16 characters | ||
// or code points may be deleted. However, in our currently supported locales, there are no such cases. | ||
// If we support additional locales in the future, this may need to change. | ||
nextValue = input.selectionEnd === input.selectionStart | ||
? input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd + 1) | ||
: input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
case 'deleteContentBackward': | ||
nextValue = input.selectionEnd === input.selectionStart | ||
? input.value.slice(0, input.selectionStart - 1) + input.value.slice(input.selectionStart) | ||
: input.value.slice(0, input.selectionStart) + input.value.slice(input.selectionEnd); | ||
break; | ||
default: | ||
if (e.data != null) { | ||
nextValue = | ||
input.value.slice(0, input.selectionStart) + | ||
e.data + | ||
input.value.slice(input.selectionEnd); | ||
} | ||
break; | ||
} | ||
// If we did not compute a value, or the new value is invalid, prevent the event | ||
// so that the browser does not update the input text, move the selection, or add to | ||
// the undo/redo stack. | ||
if (nextValue == null || !state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
}; | ||
input.addEventListener('beforeinput', onBeforeInput, false); | ||
return () => { | ||
input.removeEventListener('beforeinput', onBeforeInput, false); | ||
}; | ||
}, [inputRef, stateRef]); | ||
let onBeforeInput = !supportsNativeBeforeInputEvent() | ||
? e => { | ||
let nextValue = | ||
e.target.value.slice(0, e.target.selectionStart) + | ||
e.data + | ||
e.target.value.slice(e.target.selectionEnd); | ||
if (!state.validate(nextValue)) { | ||
e.preventDefault(); | ||
} | ||
} | ||
: null; | ||
let onChange = value => { | ||
@@ -264,4 +164,3 @@ state.setInputValue(value); | ||
let compositionStartState = useRef(null); | ||
let {labelProps, inputProps: textFieldProps} = useTextField({ | ||
let {labelProps, inputProps: textFieldProps} = useFormattedTextField({ | ||
label, | ||
@@ -280,31 +179,4 @@ autoFocus, | ||
inputMode, | ||
onChange, | ||
onBeforeInput, | ||
onCompositionStart() { | ||
// Chrome does not implement Input Events Level 2, which specifies the insertFromComposition | ||
// and deleteByComposition inputType values for the beforeinput event. These are meant to occur | ||
// at the end of a composition (e.g. Pinyin IME, Android auto correct, etc.), and crucially, are | ||
// cancelable. The insertCompositionText and deleteCompositionText input types are not cancelable, | ||
// nor would we want to cancel them because the input from the user is incomplete at that point. | ||
// In Safari, insertFromComposition/deleteFromComposition will fire, however, allowing us to cancel | ||
// the final composition result if it is invalid. As a fallback for Chrome and Firefox, which either | ||
// don't support Input Events Level 2, or beforeinput at all, we store the state of the input when | ||
// the compositionstart event fires, and undo the changes in compositionend (below) if it is invalid. | ||
// Unfortunately, this messes up the undo/redo stack, but until insertFromComposition/deleteByComposition | ||
// are implemented, there is no other way to prevent composed input. | ||
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1022204 | ||
let {value, selectionStart, selectionEnd} = inputRef.current; | ||
compositionStartState.current = {value, selectionStart, selectionEnd}; | ||
}, | ||
onCompositionEnd() { | ||
if (!state.validate(inputRef.current.value)) { | ||
// Restore the input value in the DOM immediately so we can synchronously update the selection position. | ||
// But also update the value in React state as well so it is correct for future updates. | ||
let {value, selectionStart, selectionEnd} = compositionStartState.current; | ||
inputRef.current.value = value; | ||
inputRef.current.setSelectionRange(selectionStart, selectionEnd); | ||
state.setInputValue(value); | ||
} | ||
} | ||
}, inputRef); | ||
onChange | ||
}, state, inputRef); | ||
@@ -400,18 +272,1 @@ let inputProps = mergeProps( | ||
} | ||
// scroll wheel needs to be added not passively so it's cancelable, small helper hook to remember that | ||
function useScrollWheel({onScroll, capture, isDisabled}: {onScroll: (e) => void, capture: boolean, isDisabled: boolean}, ref: RefObject<HTMLElement>) { | ||
useEffect(() => { | ||
let elem = ref.current; | ||
if (!isDisabled) { | ||
elem.addEventListener('wheel', onScroll, capture); | ||
} | ||
return () => { | ||
if (!isDisabled) { | ||
elem.removeEventListener('wheel', onScroll, capture); | ||
} | ||
}; | ||
}, [onScroll, ref, capture, isDisabled]); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
118999
997