react-magic-portal 1.1.0
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/.commitlintrc +5 -0
- package/.github/dependabot.yml +11 -0
- package/.github/workflows/cd.yml +85 -0
- package/.github/workflows/ci.yml +65 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.prettierrc +6 -0
- package/.releaserc +13 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/__tests__/eslint.config.ts +25 -0
- package/__tests__/package.json +42 -0
- package/__tests__/src/MagicPortal.test.tsx +506 -0
- package/__tests__/tsconfig.json +23 -0
- package/__tests__/vite.config.ts +11 -0
- package/eslint.config.mts +16 -0
- package/package.json +64 -0
- package/packages/component/.prettierrc +6 -0
- package/packages/component/README.md +6 -0
- package/packages/component/dist/index.d.ts +27 -0
- package/packages/component/dist/index.d.ts.map +1 -0
- package/packages/component/dist/index.js +2 -0
- package/packages/component/dist/index.js.map +1 -0
- package/packages/component/eslint.config.ts +25 -0
- package/packages/component/package.json +70 -0
- package/packages/component/src/index.ts +123 -0
- package/packages/component/tsconfig.json +27 -0
- package/packages/example/.prettierrc +6 -0
- package/packages/example/README.md +6 -0
- package/packages/example/eslint.config.ts +25 -0
- package/packages/example/index.html +13 -0
- package/packages/example/package.json +32 -0
- package/packages/example/pnpm-lock.yaml +2098 -0
- package/packages/example/public/vite.svg +1 -0
- package/packages/example/src/App.css +332 -0
- package/packages/example/src/App.tsx +82 -0
- package/packages/example/src/assets/react.svg +1 -0
- package/packages/example/src/components/portal-content.tsx +33 -0
- package/packages/example/src/index.css +68 -0
- package/packages/example/src/main.tsx +13 -0
- package/packages/example/src/vite-env.d.ts +1 -0
- package/packages/example/tsconfig.json +25 -0
- package/packages/example/vite.config.ts +7 -0
- package/pnpm-workspace.yaml +3 -0
package/.commitlintrc
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# https://github.com/dependabot/dependabot-core/issues/1736
|
|
2
|
+
|
|
3
|
+
version: 2
|
|
4
|
+
updates:
|
|
5
|
+
# Enable version updates for npm
|
|
6
|
+
- package-ecosystem: 'npm'
|
|
7
|
+
# Look for `package.json` and `lock` files in the `root` directory
|
|
8
|
+
directory: '/'
|
|
9
|
+
# Check the npm registry for updates every day (weekdays)
|
|
10
|
+
schedule:
|
|
11
|
+
interval: 'weekly'
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
jobs:
|
|
9
|
+
setup:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
outputs:
|
|
12
|
+
cache-hit: ${{ steps.pnpm-cache.outputs.cache-hit }}
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: lts/*
|
|
18
|
+
- uses: pnpm/action-setup@v4
|
|
19
|
+
with:
|
|
20
|
+
version: latest
|
|
21
|
+
- name: Cache pnpm store
|
|
22
|
+
uses: actions/cache@v3
|
|
23
|
+
id: pnpm-cache
|
|
24
|
+
with:
|
|
25
|
+
path: |
|
|
26
|
+
~/.pnpm-store
|
|
27
|
+
node_modules
|
|
28
|
+
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
29
|
+
restore-keys: |
|
|
30
|
+
${{ runner.os }}-pnpm-
|
|
31
|
+
linter:
|
|
32
|
+
needs: [setup]
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: actions/setup-node@v4
|
|
37
|
+
with:
|
|
38
|
+
node-version: lts/*
|
|
39
|
+
- uses: pnpm/action-setup@v4
|
|
40
|
+
with:
|
|
41
|
+
version: latest
|
|
42
|
+
- name: Restore dependencies
|
|
43
|
+
if: needs.setup.outputs.cache-hit != 'true'
|
|
44
|
+
run: pnpm install --frozen-lockfile
|
|
45
|
+
- run: pnpm run build
|
|
46
|
+
- run: pnpm run lint
|
|
47
|
+
- run: pnpm run check
|
|
48
|
+
|
|
49
|
+
tests:
|
|
50
|
+
needs: [setup]
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
- uses: actions/setup-node@v4
|
|
55
|
+
with:
|
|
56
|
+
node-version: lts/*
|
|
57
|
+
- uses: pnpm/action-setup@v4
|
|
58
|
+
with:
|
|
59
|
+
version: latest
|
|
60
|
+
- name: Restore dependencies
|
|
61
|
+
if: needs.setup.outputs.cache-hit != 'true'
|
|
62
|
+
run: pnpm install --frozen-lockfile
|
|
63
|
+
- run: pnpm run build
|
|
64
|
+
- run: pnpm run test
|
|
65
|
+
release:
|
|
66
|
+
needs: [setup, linter, tests]
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
with:
|
|
71
|
+
persist-credentials: false
|
|
72
|
+
- uses: actions/setup-node@v4
|
|
73
|
+
with:
|
|
74
|
+
node-version: lts/*
|
|
75
|
+
- uses: pnpm/action-setup@v4
|
|
76
|
+
with:
|
|
77
|
+
version: latest
|
|
78
|
+
- name: Restore dependencies
|
|
79
|
+
if: needs.setup.outputs.cache-hit != 'true'
|
|
80
|
+
run: pnpm install --frozen-lockfile --ignore-scripts
|
|
81
|
+
- run: pnpm run build
|
|
82
|
+
- run: pnpm semantic-release
|
|
83
|
+
env:
|
|
84
|
+
GH_TOKEN: ${{ secrets.REACT_DYNAMIC_PORTAL_GITHUB_TOKEN }}
|
|
85
|
+
NPM_TOKEN: ${{ secrets.REACT_DYNAMIC_PORTAL_NPM_TOKEN }}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [develop]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
setup:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
outputs:
|
|
13
|
+
cache-hit: ${{ steps.pnpm-cache.outputs.cache-hit }}
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: lts/*
|
|
19
|
+
- uses: pnpm/action-setup@v4
|
|
20
|
+
with:
|
|
21
|
+
version: latest
|
|
22
|
+
- name: Cache pnpm store
|
|
23
|
+
uses: actions/cache@v3
|
|
24
|
+
id: pnpm-cache
|
|
25
|
+
with:
|
|
26
|
+
path: |
|
|
27
|
+
~/.pnpm-store
|
|
28
|
+
node_modules
|
|
29
|
+
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
30
|
+
restore-keys: |
|
|
31
|
+
${{ runner.os }}-pnpm-
|
|
32
|
+
linter:
|
|
33
|
+
needs: [setup]
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-node@v4
|
|
38
|
+
with:
|
|
39
|
+
node-version: lts/*
|
|
40
|
+
- uses: pnpm/action-setup@v4
|
|
41
|
+
with:
|
|
42
|
+
version: latest
|
|
43
|
+
- name: Restore dependencies
|
|
44
|
+
if: needs.setup.outputs.cache-hit != 'true'
|
|
45
|
+
run: pnpm install --frozen-lockfile
|
|
46
|
+
- run: pnpm run build
|
|
47
|
+
- run: pnpm run lint
|
|
48
|
+
- run: pnpm run check
|
|
49
|
+
|
|
50
|
+
tests:
|
|
51
|
+
needs: [setup]
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- uses: actions/setup-node@v4
|
|
56
|
+
with:
|
|
57
|
+
node-version: lts/*
|
|
58
|
+
- uses: pnpm/action-setup@v4
|
|
59
|
+
with:
|
|
60
|
+
version: latest
|
|
61
|
+
- name: Restore dependencies
|
|
62
|
+
if: needs.setup.outputs.cache-hit != 'true'
|
|
63
|
+
run: pnpm install --frozen-lockfile
|
|
64
|
+
- run: pnpm run build
|
|
65
|
+
- run: pnpm run test
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pnpm commitlint --edit "$1"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pnpm lint && pnpm check
|
package/.prettierrc
ADDED
package/.releaserc
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"branches": [
|
|
3
|
+
"master"
|
|
4
|
+
],
|
|
5
|
+
"plugins": [
|
|
6
|
+
"@semantic-release/commit-analyzer",
|
|
7
|
+
"@semantic-release/release-notes-generator",
|
|
8
|
+
"@semantic-release/changelog",
|
|
9
|
+
"@semantic-release/github",
|
|
10
|
+
"@semantic-release/npm",
|
|
11
|
+
"@semantic-release/git"
|
|
12
|
+
]
|
|
13
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# [1.1.0](https://github.com/molvqingtai/react-magic-portal/compare/v1.0.0...v1.1.0) (2025-09-24)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* rename repo ([794af06](https://github.com/molvqingtai/react-magic-portal/commit/794af06f683a6c330132fbb2951b3abf39f167df))
|
|
7
|
+
|
|
8
|
+
# 1.0.0 (2025-09-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* release v1.0.0 ([a79203b](https://github.com/molvqingtai/react-dynamic-portal/commit/a79203b02295e0cb40404ce7a208667410b42054))
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 John Wu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# React Magic Portal
|
|
2
|
+
|
|
3
|
+
A React component designed for browser extension development that provides magical portal functionality with automatic anchor detection and DOM mutation monitoring.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-magic-portal) [](https://github.com/molvqingtai/react-magic-portal/actions) [](https://www.npmjs.com/package/react-magic-portal) [](https://www.npmjs.com/package/react-magic-portal) [](https://deepwiki.com/molvqingtai/react-magic-portal)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
$ pnpm add react-magic-portal
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Introduction
|
|
12
|
+
|
|
13
|
+
When developing browser extensions with React, you often need to inject React components into host web pages. However, the target mounting points in these pages are frequently dynamic - they may not exist when your extension loads, or they might be created and destroyed as users navigate and interact with the page.
|
|
14
|
+
|
|
15
|
+
Traditional React portals require the target DOM element to exist before rendering, which creates challenges in browser extension scenarios where:
|
|
16
|
+
|
|
17
|
+
- **Host pages load content dynamically** - Target elements appear after AJAX requests, user interactions, or page navigation
|
|
18
|
+
- **Single Page Applications (SPAs)** - Content changes without full page reloads, causing mounting points to appear and disappear
|
|
19
|
+
- **Dynamic DOM manipulation** - Third-party scripts or frameworks modify the DOM structure continuously
|
|
20
|
+
- **Uncertain timing** - You can't predict when or if target elements will be available
|
|
21
|
+
|
|
22
|
+
React Magic Portal solves these challenges by automatically detecting when target elements appear or disappear in the DOM, ensuring your React components are always rendered in the right place at the right time.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- **Magic Anchor Detection** - Automatically detects when target elements appear or disappear in the DOM
|
|
27
|
+
- **Multiple Positioning Options** - Support for `append`, `prepend`, `before`, and `after` positioning
|
|
28
|
+
- **Flexible Anchor Selection** - Support for CSS selectors, element references, functions, and direct elements
|
|
29
|
+
- **Lifecycle Callbacks** - `onMount` and `onUnmount` callbacks for portal lifecycle management
|
|
30
|
+
- **TypeScript Support** - Full TypeScript support with comprehensive type definitions
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Magic Content Loading
|
|
35
|
+
|
|
36
|
+
```jsx
|
|
37
|
+
function MagicContent() {
|
|
38
|
+
const [showTarget, setShowTarget] = useState(false)
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<button onClick={() => setShowTarget(!showTarget)}>Toggle Target</button>
|
|
43
|
+
|
|
44
|
+
{showTarget && <div id="anchor-target">Magic Target Element</div>}
|
|
45
|
+
|
|
46
|
+
{/* Portal will automatically mount/unmount based on target availability */}
|
|
47
|
+
<MagicPortal
|
|
48
|
+
anchor="#anchor-target"
|
|
49
|
+
onMount={() => console.log('Portal mounted')}
|
|
50
|
+
onUnmount={() => console.log('Portal unmounted')}
|
|
51
|
+
>
|
|
52
|
+
<div>This content follows the target element</div>
|
|
53
|
+
</MagicPortal>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Multiple Portals on Same Anchor
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
function MultiplePortals() {
|
|
63
|
+
return (
|
|
64
|
+
<div>
|
|
65
|
+
<div id="target">Target Element</div>
|
|
66
|
+
|
|
67
|
+
<MagicPortal anchor="#target" position="before">
|
|
68
|
+
<div>Content before target</div>
|
|
69
|
+
</MagicPortal>
|
|
70
|
+
|
|
71
|
+
<MagicPortal anchor="#target" position="prepend">
|
|
72
|
+
<div>Content at start of target</div>
|
|
73
|
+
</MagicPortal>
|
|
74
|
+
|
|
75
|
+
<MagicPortal anchor="#target" position="append">
|
|
76
|
+
<div>Content at end of target</div>
|
|
77
|
+
</MagicPortal>
|
|
78
|
+
|
|
79
|
+
<MagicPortal anchor="#target" position="after">
|
|
80
|
+
<div>Content after target</div>
|
|
81
|
+
</MagicPortal>
|
|
82
|
+
</div>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
### Props
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Default | Description |
|
|
92
|
+
| ----------- | ------------------------------------------------------------------------------------------ | ------------ | ------------------------------------------------------------ |
|
|
93
|
+
| `anchor` | `string \| (() => Element \| null) \| Element \| React.RefObject<Element \| null> \| null` | **Required** | The target element where the portal content will be rendered |
|
|
94
|
+
| `position` | `'append' \| 'prepend' \| 'before' \| 'after'` | `'append'` | Position relative to the anchor element |
|
|
95
|
+
| `children` | `React.ReactNode` | **Required** | The content to render in the portal |
|
|
96
|
+
| `onMount` | `(anchor: Element, container: HTMLDivElement) => void` | `undefined` | Callback fired when the portal is mounted |
|
|
97
|
+
| `onUnmount` | `(anchor: Element, container: HTMLDivElement) => void` | `undefined` | Callback fired when the portal is unmounted |
|
|
98
|
+
| `ref` | `React.Ref<HTMLDivElement \| null>` | `undefined` | Ref to the portal container element |
|
|
99
|
+
| `key` | `React.Key` | `undefined` | Key for the ReactDOM.createPortal |
|
|
100
|
+
|
|
101
|
+
### Anchor Types
|
|
102
|
+
|
|
103
|
+
#### CSS Selector String
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
<MagicPortal anchor="#my-element">
|
|
107
|
+
<div>Content</div>
|
|
108
|
+
</MagicPortal>
|
|
109
|
+
|
|
110
|
+
<MagicPortal anchor=".my-class">
|
|
111
|
+
<div>Content</div>
|
|
112
|
+
</MagicPortal>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Element Reference
|
|
116
|
+
|
|
117
|
+
```jsx
|
|
118
|
+
const elementRef = useRef(null)
|
|
119
|
+
|
|
120
|
+
<div ref={elementRef}>Target</div>
|
|
121
|
+
<MagicPortal anchor={elementRef}>
|
|
122
|
+
<div>Content</div>
|
|
123
|
+
</MagicPortal>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Function
|
|
127
|
+
|
|
128
|
+
```jsx
|
|
129
|
+
<MagicPortal anchor={() => document.querySelector('.magic-element')}>
|
|
130
|
+
<div>Content</div>
|
|
131
|
+
</MagicPortal>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Direct Element
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
<MagicPortal anchor={document.body}>
|
|
138
|
+
<div>Content</div>
|
|
139
|
+
</MagicPortal>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Position Options
|
|
143
|
+
|
|
144
|
+
#### `append` (default)
|
|
145
|
+
|
|
146
|
+
Adds content inside the anchor element at the end:
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<div id="anchor">
|
|
150
|
+
Existing content
|
|
151
|
+
<!-- Portal content appears here -->
|
|
152
|
+
</div>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### `prepend`
|
|
156
|
+
|
|
157
|
+
Adds content inside the anchor element at the beginning:
|
|
158
|
+
|
|
159
|
+
```html
|
|
160
|
+
<div id="anchor">
|
|
161
|
+
<!-- Portal content appears here -->
|
|
162
|
+
Existing content
|
|
163
|
+
</div>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### `before`
|
|
167
|
+
|
|
168
|
+
Adds content as a sibling before the anchor element:
|
|
169
|
+
|
|
170
|
+
```html
|
|
171
|
+
<!-- Portal content appears here -->
|
|
172
|
+
<div id="anchor">Existing content</div>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### `after`
|
|
176
|
+
|
|
177
|
+
Adds content as a sibling after the anchor element:
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<div id="anchor">Existing content</div>
|
|
181
|
+
<!-- Portal content appears here -->
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT © [molvqingtai](https://github.com/molvqingtai)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import globals from 'globals'
|
|
2
|
+
import pluginJs from '@eslint/js'
|
|
3
|
+
import { defineConfig } from 'eslint/config'
|
|
4
|
+
import tseslint from 'typescript-eslint'
|
|
5
|
+
import prettierPlugin from 'eslint-plugin-prettier/recommended'
|
|
6
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
7
|
+
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
8
|
+
|
|
9
|
+
export default defineConfig([
|
|
10
|
+
{ files: ['**/*.{js,mjs,cjs,ts}'] },
|
|
11
|
+
{
|
|
12
|
+
languageOptions: {
|
|
13
|
+
globals: { ...globals.browser, ...globals.node },
|
|
14
|
+
parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname }
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
pluginJs.configs.recommended,
|
|
18
|
+
...tseslint.configs.recommended,
|
|
19
|
+
prettierPlugin,
|
|
20
|
+
reactHooks.configs['recommended-latest'],
|
|
21
|
+
reactRefresh.configs.vite,
|
|
22
|
+
{
|
|
23
|
+
ignores: ['**/dist/*']
|
|
24
|
+
}
|
|
25
|
+
])
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__tests__",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Test suite for react-dynamic-portal",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "vitest",
|
|
9
|
+
"test:ui": "vitest --ui",
|
|
10
|
+
"test:coverage": "vitest run --coverage",
|
|
11
|
+
"lint": "eslint --fix --cache",
|
|
12
|
+
"check": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"author": "molvqingtai",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"react-magic-portal": "workspace:*"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@eslint/js": "^9.36.0",
|
|
22
|
+
"@testing-library/react": "^16.3.0",
|
|
23
|
+
"@testing-library/user-event": "^14.6.1",
|
|
24
|
+
"@types/react": "^19.1.13",
|
|
25
|
+
"@types/react-dom": "^19.1.9",
|
|
26
|
+
"@vitejs/plugin-react": "^5.0.3",
|
|
27
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
28
|
+
"@vitest/ui": "^3.2.4",
|
|
29
|
+
"eslint": "^9.36.0",
|
|
30
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
31
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
32
|
+
"eslint-plugin-react-refresh": "^0.4.21",
|
|
33
|
+
"globals": "^16.4.0",
|
|
34
|
+
"happy-dom": "^18.0.1",
|
|
35
|
+
"react": "^19.1.1",
|
|
36
|
+
"react-dom": "^19.1.1",
|
|
37
|
+
"typescript": "^5.9.2",
|
|
38
|
+
"typescript-eslint": "^8.44.1",
|
|
39
|
+
"vite": "^7.1.7",
|
|
40
|
+
"vitest": "^3.2.4"
|
|
41
|
+
}
|
|
42
|
+
}
|