UNPKG

@atlaskit/inline-dialog

Version:

An inline dialog is a pop-up container for small amounts of information. It can also contain controls.

155 lines (150 loc) 5.49 kB
/* inline-dialog-top-layer.tsx generated by @compiled/babel-plugin v0.39.1 */ import "./inline-dialog-top-layer.compiled.css"; import * as React from 'react'; import { ax, ix } from "@compiled/react/runtime"; import { Fragment, memo, useCallback, useEffect, useMemo, useRef } from 'react'; import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next'; import noop from '@atlaskit/ds-lib/noop'; import { slideAndFade } from '@atlaskit/top-layer/animations'; import { getAriaForTrigger } from '@atlaskit/top-layer/get-aria-for-trigger'; import { fromLegacyPlacement } from '@atlaskit/top-layer/placement-map'; import { createPopoverCloseEvent, Popover } from '@atlaskit/top-layer/popover'; import { useAnchorPosition } from '@atlaskit/top-layer/use-anchor-position'; import { usePopoverId } from '@atlaskit/top-layer/use-popover-id'; const displayContentsStyles = { root: "_1e0c1bgi" }; const styles = { container: "_2rkofajl _vchh1ntv _p12flti4 _c71llti4 _bfhk1bhr _16qs130s _syazi7uo _85i5pxbi _1q51pxbi _y4ti1ejb _bozg1ejb" }; const animation = slideAndFade(); /** * Applies ARIA attributes to the child trigger element via an effect, * keeping them in sync with popup state. */ function TriggerWrapper({ children, triggerRef, ariaAttributes }) { useEffect(() => { const trigger = triggerRef.current; if (!trigger) { return; } // Apply each attribute. When a value is `undefined` (e.g. // `aria-controls` while the popover host is not in the DOM), // remove the attribute so the trigger does not retain a stale // reference from a previous open. Object.entries(ariaAttributes).forEach(([key, value]) => { if (value === undefined) { trigger.removeAttribute(key); return; } trigger.setAttribute(key, String(value)); }); }, [ariaAttributes, triggerRef]); return /*#__PURE__*/React.createElement("div", { ref: node => { var _node$firstElementChi; const firstElementChild = (_node$firstElementChi = node === null || node === void 0 ? void 0 : node.firstElementChild) !== null && _node$firstElementChi !== void 0 ? _node$firstElementChi : null; triggerRef.current = firstElementChild; }, className: ax([displayContentsStyles.root]) }, children); } /** * Top-layer implementation of InlineDialog. * * Replaces the legacy rendering pipeline (Popper.js + Portal + @atlaskit/layering) * with the native Popover API + CSS Anchor Positioning via @atlaskit/top-layer. * * Gated behind the `platform-dst-top-layer` feature flag. */ const InlineDialogTopLayer = /*#__PURE__*/memo(function InlineDialogTopLayer({ isOpen = false, onContentBlur = noop, onContentClick = noop, onContentFocus = noop, onClose: providedOnClose = noop, placement = 'bottom-start', testId, content, children, // No-op props. // These props are accepted for API compatibility but have no effect // in the top-layer path. Each is documented with why it is unnecessary. // top-layer: CSS Anchor Positioning replaces Popper strategy. No-op. // eslint-disable-next-line @typescript-eslint/no-unused-vars strategy: _strategy, // top-layer: Popper.js fallbackPlacements not applicable. No-op. // eslint-disable-next-line @typescript-eslint/no-unused-vars fallbackPlacements: _fallbackPlacements }) { const triggerRef = useRef(null); const popoverRef = useRef(null); const popoverId = usePopoverId(); const onClose = usePlatformLeafEventHandler({ fn: event => providedOnClose(event), action: 'closed', componentName: 'inlineDialog', packageName: "@atlaskit/inline-dialog", packageVersion: "19.0.1" }); // Placement conversion. const topLayerPlacement = useMemo(() => fromLegacyPlacement({ legacy: placement }), [placement]); // `isOpen` is included so the anchor positioning effect re-runs when // the Popover host element is unmounted/remounted across open cycles. useAnchorPosition({ anchorRef: triggerRef, popoverRef, placement: topLayerPlacement, isOpen }); // onClose bridge. // Translates top-layer's { reason } into the legacy onClose({ isOpen, event }) shape. // Focus restoration is handled automatically by the Popover based on the content role // (role="dialog" -> auto-restore). const handleOnClose = useCallback(({ reason }) => { const syntheticEvent = createPopoverCloseEvent({ reason }); onClose({ isOpen: false, event: syntheticEvent }); }, [onClose]); const ariaAttributes = getAriaForTrigger({ role: 'dialog', isOpen, popoverId }); return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(TriggerWrapper, { triggerRef: triggerRef, ariaAttributes: ariaAttributes }, children), /*#__PURE__*/React.createElement(Popover, { ref: popoverRef, id: popoverId, role: "dialog" // TODO: i18n. Hardcoded label is not translatable. // Acceptable given this component is intent-to-deprecate. , label: "Inline dialog", isOpen: isOpen, onClose: handleOnClose, animate: animation, placement: topLayerPlacement, testId: testId }, /*#__PURE__*/React.createElement("div", { role: "presentation", onBlur: onContentBlur, onClick: onContentClick, onFocus: onContentFocus, className: ax([styles.container]) }, typeof content === 'function' ? content() : content))); }); export default InlineDialogTopLayer;