@wordpress/components 25.8.0 → 25.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/build/date-time/time/index.js +6 -1
  3. package/build/date-time/time/index.js.map +1 -1
  4. package/build/modal/index.js +12 -3
  5. package/build/modal/index.js.map +1 -1
  6. package/build/modal/types.js.map +1 -1
  7. package/build/placeholder/index.js +10 -4
  8. package/build/placeholder/index.js.map +1 -1
  9. package/build-module/date-time/time/index.js +6 -1
  10. package/build-module/date-time/time/index.js.map +1 -1
  11. package/build-module/modal/index.js +12 -3
  12. package/build-module/modal/index.js.map +1 -1
  13. package/build-module/modal/types.js.map +1 -1
  14. package/build-module/placeholder/index.js +11 -4
  15. package/build-module/placeholder/index.js.map +1 -1
  16. package/build-style/style-rtl.css +0 -10
  17. package/build-style/style.css +0 -10
  18. package/build-types/date-time/time/index.d.ts.map +1 -1
  19. package/build-types/modal/index.d.ts.map +1 -1
  20. package/build-types/modal/stories/index.story.d.ts.map +1 -1
  21. package/build-types/modal/types.d.ts +1 -1
  22. package/build-types/modal/types.d.ts.map +1 -1
  23. package/build-types/placeholder/index.d.ts.map +1 -1
  24. package/package.json +20 -20
  25. package/src/date-time/time/index.tsx +8 -1
  26. package/src/modal/README.md +7 -1
  27. package/src/modal/index.tsx +27 -3
  28. package/src/modal/stories/index.story.tsx +2 -1
  29. package/src/modal/test/index.tsx +124 -0
  30. package/src/modal/types.ts +3 -1
  31. package/src/placeholder/index.tsx +15 -8
  32. package/src/placeholder/style.scss +0 -12
  33. package/src/placeholder/test/index.tsx +34 -15
  34. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":["classnames","createPortal","useCallback","useEffect","useRef","useState","forwardRef","useLayoutEffect","useInstanceId","useFocusReturn","useFocusOnMount","__experimentalUseFocusOutside","useFocusOutside","useConstrainedTabbing","useMergeRefs","__","close","getScrollContainer","ariaHelper","Button","StyleProvider","openModalCount","UnforwardedModal","props","forwardedRef","bodyOpenClassName","role","title","focusOnMount","shouldCloseOnEsc","shouldCloseOnClickOutside","isDismissible","aria","labelledby","undefined","describedby","onRequestClose","icon","closeButtonLabel","children","style","overlayClassName","className","contentLabel","onKeyDown","isFullScreen","headerActions","__experimentalHideHeader","ref","instanceId","Modal","headingId","focusOnMountRef","constrainedTabbingRef","focusReturnRef","focusOutsideProps","contentRef","childrenContainerRef","hasScrolledContent","setHasScrolledContent","hasScrollableContent","setHasScrollableContent","isContentScrollable","current","closestScrollContainer","hideApp","document","body","classList","add","remove","showApp","window","ResizeObserver","resizeObserver","observe","disconnect","handleEscapeKeyDown","event","nativeEvent","isComposing","keyCode","code","defaultPrevented","preventDefault","onContentContainerScroll","e","_e$currentTarget$scro","scrollY","currentTarget","scrollTop","pressTarget","overlayPressHandlers","onPointerDown","isPrimary","target","onPointerUp","button","isSameTarget","createElement","tabIndex","onScroll","id","onClick","label"],"sources":["@wordpress/components/src/modal/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\nimport type { ForwardedRef, KeyboardEvent, UIEvent } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport {\n\tcreatePortal,\n\tuseCallback,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tforwardRef,\n\tuseLayoutEffect,\n} from '@wordpress/element';\nimport {\n\tuseInstanceId,\n\tuseFocusReturn,\n\tuseFocusOnMount,\n\t__experimentalUseFocusOutside as useFocusOutside,\n\tuseConstrainedTabbing,\n\tuseMergeRefs,\n} from '@wordpress/compose';\nimport { __ } from '@wordpress/i18n';\nimport { close } from '@wordpress/icons';\nimport { getScrollContainer } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport * as ariaHelper from './aria-helper';\nimport Button from '../button';\nimport StyleProvider from '../style-provider';\nimport type { ModalProps } from './types';\n\n// Used to count the number of open modals.\nlet openModalCount = 0;\n\nfunction UnforwardedModal(\n\tprops: ModalProps,\n\tforwardedRef: ForwardedRef< HTMLDivElement >\n) {\n\tconst {\n\t\tbodyOpenClassName = 'modal-open',\n\t\trole = 'dialog',\n\t\ttitle = null,\n\t\tfocusOnMount = true,\n\t\tshouldCloseOnEsc = true,\n\t\tshouldCloseOnClickOutside = true,\n\t\tisDismissible = true,\n\t\t/* Accessibility. */\n\t\taria = {\n\t\t\tlabelledby: undefined,\n\t\t\tdescribedby: undefined,\n\t\t},\n\t\tonRequestClose,\n\t\ticon,\n\t\tcloseButtonLabel,\n\t\tchildren,\n\t\tstyle,\n\t\toverlayClassName,\n\t\tclassName,\n\t\tcontentLabel,\n\t\tonKeyDown,\n\t\tisFullScreen = false,\n\t\theaderActions = null,\n\t\t__experimentalHideHeader = false,\n\t} = props;\n\n\tconst ref = useRef< HTMLDivElement >();\n\tconst instanceId = useInstanceId( Modal );\n\tconst headingId = title\n\t\t? `components-modal-header-${ instanceId }`\n\t\t: aria.labelledby;\n\tconst focusOnMountRef = useFocusOnMount( focusOnMount );\n\tconst constrainedTabbingRef = useConstrainedTabbing();\n\tconst focusReturnRef = useFocusReturn();\n\tconst focusOutsideProps = useFocusOutside( onRequestClose );\n\tconst contentRef = useRef< HTMLDivElement >( null );\n\tconst childrenContainerRef = useRef< HTMLDivElement >( null );\n\n\tconst [ hasScrolledContent, setHasScrolledContent ] = useState( false );\n\tconst [ hasScrollableContent, setHasScrollableContent ] = useState( false );\n\n\t// Determines whether the Modal content is scrollable and updates the state.\n\tconst isContentScrollable = useCallback( () => {\n\t\tif ( ! contentRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst closestScrollContainer = getScrollContainer( contentRef.current );\n\n\t\tif ( contentRef.current === closestScrollContainer ) {\n\t\t\tsetHasScrollableContent( true );\n\t\t} else {\n\t\t\tsetHasScrollableContent( false );\n\t\t}\n\t}, [ contentRef ] );\n\n\tuseEffect( () => {\n\t\topenModalCount++;\n\n\t\tif ( openModalCount === 1 ) {\n\t\t\tariaHelper.hideApp( ref.current );\n\t\t\tdocument.body.classList.add( bodyOpenClassName );\n\t\t}\n\n\t\treturn () => {\n\t\t\topenModalCount--;\n\n\t\t\tif ( openModalCount === 0 ) {\n\t\t\t\tdocument.body.classList.remove( bodyOpenClassName );\n\t\t\t\tariaHelper.showApp();\n\t\t\t}\n\t\t};\n\t}, [ bodyOpenClassName ] );\n\n\t// Calls the isContentScrollable callback when the Modal children container resizes.\n\tuseLayoutEffect( () => {\n\t\tif ( ! window.ResizeObserver || ! childrenContainerRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst resizeObserver = new ResizeObserver( isContentScrollable );\n\t\tresizeObserver.observe( childrenContainerRef.current );\n\n\t\tisContentScrollable();\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, [ isContentScrollable, childrenContainerRef ] );\n\n\tfunction handleEscapeKeyDown( event: KeyboardEvent< HTMLDivElement > ) {\n\t\tif (\n\t\t\t// Ignore keydowns from IMEs\n\t\t\tevent.nativeEvent.isComposing ||\n\t\t\t// Workaround for Mac Safari where the final Enter/Backspace of an IME composition\n\t\t\t// is `isComposing=false`, even though it's technically still part of the composition.\n\t\t\t// These can only be detected by keyCode.\n\t\t\tevent.keyCode === 229\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tshouldCloseOnEsc &&\n\t\t\tevent.code === 'Escape' &&\n\t\t\t! event.defaultPrevented\n\t\t) {\n\t\t\tevent.preventDefault();\n\t\t\tif ( onRequestClose ) {\n\t\t\t\tonRequestClose( event );\n\t\t\t}\n\t\t}\n\t}\n\n\tconst onContentContainerScroll = useCallback(\n\t\t( e: UIEvent< HTMLDivElement > ) => {\n\t\t\tconst scrollY = e?.currentTarget?.scrollTop ?? -1;\n\n\t\t\tif ( ! hasScrolledContent && scrollY > 0 ) {\n\t\t\t\tsetHasScrolledContent( true );\n\t\t\t} else if ( hasScrolledContent && scrollY <= 0 ) {\n\t\t\t\tsetHasScrolledContent( false );\n\t\t\t}\n\t\t},\n\t\t[ hasScrolledContent ]\n\t);\n\n\tlet pressTarget: EventTarget | null = null;\n\tconst overlayPressHandlers: {\n\t\tonPointerDown: React.PointerEventHandler< HTMLDivElement >;\n\t\tonPointerUp: React.PointerEventHandler< HTMLDivElement >;\n\t} = {\n\t\tonPointerDown: ( event ) => {\n\t\t\tif ( event.isPrimary && event.target === event.currentTarget ) {\n\t\t\t\tpressTarget = event.target;\n\t\t\t\t// Avoids loss of focus yet also leaves `useFocusOutside`\n\t\t\t\t// practically useless with its only potential trigger being\n\t\t\t\t// programmatic focus movement. TODO opt for either removing\n\t\t\t\t// the hook or enhancing it such that this isn't needed.\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t},\n\t\t// Closes the modal with two exceptions. 1. Opening the context menu on\n\t\t// the overlay. 2. Pressing on the overlay then dragging the pointer\n\t\t// over the modal and releasing. Due to the modal being a child of the\n\t\t// overlay, such a gesture is a `click` on the overlay and cannot be\n\t\t// excepted by a `click` handler. Thus the tactic of handling\n\t\t// `pointerup` and comparing its target to that of the `pointerdown`.\n\t\tonPointerUp: ( { target, button } ) => {\n\t\t\tconst isSameTarget = target === pressTarget;\n\t\t\tpressTarget = null;\n\t\t\tif ( button === 0 && isSameTarget ) onRequestClose();\n\t\t},\n\t};\n\n\treturn createPortal(\n\t\t// eslint-disable-next-line jsx-a11y/no-static-element-interactions\n\t\t<div\n\t\t\tref={ useMergeRefs( [ ref, forwardedRef ] ) }\n\t\t\tclassName={ classnames(\n\t\t\t\t'components-modal__screen-overlay',\n\t\t\t\toverlayClassName\n\t\t\t) }\n\t\t\tonKeyDown={ handleEscapeKeyDown }\n\t\t\t{ ...( shouldCloseOnClickOutside ? overlayPressHandlers : {} ) }\n\t\t>\n\t\t\t<StyleProvider document={ document }>\n\t\t\t\t<div\n\t\t\t\t\tclassName={ classnames(\n\t\t\t\t\t\t'components-modal__frame',\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t'is-full-screen': isFullScreen,\n\t\t\t\t\t\t}\n\t\t\t\t\t) }\n\t\t\t\t\tstyle={ style }\n\t\t\t\t\tref={ useMergeRefs( [\n\t\t\t\t\t\tconstrainedTabbingRef,\n\t\t\t\t\t\tfocusReturnRef,\n\t\t\t\t\t\tfocusOnMountRef,\n\t\t\t\t\t] ) }\n\t\t\t\t\trole={ role }\n\t\t\t\t\taria-label={ contentLabel }\n\t\t\t\t\taria-labelledby={ contentLabel ? undefined : headingId }\n\t\t\t\t\taria-describedby={ aria.describedby }\n\t\t\t\t\ttabIndex={ -1 }\n\t\t\t\t\t{ ...( shouldCloseOnClickOutside\n\t\t\t\t\t\t? focusOutsideProps\n\t\t\t\t\t\t: {} ) }\n\t\t\t\t\tonKeyDown={ onKeyDown }\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={ classnames( 'components-modal__content', {\n\t\t\t\t\t\t\t'hide-header': __experimentalHideHeader,\n\t\t\t\t\t\t\t'is-scrollable': hasScrollableContent,\n\t\t\t\t\t\t\t'has-scrolled-content': hasScrolledContent,\n\t\t\t\t\t\t} ) }\n\t\t\t\t\t\trole=\"document\"\n\t\t\t\t\t\tonScroll={ onContentContainerScroll }\n\t\t\t\t\t\tref={ contentRef }\n\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\thasScrollableContent\n\t\t\t\t\t\t\t\t? __( 'Scrollable section' )\n\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttabIndex={ hasScrollableContent ? 0 : undefined }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ ! __experimentalHideHeader && (\n\t\t\t\t\t\t\t<div className=\"components-modal__header\">\n\t\t\t\t\t\t\t\t<div className=\"components-modal__header-heading-container\">\n\t\t\t\t\t\t\t\t\t{ icon && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"components-modal__icon-container\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{ icon }\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t{ title && (\n\t\t\t\t\t\t\t\t\t\t<h1\n\t\t\t\t\t\t\t\t\t\t\tid={ headingId }\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"components-modal__header-heading\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{ title }\n\t\t\t\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{ headerActions }\n\t\t\t\t\t\t\t\t{ isDismissible && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tonClick={ onRequestClose }\n\t\t\t\t\t\t\t\t\t\ticon={ close }\n\t\t\t\t\t\t\t\t\t\tlabel={\n\t\t\t\t\t\t\t\t\t\t\tcloseButtonLabel || __( 'Close' )\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t<div ref={ childrenContainerRef }>{ children }</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</StyleProvider>\n\t\t</div>,\n\t\tdocument.body\n\t);\n}\n\n/**\n * Modals give users information and choices related to a task they’re trying to\n * accomplish. They can contain critical information, require decisions, or\n * involve multiple tasks.\n *\n * ```jsx\n * import { Button, Modal } from '@wordpress/components';\n * import { useState } from '@wordpress/element';\n *\n * const MyModal = () => {\n * const [ isOpen, setOpen ] = useState( false );\n * const openModal = () => setOpen( true );\n * const closeModal = () => setOpen( false );\n *\n * return (\n * <>\n * <Button variant=\"secondary\" onClick={ openModal }>\n * Open Modal\n * </Button>\n * { isOpen && (\n * <Modal title=\"This is my modal\" onRequestClose={ closeModal }>\n * <Button variant=\"secondary\" onClick={ closeModal }>\n * My custom close button\n * </Button>\n * </Modal>\n * ) }\n * </>\n * );\n * };\n * ```\n */\nexport const Modal = forwardRef( UnforwardedModal );\n\nexport default Modal;\n"],"mappings":"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"}
1
+ {"version":3,"names":["classnames","createPortal","useCallback","useEffect","useRef","useState","forwardRef","useLayoutEffect","useInstanceId","useFocusReturn","useFocusOnMount","__experimentalUseFocusOutside","useFocusOutside","useConstrainedTabbing","useMergeRefs","__","close","getScrollContainer","ariaHelper","Button","StyleProvider","openModalCount","UnforwardedModal","props","forwardedRef","bodyOpenClassName","role","title","focusOnMount","shouldCloseOnEsc","shouldCloseOnClickOutside","isDismissible","aria","labelledby","undefined","describedby","onRequestClose","icon","closeButtonLabel","children","style","overlayClassName","className","contentLabel","onKeyDown","isFullScreen","headerActions","__experimentalHideHeader","ref","instanceId","Modal","headingId","focusOnMountRef","constrainedTabbingRef","focusReturnRef","focusOutsideProps","contentRef","childrenContainerRef","hasScrolledContent","setHasScrolledContent","hasScrollableContent","setHasScrollableContent","isContentScrollable","current","closestScrollContainer","hideApp","document","body","classList","add","remove","showApp","window","ResizeObserver","resizeObserver","observe","disconnect","handleEscapeKeyDown","event","nativeEvent","isComposing","keyCode","code","defaultPrevented","preventDefault","onContentContainerScroll","e","_e$currentTarget$scro","scrollY","currentTarget","scrollTop","pressTarget","overlayPressHandlers","onPointerDown","isPrimary","target","onPointerUp","button","isSameTarget","createElement","tabIndex","onScroll","id","onClick","label"],"sources":["@wordpress/components/src/modal/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\nimport type { ForwardedRef, KeyboardEvent, UIEvent } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport {\n\tcreatePortal,\n\tuseCallback,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n\tforwardRef,\n\tuseLayoutEffect,\n} from '@wordpress/element';\nimport {\n\tuseInstanceId,\n\tuseFocusReturn,\n\tuseFocusOnMount,\n\t__experimentalUseFocusOutside as useFocusOutside,\n\tuseConstrainedTabbing,\n\tuseMergeRefs,\n} from '@wordpress/compose';\nimport { __ } from '@wordpress/i18n';\nimport { close } from '@wordpress/icons';\nimport { getScrollContainer } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport * as ariaHelper from './aria-helper';\nimport Button from '../button';\nimport StyleProvider from '../style-provider';\nimport type { ModalProps } from './types';\n\n// Used to count the number of open modals.\nlet openModalCount = 0;\n\nfunction UnforwardedModal(\n\tprops: ModalProps,\n\tforwardedRef: ForwardedRef< HTMLDivElement >\n) {\n\tconst {\n\t\tbodyOpenClassName = 'modal-open',\n\t\trole = 'dialog',\n\t\ttitle = null,\n\t\tfocusOnMount = true,\n\t\tshouldCloseOnEsc = true,\n\t\tshouldCloseOnClickOutside = true,\n\t\tisDismissible = true,\n\t\t/* Accessibility. */\n\t\taria = {\n\t\t\tlabelledby: undefined,\n\t\t\tdescribedby: undefined,\n\t\t},\n\t\tonRequestClose,\n\t\ticon,\n\t\tcloseButtonLabel,\n\t\tchildren,\n\t\tstyle,\n\t\toverlayClassName,\n\t\tclassName,\n\t\tcontentLabel,\n\t\tonKeyDown,\n\t\tisFullScreen = false,\n\t\theaderActions = null,\n\t\t__experimentalHideHeader = false,\n\t} = props;\n\n\tconst ref = useRef< HTMLDivElement >();\n\n\tconst instanceId = useInstanceId( Modal );\n\tconst headingId = title\n\t\t? `components-modal-header-${ instanceId }`\n\t\t: aria.labelledby;\n\n\t// The focus hook does not support 'firstContentElement' but this is a valid\n\t// value for the Modal's focusOnMount prop. The following code ensures the focus\n\t// hook will focus the first focusable node within the element to which it is applied.\n\t// When `firstContentElement` is passed as the value of the focusOnMount prop,\n\t// the focus hook is applied to the Modal's content element.\n\t// Otherwise, the focus hook is applied to the Modal's ref. This ensures that the\n\t// focus hook will focus the first element in the Modal's **content** when\n\t// `firstContentElement` is passed.\n\tconst focusOnMountRef = useFocusOnMount(\n\t\tfocusOnMount === 'firstContentElement' ? 'firstElement' : focusOnMount\n\t);\n\tconst constrainedTabbingRef = useConstrainedTabbing();\n\tconst focusReturnRef = useFocusReturn();\n\tconst focusOutsideProps = useFocusOutside( onRequestClose );\n\tconst contentRef = useRef< HTMLDivElement >( null );\n\tconst childrenContainerRef = useRef< HTMLDivElement >( null );\n\n\tconst [ hasScrolledContent, setHasScrolledContent ] = useState( false );\n\tconst [ hasScrollableContent, setHasScrollableContent ] = useState( false );\n\n\t// Determines whether the Modal content is scrollable and updates the state.\n\tconst isContentScrollable = useCallback( () => {\n\t\tif ( ! contentRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst closestScrollContainer = getScrollContainer( contentRef.current );\n\n\t\tif ( contentRef.current === closestScrollContainer ) {\n\t\t\tsetHasScrollableContent( true );\n\t\t} else {\n\t\t\tsetHasScrollableContent( false );\n\t\t}\n\t}, [ contentRef ] );\n\n\tuseEffect( () => {\n\t\topenModalCount++;\n\n\t\tif ( openModalCount === 1 ) {\n\t\t\tariaHelper.hideApp( ref.current );\n\t\t\tdocument.body.classList.add( bodyOpenClassName );\n\t\t}\n\n\t\treturn () => {\n\t\t\topenModalCount--;\n\n\t\t\tif ( openModalCount === 0 ) {\n\t\t\t\tdocument.body.classList.remove( bodyOpenClassName );\n\t\t\t\tariaHelper.showApp();\n\t\t\t}\n\t\t};\n\t}, [ bodyOpenClassName ] );\n\n\t// Calls the isContentScrollable callback when the Modal children container resizes.\n\tuseLayoutEffect( () => {\n\t\tif ( ! window.ResizeObserver || ! childrenContainerRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst resizeObserver = new ResizeObserver( isContentScrollable );\n\t\tresizeObserver.observe( childrenContainerRef.current );\n\n\t\tisContentScrollable();\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t};\n\t}, [ isContentScrollable, childrenContainerRef ] );\n\n\tfunction handleEscapeKeyDown( event: KeyboardEvent< HTMLDivElement > ) {\n\t\tif (\n\t\t\t// Ignore keydowns from IMEs\n\t\t\tevent.nativeEvent.isComposing ||\n\t\t\t// Workaround for Mac Safari where the final Enter/Backspace of an IME composition\n\t\t\t// is `isComposing=false`, even though it's technically still part of the composition.\n\t\t\t// These can only be detected by keyCode.\n\t\t\tevent.keyCode === 229\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tshouldCloseOnEsc &&\n\t\t\tevent.code === 'Escape' &&\n\t\t\t! event.defaultPrevented\n\t\t) {\n\t\t\tevent.preventDefault();\n\t\t\tif ( onRequestClose ) {\n\t\t\t\tonRequestClose( event );\n\t\t\t}\n\t\t}\n\t}\n\n\tconst onContentContainerScroll = useCallback(\n\t\t( e: UIEvent< HTMLDivElement > ) => {\n\t\t\tconst scrollY = e?.currentTarget?.scrollTop ?? -1;\n\n\t\t\tif ( ! hasScrolledContent && scrollY > 0 ) {\n\t\t\t\tsetHasScrolledContent( true );\n\t\t\t} else if ( hasScrolledContent && scrollY <= 0 ) {\n\t\t\t\tsetHasScrolledContent( false );\n\t\t\t}\n\t\t},\n\t\t[ hasScrolledContent ]\n\t);\n\n\tlet pressTarget: EventTarget | null = null;\n\tconst overlayPressHandlers: {\n\t\tonPointerDown: React.PointerEventHandler< HTMLDivElement >;\n\t\tonPointerUp: React.PointerEventHandler< HTMLDivElement >;\n\t} = {\n\t\tonPointerDown: ( event ) => {\n\t\t\tif ( event.isPrimary && event.target === event.currentTarget ) {\n\t\t\t\tpressTarget = event.target;\n\t\t\t\t// Avoids loss of focus yet also leaves `useFocusOutside`\n\t\t\t\t// practically useless with its only potential trigger being\n\t\t\t\t// programmatic focus movement. TODO opt for either removing\n\t\t\t\t// the hook or enhancing it such that this isn't needed.\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t},\n\t\t// Closes the modal with two exceptions. 1. Opening the context menu on\n\t\t// the overlay. 2. Pressing on the overlay then dragging the pointer\n\t\t// over the modal and releasing. Due to the modal being a child of the\n\t\t// overlay, such a gesture is a `click` on the overlay and cannot be\n\t\t// excepted by a `click` handler. Thus the tactic of handling\n\t\t// `pointerup` and comparing its target to that of the `pointerdown`.\n\t\tonPointerUp: ( { target, button } ) => {\n\t\t\tconst isSameTarget = target === pressTarget;\n\t\t\tpressTarget = null;\n\t\t\tif ( button === 0 && isSameTarget ) onRequestClose();\n\t\t},\n\t};\n\n\treturn createPortal(\n\t\t// eslint-disable-next-line jsx-a11y/no-static-element-interactions\n\t\t<div\n\t\t\tref={ useMergeRefs( [ ref, forwardedRef ] ) }\n\t\t\tclassName={ classnames(\n\t\t\t\t'components-modal__screen-overlay',\n\t\t\t\toverlayClassName\n\t\t\t) }\n\t\t\tonKeyDown={ handleEscapeKeyDown }\n\t\t\t{ ...( shouldCloseOnClickOutside ? overlayPressHandlers : {} ) }\n\t\t>\n\t\t\t<StyleProvider document={ document }>\n\t\t\t\t<div\n\t\t\t\t\tclassName={ classnames(\n\t\t\t\t\t\t'components-modal__frame',\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t'is-full-screen': isFullScreen,\n\t\t\t\t\t\t}\n\t\t\t\t\t) }\n\t\t\t\t\tstyle={ style }\n\t\t\t\t\tref={ useMergeRefs( [\n\t\t\t\t\t\tconstrainedTabbingRef,\n\t\t\t\t\t\tfocusReturnRef,\n\t\t\t\t\t\tfocusOnMount !== 'firstContentElement'\n\t\t\t\t\t\t\t? focusOnMountRef\n\t\t\t\t\t\t\t: null,\n\t\t\t\t\t] ) }\n\t\t\t\t\trole={ role }\n\t\t\t\t\taria-label={ contentLabel }\n\t\t\t\t\taria-labelledby={ contentLabel ? undefined : headingId }\n\t\t\t\t\taria-describedby={ aria.describedby }\n\t\t\t\t\ttabIndex={ -1 }\n\t\t\t\t\t{ ...( shouldCloseOnClickOutside\n\t\t\t\t\t\t? focusOutsideProps\n\t\t\t\t\t\t: {} ) }\n\t\t\t\t\tonKeyDown={ onKeyDown }\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={ classnames( 'components-modal__content', {\n\t\t\t\t\t\t\t'hide-header': __experimentalHideHeader,\n\t\t\t\t\t\t\t'is-scrollable': hasScrollableContent,\n\t\t\t\t\t\t\t'has-scrolled-content': hasScrolledContent,\n\t\t\t\t\t\t} ) }\n\t\t\t\t\t\trole=\"document\"\n\t\t\t\t\t\tonScroll={ onContentContainerScroll }\n\t\t\t\t\t\tref={ contentRef }\n\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\thasScrollableContent\n\t\t\t\t\t\t\t\t? __( 'Scrollable section' )\n\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttabIndex={ hasScrollableContent ? 0 : undefined }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ ! __experimentalHideHeader && (\n\t\t\t\t\t\t\t<div className=\"components-modal__header\">\n\t\t\t\t\t\t\t\t<div className=\"components-modal__header-heading-container\">\n\t\t\t\t\t\t\t\t\t{ icon && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"components-modal__icon-container\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{ icon }\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t{ title && (\n\t\t\t\t\t\t\t\t\t\t<h1\n\t\t\t\t\t\t\t\t\t\t\tid={ headingId }\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"components-modal__header-heading\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{ title }\n\t\t\t\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{ headerActions }\n\t\t\t\t\t\t\t\t{ isDismissible && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tonClick={ onRequestClose }\n\t\t\t\t\t\t\t\t\t\ticon={ close }\n\t\t\t\t\t\t\t\t\t\tlabel={\n\t\t\t\t\t\t\t\t\t\t\tcloseButtonLabel || __( 'Close' )\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) }\n\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tref={ useMergeRefs( [\n\t\t\t\t\t\t\t\tchildrenContainerRef,\n\t\t\t\t\t\t\t\tfocusOnMount === 'firstContentElement'\n\t\t\t\t\t\t\t\t\t? focusOnMountRef\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t\t] ) }\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{ children }\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</StyleProvider>\n\t\t</div>,\n\t\tdocument.body\n\t);\n}\n\n/**\n * Modals give users information and choices related to a task they’re trying to\n * accomplish. They can contain critical information, require decisions, or\n * involve multiple tasks.\n *\n * ```jsx\n * import { Button, Modal } from '@wordpress/components';\n * import { useState } from '@wordpress/element';\n *\n * const MyModal = () => {\n * const [ isOpen, setOpen ] = useState( false );\n * const openModal = () => setOpen( true );\n * const closeModal = () => setOpen( false );\n *\n * return (\n * <>\n * <Button variant=\"secondary\" onClick={ openModal }>\n * Open Modal\n * </Button>\n * { isOpen && (\n * <Modal title=\"This is my modal\" onRequestClose={ closeModal }>\n * <Button variant=\"secondary\" onClick={ closeModal }>\n * My custom close button\n * </Button>\n * </Modal>\n * ) }\n * </>\n * );\n * };\n * ```\n */\nexport const Modal = forwardRef( UnforwardedModal );\n\nexport default Modal;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["@wordpress/components/src/modal/types.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type {\n\tAriaRole,\n\tCSSProperties,\n\tReactNode,\n\tKeyboardEventHandler,\n\tKeyboardEvent,\n\tSyntheticEvent,\n} from 'react';\n\n/**\n * WordPress dependencies\n */\nimport type { useFocusOnMount } from '@wordpress/compose';\n\nexport type ModalProps = {\n\taria?: {\n\t\t/**\n\t\t * If this property is added, it will be added to the modal content\n\t\t * `div` as `aria-describedby`.\n\t\t */\n\t\tdescribedby?: string;\n\t\t/**\n\t\t * If this property is added, it will be added to the modal content\n\t\t * `div` as `aria-labelledby`. Use this when you are rendering the title\n\t\t * yourself within the modal's content area instead of using the `title`\n\t\t * prop. This ensures the title is usable by assistive technology.\n\t\t *\n\t\t * Titles are required for accessibility reasons, see `contentLabel` and\n\t\t * `title` for other ways to provide a title.\n\t\t */\n\t\tlabelledby?: string;\n\t};\n\t/**\n\t * Class name added to the body element when the modal is open.\n\t *\n\t * @default 'modal-open'\n\t */\n\tbodyOpenClassName?: string;\n\t/**\n\t * The children elements.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * If this property is added, it will an additional class name to the modal\n\t * content `div`.\n\t */\n\tclassName?: string;\n\t/**\n\t * Label on the close button.\n\t *\n\t * @default `__( 'Close' )`\n\t */\n\tcloseButtonLabel?: string;\n\t/**\n\t * If this property is added, it will be added to the modal content `div` as\n\t * `aria-label`.\n\t *\n\t * Titles are required for accessibility reasons, see `aria.labelledby` and\n\t * `title` for other ways to provide a title.\n\t */\n\tcontentLabel?: string;\n\t/**\n\t * If this property is true, it will focus the first tabbable element\n\t * rendered in the modal.\n\t *\n\t * @default true\n\t */\n\tfocusOnMount?: Parameters< typeof useFocusOnMount >[ 0 ];\n\t/**\n\t * Elements that are injected into the modal header to the left of the close button (if rendered).\n\t * Hidden if `__experimentalHideHeader` is `true`.\n\t *\n\t * @default null\n\t */\n\theaderActions?: ReactNode;\n\n\t/**\n\t * If this property is added, an icon will be added before the title.\n\t */\n\ticon?: JSX.Element;\n\t/**\n\t * If this property is set to false, the modal will not display a close icon\n\t * and cannot be dismissed.\n\t *\n\t * @default true\n\t */\n\tisDismissible?: boolean;\n\t/**\n\t * This property when set to `true` will render a full screen modal.\n\t *\n\t * @default false\n\t */\n\tisFullScreen?: boolean;\n\t/**\n\t * Handle the key down on the modal frame `div`.\n\t */\n\tonKeyDown?: KeyboardEventHandler< HTMLDivElement >;\n\t/**\n\t * This function is called to indicate that the modal should be closed.\n\t */\n\tonRequestClose: (\n\t\tevent?: KeyboardEvent< HTMLDivElement > | SyntheticEvent\n\t) => void;\n\t/**\n\t * If this property is added, it will an additional class name to the modal\n\t * overlay `div`.\n\t */\n\toverlayClassName?: string;\n\t/**\n\t * If this property is added, it will override the default role of the\n\t * modal.\n\t *\n\t * @default 'dialog'\n\t */\n\trole?: AriaRole;\n\t/**\n\t * If this property is added, it will determine whether the modal requests\n\t * to close when a mouse click occurs outside of the modal content.\n\t *\n\t * @default true\n\t */\n\tshouldCloseOnClickOutside?: boolean;\n\t/**\n\t * If this property is added, it will determine whether the modal requests\n\t * to close when the escape key is pressed.\n\t *\n\t * @default true\n\t */\n\tshouldCloseOnEsc?: boolean;\n\t/**\n\t * If this property is added, it will be added to the modal frame `div`.\n\t */\n\tstyle?: CSSProperties;\n\t/**\n\t * This property is used as the modal header's title.\n\t *\n\t * Titles are required for accessibility reasons, see `aria.labelledby` and\n\t * `contentLabel` for other ways to provide a title.\n\t */\n\ttitle?: string;\n\t/**\n\t * When set to `true`, the Modal's header (including the icon, title and\n\t * close button) will not be rendered.\n\t *\n\t * _Warning_: This property is still experimental. “Experimental” means this\n\t * is an early implementation subject to drastic and breaking changes.\n\t *\n\t * @default false\n\t */\n\t__experimentalHideHeader?: boolean;\n};\n"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["@wordpress/components/src/modal/types.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type {\n\tAriaRole,\n\tCSSProperties,\n\tReactNode,\n\tKeyboardEventHandler,\n\tKeyboardEvent,\n\tSyntheticEvent,\n} from 'react';\n\n/**\n * WordPress dependencies\n */\nimport type { useFocusOnMount } from '@wordpress/compose';\n\nexport type ModalProps = {\n\taria?: {\n\t\t/**\n\t\t * If this property is added, it will be added to the modal content\n\t\t * `div` as `aria-describedby`.\n\t\t */\n\t\tdescribedby?: string;\n\t\t/**\n\t\t * If this property is added, it will be added to the modal content\n\t\t * `div` as `aria-labelledby`. Use this when you are rendering the title\n\t\t * yourself within the modal's content area instead of using the `title`\n\t\t * prop. This ensures the title is usable by assistive technology.\n\t\t *\n\t\t * Titles are required for accessibility reasons, see `contentLabel` and\n\t\t * `title` for other ways to provide a title.\n\t\t */\n\t\tlabelledby?: string;\n\t};\n\t/**\n\t * Class name added to the body element when the modal is open.\n\t *\n\t * @default 'modal-open'\n\t */\n\tbodyOpenClassName?: string;\n\t/**\n\t * The children elements.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * If this property is added, it will an additional class name to the modal\n\t * content `div`.\n\t */\n\tclassName?: string;\n\t/**\n\t * Label on the close button.\n\t *\n\t * @default `__( 'Close' )`\n\t */\n\tcloseButtonLabel?: string;\n\t/**\n\t * If this property is added, it will be added to the modal content `div` as\n\t * `aria-label`.\n\t *\n\t * Titles are required for accessibility reasons, see `aria.labelledby` and\n\t * `title` for other ways to provide a title.\n\t */\n\tcontentLabel?: string;\n\t/**\n\t * If this property is true, it will focus the first tabbable element\n\t * rendered in the modal.\n\t *\n\t * @default true\n\t */\n\tfocusOnMount?:\n\t\t| Parameters< typeof useFocusOnMount >[ 0 ]\n\t\t| 'firstContentElement';\n\t/**\n\t * Elements that are injected into the modal header to the left of the close button (if rendered).\n\t * Hidden if `__experimentalHideHeader` is `true`.\n\t *\n\t * @default null\n\t */\n\theaderActions?: ReactNode;\n\n\t/**\n\t * If this property is added, an icon will be added before the title.\n\t */\n\ticon?: JSX.Element;\n\t/**\n\t * If this property is set to false, the modal will not display a close icon\n\t * and cannot be dismissed.\n\t *\n\t * @default true\n\t */\n\tisDismissible?: boolean;\n\t/**\n\t * This property when set to `true` will render a full screen modal.\n\t *\n\t * @default false\n\t */\n\tisFullScreen?: boolean;\n\t/**\n\t * Handle the key down on the modal frame `div`.\n\t */\n\tonKeyDown?: KeyboardEventHandler< HTMLDivElement >;\n\t/**\n\t * This function is called to indicate that the modal should be closed.\n\t */\n\tonRequestClose: (\n\t\tevent?: KeyboardEvent< HTMLDivElement > | SyntheticEvent\n\t) => void;\n\t/**\n\t * If this property is added, it will an additional class name to the modal\n\t * overlay `div`.\n\t */\n\toverlayClassName?: string;\n\t/**\n\t * If this property is added, it will override the default role of the\n\t * modal.\n\t *\n\t * @default 'dialog'\n\t */\n\trole?: AriaRole;\n\t/**\n\t * If this property is added, it will determine whether the modal requests\n\t * to close when a mouse click occurs outside of the modal content.\n\t *\n\t * @default true\n\t */\n\tshouldCloseOnClickOutside?: boolean;\n\t/**\n\t * If this property is added, it will determine whether the modal requests\n\t * to close when the escape key is pressed.\n\t *\n\t * @default true\n\t */\n\tshouldCloseOnEsc?: boolean;\n\t/**\n\t * If this property is added, it will be added to the modal frame `div`.\n\t */\n\tstyle?: CSSProperties;\n\t/**\n\t * This property is used as the modal header's title.\n\t *\n\t * Titles are required for accessibility reasons, see `aria.labelledby` and\n\t * `contentLabel` for other ways to provide a title.\n\t */\n\ttitle?: string;\n\t/**\n\t * When set to `true`, the Modal's header (including the icon, title and\n\t * close button) will not be rendered.\n\t *\n\t * _Warning_: This property is still experimental. “Experimental” means this\n\t * is an early implementation subject to drastic and breaking changes.\n\t *\n\t * @default false\n\t */\n\t__experimentalHideHeader?: boolean;\n};\n"],"mappings":""}
@@ -9,6 +9,8 @@ import classnames from 'classnames';
9
9
  */
10
10
  import { useResizeObserver } from '@wordpress/compose';
11
11
  import { SVG, Path } from '@wordpress/primitives';
12
+ import { useEffect } from '@wordpress/element';
13
+ import { speak } from '@wordpress/a11y';
12
14
 
13
15
  /**
14
16
  * Internal dependencies
@@ -66,6 +68,11 @@ export function Placeholder(props) {
66
68
  const fieldsetClasses = classnames('components-placeholder__fieldset', {
67
69
  'is-column-layout': isColumnLayout
68
70
  });
71
+ useEffect(() => {
72
+ if (instructions) {
73
+ speak(instructions);
74
+ }
75
+ }, [instructions]);
69
76
  return createElement("div", {
70
77
  ...additionalProps,
71
78
  className: classes
@@ -75,11 +82,11 @@ export function Placeholder(props) {
75
82
  className: "components-placeholder__label"
76
83
  }, createElement(Icon, {
77
84
  icon: icon
78
- }), label), createElement("fieldset", {
79
- className: fieldsetClasses
80
- }, !!instructions && createElement("legend", {
85
+ }), label), !!instructions && createElement("div", {
81
86
  className: "components-placeholder__instructions"
82
- }, instructions), children));
87
+ }, instructions), createElement("div", {
88
+ className: fieldsetClasses
89
+ }, children));
83
90
  }
84
91
  export default Placeholder;
85
92
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["classnames","useResizeObserver","SVG","Path","Icon","PlaceholderIllustration","createElement","className","fill","xmlns","viewBox","preserveAspectRatio","vectorEffect","d","Placeholder","props","icon","children","label","instructions","notices","preview","isColumnLayout","withIllustration","additionalProps","resizeListener","width","modifierClassNames","classes","fieldsetClasses"],"sources":["@wordpress/components/src/placeholder/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\n\n/**\n * WordPress dependencies\n */\nimport { useResizeObserver } from '@wordpress/compose';\nimport { SVG, Path } from '@wordpress/primitives';\n\n/**\n * Internal dependencies\n */\nimport Icon from '../icon';\nimport type { PlaceholderProps } from './types';\nimport type { WordPressComponentProps } from '../ui/context';\n\nconst PlaceholderIllustration = (\n\t<SVG\n\t\tclassName=\"components-placeholder__illustration\"\n\t\tfill=\"none\"\n\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\tviewBox=\"0 0 60 60\"\n\t\tpreserveAspectRatio=\"none\"\n\t>\n\t\t<Path vectorEffect=\"non-scaling-stroke\" d=\"M60 60 0 0\" />\n\t</SVG>\n);\n\n/**\n * Renders a placeholder. Normally used by blocks to render their empty state.\n *\n * ```jsx\n * import { Placeholder } from '@wordpress/components';\n * import { more } from '@wordpress/icons';\n *\n * const MyPlaceholder = () => <Placeholder icon={ more } label=\"Placeholder\" />;\n * ```\n */\nexport function Placeholder(\n\tprops: WordPressComponentProps< PlaceholderProps, 'div', false >\n) {\n\tconst {\n\t\ticon,\n\t\tchildren,\n\t\tlabel,\n\t\tinstructions,\n\t\tclassName,\n\t\tnotices,\n\t\tpreview,\n\t\tisColumnLayout,\n\t\twithIllustration,\n\t\t...additionalProps\n\t} = props;\n\tconst [ resizeListener, { width } ] = useResizeObserver();\n\n\t// Since `useResizeObserver` will report a width of `null` until after the\n\t// first render, avoid applying any modifier classes until width is known.\n\tlet modifierClassNames;\n\tif ( typeof width === 'number' ) {\n\t\tmodifierClassNames = {\n\t\t\t'is-large': width >= 480,\n\t\t\t'is-medium': width >= 160 && width < 480,\n\t\t\t'is-small': width < 160,\n\t\t};\n\t}\n\n\tconst classes = classnames(\n\t\t'components-placeholder',\n\t\tclassName,\n\t\tmodifierClassNames,\n\t\twithIllustration ? 'has-illustration' : null\n\t);\n\tconst fieldsetClasses = classnames( 'components-placeholder__fieldset', {\n\t\t'is-column-layout': isColumnLayout,\n\t} );\n\n\treturn (\n\t\t<div { ...additionalProps } className={ classes }>\n\t\t\t{ withIllustration ? PlaceholderIllustration : null }\n\t\t\t{ resizeListener }\n\t\t\t{ notices }\n\t\t\t{ preview && (\n\t\t\t\t<div className=\"components-placeholder__preview\">\n\t\t\t\t\t{ preview }\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div className=\"components-placeholder__label\">\n\t\t\t\t<Icon icon={ icon } />\n\t\t\t\t{ label }\n\t\t\t</div>\n\t\t\t<fieldset className={ fieldsetClasses }>\n\t\t\t\t{ !! instructions && (\n\t\t\t\t\t<legend className=\"components-placeholder__instructions\">\n\t\t\t\t\t\t{ instructions }\n\t\t\t\t\t</legend>\n\t\t\t\t) }\n\t\t\t\t{ children }\n\t\t\t</fieldset>\n\t\t</div>\n\t);\n}\n\nexport default Placeholder;\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,UAAU,MAAM,YAAY;;AAEnC;AACA;AACA;AACA,SAASC,iBAAiB,QAAQ,oBAAoB;AACtD,SAASC,GAAG,EAAEC,IAAI,QAAQ,uBAAuB;;AAEjD;AACA;AACA;AACA,OAAOC,IAAI,MAAM,SAAS;AAI1B,MAAMC,uBAAuB,GAC5BC,aAAA,CAACJ,GAAG;EACHK,SAAS,EAAC,sCAAsC;EAChDC,IAAI,EAAC,MAAM;EACXC,KAAK,EAAC,4BAA4B;EAClCC,OAAO,EAAC,WAAW;EACnBC,mBAAmB,EAAC;AAAM,GAE1BL,aAAA,CAACH,IAAI;EAACS,YAAY,EAAC,oBAAoB;EAACC,CAAC,EAAC;AAAY,CAAE,CACpD,CACL;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAC1BC,KAAgE,EAC/D;EACD,MAAM;IACLC,IAAI;IACJC,QAAQ;IACRC,KAAK;IACLC,YAAY;IACZZ,SAAS;IACTa,OAAO;IACPC,OAAO;IACPC,cAAc;IACdC,gBAAgB;IAChB,GAAGC;EACJ,CAAC,GAAGT,KAAK;EACT,MAAM,CAAEU,cAAc,EAAE;IAAEC;EAAM,CAAC,CAAE,GAAGzB,iBAAiB,CAAC,CAAC;;EAEzD;EACA;EACA,IAAI0B,kBAAkB;EACtB,IAAK,OAAOD,KAAK,KAAK,QAAQ,EAAG;IAChCC,kBAAkB,GAAG;MACpB,UAAU,EAAED,KAAK,IAAI,GAAG;MACxB,WAAW,EAAEA,KAAK,IAAI,GAAG,IAAIA,KAAK,GAAG,GAAG;MACxC,UAAU,EAAEA,KAAK,GAAG;IACrB,CAAC;EACF;EAEA,MAAME,OAAO,GAAG5B,UAAU,CACzB,wBAAwB,EACxBO,SAAS,EACToB,kBAAkB,EAClBJ,gBAAgB,GAAG,kBAAkB,GAAG,IACzC,CAAC;EACD,MAAMM,eAAe,GAAG7B,UAAU,CAAE,kCAAkC,EAAE;IACvE,kBAAkB,EAAEsB;EACrB,CAAE,CAAC;EAEH,OACChB,aAAA;IAAA,GAAUkB,eAAe;IAAGjB,SAAS,EAAGqB;EAAS,GAC9CL,gBAAgB,GAAGlB,uBAAuB,GAAG,IAAI,EACjDoB,cAAc,EACdL,OAAO,EACPC,OAAO,IACRf,aAAA;IAAKC,SAAS,EAAC;EAAiC,GAC7Cc,OACE,CACL,EACDf,aAAA;IAAKC,SAAS,EAAC;EAA+B,GAC7CD,aAAA,CAACF,IAAI;IAACY,IAAI,EAAGA;EAAM,CAAE,CAAC,EACpBE,KACE,CAAC,EACNZ,aAAA;IAAUC,SAAS,EAAGsB;EAAiB,GACpC,CAAC,CAAEV,YAAY,IAChBb,aAAA;IAAQC,SAAS,EAAC;EAAsC,GACrDY,YACK,CACR,EACCF,QACO,CACN,CAAC;AAER;AAEA,eAAeH,WAAW"}
1
+ {"version":3,"names":["classnames","useResizeObserver","SVG","Path","useEffect","speak","Icon","PlaceholderIllustration","createElement","className","fill","xmlns","viewBox","preserveAspectRatio","vectorEffect","d","Placeholder","props","icon","children","label","instructions","notices","preview","isColumnLayout","withIllustration","additionalProps","resizeListener","width","modifierClassNames","classes","fieldsetClasses"],"sources":["@wordpress/components/src/placeholder/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\n\n/**\n * WordPress dependencies\n */\nimport { useResizeObserver } from '@wordpress/compose';\nimport { SVG, Path } from '@wordpress/primitives';\nimport { useEffect } from '@wordpress/element';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport Icon from '../icon';\nimport type { PlaceholderProps } from './types';\nimport type { WordPressComponentProps } from '../ui/context';\n\nconst PlaceholderIllustration = (\n\t<SVG\n\t\tclassName=\"components-placeholder__illustration\"\n\t\tfill=\"none\"\n\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\tviewBox=\"0 0 60 60\"\n\t\tpreserveAspectRatio=\"none\"\n\t>\n\t\t<Path vectorEffect=\"non-scaling-stroke\" d=\"M60 60 0 0\" />\n\t</SVG>\n);\n\n/**\n * Renders a placeholder. Normally used by blocks to render their empty state.\n *\n * ```jsx\n * import { Placeholder } from '@wordpress/components';\n * import { more } from '@wordpress/icons';\n *\n * const MyPlaceholder = () => <Placeholder icon={ more } label=\"Placeholder\" />;\n * ```\n */\nexport function Placeholder(\n\tprops: WordPressComponentProps< PlaceholderProps, 'div', false >\n) {\n\tconst {\n\t\ticon,\n\t\tchildren,\n\t\tlabel,\n\t\tinstructions,\n\t\tclassName,\n\t\tnotices,\n\t\tpreview,\n\t\tisColumnLayout,\n\t\twithIllustration,\n\t\t...additionalProps\n\t} = props;\n\tconst [ resizeListener, { width } ] = useResizeObserver();\n\n\t// Since `useResizeObserver` will report a width of `null` until after the\n\t// first render, avoid applying any modifier classes until width is known.\n\tlet modifierClassNames;\n\tif ( typeof width === 'number' ) {\n\t\tmodifierClassNames = {\n\t\t\t'is-large': width >= 480,\n\t\t\t'is-medium': width >= 160 && width < 480,\n\t\t\t'is-small': width < 160,\n\t\t};\n\t}\n\n\tconst classes = classnames(\n\t\t'components-placeholder',\n\t\tclassName,\n\t\tmodifierClassNames,\n\t\twithIllustration ? 'has-illustration' : null\n\t);\n\n\tconst fieldsetClasses = classnames( 'components-placeholder__fieldset', {\n\t\t'is-column-layout': isColumnLayout,\n\t} );\n\n\tuseEffect( () => {\n\t\tif ( instructions ) {\n\t\t\tspeak( instructions );\n\t\t}\n\t}, [ instructions ] );\n\n\treturn (\n\t\t<div { ...additionalProps } className={ classes }>\n\t\t\t{ withIllustration ? PlaceholderIllustration : null }\n\t\t\t{ resizeListener }\n\t\t\t{ notices }\n\t\t\t{ preview && (\n\t\t\t\t<div className=\"components-placeholder__preview\">\n\t\t\t\t\t{ preview }\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div className=\"components-placeholder__label\">\n\t\t\t\t<Icon icon={ icon } />\n\t\t\t\t{ label }\n\t\t\t</div>\n\t\t\t{ !! instructions && (\n\t\t\t\t<div className=\"components-placeholder__instructions\">\n\t\t\t\t\t{ instructions }\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div className={ fieldsetClasses }>{ children }</div>\n\t\t</div>\n\t);\n}\n\nexport default Placeholder;\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,UAAU,MAAM,YAAY;;AAEnC;AACA;AACA;AACA,SAASC,iBAAiB,QAAQ,oBAAoB;AACtD,SAASC,GAAG,EAAEC,IAAI,QAAQ,uBAAuB;AACjD,SAASC,SAAS,QAAQ,oBAAoB;AAC9C,SAASC,KAAK,QAAQ,iBAAiB;;AAEvC;AACA;AACA;AACA,OAAOC,IAAI,MAAM,SAAS;AAI1B,MAAMC,uBAAuB,GAC5BC,aAAA,CAACN,GAAG;EACHO,SAAS,EAAC,sCAAsC;EAChDC,IAAI,EAAC,MAAM;EACXC,KAAK,EAAC,4BAA4B;EAClCC,OAAO,EAAC,WAAW;EACnBC,mBAAmB,EAAC;AAAM,GAE1BL,aAAA,CAACL,IAAI;EAACW,YAAY,EAAC,oBAAoB;EAACC,CAAC,EAAC;AAAY,CAAE,CACpD,CACL;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAC1BC,KAAgE,EAC/D;EACD,MAAM;IACLC,IAAI;IACJC,QAAQ;IACRC,KAAK;IACLC,YAAY;IACZZ,SAAS;IACTa,OAAO;IACPC,OAAO;IACPC,cAAc;IACdC,gBAAgB;IAChB,GAAGC;EACJ,CAAC,GAAGT,KAAK;EACT,MAAM,CAAEU,cAAc,EAAE;IAAEC;EAAM,CAAC,CAAE,GAAG3B,iBAAiB,CAAC,CAAC;;EAEzD;EACA;EACA,IAAI4B,kBAAkB;EACtB,IAAK,OAAOD,KAAK,KAAK,QAAQ,EAAG;IAChCC,kBAAkB,GAAG;MACpB,UAAU,EAAED,KAAK,IAAI,GAAG;MACxB,WAAW,EAAEA,KAAK,IAAI,GAAG,IAAIA,KAAK,GAAG,GAAG;MACxC,UAAU,EAAEA,KAAK,GAAG;IACrB,CAAC;EACF;EAEA,MAAME,OAAO,GAAG9B,UAAU,CACzB,wBAAwB,EACxBS,SAAS,EACToB,kBAAkB,EAClBJ,gBAAgB,GAAG,kBAAkB,GAAG,IACzC,CAAC;EAED,MAAMM,eAAe,GAAG/B,UAAU,CAAE,kCAAkC,EAAE;IACvE,kBAAkB,EAAEwB;EACrB,CAAE,CAAC;EAEHpB,SAAS,CAAE,MAAM;IAChB,IAAKiB,YAAY,EAAG;MACnBhB,KAAK,CAAEgB,YAAa,CAAC;IACtB;EACD,CAAC,EAAE,CAAEA,YAAY,CAAG,CAAC;EAErB,OACCb,aAAA;IAAA,GAAUkB,eAAe;IAAGjB,SAAS,EAAGqB;EAAS,GAC9CL,gBAAgB,GAAGlB,uBAAuB,GAAG,IAAI,EACjDoB,cAAc,EACdL,OAAO,EACPC,OAAO,IACRf,aAAA;IAAKC,SAAS,EAAC;EAAiC,GAC7Cc,OACE,CACL,EACDf,aAAA;IAAKC,SAAS,EAAC;EAA+B,GAC7CD,aAAA,CAACF,IAAI;IAACY,IAAI,EAAGA;EAAM,CAAE,CAAC,EACpBE,KACE,CAAC,EACJ,CAAC,CAAEC,YAAY,IAChBb,aAAA;IAAKC,SAAS,EAAC;EAAsC,GAClDY,YACE,CACL,EACDb,aAAA;IAAKC,SAAS,EAAGsB;EAAiB,GAAGZ,QAAe,CAChD,CAAC;AAER;AAEA,eAAeH,WAAW"}
@@ -2246,16 +2246,6 @@ body.rtl .components-panel__body-toggle.components-button .dashicons-arrow-right
2246
2246
  font-size: 13px;
2247
2247
  }
2248
2248
 
2249
- .components-placeholder__fieldset.components-placeholder__fieldset {
2250
- border: none;
2251
- padding: 0;
2252
- }
2253
- .components-placeholder__fieldset.components-placeholder__fieldset .components-placeholder__instructions {
2254
- padding: 0;
2255
- font-weight: normal;
2256
- font-size: 1em;
2257
- }
2258
-
2259
2249
  .components-placeholder__fieldset.is-column-layout,
2260
2250
  .components-placeholder__fieldset.is-column-layout form {
2261
2251
  flex-direction: column;
@@ -2253,16 +2253,6 @@ body.rtl .components-panel__body-toggle.components-button .dashicons-arrow-right
2253
2253
  font-size: 13px;
2254
2254
  }
2255
2255
 
2256
- .components-placeholder__fieldset.components-placeholder__fieldset {
2257
- border: none;
2258
- padding: 0;
2259
- }
2260
- .components-placeholder__fieldset.components-placeholder__fieldset .components-placeholder__instructions {
2261
- padding: 0;
2262
- font-weight: normal;
2263
- font-size: 1em;
2264
- }
2265
-
2266
2256
  .components-placeholder__fieldset.is-column-layout,
2267
2257
  .components-placeholder__fieldset.is-column-layout form {
2268
2258
  flex-direction: column;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/date-time/time/index.tsx"],"names":[],"mappings":";AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAuDhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAE,EAC3B,QAAQ,EACR,WAAW,EACX,QAAQ,GACR,EAAE,eAAe,eAsQjB;AAED,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/date-time/time/index.tsx"],"names":[],"mappings":";AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAuDhD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,UAAU,CAAE,EAC3B,QAAQ,EACR,WAAW,EACX,QAAQ,GACR,EAAE,eAAe,eA6QjB;AAED,eAAe,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modal/index.tsx"],"names":[],"mappings":";AAoCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAkQ1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,KAAK,uGAAiC,CAAC;AAEpD,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/modal/index.tsx"],"names":[],"mappings":";AAoCA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA0R1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,KAAK,uGAAiC,CAAC;AAEpD,eAAe,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.story.d.ts","sourceRoot":"","sources":["../../../src/modal/stories/index.story.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAatD,OAAO,KAAK,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,IAAI,EAAE,IAAI,CAAE,OAAO,KAAK,CA0B7B,CAAC;AACF,eAAe,IAAI,CAAC;AA4CpB,eAAO,MAAM,OAAO,EAAE,OAAO,CAAE,OAAO,KAAK,CAAwB,CAAC;AAuBpE,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAE,OAAO,KAAK,CAAwB,CAAC"}
1
+ {"version":3,"file":"index.story.d.ts","sourceRoot":"","sources":["../../../src/modal/stories/index.story.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAatD,OAAO,KAAK,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,IAAI,EAAE,IAAI,CAAE,OAAO,KAAK,CA2B7B,CAAC;AACF,eAAe,IAAI,CAAC;AA4CpB,eAAO,MAAM,OAAO,EAAE,OAAO,CAAE,OAAO,KAAK,CAAwB,CAAC;AAuBpE,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAE,OAAO,KAAK,CAAwB,CAAC"}
@@ -59,7 +59,7 @@ export type ModalProps = {
59
59
  *
60
60
  * @default true
61
61
  */
62
- focusOnMount?: Parameters<typeof useFocusOnMount>[0];
62
+ focusOnMount?: Parameters<typeof useFocusOnMount>[0] | 'firstContentElement';
63
63
  /**
64
64
  * Elements that are injected into the modal header to the left of the close button (if rendered).
65
65
  * Hidden if `__experimentalHideHeader` is `true`.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/modal/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EACX,QAAQ,EACR,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,CAAC,EAAE;QACN;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;;;;;;WAQG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,UAAU,CAAE,OAAO,eAAe,CAAE,CAAE,CAAC,CAAE,CAAC;IACzD;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC;IAE1B;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,oBAAoB,CAAE,cAAc,CAAE,CAAC;IACnD;;OAEG;IACH,cAAc,EAAE,CACf,KAAK,CAAC,EAAE,aAAa,CAAE,cAAc,CAAE,GAAG,cAAc,KACpD,IAAI,CAAC;IACV;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/modal/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EACX,QAAQ,EACR,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,CAAC,EAAE;QACN;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;;;;;;WAQG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,YAAY,CAAC,EACV,UAAU,CAAE,OAAO,eAAe,CAAE,CAAE,CAAC,CAAE,GACzC,qBAAqB,CAAC;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC;IAE1B;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,oBAAoB,CAAE,cAAc,CAAE,CAAC;IACnD;;OAEG;IACH,cAAc,EAAE,CACf,KAAK,CAAC,EAAE,aAAa,CAAE,cAAc,CAAE,GAAG,cAAc,KACpD,IAAI,CAAC;IACV;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/placeholder/index.tsx"],"names":[],"mappings":";AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAc7D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,uBAAuB,CAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,CAAE,eA6DhE;AAED,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/placeholder/index.tsx"],"names":[],"mappings":";AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAc7D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,uBAAuB,CAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,CAAE,eAkEhE;AAED,eAAe,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/components",
3
- "version": "25.8.0",
3
+ "version": "25.8.2",
4
4
  "description": "UI components for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -41,23 +41,23 @@
41
41
  "@floating-ui/react-dom": "^2.0.1",
42
42
  "@radix-ui/react-dropdown-menu": "2.0.4",
43
43
  "@use-gesture/react": "^10.2.24",
44
- "@wordpress/a11y": "^3.42.0",
45
- "@wordpress/compose": "^6.19.0",
46
- "@wordpress/date": "^4.42.0",
47
- "@wordpress/deprecated": "^3.42.0",
48
- "@wordpress/dom": "^3.42.0",
49
- "@wordpress/element": "^5.19.0",
50
- "@wordpress/escape-html": "^2.42.0",
51
- "@wordpress/hooks": "^3.42.0",
52
- "@wordpress/html-entities": "^3.42.0",
53
- "@wordpress/i18n": "^4.42.0",
54
- "@wordpress/icons": "^9.33.0",
55
- "@wordpress/is-shallow-equal": "^4.42.0",
56
- "@wordpress/keycodes": "^3.42.0",
57
- "@wordpress/primitives": "^3.40.0",
58
- "@wordpress/private-apis": "^0.24.0",
59
- "@wordpress/rich-text": "^6.19.0",
60
- "@wordpress/warning": "^2.42.0",
44
+ "@wordpress/a11y": "^3.42.2",
45
+ "@wordpress/compose": "^6.19.2",
46
+ "@wordpress/date": "^4.42.2",
47
+ "@wordpress/deprecated": "^3.42.2",
48
+ "@wordpress/dom": "^3.42.2",
49
+ "@wordpress/element": "^5.19.2",
50
+ "@wordpress/escape-html": "^2.42.2",
51
+ "@wordpress/hooks": "^3.42.2",
52
+ "@wordpress/html-entities": "^3.42.2",
53
+ "@wordpress/i18n": "^4.42.2",
54
+ "@wordpress/icons": "^9.33.2",
55
+ "@wordpress/is-shallow-equal": "^4.42.2",
56
+ "@wordpress/keycodes": "^3.42.2",
57
+ "@wordpress/primitives": "^3.40.2",
58
+ "@wordpress/private-apis": "^0.24.2",
59
+ "@wordpress/rich-text": "^6.19.2",
60
+ "@wordpress/warning": "^2.42.2",
61
61
  "change-case": "^4.1.2",
62
62
  "classnames": "^2.3.1",
63
63
  "colord": "^2.7.0",
@@ -77,7 +77,7 @@
77
77
  "reakit": "^1.3.11",
78
78
  "remove-accents": "^0.5.0",
79
79
  "use-lilius": "^2.0.1",
80
- "uuid": "^8.3.0",
80
+ "uuid": "^9.0.1",
81
81
  "valtio": "1.7.0"
82
82
  },
83
83
  "peerDependencies": {
@@ -87,5 +87,5 @@
87
87
  "publishConfig": {
88
88
  "access": "public"
89
89
  },
90
- "gitHead": "cc35f517ed017ab7131319af3e87c359e8de175d"
90
+ "gitHead": "5d2e3d07cc97af8090fc32c1e5d5013a2967e752"
91
91
  }
@@ -127,7 +127,14 @@ export function TimePicker( {
127
127
  method: 'hours' | 'minutes' | 'date' | 'year'
128
128
  ) => {
129
129
  const callback: InputChangeCallback = ( value, { event } ) => {
130
- if ( ! ( event.target instanceof HTMLInputElement ) ) {
130
+ // `instanceof` checks need to get the instance definition from the
131
+ // corresponding window object — therefore, the following logic makes
132
+ // the component work correctly even when rendered inside an iframe.
133
+ const HTMLInputElementInstance =
134
+ ( event.target as HTMLInputElement )?.ownerDocument.defaultView
135
+ ?.HTMLInputElement ?? HTMLInputElement;
136
+
137
+ if ( ! ( event.target instanceof HTMLInputElementInstance ) ) {
131
138
  return;
132
139
  }
133
140
 
@@ -187,10 +187,16 @@ Titles are required for accessibility reasons, see `aria.labelledby` and `title`
187
187
 
188
188
  - Required: No
189
189
 
190
- #### `focusOnMount`: `boolean | 'firstElement'`
190
+ #### `focusOnMount`: `boolean | 'firstElement'` | 'firstContentElement'
191
191
 
192
192
  If this property is true, it will focus the first tabbable element rendered in the modal.
193
193
 
194
+ If this property is false, focus will not be transferred and it is the responsibility of the consumer to ensure accessible focus management.
195
+
196
+ If set to `firstElement` focus will be placed on the first tabbable element anywhere within the Modal.
197
+
198
+ If set to `firstContentElement` focus will be placed on the first tabbable element within the Modal's **content** (i.e. children). Note that it is the responsibility of the consumer to ensure there is at least one tabbable element within the children **or the focus will be lost**.
199
+
194
200
  - Required: No
195
201
  - Default: `true`
196
202
 
@@ -71,11 +71,23 @@ function UnforwardedModal(
71
71
  } = props;
72
72
 
73
73
  const ref = useRef< HTMLDivElement >();
74
+
74
75
  const instanceId = useInstanceId( Modal );
75
76
  const headingId = title
76
77
  ? `components-modal-header-${ instanceId }`
77
78
  : aria.labelledby;
78
- const focusOnMountRef = useFocusOnMount( focusOnMount );
79
+
80
+ // The focus hook does not support 'firstContentElement' but this is a valid
81
+ // value for the Modal's focusOnMount prop. The following code ensures the focus
82
+ // hook will focus the first focusable node within the element to which it is applied.
83
+ // When `firstContentElement` is passed as the value of the focusOnMount prop,
84
+ // the focus hook is applied to the Modal's content element.
85
+ // Otherwise, the focus hook is applied to the Modal's ref. This ensures that the
86
+ // focus hook will focus the first element in the Modal's **content** when
87
+ // `firstContentElement` is passed.
88
+ const focusOnMountRef = useFocusOnMount(
89
+ focusOnMount === 'firstContentElement' ? 'firstElement' : focusOnMount
90
+ );
79
91
  const constrainedTabbingRef = useConstrainedTabbing();
80
92
  const focusReturnRef = useFocusReturn();
81
93
  const focusOutsideProps = useFocusOutside( onRequestClose );
@@ -223,7 +235,9 @@ function UnforwardedModal(
223
235
  ref={ useMergeRefs( [
224
236
  constrainedTabbingRef,
225
237
  focusReturnRef,
226
- focusOnMountRef,
238
+ focusOnMount !== 'firstContentElement'
239
+ ? focusOnMountRef
240
+ : null,
227
241
  ] ) }
228
242
  role={ role }
229
243
  aria-label={ contentLabel }
@@ -283,7 +297,17 @@ function UnforwardedModal(
283
297
  ) }
284
298
  </div>
285
299
  ) }
286
- <div ref={ childrenContainerRef }>{ children }</div>
300
+
301
+ <div
302
+ ref={ useMergeRefs( [
303
+ childrenContainerRef,
304
+ focusOnMount === 'firstContentElement'
305
+ ? focusOnMountRef
306
+ : null,
307
+ ] ) }
308
+ >
309
+ { children }
310
+ </div>
287
311
  </div>
288
312
  </div>
289
313
  </StyleProvider>
@@ -28,7 +28,8 @@ const meta: Meta< typeof Modal > = {
28
28
  control: { type: null },
29
29
  },
30
30
  focusOnMount: {
31
- control: { type: 'boolean' },
31
+ options: [ true, false, 'firstElement', 'firstContentElement' ],
32
+ control: { type: 'select' },
32
33
  },
33
34
  role: {
34
35
  control: { type: 'text' },
@@ -13,6 +13,7 @@ import { useState } from '@wordpress/element';
13
13
  * Internal dependencies
14
14
  */
15
15
  import Modal from '../';
16
+ import type { ModalProps } from '../types';
16
17
 
17
18
  const noop = () => {};
18
19
 
@@ -236,4 +237,127 @@ describe( 'Modal', () => {
236
237
  screen.getByText( 'A sweet button', { selector: 'button' } )
237
238
  ).toBeInTheDocument();
238
239
  } );
240
+
241
+ describe( 'Focus handling', () => {
242
+ let originalGetClientRects: () => DOMRectList;
243
+
244
+ const FocusMountDemo = ( {
245
+ focusOnMount,
246
+ }: Pick< ModalProps, 'focusOnMount' > ) => {
247
+ const [ isShown, setIsShown ] = useState( false );
248
+ return (
249
+ <>
250
+ <button onClick={ () => setIsShown( true ) }>
251
+ Toggle Modal
252
+ </button>
253
+ { isShown && (
254
+ <Modal
255
+ focusOnMount={ focusOnMount }
256
+ onRequestClose={ () => setIsShown( false ) }
257
+ >
258
+ <p>Modal content</p>
259
+ <a href="https://wordpress.org">
260
+ First Focusable Content Element
261
+ </a>
262
+
263
+ <a href="https://wordpress.org">
264
+ Another Focusable Content Element
265
+ </a>
266
+ </Modal>
267
+ ) }
268
+ </>
269
+ );
270
+ };
271
+
272
+ beforeEach( () => {
273
+ /**
274
+ * The test environment does not have a layout engine, so we need to mock
275
+ * the getClientRects method. This ensures that the focusable elements can be
276
+ * found by the `focusOnMount` logic which depends on layout information
277
+ * to determine if the element is visible or not.
278
+ * See https://github.com/WordPress/gutenberg/blob/trunk/packages/dom/src/focusable.js#L55-L61.
279
+ */
280
+ // @ts-expect-error We're not trying to comply to the DOM spec, only mocking
281
+ window.HTMLElement.prototype.getClientRects = function () {
282
+ return [ 'trick-jsdom-into-having-size-for-element-rect' ];
283
+ };
284
+ } );
285
+
286
+ afterEach( () => {
287
+ // Restore original HTMLElement prototype.
288
+ // See beforeEach for details.
289
+ window.HTMLElement.prototype.getClientRects =
290
+ originalGetClientRects;
291
+ } );
292
+
293
+ it( 'should focus the Modal dialog by default when `focusOnMount` prop is not provided', async () => {
294
+ const user = userEvent.setup();
295
+
296
+ render( <FocusMountDemo /> );
297
+
298
+ const opener = screen.getByRole( 'button', {
299
+ name: 'Toggle Modal',
300
+ } );
301
+
302
+ await user.click( opener );
303
+
304
+ expect( screen.getByRole( 'dialog' ) ).toHaveFocus();
305
+ } );
306
+
307
+ it( 'should focus the Modal dialog when `true` passed as value for `focusOnMount` prop', async () => {
308
+ const user = userEvent.setup();
309
+
310
+ render( <FocusMountDemo focusOnMount={ true } /> );
311
+
312
+ const opener = screen.getByRole( 'button', {
313
+ name: 'Toggle Modal',
314
+ } );
315
+
316
+ await user.click( opener );
317
+
318
+ expect( screen.getByRole( 'dialog' ) ).toHaveFocus();
319
+ } );
320
+
321
+ it( 'should focus the first focusable element in the contents (if found) when `firstContentElement` passed as value for `focusOnMount` prop', async () => {
322
+ const user = userEvent.setup();
323
+
324
+ render( <FocusMountDemo focusOnMount="firstContentElement" /> );
325
+
326
+ const opener = screen.getByRole( 'button' );
327
+
328
+ await user.click( opener );
329
+
330
+ expect(
331
+ screen.getByText( 'First Focusable Content Element' )
332
+ ).toHaveFocus();
333
+ } );
334
+
335
+ it( 'should focus the first element anywhere within the Modal when `firstElement` passed as value for `focusOnMount` prop', async () => {
336
+ const user = userEvent.setup();
337
+
338
+ render( <FocusMountDemo focusOnMount="firstElement" /> );
339
+
340
+ const opener = screen.getByRole( 'button' );
341
+
342
+ await user.click( opener );
343
+
344
+ expect(
345
+ screen.getByRole( 'button', { name: 'Close' } )
346
+ ).toHaveFocus();
347
+ } );
348
+
349
+ it( 'should not move focus when `false` passed as value for `focusOnMount` prop', async () => {
350
+ const user = userEvent.setup();
351
+
352
+ render( <FocusMountDemo focusOnMount={ false } /> );
353
+
354
+ const opener = screen.getByRole( 'button', {
355
+ name: 'Toggle Modal',
356
+ } );
357
+
358
+ await user.click( opener );
359
+
360
+ expect( opener ).toHaveFocus();
361
+ } );
362
+ } );
239
363
  } );
@@ -68,7 +68,9 @@ export type ModalProps = {
68
68
  *
69
69
  * @default true
70
70
  */
71
- focusOnMount?: Parameters< typeof useFocusOnMount >[ 0 ];
71
+ focusOnMount?:
72
+ | Parameters< typeof useFocusOnMount >[ 0 ]
73
+ | 'firstContentElement';
72
74
  /**
73
75
  * Elements that are injected into the modal header to the left of the close button (if rendered).
74
76
  * Hidden if `__experimentalHideHeader` is `true`.
@@ -8,6 +8,8 @@ import classnames from 'classnames';
8
8
  */
9
9
  import { useResizeObserver } from '@wordpress/compose';
10
10
  import { SVG, Path } from '@wordpress/primitives';
11
+ import { useEffect } from '@wordpress/element';
12
+ import { speak } from '@wordpress/a11y';
11
13
 
12
14
  /**
13
15
  * Internal dependencies
@@ -72,10 +74,17 @@ export function Placeholder(
72
74
  modifierClassNames,
73
75
  withIllustration ? 'has-illustration' : null
74
76
  );
77
+
75
78
  const fieldsetClasses = classnames( 'components-placeholder__fieldset', {
76
79
  'is-column-layout': isColumnLayout,
77
80
  } );
78
81
 
82
+ useEffect( () => {
83
+ if ( instructions ) {
84
+ speak( instructions );
85
+ }
86
+ }, [ instructions ] );
87
+
79
88
  return (
80
89
  <div { ...additionalProps } className={ classes }>
81
90
  { withIllustration ? PlaceholderIllustration : null }
@@ -90,14 +99,12 @@ export function Placeholder(
90
99
  <Icon icon={ icon } />
91
100
  { label }
92
101
  </div>
93
- <fieldset className={ fieldsetClasses }>
94
- { !! instructions && (
95
- <legend className="components-placeholder__instructions">
96
- { instructions }
97
- </legend>
98
- ) }
99
- { children }
100
- </fieldset>
102
+ { !! instructions && (
103
+ <div className="components-placeholder__instructions">
104
+ { instructions }
105
+ </div>
106
+ ) }
107
+ <div className={ fieldsetClasses }>{ children }</div>
101
108
  </div>
102
109
  );
103
110
  }