@gem-sdk/pages 1.24.11 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,732 @@
1
+ import { memo, useRef, useCallback, useEffect } from 'react';
2
+
3
+ const TOOLBAR_HOVER_HEIGHT = 24;
4
+ const TOOLBAR_ACTIVE_HEIGHT = 32;
5
+ const Toolbar = ()=>{
6
+ const currentComponentActive = useRef(null);
7
+ const isDragging = useRef(false);
8
+ const stopWatchReRenderComponent = useRef();
9
+ const isResizeSpacing = useRef(false);
10
+ /* Functions */ const changePositionToolbar = ({ state, $toolbar, $component })=>{
11
+ const $parentOverflow = findOverflowParent($component, $toolbar);
12
+ if ($parentOverflow) {
13
+ const rect = $component.getBoundingClientRect();
14
+ if (rect?.height <= 60) {
15
+ $toolbar.setAttribute(`data-toolbar-${state}-revert`, 'true');
16
+ } else {
17
+ $toolbar.setAttribute(`data-toolbar-${state}-inside`, 'true');
18
+ }
19
+ } else {
20
+ const rectComponent = $component.getBoundingClientRect();
21
+ if (rectComponent.top < TOOLBAR_ACTIVE_HEIGHT + 1) {
22
+ if (rectComponent?.height <= 60) {
23
+ $toolbar.setAttribute(`data-toolbar-${state}-revert`, 'true');
24
+ } else {
25
+ $toolbar.setAttribute(`data-toolbar-${state}-inside`, 'true');
26
+ }
27
+ }
28
+ }
29
+ };
30
+ const setHoverComponent = useCallback(({ $component, componentUid, focus, isThemeSection })=>{
31
+ if (!$component && !componentUid) return;
32
+ if (!$component) {
33
+ const $c = document.querySelector(`[data-uid="${componentUid}"]`);
34
+ if (!$c) return;
35
+ $component = $c;
36
+ }
37
+ if (!componentUid) {
38
+ const cUid = $component.getAttribute('data-uid');
39
+ if (!cUid) return;
40
+ componentUid = cUid;
41
+ }
42
+ const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
43
+ const $outline = getChildrenByAttrSelector($component, 'data-outline');
44
+ const $btnAddTop = getChildrenByAttrSelector($component, 'data-toolbar-add-top');
45
+ const $btnAddBottom = getChildrenByAttrSelector($component, 'data-toolbar-add-bottom');
46
+ const $themeSectionStatus = getChildrenByAttrSelector($component, 'data-theme-section-status');
47
+ if (isThemeSection && $themeSectionStatus) {
48
+ $themeSectionStatus.setAttribute('data-theme-section-status-active', 'true');
49
+ }
50
+ if ($toolbar) {
51
+ $toolbar.removeAttribute('style');
52
+ $toolbar.setAttribute('data-toolbar-hover', 'true');
53
+ if (focus) {
54
+ $toolbar.setAttribute('data-toolbar-hover-focus', 'true');
55
+ }
56
+ changePositionToolbar({
57
+ $toolbar,
58
+ $component,
59
+ state: 'hover'
60
+ });
61
+ }
62
+ if ($outline) {
63
+ $outline.setAttribute('data-outline-hover', 'true');
64
+ if (isThemeSection) {
65
+ $outline.setAttribute('data-outline-overlay-theme-section', 'true');
66
+ }
67
+ if (focus) {
68
+ $outline.setAttribute('data-outline-hover-focus', 'true');
69
+ }
70
+ }
71
+ if ($btnAddTop) {
72
+ $btnAddTop.setAttribute('data-toolbar-add-hover', 'true');
73
+ }
74
+ if ($btnAddBottom) {
75
+ $btnAddBottom.setAttribute('data-toolbar-add-hover', 'true');
76
+ }
77
+ }, []);
78
+ const setHoverComponentParents = useCallback(({ $component, componentUid })=>{
79
+ if (!$component) {
80
+ const $c = document.querySelector(`[data-uid="${componentUid}"]`);
81
+ if (!$c) return;
82
+ $component = $c;
83
+ }
84
+ const $parents = getDOMElementParents($component, '[data-uid][data-component-type="component"]:not([data-component-no-setting])');
85
+ if ($parents.length) {
86
+ for (const $parent of $parents){
87
+ if ($parent) {
88
+ setHoverComponent({
89
+ $component: $parent
90
+ });
91
+ }
92
+ }
93
+ changePositionToolbarParents({
94
+ $component,
95
+ $parents
96
+ });
97
+ }
98
+ }, [
99
+ setHoverComponent
100
+ ]);
101
+ const changePositionToolbarParents = ({ $component, $parents })=>{
102
+ if (!$component) return;
103
+ if (!$parents?.length) return;
104
+ const $currentToolbar = getChildrenByAttrSelector($component, 'data-toolbar-hover-focus');
105
+ if ($currentToolbar) {
106
+ const currentRect = $currentToolbar.getBoundingClientRect();
107
+ const isRevert = $currentToolbar.getAttribute('data-toolbar-hover-revert') ? true : false;
108
+ const isInside = $currentToolbar.getAttribute('data-toolbar-hover-inside') ? true : false;
109
+ let index = 1;
110
+ for (const $parent of $parents){
111
+ if ($parent) {
112
+ const tag = $parent.getAttribute('data-component-tag');
113
+ if (tag === 'Section') continue;
114
+ const $toolbar = getChildrenByAttrSelector($parent, 'data-toolbar-hover');
115
+ if ($toolbar) {
116
+ // Ignore with toolbar active
117
+ const isActive = $toolbar.getAttribute('data-toolbar-active');
118
+ if (isActive) continue;
119
+ // Start calc
120
+ const parentRect = $toolbar.getBoundingClientRect();
121
+ const checkRevert = isRevert || isInside;
122
+ if (isOverParent({
123
+ current: currentRect,
124
+ parent: parentRect,
125
+ index,
126
+ revert: checkRevert
127
+ })) {
128
+ const parentStyle = getComputedStyle($toolbar);
129
+ // parentStyle.top
130
+ const diffTop = currentRect.top - parentRect.top;
131
+ const diffLeft = currentRect.left - parentRect.left;
132
+ let newTop = parseFloat(parentStyle.top) + diffTop - (TOOLBAR_HOVER_HEIGHT - 1) * index; // -1 border bottom
133
+ if (checkRevert) {
134
+ newTop = parseFloat(parentStyle.top) - diffTop + (TOOLBAR_HOVER_HEIGHT - 1) * index; // -1 border bottom
135
+ }
136
+ const newLeft = parseFloat(parentStyle.left) + diffLeft;
137
+ $toolbar.setAttribute('style', `top: ${newTop}px;left: ${newLeft}px;`);
138
+ index++;
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ };
145
+ const removeHoverOverlayComponent = useCallback(()=>{
146
+ const clearAttrs = [
147
+ 'data-outline-overlay',
148
+ 'data-outline-overlay-theme-section',
149
+ 'data-theme-section-status-active'
150
+ ];
151
+ const $elms = document.querySelectorAll(clearAttrs.map((attr)=>`[${attr}]`).join(','));
152
+ if ($elms) {
153
+ clearAttrs.forEach((attr)=>{
154
+ $elms.forEach(($el)=>$el.removeAttribute(attr));
155
+ });
156
+ }
157
+ }, []);
158
+ const removeHoverComponent = useCallback(()=>{
159
+ const clearAttrs = [
160
+ 'data-toolbar-hover-focus',
161
+ 'data-toolbar-hover',
162
+ 'data-outline-hover-focus',
163
+ 'data-toolbar-hover-revert',
164
+ 'data-toolbar-hover-inside',
165
+ 'data-outline-hover',
166
+ 'data-toolbar-add-hover'
167
+ ];
168
+ const $elms = document.querySelectorAll(clearAttrs.map((attr)=>`[${attr}]`).join(','));
169
+ if ($elms) {
170
+ clearAttrs.forEach((attr)=>{
171
+ $elms.forEach(($el)=>$el.removeAttribute(attr));
172
+ });
173
+ }
174
+ removeHoverOverlayComponent();
175
+ }, [
176
+ removeHoverOverlayComponent
177
+ ]);
178
+ const removeActiveComponent = useCallback(()=>{
179
+ currentComponentActive.current = null;
180
+ const clearAttrs = [
181
+ 'data-toolbar-active',
182
+ 'data-outline-active',
183
+ 'data-toolbar-add-active',
184
+ 'data-toolbar-active-revert',
185
+ 'data-toolbar-active-inside',
186
+ 'data-spacing-margin-bottom-active',
187
+ 'data-toolbar-force-hover',
188
+ 'data-outline-force-hover'
189
+ ];
190
+ const $elms = document.querySelectorAll(clearAttrs.map((attr)=>`[${attr}]`).join(','));
191
+ if ($elms) {
192
+ clearAttrs.forEach((attr)=>{
193
+ $elms.forEach(($el)=>$el.removeAttribute(attr));
194
+ });
195
+ }
196
+ setFocusTextEditor(false);
197
+ if (stopWatchReRenderComponent.current) stopWatchReRenderComponent.current();
198
+ }, []);
199
+ const watchComponentReRender = ($el, callback)=>{
200
+ // editor:component:render
201
+ const onComponentReRender = (e)=>{
202
+ const detail = e.detail;
203
+ if (detail?.componentUid == currentComponentActive.current?.componentUid) {
204
+ callback();
205
+ }
206
+ };
207
+ window.removeEventListener('editor:component:render', onComponentReRender);
208
+ window.addEventListener('editor:component:render', onComponentReRender);
209
+ const $images = $el.querySelectorAll('img');
210
+ if ($images?.length) {
211
+ $images.forEach(($img)=>{
212
+ $img.addEventListener('load', ()=>{
213
+ callback();
214
+ });
215
+ });
216
+ }
217
+ stopWatchReRenderComponent.current = ()=>{
218
+ window.removeEventListener('editor:component:render', onComponentReRender);
219
+ };
220
+ };
221
+ const setActiveComponentSpacing = useCallback(({ $component })=>{
222
+ if (!$component) return;
223
+ const style = getComputedStyle($component);
224
+ const $spacing = getChildrenByAttrSelector($component, 'data-spacing');
225
+ const $marginBottom = ($spacing?.querySelector('[data-spacing-margin-bottom]')) || null;
226
+ if ($marginBottom) {
227
+ const $bg = $marginBottom.querySelector('[data-spacing-margin-bottom-bg]') || null;
228
+ const $drag = $marginBottom.querySelector('[data-spacing-margin-bottom-drag]') || null;
229
+ if ($bg && $drag) {
230
+ const value = style.marginBottom;
231
+ $bg.style.height = value;
232
+ $drag.style.top = value;
233
+ $marginBottom.setAttribute('data-spacing-margin-bottom-active', 'true');
234
+ }
235
+ }
236
+ }, []);
237
+ const setActiveComponentForceHoverSection = useCallback(($component, value)=>{
238
+ const $section = $component.closest('[data-toolbar-wrap][data-component-tag="Section"]');
239
+ if ($section) {
240
+ if (value) {
241
+ const $toolbar = getChildrenByAttrSelector($section, 'data-toolbar');
242
+ const $outline = getChildrenByAttrSelector($section, 'data-outline');
243
+ if ($toolbar) {
244
+ $toolbar.setAttribute('data-toolbar-force-hover', 'true');
245
+ changePositionToolbar({
246
+ $toolbar,
247
+ $component,
248
+ state: 'hover'
249
+ });
250
+ }
251
+ if ($outline) {
252
+ $outline.setAttribute('data-outline-force-hover', 'true');
253
+ }
254
+ } else {
255
+ const $toolbar = getChildrenByAttrSelector($section, 'data-toolbar');
256
+ const $outline = getChildrenByAttrSelector($section, 'data-outline');
257
+ if ($toolbar) {
258
+ $toolbar.removeAttribute('data-toolbar-force-hover');
259
+ }
260
+ if ($outline) {
261
+ $outline.removeAttribute('data-outline-force-hover');
262
+ }
263
+ }
264
+ }
265
+ }, []);
266
+ const setActiveComponent = useCallback(async ({ componentUid, productId, timeAwait = 500, forceReActive })=>{
267
+ if (!componentUid) return;
268
+ let $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, timeAwait);
269
+ // check element fetch data: product, product list
270
+ if (!$component) {
271
+ const isLoading = document.querySelector(`.gp-loading-placeholder`);
272
+ if (!isLoading) {
273
+ return;
274
+ }
275
+ if (isLoading) {
276
+ // await element onload
277
+ $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, 15000);
278
+ }
279
+ }
280
+ if (!$component) {
281
+ return;
282
+ }
283
+ if (!forceReActive && componentUid == currentComponentActive.current?.componentUid && productId == currentComponentActive.current?.productId) return;
284
+ if (componentUid !== currentComponentActive.current?.componentUid || productId !== currentComponentActive.current?.productId || forceReActive) removeActiveComponent();
285
+ const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
286
+ const $outline = getChildrenByAttrSelector($component, 'data-outline');
287
+ const $btnAddTop = getChildrenByAttrSelector($component, 'data-toolbar-add-top');
288
+ const $btnAddBottom = getChildrenByAttrSelector($component, 'data-toolbar-add-bottom');
289
+ if ($toolbar) {
290
+ currentComponentActive.current = {
291
+ componentUid,
292
+ productId
293
+ };
294
+ $toolbar.removeAttribute('style');
295
+ $toolbar.setAttribute('data-toolbar-active', 'true');
296
+ changePositionToolbar({
297
+ $toolbar,
298
+ $component,
299
+ state: 'active'
300
+ });
301
+ }
302
+ if ($outline) {
303
+ $outline.setAttribute('data-outline-active', 'true');
304
+ }
305
+ if ($btnAddTop) {
306
+ $btnAddTop.setAttribute('data-toolbar-add-active', 'true');
307
+ }
308
+ if ($btnAddBottom) {
309
+ $btnAddBottom.setAttribute('data-toolbar-add-active', 'true');
310
+ }
311
+ // Active same element in product list
312
+ if (productId) {
313
+ const $relatedElements = document.querySelectorAll(`[data-uid="${componentUid}"]`);
314
+ if ($relatedElements?.length) {
315
+ $relatedElements.forEach(($relatedElement)=>{
316
+ const $outline = getChildrenByAttrSelector($relatedElement, 'data-outline');
317
+ if ($outline) {
318
+ $outline.setAttribute('data-outline-active', 'true');
319
+ }
320
+ });
321
+ }
322
+ }
323
+ setActiveComponentSpacing({
324
+ $component
325
+ });
326
+ setActiveComponentForceHoverSection($component, true);
327
+ removeHoverComponent();
328
+ // Reactive when component re-render
329
+ watchComponentReRender($component, ()=>{
330
+ setActiveComponent({
331
+ componentUid,
332
+ productId,
333
+ timeAwait: 2000,
334
+ forceReActive: true
335
+ });
336
+ });
337
+ }, [
338
+ removeActiveComponent,
339
+ removeHoverComponent,
340
+ setActiveComponentForceHoverSection,
341
+ setActiveComponentSpacing
342
+ ]);
343
+ const setFocusTextEditor = async (value)=>{
344
+ if (!value) {
345
+ const $components = document.querySelectorAll('[data-outline-editor-inline-focus],[data-toolbar-editor-inline-focus],[data-spacing-hidden]');
346
+ if ($components.length) {
347
+ $components.forEach(($component)=>{
348
+ if ($component) {
349
+ $component.removeAttribute('data-toolbar-editor-inline-focus');
350
+ $component.removeAttribute('data-outline-editor-inline-focus');
351
+ $component.removeAttribute('data-spacing-hidden');
352
+ }
353
+ });
354
+ }
355
+ } else {
356
+ if (currentComponentActive.current?.componentUid) {
357
+ const componentUid = currentComponentActive.current?.componentUid;
358
+ const productId = currentComponentActive.current?.productId;
359
+ const $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, 500);
360
+ if ($component) {
361
+ const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
362
+ const $outline = getChildrenByAttrSelector($component, 'data-outline');
363
+ const $spacing = getChildrenByAttrSelector($component, 'data-spacing');
364
+ if ($toolbar) {
365
+ if (value) {
366
+ $toolbar.setAttribute('data-toolbar-editor-inline-focus', 'true');
367
+ }
368
+ }
369
+ if ($outline) {
370
+ if (value) {
371
+ $outline.setAttribute('data-outline-editor-inline-focus', 'true');
372
+ }
373
+ }
374
+ if ($spacing) {
375
+ if (value) {
376
+ $spacing.setAttribute('data-spacing-hidden', 'true');
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ };
383
+ const hoverActiveThemeSection = useCallback(($target)=>{
384
+ const $themeSection = $target.closest('[data-theme-section]');
385
+ const $themeSectionUid = $themeSection?.getAttribute('data-uid');
386
+ const isActiveThemeSection = $themeSection && $themeSectionUid === currentComponentActive.current?.componentUid;
387
+ if (!isActiveThemeSection) return;
388
+ const $themeSectionStatus = getChildrenByAttrSelector($themeSection, 'data-theme-section-status');
389
+ if ($themeSectionStatus) {
390
+ $themeSectionStatus.setAttribute('data-theme-section-status-active', 'true');
391
+ }
392
+ }, []);
393
+ const setShowParents = async ({ value })=>{
394
+ if (!value) {
395
+ return;
396
+ }
397
+ const $component = await waitForElementToExist(`${currentComponentActive.current?.productId ? `[data-product-id="${currentComponentActive.current?.productId}"] ` : ''}[data-uid="${currentComponentActive.current?.componentUid}"]`, 500);
398
+ if ($component) {
399
+ const $parents = $component?.querySelectorAll('[data-toolbar-parent]');
400
+ if ($parents.length) {
401
+ const onHover = ($parent)=>{
402
+ const uid = $parent.getAttribute('data-parent-uid');
403
+ if (!uid) return;
404
+ const $parentComponents = document.querySelectorAll(`[data-uid="${uid}"]`);
405
+ if ($parentComponents.length) {
406
+ $parentComponents.forEach(($parentComponent)=>{
407
+ const $outline = getChildrenByAttrSelector($parentComponent, 'data-outline');
408
+ if ($outline) {
409
+ $outline.setAttribute('data-outline-force-hover', 'true');
410
+ $outline.setAttribute('data-outline-force-overlay', 'true');
411
+ }
412
+ });
413
+ }
414
+ };
415
+ const outHover = ($parent)=>{
416
+ const uid = $parent.getAttribute('data-parent-uid');
417
+ if (!uid) return;
418
+ const $parentComponents = document.querySelectorAll(`[data-uid="${uid}"]`);
419
+ if ($parentComponents.length) {
420
+ $parentComponents.forEach(($parentComponent)=>{
421
+ const $outline = getChildrenByAttrSelector($parentComponent, 'data-outline');
422
+ if ($outline) {
423
+ $outline.removeAttribute('data-outline-force-hover');
424
+ $outline.removeAttribute('data-outline-force-overlay');
425
+ }
426
+ });
427
+ }
428
+ };
429
+ const onClick = async ($parent)=>{
430
+ const uid = $parent.getAttribute('data-parent-uid');
431
+ if (!uid) return;
432
+ const isElementInsideProduct = async ()=>{
433
+ const $component = await waitForElementToExist(`[data-uid="${uid}"]`, 500);
434
+ const $product = $component?.closest('[data-product-id]');
435
+ const productId = $product?.getAttribute('data-product-id') || '';
436
+ return productId ? true : false;
437
+ };
438
+ let productId = '';
439
+ if (await isElementInsideProduct()) {
440
+ productId = currentComponentActive.current?.productId || '';
441
+ }
442
+ const event = new CustomEvent('editor:toolbar:force-active-component', {
443
+ bubbles: true,
444
+ detail: {
445
+ componentUid: uid,
446
+ productId: productId
447
+ }
448
+ });
449
+ outHover($parent);
450
+ window.dispatchEvent(event);
451
+ };
452
+ $parents.forEach(($parent)=>{
453
+ $parent.addEventListener('mouseover', ()=>onHover($parent));
454
+ $parent.addEventListener('mouseout', ()=>outHover($parent));
455
+ $parent.addEventListener('click', ()=>onClick($parent));
456
+ });
457
+ }
458
+ }
459
+ };
460
+ /* Event listener */ const onMouseMove = useCallback((e)=>{
461
+ if (isDragging.current) return;
462
+ if (isResizeSpacing.current) return;
463
+ const $target = e.target;
464
+ if (!$target) {
465
+ removeHoverOverlayComponent();
466
+ return;
467
+ }
468
+ const $toolbarHover = $target.closest('[data-toolbar-hover]');
469
+ if ($toolbarHover) {
470
+ // Disable feature overlay when hover to toolbar parents
471
+ return;
472
+ // removeHoverOverlayComponent(); // remove overlay old
473
+ // // Hover to toolbar is focus
474
+ // if ($toolbarHover?.getAttribute('data-toolbar-hover-focus')) return;
475
+ // const $component = $target.closest('[data-toolbar-wrap]');
476
+ // if (!$component) return;
477
+ // const $outline = getChildrenByAttrSelector($component, 'data-outline');
478
+ // if (!$outline) return;
479
+ // const isThemeSection = $component.getAttribute('data-theme-section');
480
+ // const outlineOverlay = isThemeSection
481
+ // ? 'data-outline-overlay-theme-section'
482
+ // : 'data-outline-overlay';
483
+ // $outline.setAttribute(outlineOverlay, 'true');
484
+ }
485
+ // Hover to other component
486
+ const $component = $target.closest('[data-toolbar-wrap]');
487
+ const componentUid = $component?.getAttribute('data-uid');
488
+ if (!$component || !componentUid || componentUid == 'ROOT') {
489
+ removeHoverComponent();
490
+ return;
491
+ }
492
+ const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
493
+ const $outline = getChildrenByAttrSelector($component, 'data-outline');
494
+ if ($outline) $outline.removeAttribute('data-outline-overlay');
495
+ if (!componentUid) return;
496
+ if (componentUid == 'ROOT') return;
497
+ if ($toolbar?.getAttribute('data-toolbar-hover-focus')) return;
498
+ if (!$toolbar?.getAttribute('data-toolbar-hover-focus')) removeHoverComponent();
499
+ hoverActiveThemeSection($target);
500
+ // Disable event when hover active component
501
+ if (componentUid == currentComponentActive.current?.componentUid) {
502
+ if (currentComponentActive.current.productId) {
503
+ const $product = $component.closest(`[data-product-id]`);
504
+ if ($product) {
505
+ const productId = $product.getAttribute('data-product-id');
506
+ if (productId == currentComponentActive.current.productId) {
507
+ removeHoverComponent();
508
+ return;
509
+ }
510
+ }
511
+ }
512
+ const $themeSection = $target.closest('[data-theme-section]');
513
+ if ($themeSection) {
514
+ setHoverComponent({
515
+ $component: $themeSection,
516
+ focus: true,
517
+ isThemeSection: true
518
+ });
519
+ } else {
520
+ return;
521
+ }
522
+ }
523
+ const $themeSection = $target.closest('[data-theme-section]');
524
+ if ($themeSection) {
525
+ setHoverComponent({
526
+ $component: $themeSection,
527
+ focus: true,
528
+ isThemeSection: true
529
+ });
530
+ } else {
531
+ setHoverComponent({
532
+ $component,
533
+ componentUid,
534
+ focus: true
535
+ });
536
+ setHoverComponentParents({
537
+ $component,
538
+ componentUid
539
+ });
540
+ }
541
+ }, [
542
+ hoverActiveThemeSection,
543
+ removeHoverComponent,
544
+ setHoverComponent,
545
+ setHoverComponentParents,
546
+ removeHoverOverlayComponent,
547
+ currentComponentActive
548
+ ]);
549
+ const onActiveComponent = useCallback((e)=>{
550
+ if (isDragging.current) return;
551
+ const detail = e.detail;
552
+ if (detail?.componentUid) {
553
+ setActiveComponent({
554
+ componentUid: detail.componentUid,
555
+ productId: detail.productId
556
+ });
557
+ } else {
558
+ removeActiveComponent();
559
+ }
560
+ }, [
561
+ setActiveComponent,
562
+ removeActiveComponent,
563
+ isDragging
564
+ ]);
565
+ const onFocusOutsidePreview = useCallback(()=>{
566
+ removeHoverComponent();
567
+ }, [
568
+ removeHoverComponent
569
+ ]);
570
+ const onIsDragging = useCallback((e)=>{
571
+ const detail = e.detail;
572
+ if (detail.value) {
573
+ removeHoverComponent();
574
+ removeActiveComponent();
575
+ }
576
+ isDragging.current = detail.value;
577
+ }, [
578
+ removeHoverComponent,
579
+ removeActiveComponent
580
+ ]);
581
+ const onIsEditingTextEditor = useCallback((e)=>{
582
+ const detail = e.detail;
583
+ if (detail.value) {
584
+ setFocusTextEditor(true);
585
+ } else {
586
+ setFocusTextEditor(false);
587
+ }
588
+ }, []);
589
+ const onShowParents = useCallback((e)=>{
590
+ if (isDragging.current) return;
591
+ const detail = e.detail;
592
+ setShowParents({
593
+ value: detail?.value || false
594
+ });
595
+ }, []);
596
+ const onResizeSpacing = useCallback((e)=>{
597
+ const detail = e.detail;
598
+ if (detail?.value) {
599
+ removeHoverComponent();
600
+ isResizeSpacing.current = true;
601
+ } else {
602
+ isResizeSpacing.current = false;
603
+ }
604
+ }, [
605
+ removeHoverComponent
606
+ ]);
607
+ /* Register event */ useEffect(()=>{
608
+ document.addEventListener('mousemove', onMouseMove);
609
+ window.addEventListener('editor:active-component', onActiveComponent);
610
+ window.addEventListener('editor:focus-outside-preview', onFocusOutsidePreview);
611
+ window.addEventListener('editor:is-dragging', onIsDragging);
612
+ window.addEventListener('editor:is-editing-text-editor', onIsEditingTextEditor);
613
+ window.addEventListener('editor:toolbar:show-parents', onShowParents);
614
+ window.addEventListener('editor:toolbar:resize-spacing', onResizeSpacing);
615
+ return ()=>{
616
+ document.removeEventListener('mousemove', onMouseMove);
617
+ window.removeEventListener('editor:active-component', onActiveComponent);
618
+ window.removeEventListener('editor:is-dragging', onFocusOutsidePreview);
619
+ window.removeEventListener('editor:is-dragging', onIsDragging);
620
+ window.removeEventListener('editor:is-editing-text-editor', onIsEditingTextEditor);
621
+ window.removeEventListener('editor:toolbar:show-parents', onShowParents);
622
+ window.removeEventListener('editor:toolbar:resize-spacing', onResizeSpacing);
623
+ };
624
+ }, [
625
+ onMouseMove,
626
+ onActiveComponent,
627
+ onFocusOutsidePreview,
628
+ onIsDragging,
629
+ onIsEditingTextEditor,
630
+ onShowParents,
631
+ onResizeSpacing
632
+ ]);
633
+ return null;
634
+ };
635
+ const getDOMElementParents = ($el, selector, limit)=>{
636
+ // Set up a parent array
637
+ const parents = [];
638
+ // Push each parent $elms to the array
639
+ while($el){
640
+ $el = $el.parentElement ?? undefined;
641
+ if ($el) {
642
+ if ($el.tagName === 'BODY' || $el.getAttribute('data-uid') === 'ROOT') {
643
+ break;
644
+ }
645
+ if (selector) {
646
+ if ($el.matches(selector)) {
647
+ parents.push($el);
648
+ if (limit && parents.length == limit) {
649
+ return parents;
650
+ }
651
+ }
652
+ continue;
653
+ }
654
+ parents.push($el);
655
+ if (limit && parents.length == limit) {
656
+ return parents;
657
+ }
658
+ }
659
+ }
660
+ // Return our parent array
661
+ return parents;
662
+ };
663
+ const getChildrenByAttrSelector = ($el, attrSelector)=>{
664
+ const childLen = $el.children.length;
665
+ if (childLen) {
666
+ for(let i = 0; i < childLen; i++){
667
+ const children = $el.children[i];
668
+ if (children) {
669
+ const is = children.getAttribute(attrSelector);
670
+ if (is) {
671
+ return children;
672
+ }
673
+ }
674
+ }
675
+ }
676
+ };
677
+ const isOverParent = ({ current, parent, index, revert })=>{
678
+ for(let i = 0; i < index; i++){
679
+ let is = current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent.top && current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent.top + parent.height || current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent.top + parent.height && current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent.top;
680
+ if (revert) {
681
+ is = current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent.bottom && current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent.bottom - parent.height || current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent.bottom - parent.height && current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent.bottom;
682
+ }
683
+ if (is) return true;
684
+ }
685
+ return false;
686
+ };
687
+ const waitForElementToExist = (selector, timeout = 200)=>{
688
+ return new Promise((resolve)=>{
689
+ const intervalID = setInterval(()=>{
690
+ const el = document.querySelector(selector);
691
+ if (el) {
692
+ clearInterval(intervalID);
693
+ clearTimeout(timeoutID);
694
+ resolve(el);
695
+ }
696
+ }, 50);
697
+ const timeoutID = setTimeout(()=>{
698
+ clearInterval(intervalID);
699
+ clearTimeout(timeoutID);
700
+ resolve(null);
701
+ }, timeout);
702
+ });
703
+ };
704
+ const notVisible = (el)=>{
705
+ const overflow = getComputedStyle(el).overflow;
706
+ return overflow !== 'visible';
707
+ };
708
+ const isSection = (el)=>{
709
+ const tag = el.getAttribute('data-component-tag');
710
+ return tag === 'Section';
711
+ };
712
+ const isOverToolbarPosition = (el, parent)=>{
713
+ const rect = el.getBoundingClientRect();
714
+ const rectP = parent.getBoundingClientRect();
715
+ // 32px = toolbar active height
716
+ return rect.top - rectP.top < TOOLBAR_ACTIVE_HEIGHT + 1;
717
+ };
718
+ const findOverflowParent = (element, initEl)=>{
719
+ const thisEl = element;
720
+ const origEl = initEl || thisEl;
721
+ if (!thisEl) return;
722
+ if (isSection(thisEl)) return;
723
+ if (notVisible(thisEl) && isOverToolbarPosition(initEl, thisEl)) return thisEl;
724
+ if (thisEl.parentElement) {
725
+ return findOverflowParent(thisEl.parentElement, origEl);
726
+ } else {
727
+ return;
728
+ }
729
+ };
730
+ var Toolbar$1 = /*#__PURE__*/ memo(Toolbar);
731
+
732
+ export { Toolbar$1 as default };