@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
1 lines • 4.93 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\nexport namespace Portal {\n export type Props = PortalProps;\n}\n"],"mappings":";;;;;;;;;AAKA,SAAS,iBAAiB,OAAoC;CAC5D,MAAM,OAAO,SAAS,cAAc,KAAK;CACzC,KAAK,aAAa,eAAe,MAAM;CACvC,OAAO,MAAM,cAAc,YACzB,KAAK,UAAU,IAAI,GAAG,MAAM,UAAU,MAAM,GAAG,EAAE,OAAO,OAAO,CAAC;CAClE,OAAO,MAAM,UAAU,YAAY,OAAO,OAAO,KAAK,OAAO,MAAM,KAAK;CACxE,OAAO,MAAM,OAAO,YAAY,KAAK,aAAa,MAAM,MAAM,EAAE;CAChE,OAAO;AACT;AA8BA,SAAS,cAAc,EAAE,QAAQ,iBAAiB,GAAG,UAAwC;CAC3F,IAAI,QAAQ;EACV,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,cAA2B,MAAM,KAAK,iBAAiB,MAAM;EAG/E,OAAO;CACT;CAEA,IAAI,iBAAiB;EACnB,MAAM,eAAe,SAAS,cAA2B,mCAAmC;EAE5F,IAAI,cACF,OAAO;EAGT,MAAM,OAAO,iBAAiB,MAAM;EACpC,KAAK,aAAa,mCAAmC,MAAM;EAC3D,SAAS,KAAK,YAAY,IAAI;EAC9B,OAAO;CACT;CAEA,OAAO,iBAAiB,MAAM;AAChC;AAOA,MAAM,eAAe,EACnB,iBAAiB,KACnB;AAEA,MAAa,SAASA,gBAAAA,SAAwB,UAAU;CACtD,MAAM,EAAE,UAAU,QAAQ,iBAAiB,KAAK,GAAG,WAAWC,kBAAAA,SAC5D,UACA,cACA,KACF;CAEA,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAAuB,KAAK;CAC5C,MAAM,WAAA,GAAA,MAAA,QAAqC,IAAI;CAE/C,CAAA,GAAA,eAAA,2BAA0B;EACxB,WAAW,IAAI;EACf,QAAQ,UAAU,cAAc;GAAE;GAAQ;GAAiB,GAAG;EAAO,CAAC;EACtE,CAAA,GAAA,eAAA,WAAU,KAAK,QAAQ,OAAO;EAE9B,IAAI,CAAC,UAAU,CAAC,mBAAmB,QAAQ,SACzC,SAAS,KAAK,YAAY,QAAQ,OAAO;EAG3C,aAAa;GACX,IAAI,CAAC,UAAU,CAAC,mBAAmB,QAAQ,SACzC,SAAS,KAAK,YAAY,QAAQ,OAAO;EAE7C;CACF,GAAG,CAAC,MAAM,CAAC;CAEX,IAAI,CAAC,WAAW,CAAC,QAAQ,SACvB,OAAO;CAGT,QAAA,GAAA,UAAA,cAAoB,iBAAA,GAAA,kBAAA,KAAA,kBAAA,UAAA,EAAG,SAAW,CAAA,GAAG,QAAQ,OAAO;AACtD,CAAC;AAED,OAAO,cAAc"}