@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
1 lines • 4.83 kB
Source Map (JSON)
{"version":3,"file":"Portal.cjs","names":["factory","useProps"],"sources":["../../../src/components/Portal/Portal.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { assignRef, useIsomorphicEffect } from '@mantine/hooks';\nimport { Factory, factory, useProps } from '../../core';\n\nfunction createPortalNode(props: React.ComponentProps<'div'>) {\n const node = document.createElement('div');\n node.setAttribute('data-portal', 'true');\n typeof props.className === 'string' &&\n node.classList.add(...props.className.split(' ').filter(Boolean));\n typeof props.style === 'object' && Object.assign(node.style, props.style);\n typeof props.id === 'string' && node.setAttribute('id', props.id);\n return node;\n}\n\nexport interface BasePortalProps extends React.ComponentProps<'div'> {\n /**\n * Target element where portal should be rendered. Accepts:\n * - HTMLElement: Renders portal inside this element\n * - string: CSS selector - renders inside first matching element\n * - undefined: Uses shared portal node or creates new one based on `reuseTargetNode`\n *\n * Note: If selector doesn't match any element, portal will not render\n */\n target?: HTMLElement | string;\n\n /**\n * When true and target is not specified, all Portal instances share a single\n * container node appended to document.body. When false, each Portal creates\n * its own container node.\n *\n * Has no effect when target is specified.\n *\n * @default true\n */\n reuseTargetNode?: boolean;\n}\n\nexport interface PortalProps extends BasePortalProps {\n /** Content to render inside the portal */\n children: React.ReactNode;\n}\n\nfunction getTargetNode({ target, reuseTargetNode, ...others }: BasePortalProps): HTMLElement {\n if (target) {\n if (typeof target === 'string') {\n return document.querySelector<HTMLElement>(target) || createPortalNode(others);\n }\n\n return target;\n }\n\n if (reuseTargetNode) {\n const existingNode = document.querySelector<HTMLElement>('[data-mantine-shared-portal-node]');\n\n if (existingNode) {\n return existingNode;\n }\n\n const node = createPortalNode(others);\n node.setAttribute('data-mantine-shared-portal-node', 'true');\n document.body.appendChild(node);\n return node;\n }\n\n return createPortalNode(others);\n}\n\nexport type PortalFactory = Factory<{\n props: PortalProps;\n ref: HTMLDivElement;\n}>;\n\nconst defaultProps = {\n reuseTargetNode: true,\n} satisfies Partial<PortalProps>;\n\nexport const Portal = factory<PortalFactory>((props) => {\n const { children, target, reuseTargetNode, ref, ...others } = useProps(\n 'Portal',\n defaultProps,\n props\n );\n\n const [mounted, setMounted] = useState(false);\n const nodeRef = useRef<HTMLElement | null>(null);\n\n useIsomorphicEffect(() => {\n setMounted(true);\n nodeRef.current = getTargetNode({ target, reuseTargetNode, ...others });\n assignRef(ref, nodeRef.current);\n\n if (!target && !reuseTargetNode && nodeRef.current) {\n document.body.appendChild(nodeRef.current);\n }\n\n return () => {\n if (!target && !reuseTargetNode && nodeRef.current) {\n document.body.removeChild(nodeRef.current);\n }\n };\n }, [target]);\n\n if (!mounted || !nodeRef.current) {\n return null;\n }\n\n return createPortal(<>{children}</>, nodeRef.current);\n});\n\nPortal.displayName = '@mantine/core/Portal';\n"],"mappings":";;;;;;;;;AAKA,SAAS,iBAAiB,OAAoC;CAC5D,MAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,MAAK,aAAa,eAAe,OAAO;AACxC,QAAO,MAAM,cAAc,YACzB,KAAK,UAAU,IAAI,GAAG,MAAM,UAAU,MAAM,IAAI,CAAC,OAAO,QAAQ,CAAC;AACnE,QAAO,MAAM,UAAU,YAAY,OAAO,OAAO,KAAK,OAAO,MAAM,MAAM;AACzE,QAAO,MAAM,OAAO,YAAY,KAAK,aAAa,MAAM,MAAM,GAAG;AACjE,QAAO;;AA+BT,SAAS,cAAc,EAAE,QAAQ,iBAAiB,GAAG,UAAwC;AAC3F,KAAI,QAAQ;AACV,MAAI,OAAO,WAAW,SACpB,QAAO,SAAS,cAA2B,OAAO,IAAI,iBAAiB,OAAO;AAGhF,SAAO;;AAGT,KAAI,iBAAiB;EACnB,MAAM,eAAe,SAAS,cAA2B,oCAAoC;AAE7F,MAAI,aACF,QAAO;EAGT,MAAM,OAAO,iBAAiB,OAAO;AACrC,OAAK,aAAa,mCAAmC,OAAO;AAC5D,WAAS,KAAK,YAAY,KAAK;AAC/B,SAAO;;AAGT,QAAO,iBAAiB,OAAO;;AAQjC,MAAM,eAAe,EACnB,iBAAiB,MAClB;AAED,MAAa,SAASA,gBAAAA,SAAwB,UAAU;CACtD,MAAM,EAAE,UAAU,QAAQ,iBAAiB,KAAK,GAAG,WAAWC,kBAAAA,SAC5D,UACA,cACA,MACD;CAED,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAAuB,MAAM;CAC7C,MAAM,WAAA,GAAA,MAAA,QAAqC,KAAK;AAEhD,EAAA,GAAA,eAAA,2BAA0B;AACxB,aAAW,KAAK;AAChB,UAAQ,UAAU,cAAc;GAAE;GAAQ;GAAiB,GAAG;GAAQ,CAAC;AACvE,GAAA,GAAA,eAAA,WAAU,KAAK,QAAQ,QAAQ;AAE/B,MAAI,CAAC,UAAU,CAAC,mBAAmB,QAAQ,QACzC,UAAS,KAAK,YAAY,QAAQ,QAAQ;AAG5C,eAAa;AACX,OAAI,CAAC,UAAU,CAAC,mBAAmB,QAAQ,QACzC,UAAS,KAAK,YAAY,QAAQ,QAAQ;;IAG7C,CAAC,OAAO,CAAC;AAEZ,KAAI,CAAC,WAAW,CAAC,QAAQ,QACvB,QAAO;AAGT,SAAA,GAAA,UAAA,cAAoB,iBAAA,GAAA,kBAAA,KAAA,kBAAA,UAAA,EAAG,UAAY,CAAA,EAAE,QAAQ,QAAQ;EACrD;AAEF,OAAO,cAAc"}