@gem-sdk/pages 1.23.0 → 1.23.1

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