react-magic-card 0.0.9 → 0.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/{readme.md → README.md} +27 -2
- package/dist/MagicCircle/index.d.ts +2 -50
- package/dist/MagicCircle/index.js +80 -49
- package/dist/MagicStraight/index.d.ts +3 -0
- package/dist/MagicStraight/index.js +200 -0
- package/dist/MagicStraight/styles.module.css +9 -0
- package/dist/common/ScaleFilterImage/index.d.ts +4 -0
- package/dist/common/ScaleFilterImage/index.js +26 -0
- package/dist/common/ScaleFilterImage/styles.module.css +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/types.d.ts +87 -0
- package/dist/types.js +2 -0
- package/package.json +7 -3
- /package/dist/MagicCircle/{main.css → styles.module.css} +0 -0
package/{readme.md → README.md}
RENAMED
|
@@ -54,6 +54,8 @@ function MyComponent() {
|
|
|
54
54
|
selectRotateZ: -10
|
|
55
55
|
}}
|
|
56
56
|
transition={{ duration: 0.2 }}
|
|
57
|
+
pickTransition={{ duration: 0.4 }}
|
|
58
|
+
pickProperty={{ white: true, alpha: 0.4, blur: 4, scale: 2, offset: 220 }}
|
|
57
59
|
/>
|
|
58
60
|
)
|
|
59
61
|
}
|
|
@@ -64,9 +66,7 @@ function MyComponent() {
|
|
|
64
66
|
| images | array of images and objects containing the src and alt properties. |
|
|
65
67
|
| width | width of a single image. |
|
|
66
68
|
| height | height of a single image. |
|
|
67
|
-
| dynamic | indicating whether dynamic rotation is allowed. |
|
|
68
69
|
| start | index number of the starting scale position. |
|
|
69
|
-
| radius | radius of the circle. |
|
|
70
70
|
| controller | diameter plus the value of the controller is the size of the controller. |
|
|
71
71
|
| className | class name of the component. |
|
|
72
72
|
| classImage | class name of the images. |
|
|
@@ -74,6 +74,20 @@ function MyComponent() {
|
|
|
74
74
|
| animate | object in the animation property. |
|
|
75
75
|
| initial | object in the animation property. |
|
|
76
76
|
| transition | object in the transition property. |
|
|
77
|
+
| pickTransition | object in the transition property. |
|
|
78
|
+
| pickProperty | object in the pick property. |
|
|
79
|
+
|
|
80
|
+
| Only in MagicCircle | Explanation |
|
|
81
|
+
| ------------------- | ----------------------------------------------- |
|
|
82
|
+
| dynamic | indicating whether dynamic rotation is allowed. |
|
|
83
|
+
| radius | radius of the circle. |
|
|
84
|
+
|
|
85
|
+
| Only in MagicStraight | Explanation |
|
|
86
|
+
| --------------------- | ----------------------------------- |
|
|
87
|
+
| vertical | vertical or horizontal boolean flag |
|
|
88
|
+
| margin | spacing of the between images |
|
|
89
|
+
| selectOffsetX | X-axis position |
|
|
90
|
+
| selectOffsetY | Y-axis position |
|
|
77
91
|
|
|
78
92
|
## Animation property
|
|
79
93
|
|
|
@@ -92,6 +106,17 @@ function MyComponent() {
|
|
|
92
106
|
|
|
93
107
|
It Inherits framer motion transition properties other than intera.
|
|
94
108
|
|
|
109
|
+
## Pick property
|
|
110
|
+
|
|
111
|
+
| Property | Explanation |
|
|
112
|
+
| --------- | ---------------------------------------------------------- |
|
|
113
|
+
| classPick | class name of the pick image |
|
|
114
|
+
| white | white or black boolean flag for background |
|
|
115
|
+
| alpha | background transparency a number between 0 ~ 1 |
|
|
116
|
+
| blur | blur intensity a number between 1 and 10 a preferred |
|
|
117
|
+
| scale | scale of the pick image |
|
|
118
|
+
| offset | offset of the appearance position from the center position |
|
|
119
|
+
|
|
95
120
|
## License
|
|
96
121
|
|
|
97
122
|
MIT License
|
|
@@ -1,51 +1,3 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import '
|
|
3
|
-
|
|
4
|
-
src: string;
|
|
5
|
-
alt: string;
|
|
6
|
-
};
|
|
7
|
-
type AnimationProperty = {
|
|
8
|
-
scale?: number;
|
|
9
|
-
opacity?: number;
|
|
10
|
-
rotateY?: number;
|
|
11
|
-
rotateX?: number;
|
|
12
|
-
rotateZ?: number;
|
|
13
|
-
selectScale?: number;
|
|
14
|
-
selectOpacity?: number;
|
|
15
|
-
selectRotateY?: number;
|
|
16
|
-
selectRotateX?: number;
|
|
17
|
-
selectRotateZ?: number;
|
|
18
|
-
};
|
|
19
|
-
type TransitionProperty = {
|
|
20
|
-
duration?: number;
|
|
21
|
-
type: undefined;
|
|
22
|
-
ease: number[] | 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'circIn' | 'circOut' | 'circInOut' | 'backIn' | 'backOut' | 'backInOut' | 'anticipate';
|
|
23
|
-
} | {
|
|
24
|
-
duration?: number;
|
|
25
|
-
type?: 'spring';
|
|
26
|
-
bounce?: number;
|
|
27
|
-
damping?: number;
|
|
28
|
-
mass?: number;
|
|
29
|
-
stiffness?: number;
|
|
30
|
-
velocity?: number;
|
|
31
|
-
restSpeed?: number;
|
|
32
|
-
restDelta?: number;
|
|
33
|
-
};
|
|
34
|
-
type MagicCircleProps = {
|
|
35
|
-
images: ImageProperty[];
|
|
36
|
-
width: number;
|
|
37
|
-
height: number;
|
|
38
|
-
radius: number;
|
|
39
|
-
controller: number;
|
|
40
|
-
start: number;
|
|
41
|
-
dynamic: boolean;
|
|
42
|
-
wheelDelay: number;
|
|
43
|
-
animate?: AnimationProperty;
|
|
44
|
-
initial?: AnimationProperty;
|
|
45
|
-
transition?: TransitionProperty;
|
|
46
|
-
className?: string;
|
|
47
|
-
classImage?: string;
|
|
48
|
-
classImageUnique?: string;
|
|
49
|
-
};
|
|
50
|
-
export declare const MagicCircle: ({ images, width, height, radius, controller, start, dynamic, wheelDelay, animate, initial, transition, className, classImage, classImageUnique }: MagicCircleProps) => React.JSX.Element;
|
|
51
|
-
export {};
|
|
2
|
+
import type { MagicCircleProps } from '../types';
|
|
3
|
+
export declare const MagicCircle: ({ images, height, width, radius, controller, start, dynamic, wheelDelay, animate, initial, transition, className, classImage, classImageUnique, selectCursor, pickProperty, pickTransition }: MagicCircleProps) => React.JSX.Element;
|
|
@@ -22,30 +22,39 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
29
|
exports.MagicCircle = void 0;
|
|
27
30
|
const react_1 = __importStar(require("react"));
|
|
28
31
|
const framer_motion_1 = require("framer-motion");
|
|
29
|
-
require("./
|
|
30
|
-
const
|
|
32
|
+
const styles_module_css_1 = __importDefault(require("./styles.module.css"));
|
|
33
|
+
const ScaleFilterImage_1 = __importDefault(require("../common/ScaleFilterImage"));
|
|
34
|
+
const MagicCircle = ({ images, height, width, radius, controller, start, dynamic = true, wheelDelay, animate, initial, transition, className, classImage, classImageUnique, selectCursor = 'pointer', pickProperty, pickTransition }) => {
|
|
31
35
|
const [count, setCount] = (0, react_1.useState)(0);
|
|
32
36
|
const [touchStartY, setTouchStartY] = (0, react_1.useState)(0);
|
|
37
|
+
const [hasShift, setHasShift] = (0, react_1.useState)(false);
|
|
33
38
|
const [hasDelayed, setHasDelayed] = (0, react_1.useState)(true);
|
|
34
39
|
const [select, setSelect] = (0, react_1.useState)(start);
|
|
35
|
-
const
|
|
40
|
+
const [hasPick, setHasPick] = (0, react_1.useState)(false);
|
|
41
|
+
const div1Ref = (0, react_1.useRef)(null);
|
|
42
|
+
const div2Ref = (0, react_1.useRef)(null);
|
|
36
43
|
const centralAngle = ((2 * Math.PI) / images.length) * (180 / Math.PI);
|
|
37
44
|
// Functions of the rotation and select and delay.
|
|
38
45
|
// turn left
|
|
39
46
|
const shiftLeft = (0, react_1.useCallback)(() => {
|
|
40
|
-
setHasDelayed(false);
|
|
41
47
|
setSelect(select == images.length - 1 ? 0 : select + 1);
|
|
48
|
+
setHasShift(true);
|
|
49
|
+
setHasDelayed(false);
|
|
42
50
|
if (dynamic)
|
|
43
51
|
return setCount(count - centralAngle);
|
|
44
52
|
}, [centralAngle, count, dynamic, images.length, select]);
|
|
45
53
|
// turn right
|
|
46
54
|
const shiftRight = (0, react_1.useCallback)(() => {
|
|
47
|
-
setHasDelayed(false);
|
|
48
55
|
setSelect(select == 0 ? images.length - 1 : select - 1);
|
|
56
|
+
setHasShift(false);
|
|
57
|
+
setHasDelayed(false);
|
|
49
58
|
if (dynamic)
|
|
50
59
|
return setCount(count + centralAngle);
|
|
51
60
|
}, [centralAngle, count, dynamic, images.length, select]);
|
|
@@ -73,95 +82,116 @@ const MagicCircle = ({ images, width, height, radius, controller, start, dynamic
|
|
|
73
82
|
}, [shiftLeft, shiftRight, touchStartY]);
|
|
74
83
|
// Main functional, exit function if ref and hasDelayed does not exist.
|
|
75
84
|
(0, react_1.useEffect)(() => {
|
|
76
|
-
const
|
|
85
|
+
const elm1Div = div1Ref.current;
|
|
86
|
+
const elm2Div = div2Ref.current;
|
|
87
|
+
const elms = [elm1Div, elm2Div];
|
|
77
88
|
const timeId = setTimeout(() => {
|
|
78
89
|
setHasDelayed(true);
|
|
79
90
|
}, wheelDelay);
|
|
80
|
-
if (!range || !hasDelayed)
|
|
81
|
-
return;
|
|
82
91
|
// Add handle event when component mount and deps update.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
elms.forEach(elm => {
|
|
93
|
+
if (!elm || !hasDelayed)
|
|
94
|
+
return;
|
|
95
|
+
elm.addEventListener('wheel', handleWheel, { passive: true });
|
|
96
|
+
elm.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
97
|
+
elm.addEventListener('touchmove', handleTouchMove, { passive: true });
|
|
98
|
+
});
|
|
86
99
|
// Clean up event and timeId when component is unmount.
|
|
87
100
|
return () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
elms.forEach(elm => {
|
|
102
|
+
if (!elm)
|
|
103
|
+
return;
|
|
104
|
+
elm.removeEventListener('wheel', handleWheel);
|
|
105
|
+
elm.removeEventListener('touchstart', handleTouchStart);
|
|
106
|
+
elm.removeEventListener('touchmove', handleTouchMove);
|
|
107
|
+
});
|
|
91
108
|
clearTimeout(timeId);
|
|
92
109
|
};
|
|
93
110
|
}, [handleTouchMove, handleWheel, hasDelayed, wheelDelay]);
|
|
94
111
|
// Functions of the controller.
|
|
95
112
|
// entry ref area.
|
|
96
|
-
const enterControll = () => {
|
|
113
|
+
const enterControll = (e) => {
|
|
114
|
+
e.preventDefault();
|
|
97
115
|
document.body.style.overflow = 'hidden';
|
|
98
|
-
document.body.style.overscrollBehavior = 'none';
|
|
99
116
|
};
|
|
100
117
|
// leave ref area.
|
|
101
118
|
const leaveControll = () => {
|
|
102
119
|
document.body.style.overflow = 'auto';
|
|
103
|
-
document.body.style.overscrollBehavior = 'auto';
|
|
104
120
|
};
|
|
105
121
|
// Added event when component is mounted.
|
|
106
122
|
(0, react_1.useEffect)(() => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
const elm1Div = div1Ref.current;
|
|
124
|
+
const elm2Div = div2Ref.current;
|
|
125
|
+
const elms = [elm1Div, elm2Div];
|
|
110
126
|
// Add event.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
elms.forEach(elm => {
|
|
128
|
+
if (!elm)
|
|
129
|
+
return;
|
|
130
|
+
elm.addEventListener('mouseover', enterControll);
|
|
131
|
+
elm.addEventListener('mouseout', leaveControll);
|
|
132
|
+
elm.addEventListener('touchmove', enterControll);
|
|
133
|
+
elm.addEventListener('touchend', leaveControll);
|
|
134
|
+
});
|
|
116
135
|
// Clean up event when component is unmount.
|
|
117
136
|
return () => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
137
|
+
elms.forEach(elm => {
|
|
138
|
+
if (!elm)
|
|
139
|
+
return;
|
|
140
|
+
elm.removeEventListener('mouseover', enterControll);
|
|
141
|
+
elm.removeEventListener('mouseout', leaveControll);
|
|
142
|
+
elm.removeEventListener('touchmove', enterControll);
|
|
143
|
+
elm.addEventListener('touchend', leaveControll);
|
|
144
|
+
});
|
|
123
145
|
};
|
|
124
146
|
}, []);
|
|
125
147
|
// angle between images.
|
|
126
148
|
const angle = parseFloat((2 * Math.PI).toFixed(15)) / images.length;
|
|
127
149
|
return (react_1.default.createElement(framer_motion_1.LazyMotion, { features: framer_motion_1.domAnimation },
|
|
128
|
-
react_1.default.createElement(framer_motion_1.m.div, { ref:
|
|
150
|
+
react_1.default.createElement(framer_motion_1.m.div, { ref: div1Ref, className: className + ' ' + styles_module_css_1.default.outer, style: {
|
|
129
151
|
width: radius * 2 + controller + 'px',
|
|
130
152
|
height: radius * 2 + controller + 'px'
|
|
131
153
|
}, animate: { rotate: count }, transition: { duration: transition === null || transition === void 0 ? void 0 : transition.duration } },
|
|
132
|
-
react_1.default.createElement("div", { className:
|
|
154
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.inner, style: { width: radius * 2 + 'px', height: radius * 2 + 'px' } }, images.map((image, index) => {
|
|
133
155
|
const hasSelect = images[select] == images[index];
|
|
134
156
|
return (react_1.default.createElement(framer_motion_1.m.img, { key: index, animate: {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
?
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
: animate === null || animate === void 0 ? void 0 : animate.rotateX,
|
|
157
|
+
rotate: -count,
|
|
158
|
+
scale: hasSelect
|
|
159
|
+
? hasPick
|
|
160
|
+
? 0
|
|
161
|
+
: animate === null || animate === void 0 ? void 0 : animate.selectScale
|
|
162
|
+
: animate === null || animate === void 0 ? void 0 : animate.scale,
|
|
142
163
|
rotateY: hasSelect
|
|
143
164
|
? animate === null || animate === void 0 ? void 0 : animate.selectRotateY
|
|
144
165
|
: animate === null || animate === void 0 ? void 0 : animate.rotateY,
|
|
166
|
+
rotateX: hasSelect
|
|
167
|
+
? animate === null || animate === void 0 ? void 0 : animate.selectRotateX
|
|
168
|
+
: animate === null || animate === void 0 ? void 0 : animate.rotateX,
|
|
145
169
|
rotateZ: hasSelect
|
|
146
170
|
? animate === null || animate === void 0 ? void 0 : animate.selectRotateZ
|
|
147
171
|
: animate === null || animate === void 0 ? void 0 : animate.rotateZ,
|
|
148
|
-
|
|
172
|
+
opacity: hasSelect
|
|
173
|
+
? hasPick
|
|
174
|
+
? 0
|
|
175
|
+
: animate === null || animate === void 0 ? void 0 : animate.selectOpacity
|
|
176
|
+
: animate === null || animate === void 0 ? void 0 : animate.opacity
|
|
149
177
|
}, initial: {
|
|
178
|
+
rotate: -count,
|
|
150
179
|
scale: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectScale : initial === null || initial === void 0 ? void 0 : initial.scale,
|
|
151
|
-
opacity: hasSelect
|
|
152
|
-
? initial === null || initial === void 0 ? void 0 : initial.selectOpacity
|
|
153
|
-
: initial === null || initial === void 0 ? void 0 : initial.opacity,
|
|
154
|
-
rotateX: hasSelect
|
|
155
|
-
? initial === null || initial === void 0 ? void 0 : initial.selectRotateX
|
|
156
|
-
: initial === null || initial === void 0 ? void 0 : initial.rotateX,
|
|
157
180
|
rotateY: hasSelect
|
|
158
181
|
? initial === null || initial === void 0 ? void 0 : initial.selectRotateY
|
|
159
182
|
: initial === null || initial === void 0 ? void 0 : initial.rotateY,
|
|
183
|
+
rotateX: hasSelect
|
|
184
|
+
? initial === null || initial === void 0 ? void 0 : initial.selectRotateX
|
|
185
|
+
: initial === null || initial === void 0 ? void 0 : initial.rotateX,
|
|
160
186
|
rotateZ: hasSelect
|
|
161
187
|
? initial === null || initial === void 0 ? void 0 : initial.selectRotateZ
|
|
162
188
|
: initial === null || initial === void 0 ? void 0 : initial.rotateZ,
|
|
163
|
-
|
|
164
|
-
}, transition: transition, onClick: () =>
|
|
189
|
+
opacity: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectOpacity : initial === null || initial === void 0 ? void 0 : initial.opacity
|
|
190
|
+
}, transition: transition, onClick: () => {
|
|
191
|
+
setSelect(index);
|
|
192
|
+
hasSelect && setHasPick(true);
|
|
193
|
+
}, className: classImage + ' ' + classImageUnique + index, src: image.src, alt: image.alt, style: {
|
|
194
|
+
cursor: hasSelect ? selectCursor : 'default',
|
|
165
195
|
width: width + 'px',
|
|
166
196
|
height: height + 'px',
|
|
167
197
|
left: radius * Math.cos(index * angle) +
|
|
@@ -173,6 +203,7 @@ const MagicCircle = ({ images, width, height, radius, controller, start, dynamic
|
|
|
173
203
|
height / 2 +
|
|
174
204
|
'px'
|
|
175
205
|
} }));
|
|
176
|
-
})))
|
|
206
|
+
}))),
|
|
207
|
+
react_1.default.createElement(ScaleFilterImage_1.default, { onClick: () => setHasPick(false), hasPick: hasPick, classPick: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.classPick, white: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.white, alpha: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.alpha, blur: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.blur, scale: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.scale, offset: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.offset, hasShift: hasShift, argRef: div2Ref, argKey: select, src: images[select].src, alt: images[select].alt, width: width, height: height, transition: pickTransition, zIndex: images.length + 1 })));
|
|
177
208
|
};
|
|
178
209
|
exports.MagicCircle = MagicCircle;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { MagicStraightProps } from '../types';
|
|
3
|
+
export declare const MagicStraight: ({ images, height, width, start, controller, wheelDelay, vertical, className, classImage, classImageUnique, animate, initial, transition, margin, selectOffsetX, selectOffsetY, selectCursor, pickProperty, pickTransition }: MagicStraightProps) => React.JSX.Element;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.MagicStraight = void 0;
|
|
30
|
+
const react_1 = __importStar(require("react"));
|
|
31
|
+
const framer_motion_1 = require("framer-motion");
|
|
32
|
+
const styles_module_css_1 = __importDefault(require("./styles.module.css"));
|
|
33
|
+
const ScaleFilterImage_1 = __importDefault(require("../common/ScaleFilterImage"));
|
|
34
|
+
const MagicStraight = ({ images, height, width, start, controller, wheelDelay, vertical, className, classImage, classImageUnique, animate, initial, transition, margin = 0, selectOffsetX = 0, selectOffsetY = 0, selectCursor = 'pointer', pickProperty, pickTransition }) => {
|
|
35
|
+
const [touchStartY, setTouchStartY] = (0, react_1.useState)(0);
|
|
36
|
+
const [touchStartX, setTouchStartX] = (0, react_1.useState)(0);
|
|
37
|
+
const [hasShift, setHasShift] = (0, react_1.useState)(false);
|
|
38
|
+
const [hasDelayed, setHasDelayed] = (0, react_1.useState)(true);
|
|
39
|
+
const [select, setSelect] = (0, react_1.useState)(start);
|
|
40
|
+
const [hasPick, setHasPick] = (0, react_1.useState)(false);
|
|
41
|
+
const div1Ref = (0, react_1.useRef)(null);
|
|
42
|
+
const div2Ref = (0, react_1.useRef)(null);
|
|
43
|
+
const shiftRight = (0, react_1.useCallback)(() => {
|
|
44
|
+
setSelect(select == images.length - 1 ? 0 : select + 1);
|
|
45
|
+
setHasShift(true);
|
|
46
|
+
setHasDelayed(false);
|
|
47
|
+
}, [images.length, select]);
|
|
48
|
+
const shiftLeft = (0, react_1.useCallback)(() => {
|
|
49
|
+
setSelect(select == 0 ? images.length - 1 : select - 1);
|
|
50
|
+
setHasShift(false);
|
|
51
|
+
setHasDelayed(false);
|
|
52
|
+
}, [images.length, select]);
|
|
53
|
+
const handleWheel = (0, react_1.useCallback)((e) => {
|
|
54
|
+
const delta = e.deltaY;
|
|
55
|
+
if (delta > 0)
|
|
56
|
+
shiftRight();
|
|
57
|
+
if (delta < 0)
|
|
58
|
+
shiftLeft();
|
|
59
|
+
}, [shiftLeft, shiftRight]);
|
|
60
|
+
const handleTouchStart = (event) => {
|
|
61
|
+
const touch = event.touches[0];
|
|
62
|
+
setTouchStartY(touch.clientY);
|
|
63
|
+
setTouchStartX(touch.clientX);
|
|
64
|
+
};
|
|
65
|
+
const handleTouchMove = (0, react_1.useCallback)((event) => {
|
|
66
|
+
const touch = event.touches[0];
|
|
67
|
+
const delta = hasPick
|
|
68
|
+
? touch.clientX - touchStartX
|
|
69
|
+
: vertical
|
|
70
|
+
? touch.clientY - touchStartY
|
|
71
|
+
: touch.clientX - touchStartX;
|
|
72
|
+
if (delta > 0)
|
|
73
|
+
shiftRight();
|
|
74
|
+
if (delta < 0)
|
|
75
|
+
shiftLeft();
|
|
76
|
+
}, [hasPick, shiftLeft, shiftRight, touchStartX, touchStartY, vertical]);
|
|
77
|
+
(0, react_1.useEffect)(() => {
|
|
78
|
+
const elm1Div = div1Ref.current;
|
|
79
|
+
const elm2Div = div2Ref.current;
|
|
80
|
+
const elms = [elm1Div, elm2Div];
|
|
81
|
+
const timeId = setTimeout(() => {
|
|
82
|
+
setHasDelayed(true);
|
|
83
|
+
}, wheelDelay);
|
|
84
|
+
elms.forEach(elm => {
|
|
85
|
+
if (!elm || !hasDelayed)
|
|
86
|
+
return;
|
|
87
|
+
elm.addEventListener('wheel', handleWheel, { passive: true });
|
|
88
|
+
elm.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
89
|
+
elm.addEventListener('touchmove', handleTouchMove, { passive: true });
|
|
90
|
+
});
|
|
91
|
+
return () => {
|
|
92
|
+
elms.forEach(elm => {
|
|
93
|
+
if (!elm)
|
|
94
|
+
return;
|
|
95
|
+
elm.removeEventListener('wheel', handleWheel);
|
|
96
|
+
elm.removeEventListener('touchstart', handleTouchStart);
|
|
97
|
+
elm.removeEventListener('touchmove', handleTouchMove);
|
|
98
|
+
});
|
|
99
|
+
clearTimeout(timeId);
|
|
100
|
+
};
|
|
101
|
+
}, [handleTouchMove, handleWheel, hasDelayed, wheelDelay]);
|
|
102
|
+
const enterControll = (e) => {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
document.body.style.overflow = 'hidden';
|
|
105
|
+
};
|
|
106
|
+
const leaveControll = () => {
|
|
107
|
+
document.body.style.overflow = 'auto';
|
|
108
|
+
};
|
|
109
|
+
(0, react_1.useEffect)(() => {
|
|
110
|
+
const elm1Div = div1Ref.current;
|
|
111
|
+
const elm2Div = div2Ref.current;
|
|
112
|
+
const elms = [elm1Div, elm2Div];
|
|
113
|
+
elms.forEach(elm => {
|
|
114
|
+
if (!elm)
|
|
115
|
+
return;
|
|
116
|
+
elm.addEventListener('mouseover', enterControll);
|
|
117
|
+
elm.addEventListener('mouseout', leaveControll);
|
|
118
|
+
elm.addEventListener('touchmove', enterControll);
|
|
119
|
+
elm.addEventListener('touchend', leaveControll);
|
|
120
|
+
});
|
|
121
|
+
return () => {
|
|
122
|
+
elms.forEach(elm => {
|
|
123
|
+
if (!elm)
|
|
124
|
+
return;
|
|
125
|
+
elm.removeEventListener('mouseover', enterControll);
|
|
126
|
+
elm.removeEventListener('mouseout', leaveControll);
|
|
127
|
+
elm.removeEventListener('touchmove', enterControll);
|
|
128
|
+
elm.addEventListener('touchend', leaveControll);
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
let total = 0;
|
|
133
|
+
for (let i = 1; i < images.length; i++)
|
|
134
|
+
total += i;
|
|
135
|
+
const Total = total / images.length;
|
|
136
|
+
const clasess = className + ' ' + styles_module_css_1.default.outer;
|
|
137
|
+
return (react_1.default.createElement(framer_motion_1.LazyMotion, { features: framer_motion_1.domAnimation },
|
|
138
|
+
react_1.default.createElement("div", { ref: div1Ref, className: clasess, style: {
|
|
139
|
+
width: !vertical ? height + controller + 'px' : 'fit-content',
|
|
140
|
+
height: vertical ? width + controller + 'px' : 'fit-content',
|
|
141
|
+
padding: vertical
|
|
142
|
+
? controller + 'px' + ' ' + controller / 2 + 'px'
|
|
143
|
+
: controller / 2 + 'px' + ' ' + controller + 'px',
|
|
144
|
+
flexDirection: vertical ? 'column' : 'row'
|
|
145
|
+
} }, images.map((image, index) => {
|
|
146
|
+
const hasSelect = images[select] == images[index];
|
|
147
|
+
const reverseIndex = images.length - 1 - index;
|
|
148
|
+
return (react_1.default.createElement(framer_motion_1.m.img, { key: index, animate: {
|
|
149
|
+
y: hasSelect
|
|
150
|
+
? vertical
|
|
151
|
+
? (Total - index) * height +
|
|
152
|
+
(Total - index) * (margin * 2) +
|
|
153
|
+
selectOffsetY
|
|
154
|
+
: selectOffsetY
|
|
155
|
+
: 0,
|
|
156
|
+
x: hasSelect
|
|
157
|
+
? !vertical
|
|
158
|
+
? (Total - index) * width +
|
|
159
|
+
(Total - index) * (margin * 2) +
|
|
160
|
+
selectOffsetX
|
|
161
|
+
: selectOffsetX
|
|
162
|
+
: 0,
|
|
163
|
+
scale: hasSelect
|
|
164
|
+
? hasPick
|
|
165
|
+
? 0
|
|
166
|
+
: animate === null || animate === void 0 ? void 0 : animate.selectScale
|
|
167
|
+
: animate === null || animate === void 0 ? void 0 : animate.scale,
|
|
168
|
+
rotateY: hasSelect ? animate === null || animate === void 0 ? void 0 : animate.selectRotateY : animate === null || animate === void 0 ? void 0 : animate.rotateY,
|
|
169
|
+
rotateX: hasSelect ? animate === null || animate === void 0 ? void 0 : animate.selectRotateX : animate === null || animate === void 0 ? void 0 : animate.rotateX,
|
|
170
|
+
rotateZ: hasSelect ? animate === null || animate === void 0 ? void 0 : animate.selectRotateZ : animate === null || animate === void 0 ? void 0 : animate.rotateZ,
|
|
171
|
+
opacity: hasSelect
|
|
172
|
+
? hasPick
|
|
173
|
+
? 0
|
|
174
|
+
: animate === null || animate === void 0 ? void 0 : animate.selectOpacity
|
|
175
|
+
: animate === null || animate === void 0 ? void 0 : animate.opacity
|
|
176
|
+
}, initial: {
|
|
177
|
+
scale: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectScale : initial === null || initial === void 0 ? void 0 : initial.scale,
|
|
178
|
+
rotateY: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectRotateY : initial === null || initial === void 0 ? void 0 : initial.rotateY,
|
|
179
|
+
rotateX: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectRotateX : initial === null || initial === void 0 ? void 0 : initial.rotateX,
|
|
180
|
+
rotateZ: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectRotateZ : initial === null || initial === void 0 ? void 0 : initial.rotateZ,
|
|
181
|
+
opacity: hasSelect ? initial === null || initial === void 0 ? void 0 : initial.selectOpacity : initial === null || initial === void 0 ? void 0 : initial.opacity
|
|
182
|
+
}, transition: transition, onClick: () => {
|
|
183
|
+
setSelect(index);
|
|
184
|
+
hasSelect && setHasPick(true);
|
|
185
|
+
}, className: classImage + ' ' + classImageUnique + index, src: image.src, alt: image.alt, role: "button", style: {
|
|
186
|
+
zIndex: hasSelect
|
|
187
|
+
? hasPick
|
|
188
|
+
? 0
|
|
189
|
+
: images.length + 1
|
|
190
|
+
: reverseIndex,
|
|
191
|
+
cursor: hasSelect ? selectCursor : 'default',
|
|
192
|
+
width: width + 'px',
|
|
193
|
+
height: height + 'px',
|
|
194
|
+
margin: vertical ? margin + 'px' + ' 0' : '0 ' + margin + 'px'
|
|
195
|
+
} }));
|
|
196
|
+
})),
|
|
197
|
+
react_1.default.createElement("button", { onClick: () => shiftRight() }, hasPick ? 'true' : 'false'),
|
|
198
|
+
react_1.default.createElement(ScaleFilterImage_1.default, { onClick: () => setHasPick(false), hasPick: hasPick, classPick: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.classPick, white: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.white, alpha: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.alpha, blur: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.blur, scale: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.scale, offset: pickProperty === null || pickProperty === void 0 ? void 0 : pickProperty.offset, hasShift: hasShift, argRef: div2Ref, argKey: select, src: images[select].src, alt: images[select].alt, width: width, height: height, transition: pickTransition, zIndex: images.length + 1 })));
|
|
199
|
+
};
|
|
200
|
+
exports.MagicStraight = MagicStraight;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ScaleFilterImageProps } from '../../types';
|
|
3
|
+
declare const ScaleFilterImage: ({ onClick, classPick, hasPick, hasShift, argRef, argKey, src, alt, width, height, zIndex, white, alpha, blur, scale, offset, transition }: ScaleFilterImageProps) => React.JSX.Element;
|
|
4
|
+
export default ScaleFilterImage;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const framer_motion_1 = require("framer-motion");
|
|
8
|
+
const styles_module_css_1 = __importDefault(require("./styles.module.css"));
|
|
9
|
+
const ScaleFilterImage = ({ onClick, classPick, hasPick, hasShift, argRef, argKey, src, alt, width, height, zIndex, white, alpha = 0.4, blur = 4, scale = 2, offset = 200, transition }) => {
|
|
10
|
+
return (react_1.default.createElement(framer_motion_1.m.div, { role: "button", onClick: onClick, ref: argRef, className: styles_module_css_1.default.full_size, animate: {
|
|
11
|
+
zIndex: zIndex,
|
|
12
|
+
background: white
|
|
13
|
+
? `rgba(255, 255, 255, ${alpha})`
|
|
14
|
+
: `rgba(0, 0, 0, ${alpha})`,
|
|
15
|
+
backdropFilter: `blur(${blur}px)`,
|
|
16
|
+
opacity: hasPick ? 1 : 0,
|
|
17
|
+
pointerEvents: hasPick ? 'auto' : 'none'
|
|
18
|
+
}, initial: { background: 'none' }, transition: transition },
|
|
19
|
+
react_1.default.createElement(framer_motion_1.m.img, { className: classPick, onClick: e => e.stopPropagation(), key: argKey, src: src, alt: alt, width: width, height: height, animate: {
|
|
20
|
+
zIndex: zIndex + 1,
|
|
21
|
+
scale: scale,
|
|
22
|
+
opacity: hasPick ? 1 : 0,
|
|
23
|
+
x: 0
|
|
24
|
+
}, initial: { scale: 1, opacity: 0, x: hasShift ? offset : -offset }, transition: transition })));
|
|
25
|
+
};
|
|
26
|
+
exports.default = ScaleFilterImage;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MagicCircle = void 0;
|
|
3
|
+
exports.MagicStraight = exports.MagicCircle = void 0;
|
|
4
4
|
const MagicCircle_1 = require("./MagicCircle");
|
|
5
5
|
Object.defineProperty(exports, "MagicCircle", { enumerable: true, get: function () { return MagicCircle_1.MagicCircle; } });
|
|
6
|
+
const MagicStraight_1 = require("./MagicStraight");
|
|
7
|
+
Object.defineProperty(exports, "MagicStraight", { enumerable: true, get: function () { return MagicStraight_1.MagicStraight; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Ref, MouseEventHandler } from 'react';
|
|
2
|
+
type ImageProperty = {
|
|
3
|
+
src: string;
|
|
4
|
+
alt: string;
|
|
5
|
+
};
|
|
6
|
+
type AnimationProperty = {
|
|
7
|
+
scale?: number;
|
|
8
|
+
rotateY?: number;
|
|
9
|
+
rotateX?: number;
|
|
10
|
+
rotateZ?: number;
|
|
11
|
+
opacity?: number;
|
|
12
|
+
selectScale?: number;
|
|
13
|
+
selectRotateY?: number;
|
|
14
|
+
selectRotateX?: number;
|
|
15
|
+
selectRotateZ?: number;
|
|
16
|
+
selectOpacity?: number;
|
|
17
|
+
};
|
|
18
|
+
type TransitionProperty = {
|
|
19
|
+
duration?: number;
|
|
20
|
+
type: undefined;
|
|
21
|
+
ease: number[] | 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'circIn' | 'circOut' | 'circInOut' | 'backIn' | 'backOut' | 'backInOut' | 'anticipate';
|
|
22
|
+
} | {
|
|
23
|
+
duration?: number;
|
|
24
|
+
type?: 'spring';
|
|
25
|
+
bounce?: number;
|
|
26
|
+
damping?: number;
|
|
27
|
+
mass?: number;
|
|
28
|
+
stiffness?: number;
|
|
29
|
+
velocity?: number;
|
|
30
|
+
restSpeed?: number;
|
|
31
|
+
restDelta?: number;
|
|
32
|
+
};
|
|
33
|
+
type PickProperty = {
|
|
34
|
+
classPick?: string;
|
|
35
|
+
white?: boolean;
|
|
36
|
+
alpha?: number;
|
|
37
|
+
blur?: number;
|
|
38
|
+
scale?: number;
|
|
39
|
+
offset?: number;
|
|
40
|
+
};
|
|
41
|
+
type MagicProperty = {
|
|
42
|
+
images: ImageProperty[];
|
|
43
|
+
height: number;
|
|
44
|
+
width: number;
|
|
45
|
+
controller: number;
|
|
46
|
+
start: number;
|
|
47
|
+
wheelDelay: number;
|
|
48
|
+
className?: string;
|
|
49
|
+
classImage?: string;
|
|
50
|
+
classImageUnique?: string;
|
|
51
|
+
animate?: AnimationProperty;
|
|
52
|
+
initial?: AnimationProperty;
|
|
53
|
+
transition?: TransitionProperty;
|
|
54
|
+
selectCursor?: 'pointer' | 'zoom-in' | 'crosshair' | 'help';
|
|
55
|
+
pickProperty?: PickProperty;
|
|
56
|
+
pickTransition?: TransitionProperty;
|
|
57
|
+
};
|
|
58
|
+
export type MagicCircleProps = MagicProperty & {
|
|
59
|
+
radius: number;
|
|
60
|
+
dynamic?: boolean;
|
|
61
|
+
};
|
|
62
|
+
export type MagicStraightProps = MagicProperty & {
|
|
63
|
+
vertical?: boolean;
|
|
64
|
+
margin?: number;
|
|
65
|
+
selectOffsetX?: number;
|
|
66
|
+
selectOffsetY?: number;
|
|
67
|
+
};
|
|
68
|
+
export type ScaleFilterImageProps = {
|
|
69
|
+
onClick: MouseEventHandler<HTMLDivElement>;
|
|
70
|
+
classPick?: string;
|
|
71
|
+
hasPick: boolean;
|
|
72
|
+
hasShift: boolean;
|
|
73
|
+
argRef: Ref<HTMLDivElement>;
|
|
74
|
+
argKey: number;
|
|
75
|
+
src: string;
|
|
76
|
+
alt: string;
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
zIndex: number;
|
|
80
|
+
white?: boolean;
|
|
81
|
+
alpha?: number;
|
|
82
|
+
blur?: number;
|
|
83
|
+
scale?: number;
|
|
84
|
+
offset?: number;
|
|
85
|
+
transition?: TransitionProperty;
|
|
86
|
+
};
|
|
87
|
+
export {};
|
package/dist/types.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-magic-card",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "image gallery component with framer motion",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"tsc": "./node_modules/.bin/tsc",
|
|
14
|
-
"copy-css": "cp src/MagicCircle/main.css dist/MagicCircle/main.css",
|
|
15
14
|
"compile": "tsc && npm run copy-css",
|
|
15
|
+
"copy-css": "npm run copy-css1 && npm run copy-css2 && npm run copy-css3",
|
|
16
|
+
"copy-css1": "cp src/MagicCircle/styles.module.css dist/MagicCircle/styles.module.css",
|
|
17
|
+
"copy-css2": "cp src/MagicStraight/styles.module.css dist/MagicStraight/styles.module.css",
|
|
18
|
+
"copy-css3": "cp src/common/ScaleFilterImage/styles.module.css dist/common/ScaleFilterImage/styles.module.css",
|
|
16
19
|
"test": "test"
|
|
17
20
|
},
|
|
18
21
|
"keywords": [
|
|
@@ -29,6 +32,7 @@
|
|
|
29
32
|
"typescript": "^5.1.3"
|
|
30
33
|
},
|
|
31
34
|
"devDependencies": {
|
|
32
|
-
"@types/react": "^18.2.12"
|
|
35
|
+
"@types/react": "^18.2.12",
|
|
36
|
+
"@types/css-modules": "^1.0.2"
|
|
33
37
|
}
|
|
34
38
|
}
|
|
File without changes
|