@byeolnaerim/flex-layout 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FlexLayoutSplitScreenDragBox-eCtq4kLd.d.cts +31 -0
- package/dist/FlexLayoutSplitScreenDragBox-eCtq4kLd.d.ts +31 -0
- package/dist/chunk-3EDKZTM3.js +3 -0
- package/dist/chunk-3EDKZTM3.js.map +1 -0
- package/dist/chunk-5HWEFTNQ.js +176 -0
- package/dist/chunk-5HWEFTNQ.js.map +1 -0
- package/dist/chunk-7J5JUVZK.js +3 -0
- package/dist/chunk-7J5JUVZK.js.map +1 -0
- package/dist/chunk-CFQQ6ZDC.js +182 -0
- package/dist/chunk-CFQQ6ZDC.js.map +1 -0
- package/dist/chunk-JM3CZ5DU.js +238 -0
- package/dist/chunk-JM3CZ5DU.js.map +1 -0
- package/dist/chunk-PMTZFSP4.js +219 -0
- package/dist/chunk-PMTZFSP4.js.map +1 -0
- package/dist/chunk-UYI4Z27V.js +2432 -0
- package/dist/chunk-UYI4Z27V.js.map +1 -0
- package/dist/chunk-W4CNFJTK.js +197 -0
- package/dist/chunk-W4CNFJTK.js.map +1 -0
- package/dist/chunk-YIHCWXKY.js +3 -0
- package/dist/chunk-YIHCWXKY.js.map +1 -0
- package/dist/components.cjs +3048 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.css +471 -0
- package/dist/components.css.map +1 -0
- package/dist/components.d.cts +122 -0
- package/dist/components.d.ts +122 -0
- package/dist/components.js +7 -0
- package/dist/components.js.map +1 -0
- package/dist/hooks.cjs +425 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.cts +37 -0
- package/dist/hooks.d.ts +37 -0
- package/dist/hooks.js +5 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.cjs +2600 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -287
- package/dist/index.d.ts +10 -287
- package/dist/index.js +9 -814
- package/dist/index.js.map +1 -1
- package/dist/providers.cjs +411 -0
- package/dist/providers.cjs.map +1 -0
- package/dist/providers.d.cts +54 -0
- package/dist/providers.d.ts +54 -0
- package/dist/providers.js +6 -0
- package/dist/providers.js.map +1 -0
- package/dist/store.cjs +204 -0
- package/dist/store.cjs.map +1 -0
- package/dist/store.d.cts +67 -0
- package/dist/store.d.ts +67 -0
- package/dist/store.js +4 -0
- package/dist/store.js.map +1 -0
- package/dist/useDrag-CYQnhUFk.d.cts +108 -0
- package/dist/useDrag-DR01Ob3s.d.ts +108 -0
- package/dist/utils.cjs +209 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +28 -0
- package/dist/utils.d.ts +28 -0
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -0
- package/package.json +25 -5
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React$1 from 'react';
|
|
3
|
+
import React__default, { ReactElement, ReactNode, HTMLAttributes } from 'react';
|
|
4
|
+
import { D as DropDocumentOutsideOption } from './FlexLayoutSplitScreenDragBox-eCtq4kLd.js';
|
|
5
|
+
export { F as FlexLayoutSplitScreenDragBox } from './FlexLayoutSplitScreenDragBox-eCtq4kLd.js';
|
|
6
|
+
|
|
7
|
+
type ResizePanelMode =
|
|
8
|
+
| 'default'
|
|
9
|
+
| 'bottom-cylinder'
|
|
10
|
+
| 'bottom-cylinder-reverse'
|
|
11
|
+
| 'top-cylinder'
|
|
12
|
+
| 'left-cylinder'
|
|
13
|
+
| 'right-cylinder';
|
|
14
|
+
|
|
15
|
+
type Direction = 'row' | 'column';
|
|
16
|
+
type PanelMovementMode = 'bulldozer' | 'divorce' | 'stalker';
|
|
17
|
+
type FitContent = 'width' | 'height';
|
|
18
|
+
|
|
19
|
+
interface FlexLayoutChildrenType {
|
|
20
|
+
isInitialResizable?: boolean;
|
|
21
|
+
grow?: number;
|
|
22
|
+
prevGrow?: number;
|
|
23
|
+
panelMode?: ResizePanelMode;
|
|
24
|
+
isFitContent?: boolean;
|
|
25
|
+
isFitResize?: boolean;
|
|
26
|
+
isResizePanel?: boolean;
|
|
27
|
+
containerName: string;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface FlexContainerProps extends FlexLayoutChildrenType {
|
|
33
|
+
readonly fitContent?: FitContent;
|
|
34
|
+
readonly containerCount?: number;
|
|
35
|
+
readonly layoutName?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface FlexLayoutProps
|
|
39
|
+
extends Omit<
|
|
40
|
+
React.HTMLAttributes<HTMLDivElement>,
|
|
41
|
+
'children',
|
|
42
|
+
'id',
|
|
43
|
+
'panelClassName'
|
|
44
|
+
> {
|
|
45
|
+
direction: Direction;
|
|
46
|
+
children:
|
|
47
|
+
| ReactElement<FlexLayoutChildrenType>[]
|
|
48
|
+
| ReactElement<FlexLayoutChildrenType>;
|
|
49
|
+
layoutName: string;
|
|
50
|
+
isSplitScreen?: boolean;
|
|
51
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
52
|
+
className?: string;
|
|
53
|
+
panelClassName?: string;
|
|
54
|
+
panelMovementMode?: PanelMovementMode;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type FlexLayoutResizePanelProps = {
|
|
58
|
+
direction: string;
|
|
59
|
+
containerCount: number;
|
|
60
|
+
panelMode?: ResizePanelMode;
|
|
61
|
+
containerName: string;
|
|
62
|
+
layoutName: string;
|
|
63
|
+
panelMovementMode: PanelMovementMode;
|
|
64
|
+
panelClassName?: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
declare const FlexLayout: ({ layoutName, direction, children, ref, className, panelClassName, panelMovementMode, ...props }: FlexLayoutProps) => react_jsx_runtime.JSX.Element | null;
|
|
68
|
+
|
|
69
|
+
declare const FlexLayoutContainer: ({ isFitContent, isFitResize, containerName, grow: initialGrow, prevGrow: initialPrevGrow, isInitialResizable, isResizePanel, children, className, panelMode, }: FlexContainerProps) => react_jsx_runtime.JSX.Element;
|
|
70
|
+
|
|
71
|
+
declare const FlexLayoutResizePanel: ({ direction, containerCount, panelMode, containerName, layoutName, panelClassName, panelMovementMode, }: FlexLayoutResizePanelProps) => react_jsx_runtime.JSX.Element;
|
|
72
|
+
|
|
73
|
+
type FlexLayoutSplitScreenProps = {
|
|
74
|
+
layoutName: string;
|
|
75
|
+
containerName: string;
|
|
76
|
+
children: ReactElement;
|
|
77
|
+
navigationTitle: string;
|
|
78
|
+
dropDocumentOutsideOption?: DropDocumentOutsideOption;
|
|
79
|
+
screenKey?: string;
|
|
80
|
+
};
|
|
81
|
+
declare function FlexLayoutSplitScreen({ children, containerName, layoutName, navigationTitle, dropDocumentOutsideOption, screenKey, }: FlexLayoutSplitScreenProps): react_jsx_runtime.JSX.Element;
|
|
82
|
+
declare namespace FlexLayoutSplitScreen {
|
|
83
|
+
var displayName: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface FlexLayoutSplitScreenScrollBoxProps extends HTMLAttributes<HTMLDivElement> {
|
|
87
|
+
keyName: string;
|
|
88
|
+
className?: string;
|
|
89
|
+
direction?: "x" | "y";
|
|
90
|
+
isDefaultScrollStyle?: boolean;
|
|
91
|
+
}
|
|
92
|
+
declare const _default: React$1.MemoExoticComponent<({ className, children, keyName, direction, isDefaultScrollStyle, ...props }: FlexLayoutSplitScreenScrollBoxProps) => react_jsx_runtime.JSX.Element>;
|
|
93
|
+
|
|
94
|
+
type Edge = 'auto' | 'top' | 'bottom' | 'left' | 'right';
|
|
95
|
+
interface FlexLayoutStickyBoxProps extends React__default.HTMLAttributes<HTMLDivElement> {
|
|
96
|
+
/** 어느 방향으로 붙일지. 기본은 'auto' (세로 스크롤이면 top, 가로 스크롤이면 left) */
|
|
97
|
+
edge?: Edge;
|
|
98
|
+
/** 화면 모서리와의 여백(px). 기본 16 */
|
|
99
|
+
offset?: number;
|
|
100
|
+
/** 스크롤 루트. 명시 안 하면 가장 흔한 케이스인 <main> → 없으면 window(=viewport) */
|
|
101
|
+
scrollRoot?: Element | null;
|
|
102
|
+
/** 디버그 보조선 표시 */
|
|
103
|
+
debug?: boolean;
|
|
104
|
+
/** 자식 */
|
|
105
|
+
children: React__default.ReactNode;
|
|
106
|
+
onTranslateChange?: (value: number, rootRef: React__default.RefObject<HTMLDivElement | null>, contentRef: React__default.RefObject<HTMLDivElement | null>) => void;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* FlexLayoutStickyBox
|
|
110
|
+
* 부모(실제 경계) 안에서만 움직이며, `transform`을 동적으로 부여해
|
|
111
|
+
* “sticky처럼 보이도록” 만든다.
|
|
112
|
+
*
|
|
113
|
+
* 구조:
|
|
114
|
+
* <div data-root> // 이 박스가 부모 경계 안에서 공간을 차지
|
|
115
|
+
* <div data-content> // 이 박스가 transform으로 부드럽게 움직임
|
|
116
|
+
* {children}
|
|
117
|
+
* </div>
|
|
118
|
+
* </div>
|
|
119
|
+
*/
|
|
120
|
+
declare const FlexLayoutStickyBox: React__default.FC<FlexLayoutStickyBoxProps>;
|
|
121
|
+
|
|
122
|
+
export { FlexLayout, FlexLayoutContainer, FlexLayoutResizePanel, FlexLayoutSplitScreen, _default as FlexLayoutSplitScreenScrollBox, FlexLayoutStickyBox };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FlexLayout_default as FlexLayout, FlexLayoutContainer_default as FlexLayoutContainer, FlexLayoutResizePanel_default as FlexLayoutResizePanel, FlexLayoutSplitScreen_default as FlexLayoutSplitScreen, FlexLayoutSplitScreenDragBox, FlexLayoutSplitScreenScrollBox_default as FlexLayoutSplitScreenScrollBox, FlexLayoutStickyBox_default as FlexLayoutStickyBox } from './chunk-UYI4Z27V.js';
|
|
2
|
+
import './chunk-PMTZFSP4.js';
|
|
3
|
+
import './chunk-JM3CZ5DU.js';
|
|
4
|
+
import './chunk-W4CNFJTK.js';
|
|
5
|
+
import './chunk-CFQQ6ZDC.js';
|
|
6
|
+
//# sourceMappingURL=components.js.map
|
|
7
|
+
//# sourceMappingURL=components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"components.js"}
|
package/dist/hooks.cjs
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var equal = require('fast-deep-equal');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var rxjs = require('rxjs');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var equal__default = /*#__PURE__*/_interopDefault(equal);
|
|
10
|
+
|
|
11
|
+
// src/flex-layout/hooks/useDrag.ts
|
|
12
|
+
|
|
13
|
+
// src/flex-layout/utils/FlexLayoutUtils.ts
|
|
14
|
+
var lastTouchEvent;
|
|
15
|
+
function getClientXy(event) {
|
|
16
|
+
let clientX;
|
|
17
|
+
let clientY;
|
|
18
|
+
if (window.MouseEvent && event instanceof window.MouseEvent) {
|
|
19
|
+
clientX = event.clientX;
|
|
20
|
+
clientY = event.clientY;
|
|
21
|
+
} else if (window.TouchEvent && event instanceof window.TouchEvent) {
|
|
22
|
+
const _event = event.touches.length == 0 ? lastTouchEvent : event;
|
|
23
|
+
clientX = _event.touches[0].clientX;
|
|
24
|
+
clientY = _event.touches[0].clientY;
|
|
25
|
+
lastTouchEvent = event;
|
|
26
|
+
} else {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return { clientX, clientY };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/flex-layout/hooks/useDrag.ts
|
|
33
|
+
var dragState = new rxjs.Subject();
|
|
34
|
+
var filterChildren = (obj) => {
|
|
35
|
+
const { children, ...rest } = obj || {};
|
|
36
|
+
return rest;
|
|
37
|
+
};
|
|
38
|
+
var useDragCapture = (targetRef) => {
|
|
39
|
+
const stateRef = react.useRef(null);
|
|
40
|
+
const forceUpdate = react.useRef(0);
|
|
41
|
+
react.useEffect(() => {
|
|
42
|
+
const subscription = dragState.pipe(
|
|
43
|
+
rxjs.map((value) => {
|
|
44
|
+
if (!targetRef || !targetRef.current) return null;
|
|
45
|
+
const { x, y } = value;
|
|
46
|
+
const rect = targetRef.current.getBoundingClientRect();
|
|
47
|
+
const {
|
|
48
|
+
width,
|
|
49
|
+
height,
|
|
50
|
+
x: rectX,
|
|
51
|
+
y: rectY,
|
|
52
|
+
right,
|
|
53
|
+
bottom
|
|
54
|
+
} = rect;
|
|
55
|
+
let isOver = false;
|
|
56
|
+
if (x < rectX || x > right || y < rectY || y > bottom) {
|
|
57
|
+
isOver = true;
|
|
58
|
+
}
|
|
59
|
+
const leftBoundary = rectX + width * 0.2;
|
|
60
|
+
const rightBoundary = right - width * 0.2;
|
|
61
|
+
const topBoundary = rectY + height * 0.2;
|
|
62
|
+
const bottomBoundary = bottom - height * 0.2;
|
|
63
|
+
let position = "centerBoundary";
|
|
64
|
+
if (x < leftBoundary) {
|
|
65
|
+
position = "leftBoundary";
|
|
66
|
+
} else if (x > rightBoundary) {
|
|
67
|
+
position = "rightBoundary";
|
|
68
|
+
} else if (y < topBoundary) {
|
|
69
|
+
position = "topBoundary";
|
|
70
|
+
} else if (y > bottomBoundary) {
|
|
71
|
+
position = "bottomBoundary";
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
positionName: position,
|
|
75
|
+
isOver,
|
|
76
|
+
...value
|
|
77
|
+
};
|
|
78
|
+
}),
|
|
79
|
+
rxjs.distinctUntilChanged(
|
|
80
|
+
(prev, curr) => equal__default.default(filterChildren(prev), filterChildren(curr))
|
|
81
|
+
)
|
|
82
|
+
).subscribe({
|
|
83
|
+
next: (value) => {
|
|
84
|
+
if (value && !equal__default.default(
|
|
85
|
+
filterChildren(stateRef.current),
|
|
86
|
+
filterChildren(value)
|
|
87
|
+
)) {
|
|
88
|
+
stateRef.current = value;
|
|
89
|
+
forceUpdate.current++;
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
error: (err) => console.error(err)
|
|
93
|
+
});
|
|
94
|
+
return () => subscription.unsubscribe();
|
|
95
|
+
}, [targetRef]);
|
|
96
|
+
const [, rerender] = react.useState({});
|
|
97
|
+
react.useEffect(() => {
|
|
98
|
+
const interval = setInterval(() => {
|
|
99
|
+
rerender({});
|
|
100
|
+
}, 50);
|
|
101
|
+
return () => clearInterval(interval);
|
|
102
|
+
}, []);
|
|
103
|
+
return stateRef.current;
|
|
104
|
+
};
|
|
105
|
+
var dropMovementEventSubject = new rxjs.Subject();
|
|
106
|
+
var allSplitScreenCount = new rxjs.BehaviorSubject(0);
|
|
107
|
+
var useDragEvents = ({
|
|
108
|
+
isBlockingActiveInput = false
|
|
109
|
+
}) => {
|
|
110
|
+
const dragResumeTimer = react.useRef(null);
|
|
111
|
+
const scrollThreshold = 10;
|
|
112
|
+
const isScrolling = react.useRef(false);
|
|
113
|
+
const isPending = react.useRef(false);
|
|
114
|
+
const isMouseDown = react.useRef(false);
|
|
115
|
+
const isDragging = react.useRef(false);
|
|
116
|
+
const touchStartX = react.useRef(0);
|
|
117
|
+
const touchStartY = react.useRef(0);
|
|
118
|
+
const handleStart = react.useCallback(
|
|
119
|
+
({
|
|
120
|
+
event: _event,
|
|
121
|
+
dragStartCallback
|
|
122
|
+
}) => {
|
|
123
|
+
const event = _event instanceof Event ? _event : _event.nativeEvent;
|
|
124
|
+
if (dragResumeTimer.current) {
|
|
125
|
+
clearTimeout(dragResumeTimer.current);
|
|
126
|
+
dragResumeTimer.current = null;
|
|
127
|
+
}
|
|
128
|
+
if (event.target.contentEditable === "true" || isBlockingActiveInput && document.activeElement === event.target) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (event.cancelable) {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
}
|
|
134
|
+
isPending.current = true;
|
|
135
|
+
isMouseDown.current = true;
|
|
136
|
+
if (event instanceof globalThis.TouchEvent) {
|
|
137
|
+
const touch = event.touches[0];
|
|
138
|
+
touchStartX.current = touch.clientX;
|
|
139
|
+
touchStartY.current = touch.clientY;
|
|
140
|
+
} else if (event instanceof globalThis.MouseEvent) {
|
|
141
|
+
touchStartX.current = event.clientX;
|
|
142
|
+
touchStartY.current = event.clientY;
|
|
143
|
+
}
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
if (!isPending.current || isScrolling.current) return;
|
|
146
|
+
isPending.current = false;
|
|
147
|
+
isDragging.current = true;
|
|
148
|
+
const xy = getClientXy(event);
|
|
149
|
+
if (!xy) return;
|
|
150
|
+
const { clientX, clientY } = xy;
|
|
151
|
+
dragStartCallback({ x: clientX, y: clientY });
|
|
152
|
+
}, 300);
|
|
153
|
+
},
|
|
154
|
+
[isBlockingActiveInput]
|
|
155
|
+
);
|
|
156
|
+
const handleMove = react.useCallback(
|
|
157
|
+
({
|
|
158
|
+
event: _event,
|
|
159
|
+
notDragCallback,
|
|
160
|
+
dragStartCallback,
|
|
161
|
+
moveingCallback
|
|
162
|
+
}) => {
|
|
163
|
+
if (!isMouseDown.current) return;
|
|
164
|
+
const event = _event instanceof Event ? _event : _event.nativeEvent;
|
|
165
|
+
const xy = getClientXy(event);
|
|
166
|
+
if (!xy) return;
|
|
167
|
+
const { clientX, clientY } = xy;
|
|
168
|
+
const deltaX = Math.abs(clientX - touchStartX.current);
|
|
169
|
+
const deltaY = Math.abs(clientY - touchStartY.current);
|
|
170
|
+
if (isPending.current && (deltaX > scrollThreshold || deltaY > scrollThreshold)) {
|
|
171
|
+
isScrolling.current = true;
|
|
172
|
+
isPending.current = false;
|
|
173
|
+
isDragging.current = false;
|
|
174
|
+
if (notDragCallback)
|
|
175
|
+
notDragCallback({ x: clientX, y: clientY });
|
|
176
|
+
if (dragResumeTimer.current) {
|
|
177
|
+
clearTimeout(dragResumeTimer.current);
|
|
178
|
+
dragResumeTimer.current = null;
|
|
179
|
+
}
|
|
180
|
+
dragResumeTimer.current = setTimeout(() => {
|
|
181
|
+
if (!isMouseDown.current) return;
|
|
182
|
+
if (dragStartCallback)
|
|
183
|
+
dragStartCallback({ x: clientX, y: clientY });
|
|
184
|
+
isPending.current = true;
|
|
185
|
+
isScrolling.current = false;
|
|
186
|
+
handleStart({ event: _event, dragStartCallback });
|
|
187
|
+
}, 400);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!isDragging.current || isPending.current) return;
|
|
191
|
+
moveingCallback({ x: clientX, y: clientY });
|
|
192
|
+
},
|
|
193
|
+
[isBlockingActiveInput]
|
|
194
|
+
);
|
|
195
|
+
const handleEnd = react.useCallback(
|
|
196
|
+
({
|
|
197
|
+
event: _event,
|
|
198
|
+
dragEndCallback
|
|
199
|
+
}) => {
|
|
200
|
+
isScrolling.current = false;
|
|
201
|
+
isMouseDown.current = false;
|
|
202
|
+
if (isPending.current) {
|
|
203
|
+
isPending.current = false;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const event = _event instanceof Event ? _event : _event.nativeEvent;
|
|
207
|
+
if (!isDragging.current) return;
|
|
208
|
+
isDragging.current = false;
|
|
209
|
+
const xy = getClientXy(event);
|
|
210
|
+
if (!xy) return;
|
|
211
|
+
const { clientX, clientY } = xy;
|
|
212
|
+
dragEndCallback({ x: clientX, y: clientY });
|
|
213
|
+
},
|
|
214
|
+
[isBlockingActiveInput]
|
|
215
|
+
);
|
|
216
|
+
return {
|
|
217
|
+
handleStart,
|
|
218
|
+
handleMove,
|
|
219
|
+
handleEnd
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
var folderEventSubject = new rxjs.Subject();
|
|
223
|
+
var setFolderEvent = (newValue) => {
|
|
224
|
+
folderEventSubject.next(newValue);
|
|
225
|
+
};
|
|
226
|
+
var useFolderEvent = () => {
|
|
227
|
+
const [folderEvent, setFolderEvent2] = react.useState(
|
|
228
|
+
null
|
|
229
|
+
);
|
|
230
|
+
react.useEffect(() => {
|
|
231
|
+
const subscription = folderEventSubject.subscribe((e) => {
|
|
232
|
+
if (!e) return;
|
|
233
|
+
setFolderEvent2(e);
|
|
234
|
+
});
|
|
235
|
+
return () => {
|
|
236
|
+
if (subscription) {
|
|
237
|
+
subscription.unsubscribe();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}, []);
|
|
241
|
+
return { folderEvent };
|
|
242
|
+
};
|
|
243
|
+
var useListPagingForSentinel = ({
|
|
244
|
+
//initPageNumber,
|
|
245
|
+
//initPageSize,
|
|
246
|
+
onReachTerminal
|
|
247
|
+
}) => {
|
|
248
|
+
const [firstChildNode, setFirstChildNode] = react.useState(null);
|
|
249
|
+
const [lastChildNode, setLastChildNode] = react.useState(null);
|
|
250
|
+
const observerRef = react.useRef(null);
|
|
251
|
+
const firstChildRef = react.useCallback((node) => {
|
|
252
|
+
setFirstChildNode(node);
|
|
253
|
+
}, []);
|
|
254
|
+
const lastChildRef = react.useCallback((node) => {
|
|
255
|
+
setLastChildNode(node);
|
|
256
|
+
}, []);
|
|
257
|
+
react.useEffect(() => {
|
|
258
|
+
if (firstChildNode && observerRef.current)
|
|
259
|
+
observerRef.current.unobserve(firstChildNode);
|
|
260
|
+
if (lastChildNode && observerRef.current)
|
|
261
|
+
observerRef.current.unobserve(lastChildNode);
|
|
262
|
+
const handleIntersect = (entries, observer2) => {
|
|
263
|
+
entries.forEach((entry) => {
|
|
264
|
+
if (entry.isIntersecting) {
|
|
265
|
+
if (entry.target === firstChildNode) {
|
|
266
|
+
if (onReachTerminal)
|
|
267
|
+
onReachTerminal({
|
|
268
|
+
isFirst: true,
|
|
269
|
+
isLast: false,
|
|
270
|
+
observer: observer2
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (entry.target === lastChildNode) {
|
|
274
|
+
if (onReachTerminal)
|
|
275
|
+
onReachTerminal({
|
|
276
|
+
isFirst: false,
|
|
277
|
+
isLast: true,
|
|
278
|
+
observer: observer2
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
const observer = new IntersectionObserver(handleIntersect, {
|
|
285
|
+
threshold: 0.1
|
|
286
|
+
});
|
|
287
|
+
observerRef.current = observer;
|
|
288
|
+
if (firstChildNode) observer.observe(firstChildNode);
|
|
289
|
+
if (lastChildNode) observer.observe(lastChildNode);
|
|
290
|
+
return () => {
|
|
291
|
+
if (observerRef.current) {
|
|
292
|
+
observerRef.current.disconnect();
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}, [firstChildNode, lastChildNode]);
|
|
296
|
+
return {
|
|
297
|
+
firstChildRef,
|
|
298
|
+
lastChildRef
|
|
299
|
+
};
|
|
300
|
+
};
|
|
301
|
+
var usePaginationViewNumber = ({
|
|
302
|
+
initPageNumber
|
|
303
|
+
}) => {
|
|
304
|
+
const [showCurrentPageNumber, setShowCurrentPageNumber] = react.useState(initPageNumber);
|
|
305
|
+
const observerRef = react.useRef(null);
|
|
306
|
+
const showCurrentPageObserveTarget = react.useCallback(
|
|
307
|
+
(node) => {
|
|
308
|
+
if (!node) return;
|
|
309
|
+
if (!observerRef.current) {
|
|
310
|
+
observerRef.current = new IntersectionObserver(
|
|
311
|
+
(entries) => {
|
|
312
|
+
entries.forEach((entry) => {
|
|
313
|
+
if (entry.isIntersecting) {
|
|
314
|
+
const pageIndexAttr = entry.target.getAttribute(
|
|
315
|
+
"data-page-index"
|
|
316
|
+
);
|
|
317
|
+
if (!pageIndexAttr) return;
|
|
318
|
+
const pageIndex = parseInt(pageIndexAttr, 10);
|
|
319
|
+
setShowCurrentPageNumber(pageIndex);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
threshold: 0.1
|
|
325
|
+
// 예: 10% 이상 보여야 intersect로 판단
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
observerRef.current.observe(node);
|
|
330
|
+
},
|
|
331
|
+
[]
|
|
332
|
+
);
|
|
333
|
+
react.useEffect(() => {
|
|
334
|
+
const currentObserver = observerRef.current;
|
|
335
|
+
return () => {
|
|
336
|
+
if (currentObserver) {
|
|
337
|
+
currentObserver.disconnect();
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}, []);
|
|
341
|
+
return {
|
|
342
|
+
showCurrentPageNumber,
|
|
343
|
+
showCurrentPageObserveTarget
|
|
344
|
+
};
|
|
345
|
+
};
|
|
346
|
+
var usePagingHandler = ({
|
|
347
|
+
lastCallPageNumber,
|
|
348
|
+
dataListRef
|
|
349
|
+
}) => {
|
|
350
|
+
const jumpingPageNumberRef = react.useRef(lastCallPageNumber);
|
|
351
|
+
react.useEffect(() => {
|
|
352
|
+
if (jumpingPageNumberRef.current) {
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
jumpingPageNumberRef.current = null;
|
|
355
|
+
}, 1e3);
|
|
356
|
+
}
|
|
357
|
+
}, [jumpingPageNumberRef]);
|
|
358
|
+
const paginationScrollIntoViewTarget = react.useRef({});
|
|
359
|
+
const pageNumberRef = react.useRef(lastCallPageNumber);
|
|
360
|
+
const setPaginationRef = react.useCallback(
|
|
361
|
+
(i) => (node) => {
|
|
362
|
+
if (!node) return;
|
|
363
|
+
paginationScrollIntoViewTarget.current[i] = node;
|
|
364
|
+
if (jumpingPageNumberRef.current !== null && i === jumpingPageNumberRef.current) {
|
|
365
|
+
node.scrollIntoView({
|
|
366
|
+
behavior: "instant",
|
|
367
|
+
// 필요한 경우 'smooth' 등으로 수정 가능
|
|
368
|
+
block: "start"
|
|
369
|
+
});
|
|
370
|
+
jumpingPageNumberRef.current = null;
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
[]
|
|
374
|
+
);
|
|
375
|
+
const handleReachTerminal = ({ isFirst, isLast, observer }, dataCallFetch) => {
|
|
376
|
+
if (dataListRef.current.length === 0) return;
|
|
377
|
+
if (jumpingPageNumberRef.current != null) return;
|
|
378
|
+
if (!isFirst && !isLast) return;
|
|
379
|
+
const callPageNumber = isFirst ? Math.max(pageNumberRef.current - 1, 0) : pageNumberRef.current + 1;
|
|
380
|
+
if (dataListRef.current[callPageNumber] != null && (dataListRef.current[callPageNumber]?.length || 0) > 0)
|
|
381
|
+
return;
|
|
382
|
+
jumpingPageNumberRef.current = callPageNumber;
|
|
383
|
+
setTimeout(() => {
|
|
384
|
+
jumpingPageNumberRef.current = null;
|
|
385
|
+
}, 1e3);
|
|
386
|
+
dataCallFetch(callPageNumber);
|
|
387
|
+
};
|
|
388
|
+
const handleClickPageChange = (page, dataCallFetch) => {
|
|
389
|
+
const pageData = dataListRef.current[page];
|
|
390
|
+
if (pageData != null && Array.isArray(pageData) && pageData.length > 0) {
|
|
391
|
+
paginationScrollIntoViewTarget.current[page]?.scrollIntoView({
|
|
392
|
+
behavior: "smooth",
|
|
393
|
+
block: "start"
|
|
394
|
+
});
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
jumpingPageNumberRef.current = page;
|
|
398
|
+
setTimeout(() => {
|
|
399
|
+
jumpingPageNumberRef.current = null;
|
|
400
|
+
}, 1e3);
|
|
401
|
+
dataCallFetch(page);
|
|
402
|
+
};
|
|
403
|
+
return {
|
|
404
|
+
jumpingPageNumberRef,
|
|
405
|
+
paginationScrollIntoViewTarget,
|
|
406
|
+
pageNumberRef,
|
|
407
|
+
setPaginationRef,
|
|
408
|
+
handleReachTerminal,
|
|
409
|
+
handleClickPageChange
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
exports.allSplitScreenCount = allSplitScreenCount;
|
|
414
|
+
exports.dragState = dragState;
|
|
415
|
+
exports.dropMovementEventSubject = dropMovementEventSubject;
|
|
416
|
+
exports.folderEventSubject = folderEventSubject;
|
|
417
|
+
exports.setFolderEvent = setFolderEvent;
|
|
418
|
+
exports.useDragCapture = useDragCapture;
|
|
419
|
+
exports.useDragEvents = useDragEvents;
|
|
420
|
+
exports.useFolderEvent = useFolderEvent;
|
|
421
|
+
exports.useListPagingForSentinel = useListPagingForSentinel;
|
|
422
|
+
exports.usePaginationViewNumber = usePaginationViewNumber;
|
|
423
|
+
exports.usePagingHandler = usePagingHandler;
|
|
424
|
+
//# sourceMappingURL=hooks.cjs.map
|
|
425
|
+
//# sourceMappingURL=hooks.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/flex-layout/utils/FlexLayoutUtils.ts","../src/flex-layout/hooks/useDrag.ts","../src/flex-layout/hooks/useListPaging.ts"],"names":["Subject","useRef","useEffect","map","distinctUntilChanged","equal","useState","BehaviorSubject","useCallback","setFolderEvent","observer"],"mappings":"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","file":"hooks.cjs","sourcesContent":["export function isDocumentOut({ x, y }: { x: number; y: number }) {\r\n if (typeof window == 'undefined') return;\r\n const { innerWidth, innerHeight, scrollX, scrollY } = window;\r\n\r\n return (\r\n x < 0 || y < 0 || x > innerWidth + scrollX || y > innerHeight + scrollY\r\n );\r\n}\r\n\r\nlet lastTouchEvent: globalThis.TouchEvent;\r\nexport function getClientXy(event: Event) {\r\n let clientX: number;\r\n let clientY: number;\r\n if (window.MouseEvent && event instanceof window.MouseEvent) {\r\n clientX = event.clientX;\r\n clientY = event.clientY;\r\n } else if (window.TouchEvent && event instanceof window.TouchEvent) {\r\n const _event = event.touches.length == 0 ? lastTouchEvent : event;\r\n clientX = _event!.touches[0].clientX;\r\n clientY = _event!.touches[0].clientY;\r\n lastTouchEvent = event;\r\n } else {\r\n return; // 해당 이벤트 타입이 MouseEvent나 TouchEvent가 아니라면 무시\r\n }\r\n return { clientX, clientY };\r\n}\r\n\r\nexport function isOverMove(elementSize: number, elementMinSize: number) {\r\n return (\r\n Math.floor(elementSize) <= 0 ||\r\n (isNaN(elementMinSize)\r\n ? false\r\n : elementMinSize >= Math.floor(elementSize))\r\n );\r\n}\r\n\r\nexport function findNotCloseFlexContent(\r\n target: HTMLElement | Element | null,\r\n direction: 'previousElementSibling' | 'nextElementSibling'\r\n) {\r\n if (!target) return target;\r\n let _target = target as HTMLElement;\r\n const isCloseCheck = () => {\r\n let grow =\r\n parseFloat(window.getComputedStyle(_target).flex.split(' ')[0]) ||\r\n 0;\r\n if (grow == 0) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n };\r\n while (isCloseCheck()) {\r\n let nextTarget = _target[direction]?.[direction];\r\n _target = nextTarget as HTMLElement;\r\n if (!_target) {\r\n break;\r\n }\r\n }\r\n return _target as HTMLElement | HTMLDivElement | null;\r\n}\r\n\r\nexport function remain(flexContainerList: Array<HTMLElement>) {\r\n return new Promise(resolve => {\r\n let notGrowList: Array<HTMLElement> = [];\r\n let totalGrow = flexContainerList.reduce((t, e, i) => {\r\n if (e.hasAttribute('data-grow') == false) {\r\n notGrowList.push(e);\r\n return t;\r\n }\r\n let grow = parseFloat(e.dataset.grow || '');\r\n e.style.flex = `${grow} 1 0%`;\r\n t -= grow;\r\n return t;\r\n }, flexContainerList.length);\r\n\r\n if (notGrowList.length != 0) {\r\n resize(notGrowList, totalGrow);\r\n }\r\n\r\n resolve(flexContainerList);\r\n });\r\n}\r\n\r\nexport function resize(list: Array<HTMLElement>, totalGrow: number) {\r\n return new Promise(resolve => {\r\n // totalGrow 값을 리스트의 개수로 나누어 균등 할당\r\n let resizeWeight = totalGrow / list.length;\r\n list.forEach(e => {\r\n e.dataset.grow = resizeWeight.toString();\r\n e.style.flex = `${resizeWeight} 1 0%`;\r\n });\r\n resolve(resizeWeight);\r\n });\r\n}\r\n\r\nexport function mathWeight(totalCount: number, totalGrow: number) {\r\n return 1 + (totalGrow - totalCount) / totalCount;\r\n}\r\nexport function mathGrow(\r\n childSize: number,\r\n parentSize: number,\r\n containerCount: number\r\n) {\r\n return containerCount * (childSize / parentSize);\r\n}\r\n\r\nexport function getGrow(growTarget: HTMLElement | Element) {\r\n const target =\r\n growTarget instanceof Element\r\n ? (growTarget as HTMLElement)\r\n : growTarget;\r\n return (\r\n parseFloat(target.style.flex.split(' ')[0]) ||\r\n parseFloat(target.dataset.grow || '')\r\n );\r\n}\r\n\r\nexport function closeFlex(\r\n resizeTarget: HTMLElement,\r\n containers: HTMLElement[],\r\n {\r\n isResize = false,\r\n isDsiabledResizePanel = false,\r\n sizeName,\r\n }: {\r\n isResize?: boolean;\r\n isDsiabledResizePanel?: boolean;\r\n sizeName: 'width' | 'height';\r\n }\r\n) {\r\n return new Promise(resolve => {\r\n if (!resizeTarget.hasAttribute('data-is_resize_panel')) {\r\n // resolve(resizeTarget);\r\n // return;\r\n } else if (isDsiabledResizePanel) {\r\n resizeTarget.dataset.is_resize_panel = 'false';\r\n }\r\n\r\n resizeTarget.dataset.prev_grow = getGrow(resizeTarget).toString();\r\n\r\n let notCloseList = containers.filter(\r\n e => e.style.flex != '0 1 0%' && e != resizeTarget\r\n );\r\n let notCloseAndOpenTargetList = [...notCloseList, resizeTarget];\r\n //let resizeWeight = this.mathWeight(notCloseList, this.#forResizeList.length);\r\n notCloseAndOpenTargetList.forEach(e => {\r\n e.style.transition = 'flex 0.5s';\r\n e.ontransitionend = event => {\r\n if (event.propertyName != 'flex-grow') {\r\n return;\r\n }\r\n notCloseAndOpenTargetList.forEach(\r\n e => (e.style.transition = '')\r\n );\r\n //e.style.transition = '';\r\n e.ontransitionend = () => {};\r\n };\r\n\r\n if (e == resizeTarget) {\r\n e.dataset.grow = '0';\r\n e.style.flex = `0 1 0%`;\r\n return;\r\n }\r\n\r\n if (isResize) {\r\n return;\r\n }\r\n\r\n let percent = getGrow(e) / containers.length;\r\n //let percentWeight = this.#forResizeList.length * percent;\r\n //let remainWeight = resizeWeight * percent;\r\n if (notCloseList.length == 1) {\r\n e.dataset.grow = containers.length.toString();\r\n e.style.flex = `${containers.length} 1 0%`;\r\n return;\r\n }\r\n e.dataset.grow = (containers.length * percent).toString();\r\n e.style.flex = `${containers.length * percent} 1 0%`;\r\n });\r\n\r\n if (isResize) {\r\n resize(notCloseList, containers.length);\r\n }\r\n\r\n resolve(resizeTarget);\r\n });\r\n}\r\n\r\nexport function openFlex(\r\n resizeTarget: HTMLElement,\r\n containers: HTMLElement[],\r\n {\r\n isPrevSizeOpen = false,\r\n isResize = false,\r\n openGrowImportant = 0,\r\n sizeName,\r\n }: {\r\n isPrevSizeOpen?: boolean;\r\n isResize?: boolean;\r\n openGrowImportant?: number;\r\n sizeName?: 'width' | 'height'; // 유니언 타입으로 수정\r\n }\r\n) {\r\n return new Promise(resolve => {\r\n if (!resizeTarget.hasAttribute('data-is_resize_panel')) {\r\n // resolve(resizeTarget);\r\n // return;\r\n } else if (\r\n resizeTarget.hasAttribute('data-is_resize_panel') &&\r\n resizeTarget.dataset.is_resize_panel == 'false'\r\n ) {\r\n resizeTarget.dataset.is_resize_panel = 'true';\r\n }\r\n\r\n let notCloseList = containers.filter(\r\n e => e.style.flex != '0 1 0%' && e != resizeTarget\r\n );\r\n let notCloseAndOpenTargetList = [...notCloseList, resizeTarget];\r\n //let resizeWeight = this.mathWeight(notCloseAndOpenTargetList, this.#forResizeList.length);\r\n let openTargetGrow = 1;\r\n const sizeStyleName = ('client' +\r\n sizeName!.charAt(0).toUpperCase() +\r\n sizeName!.substring(1)) as 'clientHeight' | 'clientWidth';\r\n const parentSize =\r\n (sizeName &&\r\n resizeTarget.parentElement &&\r\n resizeTarget.parentElement[sizeStyleName]) ||\r\n 0;\r\n if (isPrevSizeOpen && resizeTarget.hasAttribute('data-prev_grow')) {\r\n openTargetGrow =\r\n parseFloat(resizeTarget.dataset.prev_grow || '1') || 1;\r\n //resizeTarget.removeAttribute('data-prev_grow');\r\n } else if (parentSize && parentSize !== 0) {\r\n openTargetGrow =\r\n (parentSize / notCloseList.length / (parentSize - 1)) *\r\n containers.length;\r\n } else {\r\n openTargetGrow = 1;\r\n }\r\n if (openGrowImportant) {\r\n openTargetGrow = openGrowImportant;\r\n }\r\n openTargetGrow = openTargetGrow === Infinity ? 1 : openTargetGrow;\r\n //notCloseList.forEach(e=>{\r\n notCloseAndOpenTargetList.forEach(e => {\r\n e.style.transition = 'flex 0.5s';\r\n e.ontransitionend = event => {\r\n if (event.propertyName != 'flex-grow') {\r\n return;\r\n }\r\n notCloseAndOpenTargetList.forEach(\r\n e => (e.style.transition = '')\r\n );\r\n //e.style.transition = '';\r\n e.ontransitionend = () => {};\r\n };\r\n\r\n if (e == resizeTarget) {\r\n resizeTarget.dataset.grow = openTargetGrow.toString();\r\n resizeTarget.style.flex = `${openTargetGrow} 1 0%`;\r\n return;\r\n }\r\n\r\n if (isResize) {\r\n return;\r\n }\r\n\r\n let grow =\r\n (parentSize / notCloseList.length / (parentSize - 1)) *\r\n (containers.length - openTargetGrow);\r\n grow = grow === Infinity ? 1 : grow;\r\n //let percent = getGrow(e) / totalGrow - openTargetGrow / totalGrow;\r\n e.dataset.grow = grow.toString();\r\n\r\n e.style.flex = `${grow} 1 0%`;\r\n });\r\n\r\n if (isResize) {\r\n resize(notCloseAndOpenTargetList, containers.length);\r\n }\r\n\r\n resolve(openTargetGrow);\r\n });\r\n}\r\n","import equal from \"fast-deep-equal\";\r\nimport {\r\n\tReactElement,\r\n\tRefObject,\r\n\tuseCallback,\r\n\tuseEffect,\r\n\tuseRef,\r\n\tuseState,\r\n} from \"react\";\r\nimport { BehaviorSubject, distinctUntilChanged, map, Subject } from \"rxjs\";\r\nimport { DropDocumentOutsideOption } from \"../components/FlexLayoutSplitScreenDragBox\";\r\nimport { getClientXy } from \"../utils/FlexLayoutUtils\";\r\nexport interface DragStateType {\r\n\tisDragging: boolean;\r\n\tisDrop: boolean;\r\n\tnavigationTitle?: string;\r\n\tchildren?: ReactElement;\r\n\tcontainerName: string;\r\n\tx: number;\r\n\ty: number;\r\n\tdropDocumentOutsideOption?: DropDocumentOutsideOption;\r\n\tdropEndCallback?: ({\r\n\t\tx,\r\n\t\ty,\r\n\t\tcontainerName,\r\n\t}: {\r\n\t\tx: number;\r\n\t\ty: number;\r\n\t\tcontainerName: string;\r\n\t}) => void;\r\n\tscreenKey?: string;\r\n\tcustomData?: Record<string, string | number | boolean | undefined>;\r\n}\r\nexport type PositionName =\r\n\t| \"centerBoundary\"\r\n\t| \"leftBoundary\"\r\n\t| \"rightBoundary\"\r\n\t| \"topBoundary\"\r\n\t| \"bottomBoundary\";\r\n\r\nexport interface DragStateResultType extends DragStateType {\r\n\tpositionName: PositionName;\r\n\tisOver: boolean;\r\n}\r\nexport const dragState = new Subject<DragStateType>();\r\nconst filterChildren = (obj: any) => {\r\n\t// 객체 복사 후 children 속성 제거\r\n\tconst { children, ...rest } = obj || {};\r\n\treturn rest;\r\n};\r\n\r\nexport const useDragCapture = (targetRef: RefObject<HTMLElement | null>) => {\r\n\tconst stateRef = useRef<DragStateResultType | null>(null); // 상태를 저장하는 useRef\r\n\tconst forceUpdate = useRef(0); // 강제로 업데이트를 트리거하기 위한 변수\r\n\r\n\tuseEffect(() => {\r\n\t\tconst subscription = dragState\r\n\t\t\t.pipe(\r\n\t\t\t\tmap((value) => {\r\n\t\t\t\t\tif (!targetRef || !targetRef.current) return null;\r\n\r\n\t\t\t\t\tconst { x, y } = value;\r\n\t\t\t\t\tconst rect = targetRef.current.getBoundingClientRect();\r\n\t\t\t\t\tconst {\r\n\t\t\t\t\t\twidth,\r\n\t\t\t\t\t\theight,\r\n\t\t\t\t\t\tx: rectX,\r\n\t\t\t\t\t\ty: rectY,\r\n\t\t\t\t\t\tright,\r\n\t\t\t\t\t\tbottom,\r\n\t\t\t\t\t} = rect;\r\n\r\n\t\t\t\t\tlet isOver = false;\r\n\t\t\t\t\tif (x < rectX || x > right || y < rectY || y > bottom) {\r\n\t\t\t\t\t\tisOver = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst leftBoundary = rectX + width * 0.2;\r\n\t\t\t\t\tconst rightBoundary = right - width * 0.2;\r\n\t\t\t\t\tconst topBoundary = rectY + height * 0.2;\r\n\t\t\t\t\tconst bottomBoundary = bottom - height * 0.2;\r\n\r\n\t\t\t\t\tlet position = \"centerBoundary\";\r\n\t\t\t\t\tif (x < leftBoundary) {\r\n\t\t\t\t\t\tposition = \"leftBoundary\";\r\n\t\t\t\t\t} else if (x > rightBoundary) {\r\n\t\t\t\t\t\tposition = \"rightBoundary\";\r\n\t\t\t\t\t} else if (y < topBoundary) {\r\n\t\t\t\t\t\tposition = \"topBoundary\";\r\n\t\t\t\t\t} else if (y > bottomBoundary) {\r\n\t\t\t\t\t\tposition = \"bottomBoundary\";\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\tpositionName: position as PositionName,\r\n\t\t\t\t\t\tisOver,\r\n\t\t\t\t\t\t...value,\r\n\t\t\t\t\t};\r\n\t\t\t\t}),\r\n\t\t\t\tdistinctUntilChanged((prev, curr) =>\r\n\t\t\t\t\tequal(filterChildren(prev), filterChildren(curr)),\r\n\t\t\t\t),\r\n\t\t\t)\r\n\t\t\t.subscribe({\r\n\t\t\t\tnext: (value) => {\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tvalue &&\r\n\t\t\t\t\t\t!equal(\r\n\t\t\t\t\t\t\tfilterChildren(stateRef.current),\r\n\t\t\t\t\t\t\tfilterChildren(value),\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tstateRef.current = value; // 상태를 업데이트\r\n\t\t\t\t\t\tforceUpdate.current++; // 업데이트 트리거\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\terror: (err) => console.error(err),\r\n\t\t\t});\r\n\r\n\t\treturn () => subscription.unsubscribe();\r\n\t}, [targetRef]);\r\n\r\n\t// 강제 렌더링을 트리거하기 위한 업데이트\r\n\tconst [, rerender] = useState({});\r\n\tuseEffect(() => {\r\n\t\tconst interval = setInterval(() => {\r\n\t\t\trerender({}); // 변경된 ref 상태를 반영\r\n\t\t}, 50); // 50ms 간격으로 렌더링 반영\r\n\t\treturn () => clearInterval(interval);\r\n\t}, []);\r\n\r\n\treturn stateRef.current;\r\n};\r\nexport interface DropTargetComponent {\r\n\tcontainerName: string;\r\n\tcomponent: ReactElement;\r\n\tnavigationTitle?: string;\r\n\tdropDocumentOutsideOption?: DropDocumentOutsideOption;\r\n\tscreenKey: string;\r\n}\r\nexport type DropPositionOrderName = \"before\" | \"center\" | \"after\";\r\n\r\nexport interface DropMovementEventType {\r\n\tstate: \"remove\" | \"append\" | \"change\";\r\n\ttargetParentLayoutName: string;\r\n\ttargetLayoutName: string;\r\n\ttargetContainerName: string;\r\n\ttargetComponent?: ReactElement;\r\n\tnextContainerName?: string;\r\n\tparentOrderName?: DropPositionOrderName;\r\n\torderName?: DropPositionOrderName;\r\n\tx?: number;\r\n\ty?: number;\r\n\tdropEndCallback?: ({\r\n\t\tx,\r\n\t\ty,\r\n\t\tcontainerName,\r\n\t}: {\r\n\t\tx: number;\r\n\t\ty: number;\r\n\t\tcontainerName: string;\r\n\t}) => void;\r\n\tdropTargetComponentEvent?: DropTargetComponentEvent;\r\n}\r\nexport interface DropTargetComponentEvent extends Omit<\r\n\tDropTargetComponent,\r\n\t\"containerName\" | \"component\"\r\n> {\r\n\tdirection: \"row\" | \"column\";\r\n}\r\nexport const dropMovementEventSubject = new Subject<DropMovementEventType>();\r\n\r\nexport const allSplitScreenCount = new BehaviorSubject<number>(0);\r\n\r\nexport const useDragEvents = ({\r\n\tisBlockingActiveInput = false,\r\n}: {\r\n\tisBlockingActiveInput?: boolean;\r\n}) => {\r\n\tconst dragResumeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\tconst scrollThreshold = 10; // 이동 거리 임계값\r\n\r\n\tconst isScrolling = useRef<boolean>(false);\r\n\tconst isPending = useRef(false);\r\n\tconst isMouseDown = useRef(false);\r\n\tconst isDragging = useRef(false); // 드래그 상태 플래그\r\n\tconst touchStartX = useRef<number>(0);\r\n\tconst touchStartY = useRef<number>(0);\r\n\r\n\tconst handleStart = useCallback(\r\n\t\t({\r\n\t\t\tevent: _event,\r\n\t\t\tdragStartCallback,\r\n\t\t}: {\r\n\t\t\tevent: React.MouseEvent | React.TouchEvent | Event;\r\n\t\t\tdragStartCallback: ({ x, y }: { x: number; y: number }) => void;\r\n\t\t}) => {\r\n\t\t\tconst event = _event instanceof Event ? _event : _event.nativeEvent;\r\n\r\n\t\t\t// 기존 타이머가 있다면 정리\r\n\t\t\tif (dragResumeTimer.current) {\r\n\t\t\t\tclearTimeout(dragResumeTimer.current);\r\n\t\t\t\tdragResumeTimer.current = null;\r\n\t\t\t}\r\n\r\n\t\t\tif (\r\n\t\t\t\t(event.target as HTMLElement).contentEditable === \"true\" ||\r\n\t\t\t\t(isBlockingActiveInput &&\r\n\t\t\t\t\tdocument.activeElement === event.target)\r\n\t\t\t) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tif (event.cancelable) {\r\n\t\t\t\tevent.preventDefault(); // cancelable=false 면 자동 skip\r\n\t\t\t}\r\n\t\t\tisPending.current = true;\r\n\t\t\tisMouseDown.current = true;\r\n\t\t\tif (event instanceof globalThis.TouchEvent) {\r\n\t\t\t\tconst touch = event.touches[0];\r\n\t\t\t\ttouchStartX.current = touch.clientX;\r\n\t\t\t\ttouchStartY.current = touch.clientY;\r\n\t\t\t} else if (event instanceof globalThis.MouseEvent) {\r\n\t\t\t\ttouchStartX.current = event.clientX;\r\n\t\t\t\ttouchStartY.current = event.clientY;\r\n\t\t\t}\r\n\t\t\t//event.preventDefault();\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tif (!isPending.current || isScrolling.current) return; // 스크롤 중이면 드래그 취소\r\n\t\t\t\tisPending.current = false;\r\n\t\t\t\tisDragging.current = true;\r\n\r\n\t\t\t\tconst xy = getClientXy(event);\r\n\t\t\t\tif (!xy) return;\r\n\r\n\t\t\t\tconst { clientX, clientY } = xy;\r\n\r\n\t\t\t\tdragStartCallback({ x: clientX, y: clientY });\r\n\t\t\t}, 300);\r\n\t\t},\r\n\t\t[isBlockingActiveInput],\r\n\t);\r\n\r\n\tconst handleMove = useCallback(\r\n\t\t({\r\n\t\t\tevent: _event,\r\n\t\t\tnotDragCallback,\r\n\t\t\tdragStartCallback,\r\n\t\t\tmoveingCallback,\r\n\t\t}: {\r\n\t\t\tevent: React.MouseEvent | React.TouchEvent | Event;\r\n\t\t\tnotDragCallback?: ({ x, y }: { x: number; y: number }) => void;\r\n\t\t\tdragStartCallback: ({ x, y }: { x: number; y: number }) => void;\r\n\t\t\tmoveingCallback: ({ x, y }: { x: number; y: number }) => void;\r\n\t\t}) => {\r\n\t\t\tif (!isMouseDown.current) return;\r\n\t\t\tconst event = _event instanceof Event ? _event : _event.nativeEvent;\r\n\r\n\t\t\tconst xy = getClientXy(event);\r\n\t\t\tif (!xy) return;\r\n\t\t\tconst { clientX, clientY } = xy;\r\n\t\t\tconst deltaX = Math.abs(clientX - touchStartX.current);\r\n\t\t\tconst deltaY = Math.abs(clientY - touchStartY.current);\r\n\r\n\t\t\tif (\r\n\t\t\t\tisPending.current &&\r\n\t\t\t\t(deltaX > scrollThreshold || deltaY > scrollThreshold)\r\n\t\t\t) {\r\n\t\t\t\tisScrolling.current = true; // 스크롤 중으로 설정\r\n\t\t\t\tisPending.current = false; // 드래그 취소\r\n\t\t\t\tisDragging.current = false;\r\n\r\n\t\t\t\tif (notDragCallback)\r\n\t\t\t\t\tnotDragCallback({ x: clientX, y: clientY });\r\n\t\t\t\t//if (clonedNodeRef.current) clonedNodeRef.current.remove();\r\n\r\n\t\t\t\tif (dragResumeTimer.current) {\r\n\t\t\t\t\tclearTimeout(dragResumeTimer.current);\r\n\t\t\t\t\tdragResumeTimer.current = null;\r\n\t\t\t\t}\r\n\t\t\t\tdragResumeTimer.current = setTimeout(() => {\r\n\t\t\t\t\tif (!isMouseDown.current) return;\r\n\t\t\t\t\tif (dragStartCallback)\r\n\t\t\t\t\t\tdragStartCallback({ x: clientX, y: clientY });\r\n\t\t\t\t\tisPending.current = true;\r\n\t\t\t\t\tisScrolling.current = false;\r\n\t\t\t\t\thandleStart({ event: _event, dragStartCallback });\r\n\t\t\t\t}, 400);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (!isDragging.current || isPending.current) return; // 드래그 중이 아닐 경우 무시\r\n\r\n\t\t\tmoveingCallback({ x: clientX, y: clientY });\r\n\t\t},\r\n\t\t[isBlockingActiveInput],\r\n\t);\r\n\tconst handleEnd = useCallback(\r\n\t\t({\r\n\t\t\tevent: _event,\r\n\t\t\tdragEndCallback,\r\n\t\t}: {\r\n\t\t\tevent: React.MouseEvent | React.TouchEvent | Event;\r\n\t\t\tdragEndCallback: ({ x, y }: { x: number; y: number }) => void;\r\n\t\t}) => {\r\n\t\t\tisScrolling.current = false;\r\n\t\t\tisMouseDown.current = false;\r\n\t\t\tif (isPending.current) {\r\n\t\t\t\tisPending.current = false;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst event = _event instanceof Event ? _event : _event.nativeEvent;\r\n\r\n\t\t\tif (!isDragging.current) return; // 드래그 중이 아닐 경우 무시\r\n\r\n\t\t\tisDragging.current = false; // 드래그 종료\r\n\r\n\t\t\tconst xy = getClientXy(event);\r\n\t\t\tif (!xy) return;\r\n\r\n\t\t\tconst { clientX, clientY } = xy;\r\n\r\n\t\t\tdragEndCallback({ x: clientX, y: clientY });\r\n\t\t\t// const href = hrefUrlRef.current;\r\n\r\n\t\t\t// if (clonedNodeRef.current) clonedNodeRef.current.remove();\r\n\t\t\t// //console.log(clientX, clientY);\r\n\t\t\t// if (\r\n\t\t\t// dropDocumentOutsideOption &&\r\n\t\t\t// isDocumentOut({ x: clientX, y: clientY })\r\n\t\t\t// ) {\r\n\t\t\t// if (\r\n\t\t\t// dropDocumentOutsideOption.isNewTap ||\r\n\t\t\t// (!dropDocumentOutsideOption.widthRatio &&\r\n\t\t\t// !dropDocumentOutsideOption.heightRatio)\r\n\t\t\t// ) {\r\n\t\t\t// window.open(href, '_blank');\r\n\t\t\t// } else {\r\n\t\t\t// const width =\r\n\t\t\t// window.innerWidth *\r\n\t\t\t// (dropDocumentOutsideOption.widthRatio || 1);\r\n\t\t\t// const height =\r\n\t\t\t// window.innerHeight *\r\n\t\t\t// (dropDocumentOutsideOption.heightRatio || 1);\r\n\t\t\t// window.open(\r\n\t\t\t// href,\r\n\t\t\t// '_blank',\r\n\t\t\t// `width=${width},height=${height},left=${window.screenLeft - clientX * -1 - width},top=${window.screenTop + clientY}`\r\n\t\t\t// );\r\n\t\t\t// }\r\n\t\t\t// }\r\n\r\n\t\t\t// dragState.next({\r\n\t\t\t// isDragging: false,\r\n\t\t\t// isDrop: true,\r\n\t\t\t// navigationTitle,\r\n\t\t\t// children: targetComponent,\r\n\t\t\t// x: clientX,\r\n\t\t\t// y: clientY,\r\n\t\t\t// containerName,\r\n\t\t\t// dropDocumentOutsideOption,\r\n\t\t\t// dropEndCallback,\r\n\t\t\t// screenKey,\r\n\t\t\t// customData,\r\n\t\t\t// });\r\n\t\t\t//if (dropEndCallback) dropEndCallback({ x: clientX, y: clientY });\r\n\t\t},\r\n\t\t[isBlockingActiveInput],\r\n\t);\r\n\r\n\treturn {\r\n\t\thandleStart,\r\n\t\thandleMove,\r\n\t\thandleEnd,\r\n\t};\r\n};\r\n\r\nexport type FolderEventType = {\r\n\ttype: \"new\" | \"sort\" | \"title\" | \"delete\" | \"insert\" | \"update\" | \"next\";\r\n\tisFolder: boolean;\r\n\ttitle: string;\r\n\tsort?: number;\r\n\tparentId?: string;\r\n\tid?: string;\r\n\tnewData?: any;\r\n};\r\n\r\nexport const folderEventSubject = new Subject<FolderEventType>();\r\n\r\nexport const setFolderEvent = (newValue: FolderEventType) => {\r\n\tfolderEventSubject.next(newValue);\r\n};\r\n\r\nexport const useFolderEvent = () => {\r\n\tconst [folderEvent, setFolderEvent] = useState<FolderEventType | null>(\r\n\t\tnull,\r\n\t);\r\n\tuseEffect(() => {\r\n\t\tconst subscription = folderEventSubject.subscribe((e) => {\r\n\t\t\tif (!e) return;\r\n\t\t\tsetFolderEvent(e);\r\n\t\t});\r\n\r\n\t\treturn () => {\r\n\t\t\tif (subscription) {\r\n\t\t\t\tsubscription.unsubscribe();\r\n\t\t\t}\r\n\t\t};\r\n\t}, []);\r\n\r\n\treturn { folderEvent };\r\n};\r\n","import {\r\n MutableRefObject,\r\n RefObject,\r\n useCallback,\r\n useEffect,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\nexport type OnReachTerminalType = {\r\n isFirst: boolean;\r\n isLast: boolean;\r\n observer: IntersectionObserver;\r\n};\r\ninterface UseListPagingForInfinityProps {\r\n onReachTerminal?: (onReachTerminalData: OnReachTerminalType) => void;\r\n}\r\nexport const useListPagingForSentinel = <E extends HTMLElement>({\r\n //initPageNumber,\r\n //initPageSize,\r\n onReachTerminal,\r\n}: UseListPagingForInfinityProps): {\r\n firstChildRef: (node: E | null) => void;\r\n lastChildRef: (node: E | null) => void;\r\n //pageNumber: number;\r\n //pageSize: number;\r\n //setPageNumber: React.Dispatch<React.SetStateAction<number>>;\r\n //setPageSize: React.Dispatch<React.SetStateAction<number>>;\r\n} => {\r\n const [firstChildNode, setFirstChildNode] = useState<E | null>(null);\r\n const [lastChildNode, setLastChildNode] = useState<E | null>(null);\r\n const observerRef = useRef<IntersectionObserver | null>(null);\r\n\r\n const firstChildRef = useCallback((node: E | null) => {\r\n setFirstChildNode(node);\r\n }, []);\r\n\r\n const lastChildRef = useCallback((node: E | null) => {\r\n setLastChildNode(node);\r\n }, []);\r\n // 페이지 번호가 변경될 때마다 데이터 로드를 위한 콜백 호출\r\n\r\n useEffect(() => {\r\n if (firstChildNode && observerRef.current)\r\n observerRef.current.unobserve(firstChildNode);\r\n if (lastChildNode && observerRef.current)\r\n observerRef.current.unobserve(lastChildNode);\r\n const handleIntersect: IntersectionObserverCallback = (\r\n entries,\r\n observer\r\n ) => {\r\n entries.forEach(entry => {\r\n if (entry.isIntersecting) {\r\n if (entry.target === firstChildNode) {\r\n if (onReachTerminal)\r\n onReachTerminal({\r\n isFirst: true,\r\n isLast: false,\r\n observer,\r\n });\r\n }\r\n\r\n if (entry.target === lastChildNode) {\r\n if (onReachTerminal)\r\n onReachTerminal({\r\n isFirst: false,\r\n isLast: true,\r\n observer,\r\n });\r\n }\r\n }\r\n });\r\n };\r\n\r\n const observer = new IntersectionObserver(handleIntersect, {\r\n threshold: 0.1,\r\n });\r\n\r\n observerRef.current = observer;\r\n\r\n if (firstChildNode) observer.observe(firstChildNode);\r\n if (lastChildNode) observer.observe(lastChildNode);\r\n\r\n return () => {\r\n if (observerRef.current) {\r\n // if (firstChildNode)\r\n // observerRef.current.unobserve(firstChildNode);\r\n // if (lastChildNode) observerRef.current.unobserve(lastChildNode);\r\n observerRef.current.disconnect();\r\n }\r\n };\r\n }, [firstChildNode, lastChildNode]);\r\n\r\n return {\r\n firstChildRef,\r\n lastChildRef,\r\n };\r\n};\r\n\r\nexport const usePaginationViewNumber = ({\r\n initPageNumber,\r\n}: {\r\n initPageNumber: number;\r\n}) => {\r\n const [showCurrentPageNumber, setShowCurrentPageNumber] =\r\n useState<number>(initPageNumber);\r\n\r\n const observerRef = useRef<IntersectionObserver | null>(null);\r\n const showCurrentPageObserveTarget = useCallback(\r\n (node: HTMLElement | null) => {\r\n if (!node) return;\r\n\r\n // 아직 observer가 없으면 새로 생성\r\n if (!observerRef.current) {\r\n observerRef.current = new IntersectionObserver(\r\n entries => {\r\n entries.forEach(entry => {\r\n if (entry.isIntersecting) {\r\n const pageIndexAttr =\r\n entry.target.getAttribute(\r\n 'data-page-index'\r\n );\r\n if (!pageIndexAttr) return;\r\n // if (!entry.target.hasAttribute('data-is-first'))\r\n // return;\r\n const pageIndex = parseInt(pageIndexAttr, 10);\r\n setShowCurrentPageNumber(pageIndex);\r\n }\r\n });\r\n },\r\n {\r\n threshold: 0.1, // 예: 10% 이상 보여야 intersect로 판단\r\n }\r\n );\r\n }\r\n\r\n // 해당 노드를 관찰\r\n observerRef.current.observe(node);\r\n },\r\n []\r\n );\r\n useEffect(() => {\r\n const currentObserver = observerRef.current;\r\n return () => {\r\n if (currentObserver) {\r\n currentObserver.disconnect();\r\n }\r\n };\r\n }, []);\r\n return {\r\n showCurrentPageNumber,\r\n showCurrentPageObserveTarget,\r\n };\r\n};\r\n\r\nexport const usePagingHandler = <T>({\r\n lastCallPageNumber,\r\n dataListRef,\r\n}: {\r\n lastCallPageNumber: number;\r\n dataListRef: MutableRefObject<Array<T[] | null>>;\r\n}) => {\r\n const jumpingPageNumberRef = useRef<number | null>(lastCallPageNumber);\r\n useEffect(() => {\r\n if (jumpingPageNumberRef.current) {\r\n setTimeout(() => {\r\n jumpingPageNumberRef.current = null;\r\n }, 1000);\r\n }\r\n }, [jumpingPageNumberRef]);\r\n const paginationScrollIntoViewTarget = useRef<\r\n Record<number, HTMLDivElement | null>\r\n >({});\r\n const pageNumberRef = useRef<number>(lastCallPageNumber);\r\n\r\n const setPaginationRef = useCallback(\r\n (i: number) => (node: HTMLDivElement | null) => {\r\n if (!node) return;\r\n\r\n paginationScrollIntoViewTarget.current[i] = node;\r\n\r\n // jumpingPageNumberRef에 값이 있고, 그 값이 현재 i와 같으면 스크롤\r\n if (\r\n jumpingPageNumberRef.current !== null &&\r\n i === jumpingPageNumberRef.current\r\n ) {\r\n node.scrollIntoView({\r\n behavior: 'instant', // 필요한 경우 'smooth' 등으로 수정 가능\r\n block: 'start',\r\n });\r\n jumpingPageNumberRef.current = null;\r\n }\r\n },\r\n []\r\n );\r\n\r\n //스크롤이 “첫 아이템” 혹은 “마지막 아이템”에 닿을 때 호출\r\n const handleReachTerminal = (\r\n { isFirst, isLast, observer }: OnReachTerminalType,\r\n dataCallFetch: (callPageNumber: number) => void\r\n ) => {\r\n // 이미 다른 페이지로 점프 중이면, 중복 호출 방지\r\n if (dataListRef.current.length === 0) return;\r\n if (jumpingPageNumberRef.current != null) return;\r\n if (!isFirst && !isLast) return;\r\n\r\n const callPageNumber = isFirst\r\n ? Math.max(pageNumberRef.current - 1, 0)\r\n : pageNumberRef.current + 1;\r\n\r\n if (\r\n dataListRef.current[callPageNumber] != null &&\r\n (dataListRef.current[callPageNumber]?.length || 0) > 0\r\n )\r\n return;\r\n jumpingPageNumberRef.current = callPageNumber;\r\n setTimeout(() => {\r\n jumpingPageNumberRef.current = null;\r\n }, 1000);\r\n dataCallFetch(callPageNumber);\r\n };\r\n\r\n //페이지네이션에서 페이지 번호를 직접 클릭했을 시\r\n const handleClickPageChange = (\r\n page: number,\r\n dataCallFetch: (callPageNumber: number) => void\r\n ) => {\r\n // PaginationLayer는 1-based, 내부 로직은 0-based\r\n // 이미 캐싱된 페이지가 있다면, 스크롤만 이동\r\n const pageData = dataListRef.current[page];\r\n\r\n // 이미 캐싱된 페이지가 있다면, 스크롤만 이동\r\n if (\r\n pageData != null &&\r\n Array.isArray(pageData) &&\r\n pageData.length > 0\r\n ) {\r\n paginationScrollIntoViewTarget.current[page]?.scrollIntoView({\r\n behavior: 'smooth',\r\n block: 'start',\r\n });\r\n return;\r\n }\r\n jumpingPageNumberRef.current = page;\r\n setTimeout(() => {\r\n jumpingPageNumberRef.current = null;\r\n }, 1000);\r\n dataCallFetch(page);\r\n };\r\n return {\r\n jumpingPageNumberRef,\r\n paginationScrollIntoViewTarget,\r\n pageNumberRef,\r\n setPaginationRef,\r\n handleReachTerminal,\r\n handleClickPageChange,\r\n };\r\n};\r\n"]}
|