@cntrl-site/sdk-nextjs 1.9.77 → 1.9.79

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 (145) hide show
  1. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/sdk-nextjs.iml +12 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/LICENSE +21 -21
  6. package/README.md +4 -4
  7. package/TODO.md +1 -1
  8. package/eslint.config.mjs +35 -35
  9. package/jest.config.js +6 -6
  10. package/lib/common/useItemFXData.js +5 -5
  11. package/lib/components/Article.js +5 -5
  12. package/lib/components/LayoutStyle.js +4 -4
  13. package/lib/components/Section/Section.js +27 -27
  14. package/lib/components/StructuredBlockItem/StructuredBlockItem.js +13 -13
  15. package/lib/components/StructuredBlockItem/StructuredComponent/StructuredComponent.js +12 -12
  16. package/lib/components/StructuredContent/StructuredContent.js +11 -11
  17. package/lib/components/items/CodeEmbedItem/CodeEmbedItem.js +36 -36
  18. package/lib/components/items/ComponentItem/ComponentItem.js +13 -13
  19. package/lib/components/items/CompoundItem/CompoundChild.js +20 -20
  20. package/lib/components/items/CompoundItem/CompoundItem.js +14 -14
  21. package/lib/components/items/CustomItem/CustomItem.js +9 -9
  22. package/lib/components/items/EmbedVideoItem/VimeoEmbed.js +24 -24
  23. package/lib/components/items/EmbedVideoItem/YoutubeEmbed.js +27 -27
  24. package/lib/components/items/FileItem/ImageItem.js +40 -40
  25. package/lib/components/items/FileItem/VideoItem.js +64 -64
  26. package/lib/components/items/GroupItem/GroupItem.js +14 -14
  27. package/lib/components/items/Item.js +30 -30
  28. package/lib/components/items/RectangleItem/RectangleItem.js +27 -27
  29. package/lib/components/items/RichTextItem/RichTextItem.js +22 -22
  30. package/lib/utils/RichTextConverter/RichTextConverter.js +21 -21
  31. package/package.json +62 -62
  32. package/src/ItemGeometry/CSSPropertyNameMap.ts +37 -37
  33. package/src/ItemGeometry/GenericGeometryController.ts +59 -59
  34. package/src/ItemGeometry/ItemGeometryContext.ts +4 -4
  35. package/src/ItemGeometry/ItemGeometryController.ts +22 -22
  36. package/src/ItemGeometry/ItemGeometryService.ts +34 -34
  37. package/src/ItemGeometry/RichTextGeometryController.ts +166 -166
  38. package/src/ItemGeometry/useItemGeometry.ts +25 -25
  39. package/src/common/useCurrentLayout.ts +52 -52
  40. package/src/common/useExemplary.ts +9 -9
  41. package/src/common/useItemFXData.ts +63 -63
  42. package/src/common/useKeyframeValue.ts +85 -85
  43. package/src/common/useRegisterResize.ts +16 -16
  44. package/src/components/Article.tsx +69 -69
  45. package/src/components/ArticleWrapper.tsx +21 -21
  46. package/src/components/Head.tsx +95 -95
  47. package/src/components/LayoutStyle.tsx +21 -21
  48. package/src/components/Page.tsx +47 -47
  49. package/src/components/ScrollPlaybackVideo.tsx +75 -75
  50. package/src/components/Section/Section.tsx +162 -162
  51. package/src/components/Section/SectionImage.tsx +48 -48
  52. package/src/components/Section/SectionVideo.tsx +144 -144
  53. package/src/components/Section/useSectionColor.ts +19 -19
  54. package/src/components/Section/useSectionHeightMap.ts +19 -19
  55. package/src/components/StructuredBlockItem/StructuredBlockItem.tsx +69 -69
  56. package/src/components/StructuredBlockItem/StructuredComponent/StructuredComponent.tsx +66 -66
  57. package/src/components/StructuredContent/StructuredContent.tsx +42 -42
  58. package/src/components/items/CodeEmbedItem/CodeEmbedItem.tsx +148 -148
  59. package/src/components/items/CodeEmbedItem/useCodeEmbedItem.ts +36 -36
  60. package/src/components/items/ComponentItem/ComponentItem.tsx +85 -85
  61. package/src/components/items/ComponentItem/useComponentItem.ts +35 -35
  62. package/src/components/items/CompoundItem/CompoundChild.tsx +151 -151
  63. package/src/components/items/CompoundItem/CompoundItem.tsx +88 -88
  64. package/src/components/items/CompoundItem/useCompoundItem.ts +21 -21
  65. package/src/components/items/CustomItem/CustomItem.tsx +50 -50
  66. package/src/components/items/EmbedVideoItem/VimeoEmbed.tsx +217 -217
  67. package/src/components/items/EmbedVideoItem/YoutubeEmbed.tsx +201 -201
  68. package/src/components/items/EmbedVideoItem/useEmbedVideoItem.ts +46 -46
  69. package/src/components/items/FileItem/ImageItem.tsx +166 -166
  70. package/src/components/items/FileItem/VideoItem.tsx +287 -287
  71. package/src/components/items/FileItem/useFileItem.ts +81 -81
  72. package/src/components/items/GroupItem/GroupItem.tsx +99 -99
  73. package/src/components/items/GroupItem/useGroupItem.ts +34 -34
  74. package/src/components/items/Item.tsx +268 -268
  75. package/src/components/items/LinkWrapper.tsx +39 -39
  76. package/src/components/items/RectangleItem/RectangleItem.tsx +177 -177
  77. package/src/components/items/RectangleItem/useRectangleItem.ts +89 -89
  78. package/src/components/items/RichTextItem/RichTextItem.tsx +113 -113
  79. package/src/components/items/RichTextItem/useRichTextItem.ts +12 -12
  80. package/src/components/items/RichTextWrapper.tsx +15 -15
  81. package/src/components/items/itemsMap.ts +28 -28
  82. package/src/components/items/useDraggable.ts +252 -252
  83. package/src/components/items/useItemAngle.ts +13 -13
  84. package/src/components/items/useItemArea.ts +35 -35
  85. package/src/components/items/useItemPointerEvents.ts +23 -23
  86. package/src/components/items/useItemScale.ts +17 -17
  87. package/src/components/items/useItemTriggers.ts +15 -15
  88. package/src/components/items/useRichTextItemValues.ts +66 -66
  89. package/src/components/items/useSizing.ts +25 -25
  90. package/src/components/items/useStickyItemTop.ts +21 -21
  91. package/src/components/useLayoutContext.ts +7 -7
  92. package/src/index.ts +25 -25
  93. package/src/interactions/InteractionsRegistry.ts +513 -513
  94. package/src/interactions/ItemInteractionCtrl.ts +78 -78
  95. package/src/interactions/getTransition.ts +27 -27
  96. package/src/interactions/types.ts +36 -36
  97. package/src/interactions/useItemInteractionCtrl.ts +18 -18
  98. package/src/provider/ArticleRectContext.ts +4 -4
  99. package/src/provider/CntrlContext.ts +5 -5
  100. package/src/provider/CntrlProvider.tsx +11 -11
  101. package/src/provider/CntrlSdkContext.ts +113 -113
  102. package/src/provider/CustomItemRegistry.ts +14 -14
  103. package/src/provider/CustomItemTypes.ts +3 -3
  104. package/src/provider/CustomSectionRegistry.ts +25 -25
  105. package/src/provider/InteractionsContext.tsx +73 -73
  106. package/src/provider/Keyframes.ts +11 -11
  107. package/src/provider/KeyframesContext.ts +5 -5
  108. package/src/provider/LayoutContext.ts +3 -3
  109. package/src/provider/WebGLContextManagerContext.tsx +4 -4
  110. package/src/provider/defaultContext.ts +8 -8
  111. package/src/provider/useCntrlContext.ts +8 -8
  112. package/src/styled-jsx.d.ts +1 -1
  113. package/src/types/components-utils.d.ts +7 -7
  114. package/src/utils/Animator/Animator.ts +570 -570
  115. package/src/utils/ArticleRectManager/ArticleRectObserver.ts +93 -93
  116. package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -17
  117. package/src/utils/ArticleRectManager/useSectionRegistry.ts +11 -11
  118. package/src/utils/CSSNumeric.ts +19 -19
  119. package/src/utils/EventEmitter.ts +41 -41
  120. package/src/utils/RichTextConverter/RichTextConverter.tsx +342 -342
  121. package/src/utils/ScaleAnchorMap.ts +13 -13
  122. package/src/utils/StickyManager/StickyManager.ts +23 -23
  123. package/src/utils/Youtube/YouTubeIframeApiLoader.ts +58 -58
  124. package/src/utils/Youtube/YoutubeIframeApi.ts +101 -101
  125. package/src/utils/Youtube/useYouTubeIframeApi.ts +12 -12
  126. package/src/utils/areFillsVisible/areFillsVisible.test.ts +63 -63
  127. package/src/utils/areFillsVisible/areFillsVisible.ts +37 -37
  128. package/src/utils/binSearchInsertAt.ts +33 -33
  129. package/src/utils/castObject.ts +10 -10
  130. package/src/utils/checkOverflowClipSupport.ts +13 -13
  131. package/src/utils/domDfs.ts +11 -11
  132. package/src/utils/effects/useImageFx.ts +154 -154
  133. package/src/utils/effects/useVideoFx.ts +156 -156
  134. package/src/utils/evaluateComponentBundle.ts +83 -83
  135. package/src/utils/getAnchoredItemTop.ts +12 -12
  136. package/src/utils/getCompoundBoundaryStyles.ts +60 -60
  137. package/src/utils/getFill.ts +46 -46
  138. package/src/utils/getFontFamilyValue.ts +3 -3
  139. package/src/utils/getInvertedRanges.ts +43 -43
  140. package/src/utils/getItemTopStyle.ts +39 -39
  141. package/src/utils/getStyleFromItemStateAndParams.ts +8 -8
  142. package/src/utils/getValidYoutubeUrl.ts +29 -29
  143. package/src/utils/isItemType.ts +5 -5
  144. package/src/utils/rangeMap.ts +13 -13
  145. package/src/utils/useElementRect.ts +23 -23
@@ -1,252 +1,252 @@
1
- import {
2
- Dispatch,
3
- SetStateAction,
4
- useCallback,
5
- useEffect,
6
- useRef
7
- } from 'react';
8
-
9
- const INITIAL_STATE: DragState = {
10
- drag: false,
11
- startX: 0,
12
- startY: 0,
13
- currentX: 0,
14
- currentY: 0,
15
- pivotX: 0,
16
- pivotY: 0,
17
- lastX: 0,
18
- lastY: 0
19
- };
20
-
21
- export function useDraggable(
22
- data: {
23
- draggableRef: HTMLElement | null | undefined,
24
- isEnabled: boolean
25
- },
26
- dragHandler?: DragHandler,
27
- preventDragOnChildren: boolean = false,
28
- ) {
29
- const dragStateRef = useRef<DragState>(INITIAL_STATE);
30
- const prevDragStateRef = useRef<DragState | undefined>();
31
- const dragHandlerRef = useRef<DragHandler | undefined>();
32
- const untrackMouseMoveRef = useRef<(() => void) | undefined>();
33
- const animationFrameRef = useRef<number | undefined>();
34
- dragHandlerRef.current = dragHandler;
35
-
36
- const setDragState = useCallback<Dispatch<SetStateAction<DragState>>>(
37
- action => {
38
- const state = isStateGetter<DragState>(action)
39
- ? action(dragStateRef.current)
40
- : action;
41
- if (!prevDragStateRef.current) {
42
- prevDragStateRef.current = dragStateRef.current;
43
- }
44
- dragStateRef.current = state;
45
- if (animationFrameRef.current !== undefined) return;
46
- animationFrameRef.current = window.requestAnimationFrame(() => {
47
- animationFrameRef.current = undefined;
48
- dragHandlerRef.current?.(
49
- dragStateRef.current,
50
- prevDragStateRef.current
51
- );
52
- prevDragStateRef.current = dragStateRef.current;
53
- });
54
- },
55
- []
56
- );
57
-
58
- const handleMouseMove = useCallback<EventHandler<MouseEvent>>(
59
- event => {
60
- event.stopPropagation();
61
- const el = event.target;
62
- if (!(el instanceof HTMLElement)) return;
63
- setDragState(state => {
64
- if (!state.drag) {
65
- const clientRect = el.getBoundingClientRect();
66
- return {
67
- drag: true,
68
- startX: event.clientX,
69
- startY: event.clientY,
70
- currentX: event.clientX,
71
- currentY: event.clientY,
72
- pivotX: event.clientX - clientRect.x,
73
- pivotY: event.clientY - clientRect.y,
74
- lastX: state.lastX,
75
- lastY: state.lastY
76
- };
77
- }
78
- return {
79
- ...state,
80
- currentX: state.currentX + event.movementX,
81
- currentY: state.currentY + event.movementY
82
- };
83
- });
84
- },
85
- [setDragState, data.draggableRef, preventDragOnChildren]
86
- );
87
-
88
- const handleMouseUp = useCallback<EventHandler<MouseEvent>>(
89
- event => {
90
- event.stopPropagation();
91
- setDragState(state => ({
92
- ...state,
93
- drag: false,
94
- lastX: state.currentX - state.startX + state.lastX,
95
- lastY: state.currentY - state.startY + state.lastY
96
- }));
97
- untrackMouseMoveRef.current?.();
98
- },
99
- [setDragState]
100
- );
101
-
102
- const handleScroll = useCallback<EventHandler<Event>>(() => {
103
- setDragState(state => state);
104
- }, [setDragState]);
105
-
106
- const trackMouseMove = useCallback(() => {
107
- window.addEventListener('mousemove', handleMouseMove, { capture: true });
108
- window.addEventListener('mouseup', handleMouseUp, { capture: true });
109
- window.addEventListener('scroll', handleScroll, { capture: true, passive: true });
110
- return () => {
111
- window.removeEventListener('mousemove', handleMouseMove, { capture: true });
112
- window.removeEventListener('mouseup', handleMouseUp, { capture: true });
113
- window.removeEventListener('scroll', handleScroll, { capture: true });
114
- };
115
- }, [handleMouseMove, handleMouseUp, handleScroll]);
116
-
117
- const handleMouseDown = useCallback<EventHandler<MouseEvent>>(
118
- event => {
119
- event.stopPropagation();
120
- if (preventDragOnChildren && event.target instanceof Node && data.draggableRef instanceof Node) {
121
- if (event.target !== data.draggableRef && data.draggableRef.contains(event.target)) return;
122
- }
123
- if (event.button !== 0) return;
124
- untrackMouseMoveRef.current?.();
125
- untrackMouseMoveRef.current = trackMouseMove();
126
- },
127
- [trackMouseMove]
128
- );
129
-
130
- const handleTouchMove = useCallback<EventHandler<TouchEvent>>(
131
- event => {
132
- event.stopPropagation();
133
- event.preventDefault();
134
- const touch = event.touches[0];
135
- const el = event.target;
136
- if (!(el instanceof HTMLElement)) return;
137
-
138
- setDragState(state => {
139
- if (!state.drag) {
140
- const clientRect = el.getBoundingClientRect();
141
- return {
142
- drag: true,
143
- startX: touch.clientX,
144
- startY: touch.clientY,
145
- currentX: touch.clientX,
146
- currentY: touch.clientY,
147
- pivotX: touch.clientX - clientRect.x,
148
- pivotY: touch.clientY - clientRect.y,
149
- lastX: state.lastX,
150
- lastY: state.lastY
151
- };
152
- }
153
-
154
- const movementX = touch.clientX - state.currentX;
155
- const movementY = touch.clientY - state.currentY;
156
-
157
- return {
158
- ...state,
159
- currentX: state.currentX + movementX,
160
- currentY: state.currentY + movementY
161
- };
162
- });
163
- },
164
- [setDragState]
165
- );
166
-
167
- const handleTouchEnd = useCallback<EventHandler<TouchEvent>>(
168
- event => {
169
- event.stopPropagation();
170
- document.body.style.overflow = '';
171
- document.documentElement.style.overflow = '';
172
- setDragState(state => ({
173
- ...state,
174
- drag: false,
175
- lastX: state.currentX - state.startX + state.lastX,
176
- lastY: state.currentY - state.startY + state.lastY
177
- }));
178
- untrackMouseMoveRef.current?.();
179
- },
180
- [setDragState]
181
- );
182
-
183
- const trackTouchMove = useCallback(() => {
184
- window.addEventListener('touchmove', handleTouchMove, { capture: true, passive: false });
185
- window.addEventListener('touchend', handleTouchEnd, { capture: true });
186
- window.addEventListener('touchcancel', handleTouchEnd, { capture: true });
187
- return () => {
188
- window.removeEventListener('touchmove', handleTouchMove, { capture: true });
189
- window.removeEventListener('touchend', handleTouchEnd, { capture: true });
190
- window.removeEventListener('touchcancel', handleTouchEnd, { capture: true });
191
- };
192
- }, [handleTouchMove, handleTouchEnd]);
193
-
194
- const handleTouchStart = useCallback<EventHandler<TouchEvent>>(
195
- event => {
196
- event.stopPropagation();
197
- if (preventDragOnChildren && event.target instanceof Node && data.draggableRef instanceof Node) {
198
- if (event.target !== data.draggableRef && data.draggableRef.contains(event.target)) return;
199
- }
200
- document.body.style.overflow = 'hidden';
201
- document.documentElement.style.overflow = 'hidden';
202
- const selection = document.getSelection();
203
- if (selection) {
204
- selection.removeAllRanges();
205
- }
206
- untrackMouseMoveRef.current?.();
207
- untrackMouseMoveRef.current = trackTouchMove();
208
- },
209
- [trackTouchMove]
210
- );
211
-
212
- useEffect(() => {
213
- if (!data.draggableRef || !data.isEnabled) return;
214
- const mouseHandler = handleMouseDown;
215
- const touchHandler = handleTouchStart;
216
-
217
- data.draggableRef.addEventListener('mousedown', mouseHandler);
218
- data.draggableRef.addEventListener('touchstart', touchHandler);
219
-
220
- return () => {
221
- data.draggableRef?.removeEventListener('mousedown', mouseHandler);
222
- data.draggableRef?.removeEventListener('touchstart', touchHandler);
223
- untrackMouseMoveRef.current?.();
224
- if (animationFrameRef.current !== undefined) {
225
- window.cancelAnimationFrame(animationFrameRef.current);
226
- }
227
- document.body.style.overflow = '';
228
- document.documentElement.style.overflow = '';
229
- };
230
- }, [data.draggableRef, data.isEnabled, handleMouseDown, handleTouchStart]);
231
- }
232
-
233
- interface DragState {
234
- drag: boolean;
235
- startX: number;
236
- startY: number;
237
- currentX: number;
238
- currentY: number;
239
- pivotX: number;
240
- pivotY: number;
241
- lastX: number;
242
- lastY: number;
243
- }
244
-
245
- type EventHandler<E extends Event> = (event: E) => void;
246
- type DragHandler = (state: DragState, prevState?: DragState) => void;
247
-
248
- function isStateGetter<T>(
249
- action: SetStateAction<T>
250
- ): action is (prevState: T) => T {
251
- return typeof action === 'function';
252
- }
1
+ import {
2
+ Dispatch,
3
+ SetStateAction,
4
+ useCallback,
5
+ useEffect,
6
+ useRef
7
+ } from 'react';
8
+
9
+ const INITIAL_STATE: DragState = {
10
+ drag: false,
11
+ startX: 0,
12
+ startY: 0,
13
+ currentX: 0,
14
+ currentY: 0,
15
+ pivotX: 0,
16
+ pivotY: 0,
17
+ lastX: 0,
18
+ lastY: 0
19
+ };
20
+
21
+ export function useDraggable(
22
+ data: {
23
+ draggableRef: HTMLElement | null | undefined,
24
+ isEnabled: boolean
25
+ },
26
+ dragHandler?: DragHandler,
27
+ preventDragOnChildren: boolean = false,
28
+ ) {
29
+ const dragStateRef = useRef<DragState>(INITIAL_STATE);
30
+ const prevDragStateRef = useRef<DragState | undefined>();
31
+ const dragHandlerRef = useRef<DragHandler | undefined>();
32
+ const untrackMouseMoveRef = useRef<(() => void) | undefined>();
33
+ const animationFrameRef = useRef<number | undefined>();
34
+ dragHandlerRef.current = dragHandler;
35
+
36
+ const setDragState = useCallback<Dispatch<SetStateAction<DragState>>>(
37
+ action => {
38
+ const state = isStateGetter<DragState>(action)
39
+ ? action(dragStateRef.current)
40
+ : action;
41
+ if (!prevDragStateRef.current) {
42
+ prevDragStateRef.current = dragStateRef.current;
43
+ }
44
+ dragStateRef.current = state;
45
+ if (animationFrameRef.current !== undefined) return;
46
+ animationFrameRef.current = window.requestAnimationFrame(() => {
47
+ animationFrameRef.current = undefined;
48
+ dragHandlerRef.current?.(
49
+ dragStateRef.current,
50
+ prevDragStateRef.current
51
+ );
52
+ prevDragStateRef.current = dragStateRef.current;
53
+ });
54
+ },
55
+ []
56
+ );
57
+
58
+ const handleMouseMove = useCallback<EventHandler<MouseEvent>>(
59
+ event => {
60
+ event.stopPropagation();
61
+ const el = event.target;
62
+ if (!(el instanceof HTMLElement)) return;
63
+ setDragState(state => {
64
+ if (!state.drag) {
65
+ const clientRect = el.getBoundingClientRect();
66
+ return {
67
+ drag: true,
68
+ startX: event.clientX,
69
+ startY: event.clientY,
70
+ currentX: event.clientX,
71
+ currentY: event.clientY,
72
+ pivotX: event.clientX - clientRect.x,
73
+ pivotY: event.clientY - clientRect.y,
74
+ lastX: state.lastX,
75
+ lastY: state.lastY
76
+ };
77
+ }
78
+ return {
79
+ ...state,
80
+ currentX: state.currentX + event.movementX,
81
+ currentY: state.currentY + event.movementY
82
+ };
83
+ });
84
+ },
85
+ [setDragState, data.draggableRef, preventDragOnChildren]
86
+ );
87
+
88
+ const handleMouseUp = useCallback<EventHandler<MouseEvent>>(
89
+ event => {
90
+ event.stopPropagation();
91
+ setDragState(state => ({
92
+ ...state,
93
+ drag: false,
94
+ lastX: state.currentX - state.startX + state.lastX,
95
+ lastY: state.currentY - state.startY + state.lastY
96
+ }));
97
+ untrackMouseMoveRef.current?.();
98
+ },
99
+ [setDragState]
100
+ );
101
+
102
+ const handleScroll = useCallback<EventHandler<Event>>(() => {
103
+ setDragState(state => state);
104
+ }, [setDragState]);
105
+
106
+ const trackMouseMove = useCallback(() => {
107
+ window.addEventListener('mousemove', handleMouseMove, { capture: true });
108
+ window.addEventListener('mouseup', handleMouseUp, { capture: true });
109
+ window.addEventListener('scroll', handleScroll, { capture: true, passive: true });
110
+ return () => {
111
+ window.removeEventListener('mousemove', handleMouseMove, { capture: true });
112
+ window.removeEventListener('mouseup', handleMouseUp, { capture: true });
113
+ window.removeEventListener('scroll', handleScroll, { capture: true });
114
+ };
115
+ }, [handleMouseMove, handleMouseUp, handleScroll]);
116
+
117
+ const handleMouseDown = useCallback<EventHandler<MouseEvent>>(
118
+ event => {
119
+ event.stopPropagation();
120
+ if (preventDragOnChildren && event.target instanceof Node && data.draggableRef instanceof Node) {
121
+ if (event.target !== data.draggableRef && data.draggableRef.contains(event.target)) return;
122
+ }
123
+ if (event.button !== 0) return;
124
+ untrackMouseMoveRef.current?.();
125
+ untrackMouseMoveRef.current = trackMouseMove();
126
+ },
127
+ [trackMouseMove]
128
+ );
129
+
130
+ const handleTouchMove = useCallback<EventHandler<TouchEvent>>(
131
+ event => {
132
+ event.stopPropagation();
133
+ event.preventDefault();
134
+ const touch = event.touches[0];
135
+ const el = event.target;
136
+ if (!(el instanceof HTMLElement)) return;
137
+
138
+ setDragState(state => {
139
+ if (!state.drag) {
140
+ const clientRect = el.getBoundingClientRect();
141
+ return {
142
+ drag: true,
143
+ startX: touch.clientX,
144
+ startY: touch.clientY,
145
+ currentX: touch.clientX,
146
+ currentY: touch.clientY,
147
+ pivotX: touch.clientX - clientRect.x,
148
+ pivotY: touch.clientY - clientRect.y,
149
+ lastX: state.lastX,
150
+ lastY: state.lastY
151
+ };
152
+ }
153
+
154
+ const movementX = touch.clientX - state.currentX;
155
+ const movementY = touch.clientY - state.currentY;
156
+
157
+ return {
158
+ ...state,
159
+ currentX: state.currentX + movementX,
160
+ currentY: state.currentY + movementY
161
+ };
162
+ });
163
+ },
164
+ [setDragState]
165
+ );
166
+
167
+ const handleTouchEnd = useCallback<EventHandler<TouchEvent>>(
168
+ event => {
169
+ event.stopPropagation();
170
+ document.body.style.overflow = '';
171
+ document.documentElement.style.overflow = '';
172
+ setDragState(state => ({
173
+ ...state,
174
+ drag: false,
175
+ lastX: state.currentX - state.startX + state.lastX,
176
+ lastY: state.currentY - state.startY + state.lastY
177
+ }));
178
+ untrackMouseMoveRef.current?.();
179
+ },
180
+ [setDragState]
181
+ );
182
+
183
+ const trackTouchMove = useCallback(() => {
184
+ window.addEventListener('touchmove', handleTouchMove, { capture: true, passive: false });
185
+ window.addEventListener('touchend', handleTouchEnd, { capture: true });
186
+ window.addEventListener('touchcancel', handleTouchEnd, { capture: true });
187
+ return () => {
188
+ window.removeEventListener('touchmove', handleTouchMove, { capture: true });
189
+ window.removeEventListener('touchend', handleTouchEnd, { capture: true });
190
+ window.removeEventListener('touchcancel', handleTouchEnd, { capture: true });
191
+ };
192
+ }, [handleTouchMove, handleTouchEnd]);
193
+
194
+ const handleTouchStart = useCallback<EventHandler<TouchEvent>>(
195
+ event => {
196
+ event.stopPropagation();
197
+ if (preventDragOnChildren && event.target instanceof Node && data.draggableRef instanceof Node) {
198
+ if (event.target !== data.draggableRef && data.draggableRef.contains(event.target)) return;
199
+ }
200
+ document.body.style.overflow = 'hidden';
201
+ document.documentElement.style.overflow = 'hidden';
202
+ const selection = document.getSelection();
203
+ if (selection) {
204
+ selection.removeAllRanges();
205
+ }
206
+ untrackMouseMoveRef.current?.();
207
+ untrackMouseMoveRef.current = trackTouchMove();
208
+ },
209
+ [trackTouchMove]
210
+ );
211
+
212
+ useEffect(() => {
213
+ if (!data.draggableRef || !data.isEnabled) return;
214
+ const mouseHandler = handleMouseDown;
215
+ const touchHandler = handleTouchStart;
216
+
217
+ data.draggableRef.addEventListener('mousedown', mouseHandler);
218
+ data.draggableRef.addEventListener('touchstart', touchHandler);
219
+
220
+ return () => {
221
+ data.draggableRef?.removeEventListener('mousedown', mouseHandler);
222
+ data.draggableRef?.removeEventListener('touchstart', touchHandler);
223
+ untrackMouseMoveRef.current?.();
224
+ if (animationFrameRef.current !== undefined) {
225
+ window.cancelAnimationFrame(animationFrameRef.current);
226
+ }
227
+ document.body.style.overflow = '';
228
+ document.documentElement.style.overflow = '';
229
+ };
230
+ }, [data.draggableRef, data.isEnabled, handleMouseDown, handleTouchStart]);
231
+ }
232
+
233
+ interface DragState {
234
+ drag: boolean;
235
+ startX: number;
236
+ startY: number;
237
+ currentX: number;
238
+ currentY: number;
239
+ pivotX: number;
240
+ pivotY: number;
241
+ lastX: number;
242
+ lastY: number;
243
+ }
244
+
245
+ type EventHandler<E extends Event> = (event: E) => void;
246
+ type DragHandler = (state: DragState, prevState?: DragState) => void;
247
+
248
+ function isStateGetter<T>(
249
+ action: SetStateAction<T>
250
+ ): action is (prevState: T) => T {
251
+ return typeof action === 'function';
252
+ }
@@ -1,13 +1,13 @@
1
- import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../../common/useKeyframeValue';
3
-
4
- export const useItemAngle = (item: ItemAny, sectionId: string) => {
5
- const angle = useKeyframeValue(
6
- item,
7
- KeyframeType.Rotation,
8
- (item, layoutId) => layoutId ? item.area[layoutId].angle : undefined,
9
- (animator, scroll, value) => value !== undefined ? animator.getRotation({ angle: value }, scroll).angle : undefined,
10
- sectionId
11
- );
12
- return angle;
13
- };
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+
4
+ export const useItemAngle = (item: ItemAny, sectionId: string) => {
5
+ const angle = useKeyframeValue(
6
+ item,
7
+ KeyframeType.Rotation,
8
+ (item, layoutId) => layoutId ? item.area[layoutId].angle : undefined,
9
+ (animator, scroll, value) => value !== undefined ? animator.getRotation({ angle: value }, scroll).angle : undefined,
10
+ sectionId
11
+ );
12
+ return angle;
13
+ };
@@ -1,35 +1,35 @@
1
- import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
- import { useLayoutContext } from '../useLayoutContext';
3
- import { useKeyframeValue } from '../../common/useKeyframeValue';
4
-
5
- export function useItemArea(
6
- item: ItemAny,
7
- sectionId: string,
8
- stateValues: { top?: number; left?: number; width?: number; height?: number }
9
- ) {
10
- const layoutId = useLayoutContext();
11
- const position = useKeyframeValue<{ top: number; left: number } | undefined>(
12
- item,
13
- KeyframeType.Position,
14
- (item, layoutId) => {
15
- if (!layoutId) return;
16
- return item.area[layoutId];
17
- },
18
- (animator, scroll, value) => value ? animator.getPositions(value, scroll) : undefined,
19
- sectionId,
20
- [layoutId]
21
- );
22
- const dimensions = useKeyframeValue<{ width: number; height: number } | undefined>(
23
- item,
24
- KeyframeType.Dimensions,
25
- (item, layoutId) => layoutId ? item.area[layoutId] : undefined,
26
- (animator, scroll, value) => value ? animator.getDimensions(value, scroll) : undefined,
27
- sectionId,
28
- [layoutId]
29
- );
30
- const width = (stateValues.width ?? dimensions?.width) as number | undefined;
31
- const height = (stateValues.height ?? dimensions?.height) as number | undefined;
32
- const top = (stateValues.top ?? position?.top) as number | undefined;
33
- const left = (stateValues.left ?? position?.left) as number | undefined;
34
- return { width, height, top, left };
35
- }
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
+ import { useLayoutContext } from '../useLayoutContext';
3
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
4
+
5
+ export function useItemArea(
6
+ item: ItemAny,
7
+ sectionId: string,
8
+ stateValues: { top?: number; left?: number; width?: number; height?: number }
9
+ ) {
10
+ const layoutId = useLayoutContext();
11
+ const position = useKeyframeValue<{ top: number; left: number } | undefined>(
12
+ item,
13
+ KeyframeType.Position,
14
+ (item, layoutId) => {
15
+ if (!layoutId) return;
16
+ return item.area[layoutId];
17
+ },
18
+ (animator, scroll, value) => value ? animator.getPositions(value, scroll) : undefined,
19
+ sectionId,
20
+ [layoutId]
21
+ );
22
+ const dimensions = useKeyframeValue<{ width: number; height: number } | undefined>(
23
+ item,
24
+ KeyframeType.Dimensions,
25
+ (item, layoutId) => layoutId ? item.area[layoutId] : undefined,
26
+ (animator, scroll, value) => value ? animator.getDimensions(value, scroll) : undefined,
27
+ sectionId,
28
+ [layoutId]
29
+ );
30
+ const width = (stateValues.width ?? dimensions?.width) as number | undefined;
31
+ const height = (stateValues.height ?? dimensions?.height) as number | undefined;
32
+ const top = (stateValues.top ?? position?.top) as number | undefined;
33
+ const left = (stateValues.left ?? position?.left) as number | undefined;
34
+ return { width, height, top, left };
35
+ }
@@ -1,23 +1,23 @@
1
- import { useCallback, useState } from 'react';
2
-
3
- export function useItemPointerEvents(
4
- pointerEvents: 'never' | 'when_visible' | 'always',
5
- isParentVisible: boolean
6
- ) {
7
- const getAllowPointerEvents = () => {
8
- switch (pointerEvents) {
9
- case 'never':
10
- return false;
11
- case 'when_visible':
12
- return isParentVisible;
13
- case 'always':
14
- return true;
15
- }
16
- };
17
- const [allowPointerEvents, setAllowPointerEvents] = useState<boolean>(getAllowPointerEvents());
18
- const handleVisibilityChange = useCallback((isVisible: boolean) => {
19
- if (!isParentVisible || pointerEvents !== 'when_visible') return;
20
- setAllowPointerEvents(isVisible);
21
- }, [isParentVisible, pointerEvents]);
22
- return { allowPointerEvents, handleVisibilityChange };
23
- }
1
+ import { useCallback, useState } from 'react';
2
+
3
+ export function useItemPointerEvents(
4
+ pointerEvents: 'never' | 'when_visible' | 'always',
5
+ isParentVisible: boolean
6
+ ) {
7
+ const getAllowPointerEvents = () => {
8
+ switch (pointerEvents) {
9
+ case 'never':
10
+ return false;
11
+ case 'when_visible':
12
+ return isParentVisible;
13
+ case 'always':
14
+ return true;
15
+ }
16
+ };
17
+ const [allowPointerEvents, setAllowPointerEvents] = useState<boolean>(getAllowPointerEvents());
18
+ const handleVisibilityChange = useCallback((isVisible: boolean) => {
19
+ if (!isParentVisible || pointerEvents !== 'when_visible') return;
20
+ setAllowPointerEvents(isVisible);
21
+ }, [isParentVisible, pointerEvents]);
22
+ return { allowPointerEvents, handleVisibilityChange };
23
+ }