react-magic-portal 1.1.7 → 1.1.8
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.
- package/CHANGELOG.md +7 -0
- package/__tests__/package.json +3 -3
- package/package.json +1 -1
- package/packages/component/dist/index.js +1 -1
- package/packages/component/dist/index.js.map +1 -1
- package/packages/component/package.json +3 -3
- package/packages/component/src/index.ts +2 -2
- package/packages/example/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [1.1.8](https://github.com/molvqingtai/react-magic-portal/compare/v1.1.7...v1.1.8) (2025-09-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Performance Improvements
|
|
5
|
+
|
|
6
|
+
* react dom uses named import ([7f94ff4](https://github.com/molvqingtai/react-magic-portal/commit/7f94ff45daac11ee995df362b472b64f72453fe2))
|
|
7
|
+
|
|
1
8
|
## [1.1.7](https://github.com/molvqingtai/react-magic-portal/compare/v1.1.6...v1.1.7) (2025-09-28)
|
|
2
9
|
|
|
3
10
|
|
package/__tests__/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@eslint/js": "^9.36.0",
|
|
22
22
|
"@testing-library/react": "^16.3.0",
|
|
23
23
|
"@testing-library/user-event": "^14.6.1",
|
|
24
|
-
"@types/react": "^19.1.
|
|
24
|
+
"@types/react": "^19.1.15",
|
|
25
25
|
"@types/react-dom": "^19.1.9",
|
|
26
26
|
"@vitejs/plugin-react": "^5.0.4",
|
|
27
27
|
"@vitest/coverage-v8": "^3.2.4",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
32
32
|
"eslint-plugin-react-refresh": "^0.4.22",
|
|
33
33
|
"globals": "^16.4.0",
|
|
34
|
-
"happy-dom": "^
|
|
34
|
+
"happy-dom": "^19.0.2",
|
|
35
35
|
"react": "^19.1.1",
|
|
36
36
|
"react-dom": "^19.1.1",
|
|
37
37
|
"typescript": "^5.9.2",
|
|
38
|
-
"typescript-eslint": "^8.
|
|
38
|
+
"typescript-eslint": "^8.45.0",
|
|
39
39
|
"vite": "^7.1.7",
|
|
40
40
|
"vitest": "^3.2.4"
|
|
41
41
|
}
|
package/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e,{useCallback as t,useEffect as n,useLayoutEffect as r,useRef as i,useState as a}from"react";import o
|
|
1
|
+
import e,{useCallback as t,useEffect as n,useLayoutEffect as r,useRef as i,useState as a}from"react";import{createPortal as o}from"react-dom";const s=e=>{let t=Object.getOwnPropertyDescriptor(e.props,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning;return n?e.ref:(t=Object.getOwnPropertyDescriptor(e,`ref`)?.get,n=t&&`isReactWarning`in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)},c=e=>typeof e==`string`?document.querySelector(e):typeof e==`function`?e():e&&`current`in e?e.current:e,l=(e,t)=>{if(typeof e==`function`)return e(t);e!=null&&(e.current=t)},u=(...e)=>t=>{let n=e.map(e=>l(e,t));return()=>n.forEach((t,n)=>typeof t==`function`?t():l(e[n],null))},d=({anchor:l,position:d=`append`,children:f,onMount:p,onUnmount:m,key:h})=>{let g=i(null),[_,v]=a(null),y=e.Children.map(f,t=>{if(!e.isValidElement(t))return null;let n=s(t);return e.cloneElement(t,{ref:u(n,e=>{e&&g.current?.insertAdjacentElement({before:`beforebegin`,prepend:`afterbegin`,append:`beforeend`,after:`afterend`}[d],e)})})}),b=t(()=>{g.current=c(l),v(d===`prepend`||d===`append`?g.current:g.current?.parentElement??null)},[l,d]);return r(()=>{b();let e=new MutationObserver(e=>{!e.flatMap(({addedNodes:e,removedNodes:t})=>[...e,...t]).some(e=>_?.contains(e))&&b()});return e.observe(document.body,{childList:!0,subtree:!0}),()=>e.disconnect()},[b,l,_]),n(()=>{if(_&&g.current)return p?.(g.current,_),()=>{m?.(g.current,_)}},[p,m,_]),_&&o(y,_,h)};d.displayName=`MagicPortal`;var f=d;export{f as default};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import React, { useEffect, useState, useRef, useCallback, useLayoutEffect } from 'react'\nimport
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import React, { useEffect, useState, useRef, useCallback, useLayoutEffect } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport interface MagicPortalProps {\n anchor: string | (() => Element | null) | Element | React.RefObject<Element | null> | null\n position?: 'append' | 'prepend' | 'before' | 'after'\n children?: React.ReactElement | React.ReactElement[]\n onMount?: (anchor: Element, container: Element) => void\n onUnmount?: (anchor: Element, container: Element) => void\n key?: React.Key\n}\n\n/**\n * https://github.com/radix-ui/primitives/blob/36d954d3c1b41c96b1d2e875b93fc9362c8c09e6/packages/react/slot/src/slot.tsx#L166\n */\nconst getElementRef = (element: React.ReactElement) => {\n // React <=18 in DEV\n let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get\n let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning\n if (mayWarn) {\n return (element as any).ref as React.Ref<Element>\n }\n // React 19 in DEV\n getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get\n mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning\n if (mayWarn) {\n return (element.props as { ref?: React.Ref<Element> }).ref\n }\n\n // Not DEV\n return (element.props as { ref?: React.Ref<Element> }).ref || ((element as any).ref as React.Ref<Element>)\n}\n\nconst resolveAnchor = (anchor: MagicPortalProps['anchor']) => {\n if (typeof anchor === 'string') {\n return document.querySelector(anchor)\n } else if (typeof anchor === 'function') {\n return anchor()\n } else if (anchor && 'current' in anchor) {\n return anchor.current\n } else {\n return anchor\n }\n}\n\n/**\n * https://github.com/facebook/react/blob/d91d28c8ba6fe7c96e651f82fc47c9d5481bf5f9/packages/react-reconciler/src/ReactFiberHooks.js#L2792\n */\nconst setRef = <T>(ref: React.Ref<T> | undefined, value: T) => {\n if (typeof ref === 'function') {\n return ref(value)\n } else if (ref !== null && ref !== undefined) {\n ref.current = value\n }\n}\n\nconst mergeRef = <T extends Element | null>(...refs: (React.Ref<T> | undefined)[]) => {\n return (node: T) => {\n const cleanups = refs.map((ref) => setRef(ref, node))\n return () =>\n cleanups.forEach((cleanup, index) => (typeof cleanup === 'function' ? cleanup() : setRef(refs[index], null)))\n }\n}\n\nconst MagicPortal = ({ anchor, position = 'append', children, onMount, onUnmount, key }: MagicPortalProps) => {\n const anchorRef = useRef<Element | null>(null)\n const [container, setContainer] = useState<Element | null>(null)\n\n const nodes = React.Children.map(children, (item) => {\n if (!React.isValidElement(item)) {\n return null\n }\n const originalRef = getElementRef(item)\n return React.cloneElement(item as React.ReactElement<any>, {\n ref: mergeRef(originalRef, (node) => {\n const positionMap = {\n before: 'beforebegin',\n prepend: 'afterbegin',\n append: 'beforeend',\n after: 'afterend'\n } as const\n node && anchorRef.current?.insertAdjacentElement(positionMap[position], node)\n })\n })\n })\n\n const update = useCallback(() => {\n anchorRef.current = resolveAnchor(anchor)\n setContainer(\n position === 'prepend' || position === 'append' ? anchorRef.current : (anchorRef.current?.parentElement ?? null)\n )\n }, [anchor, position])\n\n useLayoutEffect(() => {\n update()\n\n const observer = new MutationObserver((mutations) => {\n const isSelfMutation = mutations\n .flatMap(({ addedNodes, removedNodes }) => [...addedNodes, ...removedNodes])\n .some((node) => container?.contains(node))\n !isSelfMutation && update()\n })\n\n observer.observe(document.body, {\n childList: true,\n subtree: true\n })\n return () => observer.disconnect()\n }, [update, anchor, container])\n\n useEffect(() => {\n if (container && anchorRef.current) {\n onMount?.(anchorRef.current, container)\n return () => {\n onUnmount?.(anchorRef.current!, container)\n }\n }\n }, [onMount, onUnmount, container])\n\n return container && createPortal(nodes, container, key)\n}\n\nMagicPortal.displayName = 'MagicPortal'\n\nexport default MagicPortal\n"],"mappings":"8IAeA,MAAM,EAAiB,GAAgC,CAErD,IAAI,EAAS,OAAO,yBAAyB,EAAQ,MAAO,MAAM,EAAE,IAChE,EAAU,GAAU,mBAAoB,GAAU,EAAO,eAY7D,OAXI,EACM,EAAgB,KAG1B,EAAS,OAAO,yBAAyB,EAAS,MAAM,EAAE,IAC1D,EAAU,GAAU,mBAAoB,GAAU,EAAO,eACrD,EACM,EAAQ,MAAuC,IAIjD,EAAQ,MAAuC,KAAS,EAAgB,MAG5E,EAAiB,GACjB,OAAO,GAAW,SACb,SAAS,cAAc,EAAO,CAC5B,OAAO,GAAW,WACpB,GAAQ,CACN,GAAU,YAAa,EACzB,EAAO,QAEP,EAOL,GAAa,EAA+B,IAAa,CAC7D,GAAI,OAAO,GAAQ,WACjB,OAAO,EAAI,EAAM,CACR,GAAQ,OACjB,EAAI,QAAU,IAIZ,GAAsC,GAAG,IACrC,GAAY,CAClB,IAAM,EAAW,EAAK,IAAK,GAAQ,EAAO,EAAK,EAAK,CAAC,CACrD,UACE,EAAS,SAAS,EAAS,IAAW,OAAO,GAAY,WAAa,GAAS,CAAG,EAAO,EAAK,GAAQ,KAAK,CAAE,EAI7G,GAAe,CAAE,SAAQ,WAAW,SAAU,WAAU,UAAS,YAAW,SAA4B,CAC5G,IAAM,EAAY,EAAuB,KAAK,CACxC,CAAC,EAAW,GAAgB,EAAyB,KAAK,CAE1D,EAAQ,EAAM,SAAS,IAAI,EAAW,GAAS,CACnD,GAAI,CAAC,EAAM,eAAe,EAAK,CAC7B,OAAO,KAET,IAAM,EAAc,EAAc,EAAK,CACvC,OAAO,EAAM,aAAa,EAAiC,CACzD,IAAK,EAAS,EAAc,GAAS,CAOnC,GAAQ,EAAU,SAAS,sBANP,CAClB,OAAQ,cACR,QAAS,aACT,OAAQ,YACR,MAAO,WACR,CAC4D,GAAW,EAAK,EAC7E,CACH,CAAC,EACF,CAEI,EAAS,MAAkB,CAC/B,EAAU,QAAU,EAAc,EAAO,CACzC,EACE,IAAa,WAAa,IAAa,SAAW,EAAU,QAAW,EAAU,SAAS,eAAiB,KAC5G,EACA,CAAC,EAAQ,EAAS,CAAC,CA4BtB,OA1BA,MAAsB,CACpB,GAAQ,CAER,IAAM,EAAW,IAAI,iBAAkB,GAAc,CAInD,CAHuB,EACpB,SAAS,CAAE,aAAY,kBAAmB,CAAC,GAAG,EAAY,GAAG,EAAa,CAAC,CAC3E,KAAM,GAAS,GAAW,SAAS,EAAK,CAAC,EACzB,GAAQ,EAC3B,CAMF,OAJA,EAAS,QAAQ,SAAS,KAAM,CAC9B,UAAW,GACX,QAAS,GACV,CAAC,KACW,EAAS,YAAY,EACjC,CAAC,EAAQ,EAAQ,EAAU,CAAC,CAE/B,MAAgB,CACd,GAAI,GAAa,EAAU,QAEzB,OADA,IAAU,EAAU,QAAS,EAAU,KAC1B,CACX,IAAY,EAAU,QAAU,EAAU,GAG7C,CAAC,EAAS,EAAW,EAAU,CAAC,CAE5B,GAAa,EAAa,EAAO,EAAW,EAAI,EAGzD,EAAY,YAAc,cAE1B,IAAA,EAAe"}
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"homepage": "https://github.com/molvqingtai/react-magic-portal#readme",
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@eslint/js": "^9.36.0",
|
|
33
|
-
"@types/node": "^24.
|
|
34
|
-
"@types/react": "^19.1.
|
|
33
|
+
"@types/node": "^24.6.0",
|
|
34
|
+
"@types/react": "^19.1.15",
|
|
35
35
|
"@types/react-dom": "^19.1.9",
|
|
36
36
|
"eslint": "^9.36.0",
|
|
37
37
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"react-dom": "^19.1.1",
|
|
45
45
|
"tsdown": "^0.15.5",
|
|
46
46
|
"typescript": "^5.9.2",
|
|
47
|
-
"typescript-eslint": "^8.
|
|
47
|
+
"typescript-eslint": "^8.45.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"react": ">=18.0.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef, useCallback, useLayoutEffect } from 'react'
|
|
2
|
-
import
|
|
2
|
+
import { createPortal } from 'react-dom'
|
|
3
3
|
|
|
4
4
|
export interface MagicPortalProps {
|
|
5
5
|
anchor: string | (() => Element | null) | Element | React.RefObject<Element | null> | null
|
|
@@ -117,7 +117,7 @@ const MagicPortal = ({ anchor, position = 'append', children, onMount, onUnmount
|
|
|
117
117
|
}
|
|
118
118
|
}, [onMount, onUnmount, container])
|
|
119
119
|
|
|
120
|
-
return container &&
|
|
120
|
+
return container && createPortal(nodes, container, key)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
MagicPortal.displayName = 'MagicPortal'
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@eslint/js": "^9.36.0",
|
|
20
|
-
"@types/react": "^19.1.
|
|
20
|
+
"@types/react": "^19.1.15",
|
|
21
21
|
"@types/react-dom": "^19.1.9",
|
|
22
22
|
"@vitejs/plugin-react": "^5.0.4",
|
|
23
23
|
"eslint": "^9.36.0",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"eslint-plugin-react-refresh": "^0.4.22",
|
|
27
27
|
"globals": "^16.4.0",
|
|
28
28
|
"typescript": "~5.9.2",
|
|
29
|
-
"typescript-eslint": "^8.
|
|
29
|
+
"typescript-eslint": "^8.45.0",
|
|
30
30
|
"vite": "^7.1.7"
|
|
31
31
|
}
|
|
32
32
|
}
|