UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

260 lines (256 loc) • 7.25 kB
"use client"; import { createContext as createContext$1 } from "../../utils/context.js"; import { useSafeLayoutEffect, useUpdateEffect } from "../../utils/effect.js"; import { mergeRefs, useCallbackRef } from "../../utils/ref.js"; import { utils_exports } from "../../utils/index.js"; import { useControllableState } from "../../hooks/use-controllable-state/index.js"; import { useFieldProps } from "../field/use-field-props.js"; import { useFocusOnPointerDown } from "../../hooks/use-focus/index.js"; import { useCallback, useEffect, useRef, useState } from "react"; //#region src/components/editable/use-editable.ts const [EditableContext, useEditableContext] = createContext$1({ name: "EditableContext" }); const useEditable = (props = {}) => { const { props: { id, defaultValue, disabled, placeholder, previewFocusable = true, readOnly, required, selectAllOnFocus = true, startWithEditView, submitOnBlur = true, value: valueProp, onCancel: onCancelProp, onChange: onChangeProp, onEdit: onEditProp, onSubmit: onSubmitProp,...rest }, ariaProps, dataProps, eventProps } = useFieldProps(props); const onEditRef = useCallbackRef(onEditProp); const [editing, setEditing] = useState(!!startWithEditView && !disabled); const [value, setValue] = useControllableState({ defaultValue: defaultValue || "", value: valueProp, onChange: onChangeProp }); const interactive = !editing && !disabled; const emptyValue = value.length === 0; const [prevValue, setPrevValue] = useState(value); const inputRef = useRef(null); const previewRef = useRef(null); const editRef = useRef(null); const cancelRef = useRef(null); const submitRef = useRef(null); const onChange = useCallback((ev) => setValue(ev.currentTarget.value), [setValue]); const onUpdatePrevValue = useCallback(() => setPrevValue(value), [value]); const onEdit = useCallback(() => { if (interactive) setEditing(true); }, [interactive]); const onCancel = useCallback(() => { setEditing(false); setValue(prevValue); onCancelProp?.(prevValue); }, [ prevValue, onCancelProp, setValue ]); const onSubmit = useCallback(() => { setEditing(false); setPrevValue(value); onSubmitProp?.(value); }, [onSubmitProp, value]); const onKeyDown = useCallback((ev) => { if (ev.key !== "Escape" && ev.key !== "Enter") return; ev.preventDefault(); if (ev.key === "Escape") onCancel(); else { const { metaKey, shiftKey } = ev; if (!shiftKey && !metaKey) onSubmit(); } }, [onCancel, onSubmit]); const onKeyDownWithoutSubmit = useCallback((ev) => { if (ev.key !== "Escape") return; ev.preventDefault(); onCancel(); }, [onCancel]); const onBlur = useCallback((ev) => { if (!editing) return; const ownerDocument = ev.currentTarget.ownerDocument; const relatedTarget = ev.relatedTarget ?? ownerDocument.activeElement; const targetIsCancel = (0, utils_exports.contains)(cancelRef.current, relatedTarget); const targetIsSubmit = (0, utils_exports.contains)(submitRef.current, relatedTarget); if (!(!targetIsCancel && !targetIsSubmit)) return; if (submitOnBlur) onSubmit(); else onCancel(); }, [ editing, submitOnBlur, onSubmit, onCancel ]); useFocusOnPointerDown({ ref: inputRef, elements: [cancelRef, submitRef], enabled: editing }); useSafeLayoutEffect(() => { if (!editing) return; inputRef.current?.focus(); if (selectAllOnFocus) inputRef.current?.select(); }, []); useUpdateEffect(() => { if (!editing) { editRef.current?.focus(); return; } inputRef.current?.focus(); if (selectAllOnFocus) inputRef.current?.select(); onEditRef(); }, [ editing, onEditRef, selectAllOnFocus ]); useEffect(() => { if (editing) return; const el = inputRef.current; if (el?.ownerDocument.activeElement === el) el?.blur(); }, [editing]); const getRootProps = useCallback((props$1) => ({ ...rest, ...dataProps, ...props$1 }), [rest, dataProps]); const getPreviewProps = useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...props$1, ref: mergeRefs(previewRef, ref), children: emptyValue ? placeholder : value, hidden: editing, tabIndex: interactive && previewFocusable ? 0 : void 0, onFocus: (0, utils_exports.handlerAll)(props$1.onFocus, onEdit, onUpdatePrevValue) }), [ dataProps, editing, interactive, previewFocusable, emptyValue, onEdit, onUpdatePrevValue, placeholder, value ]); const getInputProps = useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...ariaProps, ...props$1, id, ref: mergeRefs(inputRef, ref), disabled, hidden: !editing, placeholder, readOnly, required, value, onBlur: (0, utils_exports.handlerAll)(eventProps.onBlur, props$1.onBlur, onBlur), onChange: (0, utils_exports.handlerAll)(props$1.onChange, onChange), onFocus: (0, utils_exports.handlerAll)(eventProps.onFocus, props$1.onFocus, onUpdatePrevValue), onKeyDown: (0, utils_exports.handlerAll)(props$1.onKeyDown, onKeyDown) }), [ dataProps, ariaProps, id, disabled, editing, placeholder, readOnly, required, value, eventProps.onBlur, eventProps.onFocus, onBlur, onChange, onUpdatePrevValue, onKeyDown ]); const getTextareaProps = useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...ariaProps, ...props$1, id, ref: mergeRefs(inputRef, ref), disabled, hidden: !editing, placeholder, readOnly, required, value, onBlur: (0, utils_exports.handlerAll)(eventProps.onBlur, props$1.onBlur, onBlur), onChange: (0, utils_exports.handlerAll)(props$1.onChange, onChange), onFocus: (0, utils_exports.handlerAll)(eventProps.onFocus, props$1.onFocus, onUpdatePrevValue), onKeyDown: (0, utils_exports.handlerAll)(props$1.onKeyDown, onKeyDownWithoutSubmit) }), [ dataProps, ariaProps, id, disabled, editing, placeholder, readOnly, required, value, eventProps.onBlur, eventProps.onFocus, onBlur, onChange, onUpdatePrevValue, onKeyDownWithoutSubmit ]); const getControlProps = useCallback((props$1) => ({ ...dataProps, role: "group", ...props$1 }), [dataProps]); const getEditProps = useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...props$1, ref: mergeRefs(editRef, ref), disabled, hidden: editing, onClick: (0, utils_exports.handlerAll)(props$1.onClick, onEdit) }), [ dataProps, disabled, editing, onEdit ]); const getSubmitProps = useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...props$1, ref: mergeRefs(submitRef, ref), disabled, hidden: !editing, onClick: (0, utils_exports.handlerAll)(props$1.onClick, onSubmit) }), [ dataProps, disabled, editing, onSubmit ]); return { editing, value, getCancelProps: useCallback(({ ref,...props$1 } = {}) => ({ ...dataProps, ...props$1, ref: mergeRefs(cancelRef, ref), disabled, hidden: !editing, onClick: (0, utils_exports.handlerAll)(props$1.onClick, onCancel) }), [ dataProps, disabled, editing, onCancel ]), getControlProps, getEditProps, getInputProps, getPreviewProps, getRootProps, getSubmitProps, getTextareaProps, onCancel, onEdit, onSubmit }; }; //#endregion export { EditableContext, useEditable, useEditableContext }; //# sourceMappingURL=use-editable.js.map