{"mappings":"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","sources":["packages/react-aria/src/textfield/useFormattedTextField.ts"],"sourcesContent":["/*\n * Copyright 2021 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 {AriaTextFieldProps, TextFieldAria, useTextField} from './useTextField';\nimport {getEventTarget} from '../utils/shadowdom/DOMFunctions';\nimport {InputEventHandler, useEffect, useRef} from 'react';\nimport {mergeProps} from '../utils/mergeProps';\nimport {RefObject} from '@react-types/shared';\nimport {useEffectEvent} from '../utils/useEffectEvent';\n\ninterface FormattedTextFieldState {\n  validate: (val: string) => boolean;\n  setInputValue: (val: string) => void;\n}\n\nfunction supportsNativeBeforeInputEvent() {\n  return (\n    typeof window !== 'undefined' &&\n    window.InputEvent &&\n    typeof InputEvent.prototype.getTargetRanges === 'function'\n  );\n}\n\nexport function useFormattedTextField(\n  props: AriaTextFieldProps,\n  state: FormattedTextFieldState,\n  inputRef: RefObject<HTMLInputElement | null>\n): TextFieldAria {\n  // All browsers implement the 'beforeinput' event natively except Firefox\n  // (currently behind a flag as of Firefox 84). React's polyfill does not\n  // run in all cases that the native event fires, e.g. when deleting text.\n  // Use the native event if available so that we can prevent invalid deletions.\n  // We do not attempt to polyfill this in Firefox since it would be very complicated,\n  // the benefit of doing so is fairly minor, and it's going to be natively supported soon.\n  let onBeforeInputFallback = useEffectEvent((e: InputEvent) => {\n    let input = inputRef.current;\n    if (!input) {\n      return;\n    }\n\n    // Compute the next value of the input if the event is allowed to proceed.\n    // See https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes for a full list of input types.\n    let nextValue: string | null = null;\n    switch (e.inputType) {\n      case 'historyUndo':\n      case 'historyRedo':\n        // Explicitly allow undo/redo. e.data is null in this case, but there's no need to validate,\n        // because presumably the input would have already been validated previously.\n        return;\n      case 'insertLineBreak':\n        // Explicitly allow \"insertLineBreak\" event, to allow onSubmit for \"enter\" key. e.data is null in this case.\n        return;\n      case 'deleteContent':\n      case 'deleteByCut':\n      case 'deleteByDrag':\n        nextValue =\n          input.value.slice(0, input.selectionStart!) + input.value.slice(input.selectionEnd!);\n        break;\n      case 'deleteContentForward':\n        // This is potentially incorrect, since the browser may actually delete more than a single UTF-16\n        // character. In reality, a full Unicode grapheme cluster consisting of multiple UTF-16 characters\n        // or code points may be deleted. However, in our currently supported locales, there are no such cases.\n        // If we support additional locales in the future, this may need to change.\n        nextValue =\n          input.selectionEnd === input.selectionStart\n            ? input.value.slice(0, input.selectionStart!) +\n              input.value.slice(input.selectionEnd! + 1)\n            : input.value.slice(0, input.selectionStart!) + input.value.slice(input.selectionEnd!);\n        break;\n      case 'deleteContentBackward':\n        nextValue =\n          input.selectionEnd === input.selectionStart\n            ? input.value.slice(0, input.selectionStart! - 1) +\n              input.value.slice(input.selectionStart!)\n            : input.value.slice(0, input.selectionStart!) + input.value.slice(input.selectionEnd!);\n        break;\n      case 'deleteSoftLineBackward':\n      case 'deleteHardLineBackward':\n        nextValue = input.value.slice(input.selectionStart!);\n        break;\n      default:\n        if (e.data != null) {\n          nextValue =\n            input.value.slice(0, input.selectionStart!) +\n            e.data +\n            input.value.slice(input.selectionEnd!);\n        }\n        break;\n    }\n\n    // If we did not compute a value, or the new value is invalid, prevent the event\n    // so that the browser does not update the input text, move the selection, or add to\n    // the undo/redo stack.\n    if (nextValue == null || !state.validate(nextValue)) {\n      e.preventDefault();\n    }\n  });\n\n  useEffect(() => {\n    if (!supportsNativeBeforeInputEvent() || !inputRef.current) {\n      return;\n    }\n\n    let input = inputRef.current;\n    input.addEventListener('beforeinput', onBeforeInputFallback, false);\n    return () => {\n      input.removeEventListener('beforeinput', onBeforeInputFallback, false);\n    };\n  }, [inputRef]);\n\n  let onBeforeInput: InputEventHandler<HTMLInputElement> | null = !supportsNativeBeforeInputEvent()\n    ? e => {\n        let nextValue =\n          getEventTarget(e).value.slice(0, getEventTarget(e).selectionStart!) +\n          e.data +\n          getEventTarget(e).value.slice(getEventTarget(e).selectionEnd!);\n\n        if (!state.validate(nextValue)) {\n          e.preventDefault();\n        }\n      }\n    : null;\n\n  let {\n    labelProps,\n    inputProps: textFieldProps,\n    descriptionProps,\n    errorMessageProps,\n    ...validation\n  } = useTextField(props, inputRef);\n\n  let compositionStartState = useRef<{\n    value: string;\n    selectionStart: number | null;\n    selectionEnd: number | null;\n  } | null>(null);\n  return {\n    inputProps: mergeProps(textFieldProps, {\n      onBeforeInput,\n      onCompositionStart() {\n        // Chrome does not implement Input Events Level 2, which specifies the insertFromComposition\n        // and deleteByComposition inputType values for the beforeinput event. These are meant to occur\n        // at the end of a composition (e.g. Pinyin IME, Android auto correct, etc.), and crucially, are\n        // cancelable. The insertCompositionText and deleteCompositionText input types are not cancelable,\n        // nor would we want to cancel them because the input from the user is incomplete at that point.\n        // In Safari, insertFromComposition/deleteFromComposition will fire, however, allowing us to cancel\n        // the final composition result if it is invalid. As a fallback for Chrome and Firefox, which either\n        // don't support Input Events Level 2, or beforeinput at all, we store the state of the input when\n        // the compositionstart event fires, and undo the changes in compositionend (below) if it is invalid.\n        // Unfortunately, this messes up the undo/redo stack, but until insertFromComposition/deleteByComposition\n        // are implemented, there is no other way to prevent composed input.\n        // See https://bugs.chromium.org/p/chromium/issues/detail?id=1022204\n        let {value, selectionStart, selectionEnd} = inputRef.current!;\n        compositionStartState.current = {value, selectionStart, selectionEnd};\n      },\n      onCompositionEnd() {\n        if (inputRef.current && !state.validate(inputRef.current.value)) {\n          // Restore the input value in the DOM immediately so we can synchronously update the selection position.\n          // But also update the value in React state as well so it is correct for future updates.\n          let {value, selectionStart, selectionEnd} = compositionStartState.current!;\n          inputRef.current.value = value;\n          inputRef.current.setSelectionRange(selectionStart, selectionEnd);\n          state.setInputValue(value);\n        }\n      }\n    }),\n    labelProps,\n    descriptionProps,\n    errorMessageProps,\n    ...validation\n  };\n}\n"],"names":[],"version":3,"file":"useFormattedTextField.cjs.map"}