@gem-sdk/pages 1.23.0-staging.27 → 1.23.0-staging.270

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.
@@ -2,108 +2,69 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var jsxRuntime = require('react/jsx-runtime');
5
6
  var react = require('react');
7
+ var Onboarding = require('./toolbar/Onboarding.js');
6
8
 
7
9
  const TOOLBAR_HOVER_HEIGHT = 24;
8
- // const TOOLBAR_ACTIVE_HEIGHT = 32;
9
- const getDOMElementParents = ($el, selector, limit)=>{
10
- // Set up a parent array
11
- const parents = [];
12
- // Push each parent $elms to the array
13
- while($el){
14
- $el = $el.parentElement ?? undefined;
15
- if ($el) {
16
- if ($el.tagName === 'BODY' || $el.getAttribute('data-uid') === 'ROOT') {
17
- break;
18
- }
19
- if (selector) {
20
- if ($el.matches(selector)) {
21
- parents.push($el);
22
- if (limit && parents.length == limit) {
23
- return parents;
24
- }
25
- }
26
- continue;
27
- }
28
- parents.push($el);
29
- if (limit && parents.length == limit) {
30
- return parents;
31
- }
32
- }
33
- }
34
- // Return our parent array
35
- return parents;
36
- };
37
- const getChildrenByAttrSelector = ($el, attrSelector)=>{
38
- const childLen = $el.children.length;
39
- if (childLen) {
40
- for(let i = 0; i < childLen; i++){
41
- const children = $el.children[i];
42
- if (children) {
43
- const is = children.getAttribute(attrSelector);
44
- if (is) {
45
- return children;
46
- }
47
- }
48
- }
49
- }
50
- };
51
- const isOverParent = (current, parent, index)=>{
52
- for(let i = 0; i < index; i++){
53
- const is = current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent.top && current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent.top + parent.height && current.left >= parent.left && current.left <= parent.left + parent.width;
54
- if (is) return true;
55
- }
56
- return false;
57
- };
58
- const waitForElementToExist = (selector, timeout = 200)=>{
59
- return new Promise((resolve)=>{
60
- const intervalID = setInterval(()=>{
61
- const el = document.querySelector(selector);
62
- if (el) {
63
- clearInterval(intervalID);
64
- clearTimeout(timeoutID);
65
- resolve(el);
66
- }
67
- }, 50);
68
- const timeoutID = setTimeout(()=>{
69
- clearInterval(intervalID);
70
- clearTimeout(timeoutID);
71
- resolve(null);
72
- }, timeout);
73
- });
74
- };
75
- const notVisible = (el)=>{
76
- const overflow = getComputedStyle(el).overflow;
77
- return overflow !== 'visible';
78
- };
79
- const isSection = (el)=>{
10
+ const TOOLBAR_ACTIVE_HEIGHT = 32;
11
+ const isPopup = (el)=>{
80
12
  const tag = el.getAttribute('data-component-tag');
81
- return tag === 'Section';
82
- };
83
- const isOverToolbarPosition = (el, parent)=>{
84
- const rect = el.getBoundingClientRect();
85
- const rectP = parent.getBoundingClientRect();
86
- // 32px = toolbar active height
87
- return rect.top - rectP.top < 32 + 5;
13
+ return tag === 'Dialog';
88
14
  };
89
- const findOverflowParent = (element, initEl)=>{
90
- const thisEl = element;
91
- const origEl = initEl || thisEl;
92
- if (!thisEl) return;
93
- if (isSection(thisEl)) return;
94
- if (notVisible(thisEl) && isOverToolbarPosition(initEl, thisEl)) return thisEl;
95
- if (thisEl.parentElement) {
96
- return findOverflowParent(thisEl.parentElement, origEl);
97
- } else {
98
- return;
99
- }
15
+ const isSticky = (el)=>{
16
+ const tag = el.getAttribute('data-component-tag');
17
+ return tag === 'Sticky';
100
18
  };
101
19
  const Toolbar = ()=>{
102
20
  const currentComponentActive = react.useRef(null);
103
21
  const isDragging = react.useRef(false);
104
- const obsActiveComponent = react.useRef();
22
+ const stopWatchReRenderComponent = react.useRef();
105
23
  const isResizeSpacing = react.useRef(false);
106
- /* Functions */ const setHoverComponent = react.useCallback(({ $component, componentUid, focus, isThemeSection })=>{
24
+ const [isOnboarding, setIsOnboarding] = react.useState(false);
25
+ const [countShowOnboarding, setCountShowOnboarding] = react.useState(0);
26
+ const [onboardingPosition, setOnboardingPosition] = react.useState('bottom');
27
+ const timeoutRef = react.useRef(null);
28
+ const timeoutOnboarding = 5000;
29
+ /* Functions */ const changePositionToolbar = ({ state, $toolbar, $component })=>{
30
+ const $parentOverflow = findOverflowParent($component, $toolbar);
31
+ const rect = $toolbar.getBoundingClientRect();
32
+ const rectComponent = $component.getBoundingClientRect();
33
+ const windowWidth = window.innerWidth;
34
+ if ($parentOverflow) {
35
+ if (rectComponent?.height <= 60) {
36
+ $toolbar.setAttribute(`data-toolbar-${state}-revert`, 'true');
37
+ } else {
38
+ $toolbar.setAttribute(`data-toolbar-${state}-inside`, 'true');
39
+ }
40
+ // fix toolbar overflow right side
41
+ if (rectComponent.left + rect.width > windowWidth) {
42
+ $toolbar.setAttribute(`data-toolbar-${state}-overflow`, 'true');
43
+ }
44
+ } else {
45
+ if (rect.top < TOOLBAR_ACTIVE_HEIGHT + 1) {
46
+ if (rectComponent?.height <= 60) {
47
+ $toolbar.setAttribute(`data-toolbar-${state}-revert`, 'true');
48
+ } else {
49
+ $toolbar.setAttribute(`data-toolbar-${state}-inside`, 'true');
50
+ }
51
+ }
52
+ // fix toolbar overflow right side
53
+ if (rectComponent.left + rect.width > windowWidth) {
54
+ $toolbar.setAttribute(`data-toolbar-${state}-overflow`, 'true');
55
+ }
56
+ }
57
+ // fix Popup overflow right position
58
+ const popupEl = $component?.closest('[aria-label="Dialog body"]');
59
+ if (popupEl) {
60
+ const rectPopupEl = popupEl.getBoundingClientRect();
61
+ const popupElRightPosition = rectPopupEl.left + rectPopupEl.width - 20;
62
+ if (rectComponent.left + rect.width > popupElRightPosition) {
63
+ $toolbar.setAttribute(`data-toolbar-${state}-overflow`, 'true');
64
+ }
65
+ }
66
+ };
67
+ const setHoverComponent = react.useCallback(({ $component, componentUid, focus, isThemeSection, isParent })=>{
107
68
  if (!$component && !componentUid) return;
108
69
  if (!$component) {
109
70
  const $c = document.querySelector(`[data-uid="${componentUid}"]`);
@@ -125,17 +86,23 @@ const Toolbar = ()=>{
125
86
  }
126
87
  if ($toolbar) {
127
88
  $toolbar.removeAttribute('style');
128
- $toolbar.setAttribute('data-toolbar-hover', 'true');
89
+ if (!isParent) {
90
+ $toolbar.setAttribute('data-toolbar-hover', 'true');
91
+ }
129
92
  if (focus) {
130
93
  $toolbar.setAttribute('data-toolbar-hover-focus', 'true');
131
94
  }
132
- const $parentOverflow = findOverflowParent($component, $toolbar);
133
- if ($parentOverflow) {
134
- $toolbar.setAttribute('data-toolbar-hover-revert', 'true');
135
- }
95
+ changePositionToolbar({
96
+ $toolbar,
97
+ $component,
98
+ state: 'hover'
99
+ });
136
100
  }
137
101
  if ($outline) {
138
102
  $outline.setAttribute('data-outline-hover', 'true');
103
+ if (isParent) {
104
+ $outline.setAttribute('data-outline-parent-hover', 'true');
105
+ }
139
106
  if (isThemeSection) {
140
107
  $outline.setAttribute('data-outline-overlay-theme-section', 'true');
141
108
  }
@@ -144,10 +111,14 @@ const Toolbar = ()=>{
144
111
  }
145
112
  }
146
113
  if ($btnAddTop) {
147
- $btnAddTop.setAttribute('data-toolbar-add-hover', 'true');
114
+ if (!isParent) {
115
+ $btnAddTop.setAttribute('data-toolbar-add-hover', 'true');
116
+ }
148
117
  }
149
118
  if ($btnAddBottom) {
150
- $btnAddBottom.setAttribute('data-toolbar-add-hover', 'true');
119
+ if (!isParent) {
120
+ $btnAddBottom.setAttribute('data-toolbar-add-hover', 'true');
121
+ }
151
122
  }
152
123
  }, []);
153
124
  const setHoverComponentParents = react.useCallback(({ $component, componentUid })=>{
@@ -156,12 +127,13 @@ const Toolbar = ()=>{
156
127
  if (!$c) return;
157
128
  $component = $c;
158
129
  }
159
- const $parents = getDOMElementParents($component, '[data-uid][data-component-type="component"]:not([data-component-no-setting])');
130
+ const $parents = getDOMElementParents($component, '[data-uid][data-component-type="component"]:not([data-component-no-setting])', 1);
160
131
  if ($parents.length) {
161
132
  for (const $parent of $parents){
162
133
  if ($parent) {
163
134
  setHoverComponent({
164
- $component: $parent
135
+ $component: $parent,
136
+ isParent: true
165
137
  });
166
138
  }
167
139
  }
@@ -179,6 +151,8 @@ const Toolbar = ()=>{
179
151
  const $currentToolbar = getChildrenByAttrSelector($component, 'data-toolbar-hover-focus');
180
152
  if ($currentToolbar) {
181
153
  const currentRect = $currentToolbar.getBoundingClientRect();
154
+ const isRevert = $currentToolbar.getAttribute('data-toolbar-hover-revert') ? true : false;
155
+ const isInside = $currentToolbar.getAttribute('data-toolbar-hover-inside') ? true : false;
182
156
  let index = 1;
183
157
  for (const $parent of $parents){
184
158
  if ($parent) {
@@ -191,14 +165,19 @@ const Toolbar = ()=>{
191
165
  if (isActive) continue;
192
166
  // Start calc
193
167
  const parentRect = $toolbar.getBoundingClientRect();
194
- if (isOverParent(currentRect, parentRect, index)) {
168
+ const checkRevert = isRevert || isInside;
169
+ if (isOverParent({
170
+ current: currentRect,
171
+ parent: parentRect,
172
+ index,
173
+ revert: checkRevert
174
+ })) {
195
175
  const parentStyle = getComputedStyle($toolbar);
196
- const isRevert = $toolbar.getAttribute('data-toolbar-hover-revert') ? true : false;
197
176
  // parentStyle.top
198
177
  const diffTop = currentRect.top - parentRect.top;
199
178
  const diffLeft = currentRect.left - parentRect.left;
200
179
  let newTop = parseFloat(parentStyle.top) + diffTop - (TOOLBAR_HOVER_HEIGHT - 1) * index; // -1 border bottom
201
- if (isRevert) {
180
+ if (checkRevert) {
202
181
  newTop = parseFloat(parentStyle.top) - diffTop + (TOOLBAR_HOVER_HEIGHT - 1) * index; // -1 border bottom
203
182
  }
204
183
  const newLeft = parseFloat(parentStyle.left) + diffLeft;
@@ -229,8 +208,11 @@ const Toolbar = ()=>{
229
208
  'data-toolbar-hover',
230
209
  'data-outline-hover-focus',
231
210
  'data-toolbar-hover-revert',
211
+ 'data-toolbar-hover-inside',
232
212
  'data-outline-hover',
233
- 'data-toolbar-add-hover'
213
+ 'data-toolbar-add-hover',
214
+ 'data-outline-parent-hover',
215
+ 'data-toolbar-hover-overflow'
234
216
  ];
235
217
  const $elms = document.querySelectorAll(clearAttrs.map((attr)=>`[${attr}]`).join(','));
236
218
  if ($elms) {
@@ -242,6 +224,21 @@ const Toolbar = ()=>{
242
224
  }, [
243
225
  removeHoverOverlayComponent
244
226
  ]);
227
+ const onCloseOnboarding = react.useCallback(()=>{
228
+ timeoutRef.current && clearTimeout(timeoutRef.current);
229
+ if (countShowOnboarding > 0) {
230
+ const eventCreate = new CustomEvent('editor:toolbar:close-onboarding', {
231
+ bubbles: true,
232
+ detail: {
233
+ close: 'close Onboarding'
234
+ }
235
+ });
236
+ window.dispatchEvent(eventCreate);
237
+ setIsOnboarding(false);
238
+ }
239
+ }, [
240
+ countShowOnboarding
241
+ ]);
245
242
  const removeActiveComponent = react.useCallback(()=>{
246
243
  currentComponentActive.current = null;
247
244
  const clearAttrs = [
@@ -249,9 +246,11 @@ const Toolbar = ()=>{
249
246
  'data-outline-active',
250
247
  'data-toolbar-add-active',
251
248
  'data-toolbar-active-revert',
249
+ 'data-toolbar-active-inside',
252
250
  'data-spacing-margin-bottom-active',
253
251
  'data-toolbar-force-hover',
254
- 'data-outline-force-hover'
252
+ 'data-outline-force-hover',
253
+ 'data-toolbar-active-overflow'
255
254
  ];
256
255
  const $elms = document.querySelectorAll(clearAttrs.map((attr)=>`[${attr}]`).join(','));
257
256
  if ($elms) {
@@ -260,25 +259,32 @@ const Toolbar = ()=>{
260
259
  });
261
260
  }
262
261
  setFocusTextEditor(false);
263
- if (obsActiveComponent.current) obsActiveComponent.current.disconnect();
264
- }, []);
262
+ if (stopWatchReRenderComponent.current) stopWatchReRenderComponent.current();
263
+ onCloseOnboarding();
264
+ }, [
265
+ onCloseOnboarding
266
+ ]);
265
267
  const watchComponentReRender = ($el, callback)=>{
266
- const parent = $el.parentNode;
267
- if (!parent) return;
268
- if (obsActiveComponent.current) obsActiveComponent.current.disconnect();
269
- obsActiveComponent.current = new MutationObserver((mutations)=>{
270
- for (const mutation of mutations){
271
- mutation.removedNodes.forEach((el)=>{
272
- if (el === $el) {
273
- if (obsActiveComponent.current) obsActiveComponent.current.disconnect();
274
- callback();
275
- }
276
- });
268
+ // editor:component:render
269
+ const onComponentReRender = (e)=>{
270
+ const detail = e.detail;
271
+ if (detail?.componentUid == currentComponentActive.current?.componentUid) {
272
+ callback();
277
273
  }
278
- });
279
- obsActiveComponent.current.observe(parent, {
280
- childList: true
281
- });
274
+ };
275
+ window.removeEventListener('editor:component:render', onComponentReRender);
276
+ window.addEventListener('editor:component:render', onComponentReRender);
277
+ const $images = $el.querySelectorAll('img');
278
+ if ($images?.length) {
279
+ $images.forEach(($img)=>{
280
+ $img.addEventListener('load', ()=>{
281
+ callback();
282
+ });
283
+ });
284
+ }
285
+ stopWatchReRenderComponent.current = ()=>{
286
+ window.removeEventListener('editor:component:render', onComponentReRender);
287
+ };
282
288
  };
283
289
  const setActiveComponentSpacing = react.useCallback(({ $component })=>{
284
290
  if (!$component) return;
@@ -289,43 +295,96 @@ const Toolbar = ()=>{
289
295
  const $bg = $marginBottom.querySelector('[data-spacing-margin-bottom-bg]') || null;
290
296
  const $drag = $marginBottom.querySelector('[data-spacing-margin-bottom-drag]') || null;
291
297
  if ($bg && $drag) {
292
- const value = style.marginBottom;
298
+ let value = style.marginBottom;
299
+ if (parseFloat(value) < 0) {
300
+ value = '0';
301
+ }
293
302
  $bg.style.height = value;
294
303
  $drag.style.top = value;
295
304
  $marginBottom.setAttribute('data-spacing-margin-bottom-active', 'true');
305
+ if (isLayoutElement($component)) {
306
+ $bg.style.left = '0';
307
+ } else {
308
+ const paddingLeft = style.paddingLeft;
309
+ const leftValue = `-${paddingLeft}`;
310
+ const translateCss = `translate(${leftValue}, -100%)`;
311
+ $bg.style.left = leftValue;
312
+ $drag.style.transform = translateCss;
313
+ }
296
314
  }
297
315
  }
298
316
  }, []);
299
- const setActiveComponentForceHoverSection = ($component, value)=>{
300
- const $section = $component.closest('[data-toolbar-wrap][data-component-tag="Section"]');
301
- if ($section) {
302
- if (value) {
303
- const $toolbar = getChildrenByAttrSelector($section, 'data-toolbar');
304
- const $outline = getChildrenByAttrSelector($section, 'data-outline');
305
- if ($toolbar) {
306
- $toolbar.setAttribute('data-toolbar-force-hover', 'true');
307
- }
308
- if ($outline) {
309
- $outline.setAttribute('data-outline-force-hover', 'true');
310
- }
311
- } else {
312
- const $toolbar = getChildrenByAttrSelector($section, 'data-toolbar');
313
- const $outline = getChildrenByAttrSelector($section, 'data-outline');
314
- if ($toolbar) {
315
- $toolbar.removeAttribute('data-toolbar-force-hover');
316
- }
317
- if ($outline) {
318
- $outline.removeAttribute('data-outline-force-hover');
317
+ const calculateOnboardingPosition = ()=>{
318
+ const toolbar = document.querySelector('[data-toolbar-active]');
319
+ const toolbarOnboading = document.querySelector('[data-toolbar-onboarding]');
320
+ if (toolbar && toolbarOnboading) {
321
+ toolbarOnboading?.removeAttribute('data-onboarding-active');
322
+ setTimeout(()=>{
323
+ const rect = toolbar.getBoundingClientRect();
324
+ const rectTop = rect.top || 0;
325
+ const rectOnboading = toolbarOnboading?.getBoundingClientRect();
326
+ const onboardingHeight = rectOnboading?.height || 0;
327
+ const $iframe = parent.document.querySelector('.iframe');
328
+ const $iframeWin = $iframe?.contentWindow;
329
+ const iframeWinScrollY = $iframeWin?.scrollY || 0;
330
+ const iframeHeight = $iframe?.clientHeight || 0;
331
+ if (rectTop + onboardingHeight > iframeHeight) {
332
+ const oboardingTop = rect.top + iframeWinScrollY - onboardingHeight - 8;
333
+ toolbarOnboading?.setAttribute('style', `top: ${oboardingTop}px;left: ${rect.left}px;`);
334
+ setOnboardingPosition('top');
335
+ if ($iframeWin && oboardingTop < rect.top + iframeWinScrollY) {
336
+ setTimeout(()=>{
337
+ const toTop = oboardingTop - 20;
338
+ $iframeWin.scrollTo({
339
+ top: toTop,
340
+ behavior: 'smooth'
341
+ });
342
+ }, 200);
343
+ }
344
+ } else {
345
+ const oboardingTop = rect.top + iframeWinScrollY + rect.height + 8;
346
+ toolbarOnboading?.setAttribute('style', `top: ${oboardingTop}px;left: ${rect.left}px;`);
347
+ setOnboardingPosition('bottom');
319
348
  }
320
- }
349
+ setCountShowOnboarding((countShowOnboarding)=>countShowOnboarding + 1);
350
+ toolbarOnboading?.setAttribute('data-onboarding-active', 'true');
351
+ }, 100);
321
352
  }
322
353
  };
354
+ const setToolbarOnboarding = react.useCallback(({ $component })=>{
355
+ if (!$component) return;
356
+ if (isSection($component) || isPopup($component) || isSticky($component)) return;
357
+ const toolbarOnboading = document.querySelector('[data-toolbar-onboarding]');
358
+ // only show one time
359
+ if (countShowOnboarding == 0) {
360
+ calculateOnboardingPosition();
361
+ } else {
362
+ onCloseOnboarding();
363
+ toolbarOnboading?.removeAttribute('data-onboarding-active');
364
+ }
365
+ }, [
366
+ countShowOnboarding,
367
+ onCloseOnboarding
368
+ ]);
323
369
  const setActiveComponent = react.useCallback(async ({ componentUid, productId, timeAwait = 500, forceReActive })=>{
324
370
  if (!componentUid) return;
325
- const $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, timeAwait);
326
- if (!$component) return;
371
+ let $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, timeAwait);
372
+ // check element fetch data: product, product list
373
+ if (!$component) {
374
+ const isLoading = document.querySelector(`.gp-loading-placeholder`);
375
+ if (!isLoading) {
376
+ return;
377
+ }
378
+ if (isLoading) {
379
+ // await element onload
380
+ $component = await waitForElementToExist(`${productId ? `[data-product-id="${productId}"] ` : ''}[data-uid="${componentUid}"]`, 15000);
381
+ }
382
+ }
383
+ if (!$component) {
384
+ return;
385
+ }
327
386
  if (!forceReActive && componentUid == currentComponentActive.current?.componentUid && productId == currentComponentActive.current?.productId) return;
328
- if (!forceReActive && componentUid !== currentComponentActive.current?.componentUid || productId !== currentComponentActive.current?.productId) removeActiveComponent();
387
+ if (componentUid !== currentComponentActive.current?.componentUid || productId !== currentComponentActive.current?.productId || forceReActive) removeActiveComponent();
329
388
  const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
330
389
  const $outline = getChildrenByAttrSelector($component, 'data-outline');
331
390
  const $btnAddTop = getChildrenByAttrSelector($component, 'data-toolbar-add-top');
@@ -337,10 +396,11 @@ const Toolbar = ()=>{
337
396
  };
338
397
  $toolbar.removeAttribute('style');
339
398
  $toolbar.setAttribute('data-toolbar-active', 'true');
340
- const $parentOverflow = findOverflowParent($component, $toolbar);
341
- if ($parentOverflow) {
342
- $toolbar.setAttribute('data-toolbar-active-revert', 'true');
343
- }
399
+ changePositionToolbar({
400
+ $toolbar,
401
+ $component,
402
+ state: 'active'
403
+ });
344
404
  }
345
405
  if ($outline) {
346
406
  $outline.setAttribute('data-outline-active', 'true');
@@ -366,7 +426,14 @@ const Toolbar = ()=>{
366
426
  setActiveComponentSpacing({
367
427
  $component
368
428
  });
369
- setActiveComponentForceHoverSection($component, true);
429
+ timeoutRef.current && clearTimeout(timeoutRef.current);
430
+ timeoutRef.current = setTimeout(()=>{
431
+ if ($component) {
432
+ setToolbarOnboarding({
433
+ $component
434
+ });
435
+ }
436
+ }, timeoutOnboarding);
370
437
  removeHoverComponent();
371
438
  // Reactive when component re-render
372
439
  watchComponentReRender($component, ()=>{
@@ -380,7 +447,8 @@ const Toolbar = ()=>{
380
447
  }, [
381
448
  removeActiveComponent,
382
449
  removeHoverComponent,
383
- setActiveComponentSpacing
450
+ setActiveComponentSpacing,
451
+ setToolbarOnboarding
384
452
  ]);
385
453
  const setFocusTextEditor = async (value)=>{
386
454
  if (!value) {
@@ -503,59 +571,53 @@ const Toolbar = ()=>{
503
571
  if (isDragging.current) return;
504
572
  if (isResizeSpacing.current) return;
505
573
  const $target = e.target;
506
- if (!$target) {
574
+ if (!$target || typeof $target.closest !== 'function') {
507
575
  removeHoverOverlayComponent();
508
576
  return;
509
577
  }
510
578
  const $toolbarHover = $target.closest('[data-toolbar-hover]');
511
579
  if ($toolbarHover) {
512
- removeHoverOverlayComponent(); // remove overlay old
513
- // Hover to toolbar is focus
514
- if ($toolbarHover?.getAttribute('data-toolbar-hover-focus')) return;
515
- const $component = $target.closest('[data-toolbar-wrap]');
516
- if (!$component) return;
517
- const $outline = getChildrenByAttrSelector($component, 'data-outline');
518
- if (!$outline) return;
519
- const isThemeSection = $component.getAttribute('data-theme-section');
520
- const outlineOverlay = isThemeSection ? 'data-outline-overlay-theme-section' : 'data-outline-overlay';
521
- $outline.setAttribute(outlineOverlay, 'true');
522
- } else {
523
- // Hover to other component
524
- const $component = $target.closest('[data-toolbar-wrap]');
525
- const componentUid = $component?.getAttribute('data-uid');
526
- if (!$component || !componentUid || componentUid == 'ROOT') {
527
- removeHoverComponent();
528
- return;
529
- }
530
- const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
531
- const $outline = getChildrenByAttrSelector($component, 'data-outline');
532
- if ($outline) $outline.removeAttribute('data-outline-overlay');
533
- if (!componentUid) return;
534
- if (componentUid == 'ROOT') return;
535
- if ($toolbar?.getAttribute('data-toolbar-hover-focus')) return;
536
- if (!$toolbar?.getAttribute('data-toolbar-hover-focus')) removeHoverComponent();
537
- hoverActiveThemeSection($target);
538
- // Disable event when hover active component
539
- if (componentUid == currentComponentActive.current?.componentUid) {
540
- if (currentComponentActive.current.productId) {
541
- const $product = $component.closest(`[data-product-id]`);
542
- if ($product) {
543
- const productId = $product.getAttribute('data-product-id');
544
- if (productId == currentComponentActive.current.productId) {
545
- return;
546
- }
580
+ // Disable feature overlay when hover to toolbar parents
581
+ return;
582
+ // removeHoverOverlayComponent(); // remove overlay old
583
+ // // Hover to toolbar is focus
584
+ // if ($toolbarHover?.getAttribute('data-toolbar-hover-focus')) return;
585
+ // const $component = $target.closest('[data-toolbar-wrap]');
586
+ // if (!$component) return;
587
+ // const $outline = getChildrenByAttrSelector($component, 'data-outline');
588
+ // if (!$outline) return;
589
+ // const isThemeSection = $component.getAttribute('data-theme-section');
590
+ // const outlineOverlay = isThemeSection
591
+ // ? 'data-outline-overlay-theme-section'
592
+ // : 'data-outline-overlay';
593
+ // $outline.setAttribute(outlineOverlay, 'true');
594
+ }
595
+ // Hover to other component
596
+ const $component = $target.closest('[data-toolbar-wrap]');
597
+ const componentUid = $component?.getAttribute('data-uid');
598
+ if (!$component || !componentUid || componentUid == 'ROOT') {
599
+ removeHoverComponent();
600
+ return;
601
+ }
602
+ const $toolbar = getChildrenByAttrSelector($component, 'data-toolbar');
603
+ const $outline = getChildrenByAttrSelector($component, 'data-outline');
604
+ if ($outline) $outline.removeAttribute('data-outline-overlay');
605
+ if (!componentUid) return;
606
+ if (componentUid == 'ROOT') return;
607
+ if ($toolbar?.getAttribute('data-toolbar-hover-focus')) return;
608
+ if (!$toolbar?.getAttribute('data-toolbar-hover-focus')) removeHoverComponent();
609
+ hoverActiveThemeSection($target);
610
+ // Disable event when hover active component
611
+ if (componentUid == currentComponentActive.current?.componentUid) {
612
+ if (currentComponentActive.current.productId) {
613
+ const $product = $component.closest(`[data-product-id]`);
614
+ if ($product) {
615
+ const productId = $product.getAttribute('data-product-id');
616
+ if (productId == currentComponentActive.current.productId) {
617
+ removeHoverComponent();
618
+ return;
547
619
  }
548
620
  }
549
- const $themeSection = $target.closest('[data-theme-section]');
550
- if ($themeSection) {
551
- setHoverComponent({
552
- $component: $themeSection,
553
- focus: true,
554
- isThemeSection: true
555
- });
556
- } else {
557
- return;
558
- }
559
621
  }
560
622
  const $themeSection = $target.closest('[data-theme-section]');
561
623
  if ($themeSection) {
@@ -565,17 +627,27 @@ const Toolbar = ()=>{
565
627
  isThemeSection: true
566
628
  });
567
629
  } else {
568
- setHoverComponent({
569
- $component,
570
- componentUid,
571
- focus: true
572
- });
573
- setHoverComponentParents({
574
- $component,
575
- componentUid
576
- });
630
+ return;
577
631
  }
578
632
  }
633
+ const $themeSection = $target.closest('[data-theme-section]');
634
+ if ($themeSection) {
635
+ setHoverComponent({
636
+ $component: $themeSection,
637
+ focus: true,
638
+ isThemeSection: true
639
+ });
640
+ } else {
641
+ setHoverComponent({
642
+ $component,
643
+ componentUid,
644
+ focus: true
645
+ });
646
+ setHoverComponentParents({
647
+ $component,
648
+ componentUid
649
+ });
650
+ }
579
651
  }, [
580
652
  hoverActiveThemeSection,
581
653
  removeHoverComponent,
@@ -642,6 +714,46 @@ const Toolbar = ()=>{
642
714
  }, [
643
715
  removeHoverComponent
644
716
  ]);
717
+ const setHoverParentComponent = (uid, type)=>{
718
+ if (!uid) return;
719
+ const $parentComponents = document.querySelectorAll(`[data-uid="${uid}"]`);
720
+ if ($parentComponents.length) {
721
+ $parentComponents.forEach(($parentComponent)=>{
722
+ const $outline = getChildrenByAttrSelector($parentComponent, 'data-outline');
723
+ if ($outline) {
724
+ if (type === 'in') {
725
+ $outline.setAttribute('data-outline-force-hover', 'true');
726
+ $outline.setAttribute('data-outline-force-overlay', 'true');
727
+ } else {
728
+ $outline.removeAttribute('data-outline-force-hover');
729
+ $outline.removeAttribute('data-outline-force-overlay');
730
+ }
731
+ }
732
+ });
733
+ }
734
+ };
735
+ const onHoverComponent = react.useCallback((e)=>{
736
+ if (isDragging.current) return;
737
+ const detail = e.detail;
738
+ if (detail?.componentUid) {
739
+ setHoverParentComponent(detail?.componentUid, detail?.type);
740
+ }
741
+ }, [
742
+ isDragging
743
+ ]);
744
+ const onToolbarOnboarding = react.useCallback((e)=>{
745
+ const detail = e.detail;
746
+ if (detail?.isNewUser) {
747
+ setIsOnboarding(true);
748
+ }
749
+ }, []);
750
+ const onWindowResize = react.useCallback(()=>{
751
+ if (isOnboarding) {
752
+ calculateOnboardingPosition();
753
+ }
754
+ }, [
755
+ isOnboarding
756
+ ]);
645
757
  /* Register event */ react.useEffect(()=>{
646
758
  document.addEventListener('mousemove', onMouseMove);
647
759
  window.addEventListener('editor:active-component', onActiveComponent);
@@ -650,6 +762,9 @@ const Toolbar = ()=>{
650
762
  window.addEventListener('editor:is-editing-text-editor', onIsEditingTextEditor);
651
763
  window.addEventListener('editor:toolbar:show-parents', onShowParents);
652
764
  window.addEventListener('editor:toolbar:resize-spacing', onResizeSpacing);
765
+ window.addEventListener('editor:hover-component', onHoverComponent);
766
+ window.addEventListener('editor:toolbar-onboarding', onToolbarOnboarding);
767
+ window.addEventListener('resize', onWindowResize);
653
768
  return ()=>{
654
769
  document.removeEventListener('mousemove', onMouseMove);
655
770
  window.removeEventListener('editor:active-component', onActiveComponent);
@@ -658,6 +773,9 @@ const Toolbar = ()=>{
658
773
  window.removeEventListener('editor:is-editing-text-editor', onIsEditingTextEditor);
659
774
  window.removeEventListener('editor:toolbar:show-parents', onShowParents);
660
775
  window.removeEventListener('editor:toolbar:resize-spacing', onResizeSpacing);
776
+ window.removeEventListener('editor:hover-component', onHoverComponent);
777
+ window.removeEventListener('editor:toolbar-onboarding', onToolbarOnboarding);
778
+ window.removeEventListener('resize', onWindowResize);
661
779
  };
662
780
  }, [
663
781
  onMouseMove,
@@ -666,9 +784,115 @@ const Toolbar = ()=>{
666
784
  onIsDragging,
667
785
  onIsEditingTextEditor,
668
786
  onShowParents,
669
- onResizeSpacing
787
+ onResizeSpacing,
788
+ onHoverComponent,
789
+ onToolbarOnboarding,
790
+ onWindowResize
670
791
  ]);
671
- return null;
792
+ return isOnboarding && /*#__PURE__*/ jsxRuntime.jsx(Onboarding.default, {
793
+ enable: true,
794
+ position: onboardingPosition,
795
+ onCloseOnboarding: onCloseOnboarding
796
+ });
797
+ };
798
+ const getDOMElementParents = ($el, selector, limit)=>{
799
+ // Set up a parent array
800
+ const parents = [];
801
+ // Push each parent $elms to the array
802
+ while($el){
803
+ $el = $el.parentElement ?? undefined;
804
+ if ($el) {
805
+ if ($el.tagName === 'BODY' || $el.getAttribute('data-uid') === 'ROOT') {
806
+ break;
807
+ }
808
+ if (selector) {
809
+ if ($el.matches(selector)) {
810
+ parents.push($el);
811
+ if (limit && parents.length == limit) {
812
+ return parents;
813
+ }
814
+ }
815
+ continue;
816
+ }
817
+ parents.push($el);
818
+ if (limit && parents.length == limit) {
819
+ return parents;
820
+ }
821
+ }
822
+ }
823
+ // Return our parent array
824
+ return parents;
825
+ };
826
+ const getChildrenByAttrSelector = ($el, attrSelector)=>{
827
+ const childLen = $el.children.length;
828
+ if (childLen) {
829
+ for(let i = 0; i < childLen; i++){
830
+ const children = $el.children[i];
831
+ if (children) {
832
+ const is = children.getAttribute(attrSelector);
833
+ if (is) {
834
+ return children;
835
+ }
836
+ }
837
+ }
838
+ }
839
+ };
840
+ const isOverParent = ({ current, parent: parent1, index, revert })=>{
841
+ for(let i = 0; i < index; i++){
842
+ let is = current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent1.top && current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent1.top + parent1.height || current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent1.top + parent1.height && current.top - (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent1.top;
843
+ if (revert) {
844
+ is = current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent1.bottom && current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent1.bottom - parent1.height || current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i >= parent1.bottom - parent1.height && current.bottom + (TOOLBAR_HOVER_HEIGHT - 1) * i <= parent1.bottom;
845
+ }
846
+ if (is) return true;
847
+ }
848
+ return false;
849
+ };
850
+ const waitForElementToExist = (selector, timeout = 200)=>{
851
+ return new Promise((resolve)=>{
852
+ const intervalID = setInterval(()=>{
853
+ const el = document.querySelector(selector);
854
+ if (el) {
855
+ clearInterval(intervalID);
856
+ clearTimeout(timeoutID);
857
+ resolve(el);
858
+ }
859
+ }, 50);
860
+ const timeoutID = setTimeout(()=>{
861
+ clearInterval(intervalID);
862
+ clearTimeout(timeoutID);
863
+ resolve(null);
864
+ }, timeout);
865
+ });
866
+ };
867
+ const notVisible = (el)=>{
868
+ const overflow = getComputedStyle(el).overflow;
869
+ return overflow !== 'visible';
870
+ };
871
+ const isSection = (el)=>{
872
+ const tag = el.getAttribute('data-component-tag');
873
+ return tag === 'Section';
874
+ };
875
+ const isLayoutElement = (el)=>{
876
+ const tag = el.getAttribute('data-component-tag');
877
+ return tag === 'Row' || tag === 'Product';
878
+ };
879
+ const isOverToolbarPosition = (el, parent1)=>{
880
+ const rect = el.getBoundingClientRect();
881
+ const rectP = parent1.getBoundingClientRect();
882
+ // 32px = toolbar active height
883
+ return rect.top - rectP.top < TOOLBAR_ACTIVE_HEIGHT + 1;
884
+ };
885
+ const findOverflowParent = (element, initEl)=>{
886
+ const thisEl = element;
887
+ const origEl = initEl || thisEl;
888
+ if (!thisEl) return;
889
+ if (isSection(thisEl)) return;
890
+ if (notVisible(thisEl) && isOverToolbarPosition(initEl, thisEl)) return thisEl;
891
+ if (thisEl.parentElement) {
892
+ return findOverflowParent(thisEl.parentElement, origEl);
893
+ } else {
894
+ return;
895
+ }
672
896
  };
673
897
  var Toolbar$1 = /*#__PURE__*/ react.memo(Toolbar);
674
898