react-magic-portal 1.1.2 → 1.1.4
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 +14 -0
- package/README.md +85 -4
- package/__tests__/eslint.config.ts +7 -2
- package/__tests__/src/{MagicPortal.test.tsx → magic-portal.test.tsx} +285 -20
- package/package.json +1 -1
- package/packages/component/dist/index.d.ts +3 -5
- package/packages/component/dist/index.d.ts.map +1 -1
- package/packages/component/dist/index.js +1 -1
- package/packages/component/dist/index.js.map +1 -1
- package/packages/component/eslint.config.ts +8 -2
- package/packages/component/src/index.ts +83 -76
- package/packages/example/dist/assets/index-BXJSx7fv.js +49 -0
- package/packages/example/dist/assets/index-CDQ6J_Ti.css +1 -0
- package/packages/example/dist/index.html +2 -2
- package/packages/example/eslint.config.ts +5 -5
- package/packages/example/src/App.css +9 -22
- package/packages/example/src/App.tsx +5 -5
- package/packages/example/src/components/portal-content.tsx +7 -2
- package/packages/example/dist/assets/index-BSN9W4mP.js +0 -49
- package/packages/example/dist/assets/index-DWWbQwSg.css +0 -1
|
@@ -7,8 +7,11 @@ import reactHooks from 'eslint-plugin-react-hooks'
|
|
|
7
7
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
8
8
|
|
|
9
9
|
export default defineConfig([
|
|
10
|
-
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
|
11
10
|
{
|
|
11
|
+
ignores: ['**/dist/*']
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
|
|
12
15
|
languageOptions: {
|
|
13
16
|
globals: { ...globals.browser, ...globals.node },
|
|
14
17
|
parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname }
|
|
@@ -18,8 +21,5 @@ export default defineConfig([
|
|
|
18
21
|
...tseslint.configs.recommended,
|
|
19
22
|
prettierPlugin,
|
|
20
23
|
reactHooks.configs['recommended-latest'],
|
|
21
|
-
reactRefresh.configs.vite
|
|
22
|
-
{
|
|
23
|
-
ignores: ['**/dist/*']
|
|
24
|
-
}
|
|
24
|
+
reactRefresh.configs.vite
|
|
25
25
|
])
|
|
@@ -3,12 +3,10 @@ body {
|
|
|
3
3
|
padding: 0;
|
|
4
4
|
min-height: 100vh;
|
|
5
5
|
background: white;
|
|
6
|
-
font-family:
|
|
7
|
-
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
6
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
8
7
|
display: flex;
|
|
9
8
|
justify-content: center;
|
|
10
9
|
align-items: flex-start;
|
|
11
|
-
padding-top: 2rem;
|
|
12
10
|
}
|
|
13
11
|
|
|
14
12
|
.app {
|
|
@@ -20,7 +18,6 @@ body {
|
|
|
20
18
|
h1 {
|
|
21
19
|
color: #2d3748;
|
|
22
20
|
text-align: center;
|
|
23
|
-
margin-bottom: 3rem;
|
|
24
21
|
font-size: 2.5rem;
|
|
25
22
|
font-weight: 700;
|
|
26
23
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
|
@@ -62,18 +59,13 @@ h2 {
|
|
|
62
59
|
}
|
|
63
60
|
|
|
64
61
|
.controls button::before {
|
|
65
|
-
content:
|
|
62
|
+
content: '';
|
|
66
63
|
position: absolute;
|
|
67
64
|
top: 0;
|
|
68
65
|
left: -100%;
|
|
69
66
|
width: 100%;
|
|
70
67
|
height: 100%;
|
|
71
|
-
background: linear-gradient(
|
|
72
|
-
90deg,
|
|
73
|
-
transparent,
|
|
74
|
-
rgba(255, 255, 255, 0.2),
|
|
75
|
-
transparent
|
|
76
|
-
);
|
|
68
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
|
77
69
|
transition: left 0.5s;
|
|
78
70
|
}
|
|
79
71
|
|
|
@@ -169,7 +161,7 @@ h2 {
|
|
|
169
161
|
}
|
|
170
162
|
|
|
171
163
|
.portal-preview {
|
|
172
|
-
height:
|
|
164
|
+
min-height: 500px;
|
|
173
165
|
display: flex;
|
|
174
166
|
flex-direction: column;
|
|
175
167
|
align-items: center;
|
|
@@ -183,23 +175,18 @@ h2 {
|
|
|
183
175
|
}
|
|
184
176
|
|
|
185
177
|
.portal-preview::after {
|
|
186
|
-
content:
|
|
178
|
+
content: '';
|
|
187
179
|
position: absolute;
|
|
188
180
|
top: 0;
|
|
189
181
|
left: 0;
|
|
190
182
|
right: 0;
|
|
191
183
|
bottom: 0;
|
|
192
|
-
background: linear-gradient(
|
|
193
|
-
45deg,
|
|
194
|
-
transparent 30%,
|
|
195
|
-
rgba(102, 126, 234, 0.03) 50%,
|
|
196
|
-
transparent 70%
|
|
197
|
-
);
|
|
184
|
+
background: linear-gradient(45deg, transparent 30%, rgba(102, 126, 234, 0.03) 50%, transparent 70%);
|
|
198
185
|
pointer-events: none;
|
|
199
186
|
}
|
|
200
187
|
|
|
201
188
|
.portal-preview:empty::before {
|
|
202
|
-
content:
|
|
189
|
+
content: '📍 Target anchor is hidden. Portal content will not appear.';
|
|
203
190
|
opacity: 0.8;
|
|
204
191
|
font-weight: 500;
|
|
205
192
|
color: #4a5568;
|
|
@@ -302,7 +289,7 @@ h2 {
|
|
|
302
289
|
|
|
303
290
|
/* Visual indicators for different positions */
|
|
304
291
|
.portal-content::before {
|
|
305
|
-
content:
|
|
292
|
+
content: 'Portal';
|
|
306
293
|
position: absolute;
|
|
307
294
|
top: -0.75rem;
|
|
308
295
|
left: 1rem;
|
|
@@ -317,7 +304,7 @@ h2 {
|
|
|
317
304
|
}
|
|
318
305
|
|
|
319
306
|
.dynamic-anchor::before {
|
|
320
|
-
content:
|
|
307
|
+
content: 'Anchor';
|
|
321
308
|
position: absolute;
|
|
322
309
|
top: -0.75rem;
|
|
323
310
|
left: 1rem;
|
|
@@ -4,14 +4,14 @@ import PortalContent from './components/portal-content'
|
|
|
4
4
|
import './App.css'
|
|
5
5
|
|
|
6
6
|
function App() {
|
|
7
|
-
const [showAnchor, setShowAnchor] = useState(
|
|
7
|
+
const [showAnchor, setShowAnchor] = useState(true)
|
|
8
8
|
|
|
9
|
-
const handleMount = (anchor: Element,
|
|
10
|
-
console.log('Portal mounted:', { anchor,
|
|
9
|
+
const handleMount = (anchor: Element, contaner: Element) => {
|
|
10
|
+
console.log('Portal mounted:', { anchor, contaner })
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const handleUnmount = (anchor: Element,
|
|
14
|
-
console.log('Portal unmounted:', { anchor,
|
|
13
|
+
const handleUnmount = (anchor: Element, contaner: Element) => {
|
|
14
|
+
console.log('Portal unmounted:', { anchor, contaner })
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
return (
|
|
@@ -2,9 +2,10 @@ import { useEffect } from 'react'
|
|
|
2
2
|
|
|
3
3
|
interface PortalContentProps {
|
|
4
4
|
position: string
|
|
5
|
+
ref?: React.Ref<HTMLDivElement>
|
|
5
6
|
}
|
|
6
7
|
|
|
7
|
-
function PortalContent({ position }: PortalContentProps) {
|
|
8
|
+
function PortalContent({ position, ref }: PortalContentProps) {
|
|
8
9
|
useEffect(() => {
|
|
9
10
|
console.log(`✅ ${position} Portal useEffect mounted`)
|
|
10
11
|
return () => {
|
|
@@ -27,7 +28,11 @@ function PortalContent({ position }: PortalContentProps) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
return
|
|
31
|
+
return (
|
|
32
|
+
<div ref={ref} className={`portal-content ${position}`}>
|
|
33
|
+
{getContentText()}
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
export default PortalContent
|