masoneffect 0.1.18 → 0.1.20

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/core/index.d.ts.map +1 -1
  3. package/dist/index.cjs +1 -0
  4. package/dist/index.mjs +1 -0
  5. package/dist/react/MasonEffect.cjs +1 -526
  6. package/dist/react/MasonEffect.d.ts.map +1 -1
  7. package/dist/react/MasonEffect.mjs +1 -0
  8. package/dist/react/core/index.d.ts +0 -1
  9. package/dist/react/core/index.d.ts.map +1 -1
  10. package/dist/react/index.d.ts +2 -8
  11. package/dist/react/index.mjs +1 -0
  12. package/dist/react/index.umd.d.ts +0 -1
  13. package/dist/react/react/MasonEffect.d.ts +0 -1
  14. package/dist/react/react/MasonEffect.d.ts.map +1 -1
  15. package/dist/react/react/index.d.ts +2 -0
  16. package/dist/react/react/index.d.ts.map +1 -0
  17. package/dist/react/vue/index.d.ts +5 -0
  18. package/dist/react/vue/index.d.ts.map +1 -0
  19. package/dist/vue/index.cjs +1 -0
  20. package/dist/vue/index.d.ts +90 -0
  21. package/{src/core/index.ts → dist/vue/index.mjs} +227 -237
  22. package/package.json +14 -15
  23. package/dist/index.esm.js +0 -387
  24. package/dist/index.esm.js.map +0 -1
  25. package/dist/index.esm.min.js +0 -1
  26. package/dist/index.js +0 -392
  27. package/dist/index.js.map +0 -1
  28. package/dist/index.min.js +0 -1
  29. package/dist/index.umd.js +0 -396
  30. package/dist/index.umd.js.map +0 -1
  31. package/dist/index.umd.min.js +0 -1
  32. package/dist/react/MasonEffect.cjs.map +0 -1
  33. package/dist/react/MasonEffect.js +0 -524
  34. package/dist/react/MasonEffect.js.map +0 -1
  35. package/dist/react/MasonEffect.min.cjs +0 -1
  36. package/dist/react/MasonEffect.min.js +0 -1
  37. package/src/index.ts +0 -14
  38. package/src/index.umd.ts +0 -10
  39. package/src/react/MasonEffect.tsx +0 -228
  40. package/src/react/index.js +0 -2
  41. package/src/vue/MasonEffect.vue +0 -140
@@ -1,228 +0,0 @@
1
- import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
2
- import { MasonEffect } from '../core/index.js';
3
-
4
- export interface MasonEffectOptions {
5
- text?: string;
6
- densityStep?: number;
7
- maxParticles?: number;
8
- pointSize?: number;
9
- ease?: number;
10
- repelRadius?: number;
11
- repelStrength?: number;
12
- particleColor?: string;
13
- fontFamily?: string;
14
- fontSize?: number | null;
15
- width?: number | null;
16
- height?: number | null;
17
- devicePixelRatio?: number | null;
18
- onReady?: (instance: MasonEffect) => void;
19
- onUpdate?: (instance: MasonEffect) => void;
20
- }
21
-
22
- export interface MasonEffectRef {
23
- morph: (textOrOptions?: string | Partial<MasonEffectOptions>) => void;
24
- scatter: () => void;
25
- updateConfig: (config: Partial<MasonEffectOptions>) => void;
26
- destroy: () => void;
27
- }
28
-
29
- interface MasonEffectProps extends MasonEffectOptions {
30
- className?: string;
31
- style?: React.CSSProperties;
32
- }
33
-
34
- const MasonEffectComponent = forwardRef<MasonEffectRef, MasonEffectProps>(
35
- (props, ref) => {
36
- const containerRef = useRef<HTMLDivElement>(null);
37
- const instanceRef = useRef<MasonEffect | null>(null);
38
-
39
- useEffect(() => {
40
- if (!containerRef.current) return;
41
-
42
- let resizeObserver: ResizeObserver | null = null;
43
- let initTimeout: number | null = null;
44
-
45
- // 컨테이너가 실제 크기를 가지도록 대기
46
- const initEffect = () => {
47
- const container = containerRef.current;
48
- if (!container) return;
49
-
50
- // 컨테이너 크기가 0이면 다음 프레임에 다시 시도
51
- const rect = container.getBoundingClientRect();
52
- if (rect.width === 0 || rect.height === 0) {
53
- initTimeout = window.setTimeout(initEffect, 50);
54
- return;
55
- }
56
-
57
- const {
58
- className,
59
- style,
60
- text,
61
- densityStep,
62
- maxParticles,
63
- pointSize,
64
- ease,
65
- repelRadius,
66
- repelStrength,
67
- particleColor,
68
- fontFamily,
69
- fontSize,
70
- width,
71
- height,
72
- devicePixelRatio,
73
- onReady,
74
- onUpdate,
75
- } = props;
76
-
77
- const options: MasonEffectOptions = {
78
- text,
79
- densityStep,
80
- maxParticles,
81
- pointSize,
82
- ease,
83
- repelRadius,
84
- repelStrength,
85
- particleColor,
86
- fontFamily,
87
- fontSize,
88
- width,
89
- height,
90
- devicePixelRatio,
91
- onReady,
92
- onUpdate,
93
- };
94
-
95
- instanceRef.current = new MasonEffect(container, options);
96
-
97
- // ResizeObserver로 컨테이너 크기 변경 감지
98
- if (typeof ResizeObserver !== 'undefined') {
99
- resizeObserver = new ResizeObserver(() => {
100
- if (instanceRef.current) {
101
- instanceRef.current.resize();
102
- }
103
- });
104
- resizeObserver.observe(container);
105
- }
106
- };
107
-
108
- // 다음 프레임에 초기화 (DOM이 완전히 렌더링된 후)
109
- requestAnimationFrame(initEffect);
110
-
111
- return () => {
112
- if (initTimeout) {
113
- clearTimeout(initTimeout);
114
- }
115
- if (resizeObserver) {
116
- resizeObserver.disconnect();
117
- }
118
- if (instanceRef.current) {
119
- instanceRef.current.destroy();
120
- instanceRef.current = null;
121
- }
122
- };
123
- }, []);
124
-
125
- // props 변경 시 설정 업데이트
126
- useEffect(() => {
127
- if (!instanceRef.current) return;
128
-
129
- const {
130
- text,
131
- densityStep,
132
- maxParticles,
133
- pointSize,
134
- ease,
135
- repelRadius,
136
- repelStrength,
137
- particleColor,
138
- fontFamily,
139
- fontSize,
140
- width,
141
- height,
142
- devicePixelRatio,
143
- } = props;
144
-
145
- instanceRef.current.updateConfig({
146
- text,
147
- densityStep,
148
- maxParticles,
149
- pointSize,
150
- ease,
151
- repelRadius,
152
- repelStrength,
153
- particleColor,
154
- fontFamily,
155
- fontSize,
156
- width,
157
- height,
158
- devicePixelRatio,
159
- });
160
- }, [
161
- props.text,
162
- props.densityStep,
163
- props.maxParticles,
164
- props.pointSize,
165
- props.ease,
166
- props.repelRadius,
167
- props.repelStrength,
168
- props.particleColor,
169
- props.fontFamily,
170
- props.fontSize,
171
- props.width,
172
- props.height,
173
- props.devicePixelRatio,
174
- ]);
175
-
176
- useImperativeHandle(ref, () => ({
177
- morph: (textOrOptions?: string | Partial<MasonEffectOptions>) => {
178
- if (!instanceRef.current) {
179
- console.warn('MasonEffect: 인스턴스가 아직 초기화되지 않았습니다.');
180
- return;
181
- }
182
- instanceRef.current.morph(textOrOptions);
183
- },
184
- scatter: () => {
185
- if (!instanceRef.current) {
186
- console.warn('MasonEffect: 인스턴스가 아직 초기화되지 않았습니다.');
187
- return;
188
- }
189
- instanceRef.current.scatter();
190
- },
191
- updateConfig: (config: Partial<MasonEffectOptions>) => {
192
- if (!instanceRef.current) {
193
- console.warn('MasonEffect: 인스턴스가 아직 초기화되지 않았습니다.');
194
- return;
195
- }
196
- instanceRef.current.updateConfig(config);
197
- },
198
- destroy: () => {
199
- if (instanceRef.current) {
200
- instanceRef.current.destroy();
201
- instanceRef.current = null;
202
- }
203
- },
204
- }));
205
-
206
- // 기본 스타일: 컨테이너가 크기를 가지도록 함
207
- const defaultStyle: React.CSSProperties = {
208
- width: '100%',
209
- height: '100%',
210
- minHeight: props.height || 400,
211
- position: 'relative',
212
- ...props.style,
213
- };
214
-
215
- return (
216
- <div
217
- ref={containerRef}
218
- className={props.className}
219
- style={defaultStyle}
220
- />
221
- );
222
- }
223
- );
224
-
225
- MasonEffectComponent.displayName = 'MasonEffect';
226
-
227
- export default MasonEffectComponent;
228
-
@@ -1,2 +0,0 @@
1
- export { default, MasonEffectRef, MasonEffectOptions } from './MasonEffect';
2
-
@@ -1,140 +0,0 @@
1
- <template>
2
- <div ref="container" :class="className" :style="style"></div>
3
- </template>
4
-
5
- <script setup lang="ts">
6
- import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
7
- import { MasonEffect } from '../core/index';
8
- import type { MasonEffectOptions } from '../core/index';
9
-
10
- interface Props extends Partial<MasonEffectOptions> {
11
- className?: string;
12
- style?: Record<string, any>;
13
- }
14
-
15
- const props = withDefaults(defineProps<Props>(), {
16
- text: 'mason effect',
17
- densityStep: 2,
18
- maxParticles: 3200,
19
- pointSize: 0.5,
20
- ease: 0.05,
21
- repelRadius: 150,
22
- repelStrength: 1,
23
- particleColor: '#fff',
24
- fontFamily: 'Inter, system-ui, Arial',
25
- fontSize: null,
26
- width: null,
27
- height: null,
28
- devicePixelRatio: null,
29
- className: '',
30
- style: () => ({}),
31
- onReady: null,
32
- onUpdate: null,
33
- });
34
-
35
- const emit = defineEmits<{
36
- ready: [instance: MasonEffect];
37
- update: [instance: MasonEffect];
38
- }>();
39
-
40
- const container = ref<HTMLElement | null>(null);
41
- let instance: MasonEffect | null = null;
42
-
43
- const init = () => {
44
- if (!container.value) return;
45
-
46
- const options: MasonEffectOptions = {
47
- text: props.text,
48
- densityStep: props.densityStep,
49
- maxParticles: props.maxParticles,
50
- pointSize: props.pointSize,
51
- ease: props.ease,
52
- repelRadius: props.repelRadius,
53
- repelStrength: props.repelStrength,
54
- particleColor: props.particleColor,
55
- fontFamily: props.fontFamily,
56
- fontSize: props.fontSize,
57
- width: props.width,
58
- height: props.height,
59
- devicePixelRatio: props.devicePixelRatio,
60
- onReady: (inst) => {
61
- if (props.onReady) props.onReady(inst);
62
- emit('ready', inst);
63
- },
64
- onUpdate: (inst) => {
65
- if (props.onUpdate) props.onUpdate(inst);
66
- emit('update', inst);
67
- },
68
- };
69
-
70
- instance = new MasonEffect(container.value, options);
71
- };
72
-
73
- // props 변경 감지
74
- watch(
75
- () => [
76
- props.text,
77
- props.densityStep,
78
- props.maxParticles,
79
- props.pointSize,
80
- props.ease,
81
- props.repelRadius,
82
- props.repelStrength,
83
- props.particleColor,
84
- props.fontFamily,
85
- props.fontSize,
86
- props.width,
87
- props.height,
88
- props.devicePixelRatio,
89
- ],
90
- () => {
91
- if (instance) {
92
- instance.updateConfig({
93
- text: props.text,
94
- densityStep: props.densityStep,
95
- maxParticles: props.maxParticles,
96
- pointSize: props.pointSize,
97
- ease: props.ease,
98
- repelRadius: props.repelRadius,
99
- repelStrength: props.repelStrength,
100
- particleColor: props.particleColor,
101
- fontFamily: props.fontFamily,
102
- fontSize: props.fontSize,
103
- width: props.width,
104
- height: props.height,
105
- devicePixelRatio: props.devicePixelRatio,
106
- });
107
- }
108
- }
109
- );
110
-
111
- onMounted(() => {
112
- init();
113
- });
114
-
115
- onBeforeUnmount(() => {
116
- if (instance) {
117
- instance.destroy();
118
- instance = null;
119
- }
120
- });
121
-
122
- // 외부에서 사용할 수 있는 메서드 노출
123
- defineExpose({
124
- morph: (textOrOptions?: string | Partial<MasonEffectOptions>) => {
125
- if (instance) instance.morph(textOrOptions);
126
- },
127
- scatter: () => {
128
- if (instance) instance.scatter();
129
- },
130
- updateConfig: (config: Partial<MasonEffectOptions>) => {
131
- if (instance) instance.updateConfig(config);
132
- },
133
- destroy: () => {
134
- if (instance) {
135
- instance.destroy();
136
- instance = null;
137
- }
138
- },
139
- });
140
- </script>