UNPKG

rsuite

Version:

A suite of react components

126 lines (125 loc) • 4.5 kB
'use client'; import _extends from "@babel/runtime/helpers/esm/extends"; import React, { useCallback, useRef, useEffect, useState } from 'react'; import Modal from "../Modal/index.js"; import Button from "../Button/index.js"; import Input from "../Input/index.js"; import Text from "../Text/index.js"; import { forwardRef } from "../internals/utils/index.js"; import { VStack } from "../Stack/index.js"; import { useCustom } from "../internals/hooks/index.js"; const severityMap = { info: 'blue', success: 'green', warning: 'orange', error: 'red' }; const Dialog = forwardRef((props, ref) => { const { getLocale, propsWithDefaults } = useCustom('Dialog', props); const locale = getLocale('Dialog'); const { type, title = type === 'alert' ? locale.alert : locale.confirm, content, okText = locale.ok, cancelText = locale.cancel, severity, defaultValue = '', validate, onClose, onKeyDown, ...rest } = propsWithDefaults; const [isOpen, setIsOpen] = useState(true); const [validationError, setValidationError] = useState(); const inputRef = useRef(null); const inputValue = useRef(defaultValue); const isClosing = useRef(false); const showCancelButton = type === 'confirm' || type === 'prompt'; useEffect(() => { if (type === 'prompt' && inputRef.current) { inputRef.current.focus(); } }, [type]); const handleCancel = useCallback(result => { if (isClosing.current) return; isClosing.current = true; setIsOpen(false); setTimeout(() => { onClose?.(result); }, 300); }, [onClose]); const handleConfirm = useCallback(() => { if (isClosing.current) return; if (type === 'prompt') { const value = inputValue.current; if (validate) { const [isValid, errorMessage] = validate(value); if (!isValid) { setValidationError(errorMessage || 'Invalid input'); return; } } handleCancel(value); } else { handleCancel(true); } }, [type, inputValue, validate, handleCancel]); const handleClose = useCallback(() => handleCancel(false), [handleCancel]); const handleModalClose = useCallback(event => { const keyboardEvent = event?.nativeEvent ?? event; if (keyboardEvent?.key === 'Escape' && (keyboardEvent.defaultPrevented || keyboardEvent.isComposing || keyboardEvent.keyCode === 229)) { return; } handleClose(); }, [handleClose]); const handleKeyDown = useCallback(event => { onKeyDown?.(event); if (event.key !== 'Enter' || event.defaultPrevented || event.nativeEvent.isComposing || event.keyCode === 229 || event.repeat || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { return; } // Let buttons and custom content handle their own keyboard interactions. if (event.target !== event.currentTarget && event.target !== inputRef.current) { return; } event.preventDefault(); handleConfirm(); }, [handleConfirm, onKeyDown]); const handlePromptInputChange = useCallback(value => { inputValue.current = value; if (validationError) setValidationError(undefined); }, [validationError]); return /*#__PURE__*/React.createElement(Modal, _extends({ ref: ref, open: isOpen, size: "xs", backdrop: "static" }, rest, { onClose: handleModalClose, onKeyDown: handleKeyDown }), /*#__PURE__*/React.createElement(Modal.Header, { closeButton: false }, /*#__PURE__*/React.createElement(Modal.Title, null, title)), /*#__PURE__*/React.createElement(Modal.Body, null, /*#__PURE__*/React.createElement(VStack, null, type === 'prompt' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("label", { htmlFor: "rs-prompt-input" }, content), /*#__PURE__*/React.createElement(Input, { w: "100%", required: true, ref: inputRef, id: "rs-prompt-input", defaultValue: defaultValue, onChange: handlePromptInputChange }), validationError && /*#__PURE__*/React.createElement(Text, { color: "red" }, validationError)) : content)), /*#__PURE__*/React.createElement(Modal.Footer, null, showCancelButton && /*#__PURE__*/React.createElement(Button, { onClick: handleClose, appearance: "subtle" }, cancelText), /*#__PURE__*/React.createElement(Button, { appearance: "primary", onClick: handleConfirm, color: severity ? severityMap[severity] : undefined }, okText))); }); export default Dialog;