react-manga-effects 0.1.0 → 0.1.6
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/LICENSE +21 -21
- package/README.md +167 -167
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +78 -78
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 erutobusiness
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 erutobusiness
|
|
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
CHANGED
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
# 🎬 react-manga-effects
|
|
2
|
-
|
|
3
|
-
> Add dramatic anime/manga impact effects to your React applications with zero fuss.
|
|
4
|
-
|
|
5
|
-
 to emphasize action or shock.
|
|
20
|
-
- **📘 TypeScript Support**: Fully typed props and exports.
|
|
21
|
-
- **🎈 Lightweight**: Zero runtime dependencies (other than React).
|
|
22
|
-
- **🚀 SSR Compatible**: Works with Next.js, Remix, and Gatsby.
|
|
23
|
-
- **🎨 Highly Customizable**: Control colors, density, speed, easing, and positioning.
|
|
24
|
-
|
|
25
|
-
## Installation
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npm install
|
|
29
|
-
# or
|
|
30
|
-
yarn add
|
|
31
|
-
# or
|
|
32
|
-
pnpm add
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Quick Start
|
|
36
|
-
|
|
37
|
-
Import the components and use them in your React app:
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import React, { useState } from 'react';
|
|
41
|
-
import { IrisWipe, SpeedLines } from '
|
|
42
|
-
|
|
43
|
-
const App = () => {
|
|
44
|
-
const [isOpen, setIsOpen] = useState(true);
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
|
|
48
|
-
{/* Background Content */}
|
|
49
|
-
<img src="/my-manga-scene.jpg" alt="Scene" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
|
50
|
-
|
|
51
|
-
{/* Overlay Effects */}
|
|
52
|
-
<SpeedLines
|
|
53
|
-
animated
|
|
54
|
-
color="rgba(0,0,0,0.5)"
|
|
55
|
-
center={{ x: 50, y: 50 }}
|
|
56
|
-
/>
|
|
57
|
-
|
|
58
|
-
<IrisWipe
|
|
59
|
-
isOpen={isOpen}
|
|
60
|
-
duration={1000}
|
|
61
|
-
center={{ x: 50, y: 50 }}
|
|
62
|
-
onComplete={() => console.log('Transition Complete')}
|
|
63
|
-
>
|
|
64
|
-
{/* Content to be revealed/hidden inside the wipe can go here if needed,
|
|
65
|
-
typically IrisWipe is used as an overlay. */}
|
|
66
|
-
</IrisWipe>
|
|
67
|
-
|
|
68
|
-
<button
|
|
69
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
70
|
-
style={{ position: 'absolute', bottom: 20, left: 20, zIndex: 100 }}
|
|
71
|
-
>
|
|
72
|
-
Toggle Transition
|
|
73
|
-
</button>
|
|
74
|
-
</div>
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export default App;
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Components API
|
|
82
|
-
|
|
83
|
-
### IrisWipe
|
|
84
|
-
|
|
85
|
-
A circular masking transition effect.
|
|
86
|
-
|
|
87
|
-
| Prop | Type | Default | Description |
|
|
88
|
-
|------|------|---------|-------------|
|
|
89
|
-
| `isOpen` | `boolean` | **Required** | `true` to reveal content (open iris), `false` to hide (close iris). |
|
|
90
|
-
| `duration` | `number` | `500` | Animation duration in milliseconds. |
|
|
91
|
-
| `center` | `{ x: number, y: number }` | `{ x: 50, y: 50 }` | Center point of the iris in percentage (0-100). |
|
|
92
|
-
| `easing` | `string` | `'easeInOut'` | CSS transition timing function (e.g., `'linear'`, `'ease-out'`, `'cubic-bezier(...)`'). |
|
|
93
|
-
| `onComplete` | `() => void` | `undefined` | Callback function fired when the transition finishes. |
|
|
94
|
-
| `className` | `string` | `''` | Additional CSS classes for the container. |
|
|
95
|
-
| `style` | `CSSProperties` | `{}` | Inline styles for the container. |
|
|
96
|
-
|
|
97
|
-
#### Example: Custom Center
|
|
98
|
-
```tsx
|
|
99
|
-
<IrisWipe
|
|
100
|
-
isOpen={show}
|
|
101
|
-
center={{ x: 80, y: 20 }} // Focus on top-right
|
|
102
|
-
duration={1200}
|
|
103
|
-
/>
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### SpeedLines
|
|
107
|
-
|
|
108
|
-
Concentration lines typically used to show speed, shock, or intense focus.
|
|
109
|
-
|
|
110
|
-
| Prop | Type | Default | Description |
|
|
111
|
-
|------|------|---------|-------------|
|
|
112
|
-
| `lineCount` | `number` | `60` | Number of lines to draw. Higher values create a denser effect. |
|
|
113
|
-
| `color` | `string` | `'rgba(0, 0, 0, 0.6)'` | Color of the lines. Supports valid CSS colors. |
|
|
114
|
-
| `minLength` | `number` | `10` | Minimum length of lines as a percentage of the container size. |
|
|
115
|
-
| `maxLength` | `number` | `30` | Maximum length of lines as a percentage of the container size. |
|
|
116
|
-
| `innerRadius` | `number` | `0` | Radius of the empty safe zone in the center (percentage). |
|
|
117
|
-
| `center` | `{ x: number, y: number }` | `{ x: 50, y: 50 }` | The convergence point of the lines. |
|
|
118
|
-
| `animated` | `boolean` | `false` | If `true`, lines will animate (opacity pulse/shake). |
|
|
119
|
-
| `animationSpeed`| `number` | `1` | Speed multiplier for the animation. |
|
|
120
|
-
| `className` | `string` | `''` | Additional CSS classes. |
|
|
121
|
-
| `style` | `CSSProperties` | `{}` | Inline styles. |
|
|
122
|
-
|
|
123
|
-
#### Example: Intense Action
|
|
124
|
-
```tsx
|
|
125
|
-
<SpeedLines
|
|
126
|
-
lineCount={120}
|
|
127
|
-
color="red"
|
|
128
|
-
innerRadius={10}
|
|
129
|
-
animated={true}
|
|
130
|
-
animationSpeed={1.5}
|
|
131
|
-
/>
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Storybook
|
|
135
|
-
|
|
136
|
-
We use Storybook for development and testing.
|
|
137
|
-
|
|
138
|
-
1. Clone the repository
|
|
139
|
-
2. Install dependencies: `npm install`
|
|
140
|
-
3. Run Storybook:
|
|
141
|
-
```bash
|
|
142
|
-
npm run storybook
|
|
143
|
-
```
|
|
144
|
-
4. Open [http://localhost:6006](http://localhost:6006) to view the components.
|
|
145
|
-
|
|
146
|
-
## Development
|
|
147
|
-
|
|
148
|
-
Contributions are welcome!
|
|
149
|
-
|
|
150
|
-
1. Clone the repo:
|
|
151
|
-
```bash
|
|
152
|
-
git clone https://github.com/erutobusiness/react-manga-effects.git
|
|
153
|
-
cd react-manga-effects
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
2. Install dependencies:
|
|
157
|
-
```bash
|
|
158
|
-
npm install
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
3. Start development server (Storybook):
|
|
162
|
-
```bash
|
|
163
|
-
npm run storybook
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## License
|
|
167
|
-
|
|
1
|
+
# 🎬 react-manga-effects
|
|
2
|
+
|
|
3
|
+
> Add dramatic anime/manga impact effects to your React applications with zero fuss.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
[](https://github.com/erutobusiness/react-manga-effects/actions/workflows/ci.yml)
|
|
9
|
+
|
|
10
|
+
**react-manga-effects** provides lightweight, customizable high-impact visual effects common in anime and manga, such as circular iris wipes and dynamic focus lines. Built with TypeScript and optimizing for performance.
|
|
11
|
+
|
|
12
|
+
## Demo
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **🌀 IrisWipe**: Classic anime-style circular transition to open/close scenes.
|
|
19
|
+
- **⚡ SpeedLines**: Dynamic focus/concentration lines (motion lines) to emphasize action or shock.
|
|
20
|
+
- **📘 TypeScript Support**: Fully typed props and exports.
|
|
21
|
+
- **🎈 Lightweight**: Zero runtime dependencies (other than React).
|
|
22
|
+
- **🚀 SSR Compatible**: Works with Next.js, Remix, and Gatsby.
|
|
23
|
+
- **🎨 Highly Customizable**: Control colors, density, speed, easing, and positioning.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install react-manga-effects
|
|
29
|
+
# or
|
|
30
|
+
yarn add react-manga-effects
|
|
31
|
+
# or
|
|
32
|
+
pnpm add react-manga-effects
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
Import the components and use them in your React app:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import React, { useState } from 'react';
|
|
41
|
+
import { IrisWipe, SpeedLines } from 'react-manga-effects';
|
|
42
|
+
|
|
43
|
+
const App = () => {
|
|
44
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
|
|
48
|
+
{/* Background Content */}
|
|
49
|
+
<img src="/my-manga-scene.jpg" alt="Scene" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
|
50
|
+
|
|
51
|
+
{/* Overlay Effects */}
|
|
52
|
+
<SpeedLines
|
|
53
|
+
animated
|
|
54
|
+
color="rgba(0,0,0,0.5)"
|
|
55
|
+
center={{ x: 50, y: 50 }}
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
<IrisWipe
|
|
59
|
+
isOpen={isOpen}
|
|
60
|
+
duration={1000}
|
|
61
|
+
center={{ x: 50, y: 50 }}
|
|
62
|
+
onComplete={() => console.log('Transition Complete')}
|
|
63
|
+
>
|
|
64
|
+
{/* Content to be revealed/hidden inside the wipe can go here if needed,
|
|
65
|
+
typically IrisWipe is used as an overlay. */}
|
|
66
|
+
</IrisWipe>
|
|
67
|
+
|
|
68
|
+
<button
|
|
69
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
70
|
+
style={{ position: 'absolute', bottom: 20, left: 20, zIndex: 100 }}
|
|
71
|
+
>
|
|
72
|
+
Toggle Transition
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default App;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Components API
|
|
82
|
+
|
|
83
|
+
### IrisWipe
|
|
84
|
+
|
|
85
|
+
A circular masking transition effect.
|
|
86
|
+
|
|
87
|
+
| Prop | Type | Default | Description |
|
|
88
|
+
|------|------|---------|-------------|
|
|
89
|
+
| `isOpen` | `boolean` | **Required** | `true` to reveal content (open iris), `false` to hide (close iris). |
|
|
90
|
+
| `duration` | `number` | `500` | Animation duration in milliseconds. |
|
|
91
|
+
| `center` | `{ x: number, y: number }` | `{ x: 50, y: 50 }` | Center point of the iris in percentage (0-100). |
|
|
92
|
+
| `easing` | `string` | `'easeInOut'` | CSS transition timing function (e.g., `'linear'`, `'ease-out'`, `'cubic-bezier(...)`'). |
|
|
93
|
+
| `onComplete` | `() => void` | `undefined` | Callback function fired when the transition finishes. |
|
|
94
|
+
| `className` | `string` | `''` | Additional CSS classes for the container. |
|
|
95
|
+
| `style` | `CSSProperties` | `{}` | Inline styles for the container. |
|
|
96
|
+
|
|
97
|
+
#### Example: Custom Center
|
|
98
|
+
```tsx
|
|
99
|
+
<IrisWipe
|
|
100
|
+
isOpen={show}
|
|
101
|
+
center={{ x: 80, y: 20 }} // Focus on top-right
|
|
102
|
+
duration={1200}
|
|
103
|
+
/>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### SpeedLines
|
|
107
|
+
|
|
108
|
+
Concentration lines typically used to show speed, shock, or intense focus.
|
|
109
|
+
|
|
110
|
+
| Prop | Type | Default | Description |
|
|
111
|
+
|------|------|---------|-------------|
|
|
112
|
+
| `lineCount` | `number` | `60` | Number of lines to draw. Higher values create a denser effect. |
|
|
113
|
+
| `color` | `string` | `'rgba(0, 0, 0, 0.6)'` | Color of the lines. Supports valid CSS colors. |
|
|
114
|
+
| `minLength` | `number` | `10` | Minimum length of lines as a percentage of the container size. |
|
|
115
|
+
| `maxLength` | `number` | `30` | Maximum length of lines as a percentage of the container size. |
|
|
116
|
+
| `innerRadius` | `number` | `0` | Radius of the empty safe zone in the center (percentage). |
|
|
117
|
+
| `center` | `{ x: number, y: number }` | `{ x: 50, y: 50 }` | The convergence point of the lines. |
|
|
118
|
+
| `animated` | `boolean` | `false` | If `true`, lines will animate (opacity pulse/shake). |
|
|
119
|
+
| `animationSpeed`| `number` | `1` | Speed multiplier for the animation. |
|
|
120
|
+
| `className` | `string` | `''` | Additional CSS classes. |
|
|
121
|
+
| `style` | `CSSProperties` | `{}` | Inline styles. |
|
|
122
|
+
|
|
123
|
+
#### Example: Intense Action
|
|
124
|
+
```tsx
|
|
125
|
+
<SpeedLines
|
|
126
|
+
lineCount={120}
|
|
127
|
+
color="red"
|
|
128
|
+
innerRadius={10}
|
|
129
|
+
animated={true}
|
|
130
|
+
animationSpeed={1.5}
|
|
131
|
+
/>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Storybook
|
|
135
|
+
|
|
136
|
+
We use Storybook for development and testing.
|
|
137
|
+
|
|
138
|
+
1. Clone the repository
|
|
139
|
+
2. Install dependencies: `npm install`
|
|
140
|
+
3. Run Storybook:
|
|
141
|
+
```bash
|
|
142
|
+
npm run storybook
|
|
143
|
+
```
|
|
144
|
+
4. Open [http://localhost:6006](http://localhost:6006) to view the components.
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
Contributions are welcome!
|
|
149
|
+
|
|
150
|
+
1. Clone the repo:
|
|
151
|
+
```bash
|
|
152
|
+
git clone https://github.com/erutobusiness/react-manga-effects.git
|
|
153
|
+
cd react-manga-effects
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
2. Install dependencies:
|
|
157
|
+
```bash
|
|
158
|
+
npm install
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
3. Start development server (Storybook):
|
|
162
|
+
```bash
|
|
163
|
+
npm run storybook
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
168
|
MIT © [erutobusiness](https://github.com/erutobusiness)
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("react/jsx-runtime"),a=require("react"),$=({text:e="Manga Effect Placeholder"})=>I.jsx("div",{style:{padding:"2rem",border:"4px dashed #333",textAlign:"center",fontFamily:"sans-serif",fontWeight:"bold",backgroundColor:"#f0f0f0"},children:e}),j=({children:e,isOpen:s,center:n={x:50,y:50},duration:c=
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("react/jsx-runtime"),a=require("react"),$=({text:e="Manga Effect Placeholder"})=>I.jsx("div",{style:{padding:"2rem",border:"4px dashed #333",textAlign:"center",fontFamily:"sans-serif",fontWeight:"bold",backgroundColor:"#f0f0f0"},children:e}),j=({children:e,isOpen:s,center:n={x:50,y:50},duration:c=1e3,easing:i="easeInOut",onComplete:o,className:t="",style:r})=>{const E=a.useRef(null);let p="ease-in-out";if(typeof i=="string")switch(i){case"linear":p="linear";break;case"easeIn":p="ease-in";break;case"easeOut":p="ease-out";break;case"easeInOut":p="ease-in-out";break;default:p=i}const u=M=>{M.propertyName==="clip-path"&&o&&o()},y={"--iris-cx":`${n.x}%`,"--iris-cy":`${n.y}%`,"--iris-duration":`${c}ms`,"--iris-easing":p,...r};return I.jsx("div",{ref:E,className:`iris-wipe ${t}`,"data-state":s?"open":"closed",style:y,onTransitionEnd:u,children:e})},D=(e,s)=>{const n=a.useRef(),c=a.useRef(),i=o=>{if(c.current!==void 0){const t=o-c.current;e(t)}c.current=o,n.current=requestAnimationFrame(i)};a.useEffect(()=>(s?n.current=requestAnimationFrame(i):(n.current&&cancelAnimationFrame(n.current),c.current=void 0),()=>{n.current&&cancelAnimationFrame(n.current)}),[s,e])},W=(e,s,n,c)=>{const i=Math.cos(s),o=Math.sin(s);let t=1/0;if(Math.abs(i)>1e-4)if(i>0){const r=(n-e.x)/i;r>=0&&(t=Math.min(t,r))}else{const r=(0-e.x)/i;r>=0&&(t=Math.min(t,r))}if(Math.abs(o)>1e-4)if(o>0){const r=(c-e.y)/o;r>=0&&(t=Math.min(t,r))}else{const r=(0-e.y)/o;r>=0&&(t=Math.min(t,r))}return t===1/0?0:t},q=e=>Array.from({length:e.lineCount},()=>({angle:Math.random()*Math.PI*2,length:(e.minLength+Math.random()*(e.maxLength-e.minLength))/100,width:2+Math.random()*8,opacity:.6+Math.random()*.4,pulseOffset:Math.random()*Math.PI*2,pulseSpeed:2+Math.random()*3})),F=(e,s,n,c,i,o,t,r,E=0,p=!1,u=1)=>{const y=c*(i/100);let M=s.opacity;if(p){const P=.5+(Math.sin(E*s.pulseSpeed*u+s.pulseOffset)+1)*.25;M*=P}const m=W(n,s.angle,t,r)+2;let g=m-m*s.length;if(g<y&&(g=y),g>=m)return;const T=Math.cos(s.angle),R=Math.sin(s.angle),b=n.x+T*m,h=n.y+R*m,l=n.x+T*g,f=n.y+R*g,d=-R,w=T,x=s.width/2;e.beginPath(),e.moveTo(b+d*x,h+w*x),e.lineTo(b-d*x,h-w*x),e.lineTo(l,f),e.closePath(),e.fillStyle=o,e.globalAlpha=M,e.fill(),e.globalAlpha=1},C=({center:e={x:50,y:50},lineCount:s=60,color:n="rgba(0, 0, 0, 0.6)",minLength:c=10,maxLength:i=30,innerRadius:o=0,animated:t=!1,animationSpeed:r=1,className:E="",style:p})=>{const u=a.useRef(null),y=a.useRef(null),M=a.useRef([]),S=a.useRef(e),m=a.useRef(0),[g,T]=a.useState({width:0,height:0});a.useEffect(()=>{S.current=e},[e.x,e.y]),a.useEffect(()=>{M.current=q({lineCount:s,minLength:c,maxLength:i})},[s,c,i]);const R=a.useCallback(()=>{if(y.current&&u.current){const{clientWidth:h,clientHeight:l}=y.current,f=window.devicePixelRatio||1;if(u.current.width!==h*f||u.current.height!==l*f){u.current.width=h*f,u.current.height=l*f,u.current.style.width=`${h}px`,u.current.style.height=`${l}px`;const d=u.current.getContext("2d");d&&d.scale(f,f),T({width:h,height:l})}}},[]);a.useEffect(()=>{R();const h=new ResizeObserver(R);return y.current&&h.observe(y.current),()=>h.disconnect()},[R]);const b=a.useCallback(h=>{const l=u.current,f=y.current,d=l==null?void 0:l.getContext("2d");if(!l||!f||!d||g.width===0)return;d.save(),d.setTransform(1,0,0,1,0,0),d.clearRect(0,0,l.width,l.height),d.restore();const w=f.clientWidth,x=f.clientHeight,v={x:S.current.x/100*w,y:S.current.y/100*x},P=Math.max(v.x,w-v.x),A=Math.max(v.y,x-v.y),O=Math.hypot(P,A);t&&(m.current+=h*.001),M.current.forEach(k=>{F(d,k,v,O,o,n,w,x,m.current,t,r)})},[n,o,t,r,g]);return D(b,t),a.useEffect(()=>{t||b(0)},[b,t,s,c,i,o,n,g]),I.jsx("div",{ref:y,className:`speed-lines-container ${E}`,style:{width:"100%",height:"100%",position:"relative",overflow:"hidden",pointerEvents:"none",...p},children:I.jsx("canvas",{ref:u,style:{width:"100%",height:"100%",display:"block"}})})};exports.IrisWipe=j;exports.Placeholder=$;exports.SpeedLines=C;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "react-manga-effects",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Lightweight React components for manga/anime-style visual effects - iris wipes and speed lines",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"react",
|
|
7
|
-
"manga",
|
|
8
|
-
"anime",
|
|
9
|
-
"effects",
|
|
10
|
-
"iris-wipe",
|
|
11
|
-
"speed-lines",
|
|
12
|
-
"focus-lines",
|
|
13
|
-
"transition",
|
|
14
|
-
"animation",
|
|
15
|
-
"typescript"
|
|
16
|
-
],
|
|
17
|
-
"homepage": "https://github.com/erutobusiness/react-manga-effects#readme",
|
|
18
|
-
"bugs": {
|
|
19
|
-
"url": "https://github.com/erutobusiness/react-manga-effects/issues"
|
|
20
|
-
},
|
|
21
|
-
"repository": {
|
|
22
|
-
"type": "git",
|
|
23
|
-
"url": "git+https://github.com/erutobusiness/react-manga-effects.git"
|
|
24
|
-
},
|
|
25
|
-
"license": "MIT",
|
|
26
|
-
"author": "erutobusiness",
|
|
27
|
-
"sideEffects": [
|
|
28
|
-
"*.css"
|
|
29
|
-
],
|
|
30
|
-
"files": [
|
|
31
|
-
"dist",
|
|
32
|
-
"README.md",
|
|
33
|
-
"LICENSE"
|
|
34
|
-
],
|
|
35
|
-
"type": "module",
|
|
36
|
-
"main": "./dist/index.cjs",
|
|
37
|
-
"module": "./dist/index.js",
|
|
38
|
-
"types": "./dist/index.d.ts",
|
|
39
|
-
"exports": {
|
|
40
|
-
".": {
|
|
41
|
-
"import": "./dist/index.js",
|
|
42
|
-
"require": "./dist/index.cjs",
|
|
43
|
-
"types": "./dist/index.d.ts"
|
|
44
|
-
},
|
|
45
|
-
"./style.css": "./dist/style.css"
|
|
46
|
-
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"dev": "vite",
|
|
49
|
-
"build": "tsc && vite build",
|
|
50
|
-
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
51
|
-
"preview": "vite preview",
|
|
52
|
-
"storybook": "storybook dev -p 6006",
|
|
53
|
-
"build-storybook": "storybook build",
|
|
54
|
-
"test": "vitest"
|
|
55
|
-
},
|
|
56
|
-
"peerDependencies": {
|
|
57
|
-
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
58
|
-
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
59
|
-
},
|
|
60
|
-
"devDependencies": {
|
|
61
|
-
"@storybook/react": "^8.0.0",
|
|
62
|
-
"@storybook/react-vite": "^8.0.0",
|
|
63
|
-
"@testing-library/jest-dom": "^6.9.1",
|
|
64
|
-
"@testing-library/react": "^16.3.1",
|
|
65
|
-
"@types/node": "^20.0.0",
|
|
66
|
-
"@types/react": "^18.2.0",
|
|
67
|
-
"@types/react-dom": "^18.2.0",
|
|
68
|
-
"@vitejs/plugin-react": "^4.2.0",
|
|
69
|
-
"jsdom": "^27.0.1",
|
|
70
|
-
"react": "^18.2.0",
|
|
71
|
-
"react-dom": "^18.2.0",
|
|
72
|
-
"storybook": "^8.0.0",
|
|
73
|
-
"typescript": "^5.2.0",
|
|
74
|
-
"vite": "^5.0.0",
|
|
75
|
-
"vite-plugin-dts": "^3.0.0",
|
|
76
|
-
"vitest": "^1.0.0"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "react-manga-effects",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Lightweight React components for manga/anime-style visual effects - iris wipes and speed lines",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"manga",
|
|
8
|
+
"anime",
|
|
9
|
+
"effects",
|
|
10
|
+
"iris-wipe",
|
|
11
|
+
"speed-lines",
|
|
12
|
+
"focus-lines",
|
|
13
|
+
"transition",
|
|
14
|
+
"animation",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/erutobusiness/react-manga-effects#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/erutobusiness/react-manga-effects/issues"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/erutobusiness/react-manga-effects.git"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "erutobusiness",
|
|
27
|
+
"sideEffects": [
|
|
28
|
+
"*.css"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"main": "./dist/index.cjs",
|
|
37
|
+
"module": "./dist/index.js",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"exports": {
|
|
40
|
+
".": {
|
|
41
|
+
"import": "./dist/index.js",
|
|
42
|
+
"require": "./dist/index.cjs",
|
|
43
|
+
"types": "./dist/index.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./style.css": "./dist/style.css"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"dev": "vite",
|
|
49
|
+
"build": "tsc && vite build",
|
|
50
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
51
|
+
"preview": "vite preview",
|
|
52
|
+
"storybook": "storybook dev -p 6006",
|
|
53
|
+
"build-storybook": "storybook build",
|
|
54
|
+
"test": "vitest"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
58
|
+
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@storybook/react": "^8.0.0",
|
|
62
|
+
"@storybook/react-vite": "^8.0.0",
|
|
63
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
64
|
+
"@testing-library/react": "^16.3.1",
|
|
65
|
+
"@types/node": "^20.0.0",
|
|
66
|
+
"@types/react": "^18.2.0",
|
|
67
|
+
"@types/react-dom": "^18.2.0",
|
|
68
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
69
|
+
"jsdom": "^27.0.1",
|
|
70
|
+
"react": "^18.2.0",
|
|
71
|
+
"react-dom": "^18.2.0",
|
|
72
|
+
"storybook": "^8.0.0",
|
|
73
|
+
"typescript": "^5.2.0",
|
|
74
|
+
"vite": "^5.0.0",
|
|
75
|
+
"vite-plugin-dts": "^3.0.0",
|
|
76
|
+
"vitest": "^1.0.0"
|
|
77
|
+
}
|
|
78
|
+
}
|