UNPKG

@atlaskit/form

Version:

A form allows people to input information.

82 lines (81 loc) • 3.19 kB
import React, { Children, isValidElement, useContext, useMemo, useState } from 'react'; import ExitingPersistence from '@atlaskit/motion/exiting-persistence'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import { FormSubmitContext } from './form-submit-context'; import { MessageWrapperContext } from './message-context'; import MessageGroup from './message-group'; import messageMotion from './message-motion-capability'; /** * __Message wrapper __ * * A message wrapper is used to allow assistive technologies, like screen readers, to announce error or * valid messages. This must be loaded into the DOM before the * ErrorMessage, ValidMessage is loaded. Otherwise, assistive technologies * may not render the message. * */ export const MessageWrapper = ({ children }) => { const contextValue = { isWrapper: true, hasMotionBoundary: false, transition: 'row' }; const shouldProvideMotionBoundary = fg('platform-dst-motion-uplift-input') && Children.toArray(children).every(messageMotion.isCapable); return /*#__PURE__*/React.createElement(MessageWrapperContext.Provider, { value: contextValue }, /*#__PURE__*/React.createElement("div", { "aria-live": "polite", "data-testid": "message-wrapper" }, shouldProvideMotionBoundary ? /*#__PURE__*/React.createElement(MotionMessages, null, children) : children)); }; const getChildKeys = children => Children.toArray(children).filter(isValidElement).map(child => child.key).filter(key => key !== null); const getTransition = (previousKeys, currentKeys) => { const previous = new Set(previousKeys); const current = new Set(currentKeys); const removedCount = previousKeys.filter(key => !current.has(key)).length; const addedCount = currentKeys.filter(key => !previous.has(key)).length; if (removedCount > 0 && addedCount > 0) { return 'instant'; } if (previousKeys.length === 0 && addedCount > 1) { return 'groupEnter'; } if (currentKeys.length === 0 && removedCount > 1) { return 'groupExit'; } return 'row'; }; const MotionMessages = ({ children }) => { const currentKeys = getChildKeys(children); const submitCount = useContext(FormSubmitContext); const [transition, setTransition] = useState(() => ({ keys: currentKeys, mode: 'row', submitCount })); const hasKeyChange = currentKeys.length !== transition.keys.length || currentKeys.some((key, index) => key !== transition.keys[index]); const isSubmitUpdate = submitCount !== transition.submitCount; if (hasKeyChange || isSubmitUpdate) { setTransition({ keys: currentKeys, mode: !hasKeyChange ? transition.mode : isSubmitUpdate ? 'instant' : getTransition(transition.keys, currentKeys), submitCount }); } const motionContextValue = useMemo(() => ({ isWrapper: true, hasMotionBoundary: true, transition: transition.mode }), [transition.mode]); return /*#__PURE__*/React.createElement(MessageWrapperContext.Provider, { value: motionContextValue }, /*#__PURE__*/React.createElement(MessageGroup, { transition: transition.mode }, /*#__PURE__*/React.createElement(ExitingPersistence, { appear: true }, children))); };