PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.2
Elementor Website Builder – more than just a page builder v4.3.2
4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 All 455 releases
elementor / assets / js / packages / editor-floating-panels / editor-floating-panels.js

editor-floating-panels.js in Elementor Website Builder – more than just a page builder 4.3.2, at assets/js/packages/editor-floating-panels/editor-floating-panels.js

1,085 lines 35.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function(_elementor_store, _elementor_locations, react, _elementor_ui, _elementor_icons, _wordpress_i18n, _elementor_editor, _elementor_editor_v1_adapters, _elementor_editor_ui) {
2
3 //#region \0rolldown/runtime.js
4 var __create = Object.create;
5 var __defProp = Object.defineProperty;
6 var __name = (target, value) => __defProp(target, "name", {
7 value,
8 configurable: true
9 });
10 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11 var __getOwnPropNames = Object.getOwnPropertyNames;
12 var __getProtoOf = Object.getPrototypeOf;
13 var __hasOwnProp = Object.prototype.hasOwnProperty;
14 var __exportAll = (all, no_symbols) => {
15 let target = {};
16 for (var name in all) {
17 __defProp(target, name, {
18 get: all[name],
19 enumerable: true
20 });
21 }
22 if (!no_symbols) {
23 __defProp(target, Symbol.toStringTag, { value: "Module" });
24 }
25 return target;
26 };
27 var __copyProps = (to, from, except, desc) => {
28 if (from && typeof from === "object" || typeof from === "function") {
29 for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
30 key = keys[i];
31 if (!__hasOwnProp.call(to, key) && key !== except) {
32 __defProp(to, key, {
33 get: ((k) => from[k]).bind(null, key),
34 enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
35 });
36 }
37 }
38 }
39 return to;
40 };
41 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
42 value: mod,
43 enumerable: true
44 }) : target, mod));
45
46 //#endregion
47 react = __toESM(react);
48
49 //#region packages/packages/core/editor-floating-panels/src/constants.ts
50 var FLOATING_PANEL_Z_INDEX_BASE = 1e3;
51
52 //#endregion
53 //#region packages/packages/core/editor-floating-panels/src/store/selectors.ts
54 function selectPanelState(state, id) {
55 return state.floatingPanels.byId[id];
56 }
57 function resolvePanelZIndex(state, id) {
58 return FLOATING_PANEL_Z_INDEX_BASE + (state.floatingPanels.byId[id]?.zIndex ?? 0);
59 }
60 function resolveOverlayZIndex(state, id) {
61 return resolvePanelZIndex(state, id) + 1;
62 }
63 function selectIsOpen(state, id) {
64 return state.floatingPanels.byId[id]?.isOpen ?? false;
65 }
66 function selectCorner(state, id) {
67 return state.floatingPanels.byId[id]?.corner;
68 }
69 function selectPosition(state, id) {
70 return state.floatingPanels.byId[id]?.position;
71 }
72 function selectSize(state, id) {
73 return state.floatingPanels.byId[id]?.size;
74 }
75 function selectMinSize(state, id) {
76 return state.floatingPanels.minSizeById[id];
77 }
78 function selectIsDraggable(state, id) {
79 return state.floatingPanels.isDraggableById[id] ?? false;
80 }
81 function selectIsResizable(state, id) {
82 return state.floatingPanels.isResizableById[id] ?? false;
83 }
84 function selectPanelTitle(state, id) {
85 return state.floatingPanels.titlesById[id];
86 }
87 var selectOpenPanelIds = (0, _elementor_store.__createSelector)([(state) => state.floatingPanels.byId], (byId) => Object.entries(byId).filter(([, panel]) => panel.isOpen).sort(([, a], [, b]) => a.zIndex - b.zIndex).map(([id]) => id));
88
89 //#endregion
90 //#region packages/packages/core/editor-floating-panels/src/utils/corner-position.ts
91 var DEFAULT_INSET_BLOCK_PX = 80;
92 var DEFAULT_INSET_INLINE_PX = 24;
93 var ACTIVE_INSETS = {
94 "block-start-inline-start": ["insetInlineStart", "insetBlockStart"],
95 "block-start-inline-end": ["insetInlineEnd", "insetBlockStart"],
96 "block-end-inline-start": ["insetInlineStart", "insetBlockEnd"],
97 "block-end-inline-end": ["insetInlineEnd", "insetBlockEnd"]
98 };
99 var CORNER_DEFAULTS = {
100 "block-start-inline-start": {
101 insetInlineStart: 24,
102 insetBlockStart: 80
103 },
104 "block-start-inline-end": {
105 insetInlineEnd: 24,
106 insetBlockStart: 80
107 },
108 "block-end-inline-start": {
109 insetInlineStart: 24,
110 insetBlockEnd: 80
111 },
112 "block-end-inline-end": {
113 insetInlineEnd: 24,
114 insetBlockEnd: 80
115 }
116 };
117 var EMPTY_POSITION = {
118 insetBlockStart: 0,
119 insetBlockEnd: 0,
120 insetInlineStart: 0,
121 insetInlineEnd: 0
122 };
123 function getActiveInsetKeys(corner) {
124 return ACTIVE_INSETS[corner];
125 }
126 function usesInlineStart(corner) {
127 return corner.endsWith("inline-start");
128 }
129 function usesBlockStart(corner) {
130 return corner.startsWith("block-start");
131 }
132 function buildInitialPosition(corner, overrides) {
133 const [inlineKey, blockKey] = getActiveInsetKeys(corner);
134 const defaults = CORNER_DEFAULTS[corner];
135 return {
136 ...EMPTY_POSITION,
137 [inlineKey]: overrides?.[inlineKey] ?? defaults[inlineKey] ?? 0,
138 [blockKey]: overrides?.[blockKey] ?? defaults[blockKey] ?? 0
139 };
140 }
141 function positionToCssInsets(corner, position) {
142 const [inlineKey, blockKey] = getActiveInsetKeys(corner);
143 return {
144 [inlineKey]: `${position[inlineKey]}px`,
145 [blockKey]: `${position[blockKey]}px`
146 };
147 }
148 function toStartAnchoredPosition(corner, position, size, viewport) {
149 return {
150 insetInlineStart: usesInlineStart(corner) ? position.insetInlineStart : viewport.width - position.insetInlineEnd - size.inlineSize,
151 insetBlockStart: usesBlockStart(corner) ? position.insetBlockStart : viewport.height - position.insetBlockEnd - size.blockSize
152 };
153 }
154 function fromStartAnchoredPosition(corner, startAnchored, size, viewport) {
155 if (usesInlineStart(corner) && usesBlockStart(corner)) return {
156 ...EMPTY_POSITION,
157 insetInlineStart: startAnchored.insetInlineStart,
158 insetBlockStart: startAnchored.insetBlockStart
159 };
160 const position = { ...EMPTY_POSITION };
161 if (usesInlineStart(corner)) {
162 position.insetInlineStart = startAnchored.insetInlineStart;
163 position.insetBlockEnd = viewport.height - startAnchored.insetBlockStart - size.blockSize;
164 } else if (usesBlockStart(corner)) {
165 position.insetInlineEnd = viewport.width - startAnchored.insetInlineStart - size.inlineSize;
166 position.insetBlockStart = startAnchored.insetBlockStart;
167 } else {
168 position.insetInlineEnd = viewport.width - startAnchored.insetInlineStart - size.inlineSize;
169 position.insetBlockEnd = viewport.height - startAnchored.insetBlockStart - size.blockSize;
170 }
171 return position;
172 }
173 function activePositionChanged(corner, before, after) {
174 const [inlineKey, blockKey] = getActiveInsetKeys(corner);
175 return before[inlineKey] !== after[inlineKey] || before[blockKey] !== after[blockKey];
176 }
177 function getDragBounds(size, viewport, sidePanelInlineSize, appBarHeight) {
178 return {
179 minInlineStart: sidePanelInlineSize,
180 maxInlineStart: viewport.width - size.inlineSize,
181 minInlineEnd: 0,
182 maxInlineEnd: viewport.width - sidePanelInlineSize - size.inlineSize,
183 minBlockStart: appBarHeight,
184 maxBlockStart: viewport.height - size.blockSize,
185 minBlockEnd: 0,
186 maxBlockEnd: viewport.height - appBarHeight - size.blockSize
187 };
188 }
189
190 //#endregion
191 //#region packages/packages/core/editor-floating-panels/src/store/slice.ts
192 var DEFAULT_CORNER = "block-start-inline-start";
193 var initialState = {
194 byId: {},
195 minSizeById: {},
196 titlesById: {},
197 isDraggableById: {},
198 isResizableById: {},
199 topZIndex: 0
200 };
201 var slice = (0, _elementor_store.__createSlice)({
202 name: "floatingPanels",
203 initialState,
204 reducers: {
205 register(state, action) {
206 const { id, defaults, title, isDraggable, isResizable, persisted } = action.payload;
207 state.minSizeById[id] = {
208 inlineSize: defaults.minWidth,
209 blockSize: defaults.minHeight
210 };
211 state.isDraggableById[id] = isDraggable ?? false;
212 state.isResizableById[id] = isResizable ?? false;
213 if (title !== void 0) state.titlesById[id] = title;
214 if (state.byId[id]) return;
215 const corner = defaults.corner ?? DEFAULT_CORNER;
216 const canReusePersisted = persisted && persisted.corner === corner;
217 state.byId[id] = canReusePersisted ? persisted : {
218 isOpen: false,
219 corner,
220 position: buildInitialPosition(corner, defaults.initialPosition),
221 size: {
222 inlineSize: defaults.width,
223 blockSize: defaults.height
224 },
225 zIndex: 0
226 };
227 if (persisted && persisted.zIndex > state.topZIndex) state.topZIndex = persisted.zIndex;
228 },
229 open(state, action) {
230 const panel = state.byId[action.payload];
231 if (panel) panel.isOpen = true;
232 },
233 close(state, action) {
234 const panel = state.byId[action.payload];
235 if (panel) panel.isOpen = false;
236 },
237 setPosition(state, action) {
238 const panel = state.byId[action.payload.id];
239 if (panel) panel.position = action.payload.position;
240 },
241 setSize(state, action) {
242 const panel = state.byId[action.payload.id];
243 if (panel) panel.size = action.payload.size;
244 },
245 bringToFront(state, action) {
246 const panel = state.byId[action.payload];
247 if (!panel) return;
248 state.topZIndex += 1;
249 panel.zIndex = state.topZIndex;
250 }
251 }
252 });
253
254 //#endregion
255 //#region packages/packages/core/editor-floating-panels/src/hooks/use-floating-panel-actions.ts
256 function useFloatingPanelActions(id) {
257 const dispatch = (0, _elementor_store.__useDispatch)();
258 const isOpen = (0, _elementor_store.__useSelector)((state) => selectIsOpen(state, id));
259 const open = () => {
260 dispatch(slice.actions.open(id));
261 dispatch(slice.actions.bringToFront(id));
262 };
263 const close = () => dispatch(slice.actions.close(id));
264 return {
265 open,
266 close,
267 toggle: () => isOpen ? close() : open(),
268 setPosition: (position) => dispatch(slice.actions.setPosition({
269 id,
270 position
271 })),
272 setSize: (size) => dispatch(slice.actions.setSize({
273 id,
274 size
275 })),
276 focus: () => dispatch(slice.actions.bringToFront(id))
277 };
278 }
279
280 //#endregion
281 //#region packages/packages/core/editor-floating-panels/src/hooks/use-floating-panel-status.ts
282 var selectStatus = (0, _elementor_store.__createSelector)([
283 (state, id) => selectIsOpen(state, id),
284 (state, id) => selectCorner(state, id),
285 (state, id) => selectPosition(state, id),
286 (state, id) => selectSize(state, id)
287 ], (isOpen, corner, position, size) => ({
288 isOpen,
289 corner,
290 position,
291 size
292 }));
293 function useFloatingPanelStatus(id) {
294 return (0, _elementor_store.__useSelector)((state) => selectStatus(state, id));
295 }
296
297 //#endregion
298 //#region packages/packages/core/editor-floating-panels/src/location.ts
299 var { inject: injectIntoFloatingPanels, useInjections: useFloatingPanelsInjections } = (0, _elementor_locations.createLocation)();
300
301 //#endregion
302 //#region packages/packages/core/editor-floating-panels/src/persistence.ts
303 var PERSISTENCE_STORAGE_KEY = "elementor_floating_panels_state";
304 var VALID_PANEL_CORNERS = /* @__PURE__ */ new Set([
305 "block-start-inline-start",
306 "block-start-inline-end",
307 "block-end-inline-start",
308 "block-end-inline-end"
309 ]);
310 function encodePersistedState(state) {
311 return JSON.stringify(state);
312 }
313 function decodePersistedState(raw) {
314 if (!raw) return {};
315 let parsed;
316 try {
317 parsed = JSON.parse(raw);
318 } catch {
319 return {};
320 }
321 if (typeof parsed !== "object" || parsed === null) return {};
322 const result = {};
323 for (const [id, value] of Object.entries(parsed)) if (isPanelState(value)) result[id] = value;
324 return result;
325 }
326 function isPanelState(value) {
327 if (typeof value !== "object" || value === null) return false;
328 const v = value;
329 if (typeof v.size !== "object" || v.size === null) return false;
330 if (typeof v.position !== "object" || v.position === null) return false;
331 const size = v.size;
332 const position = v.position;
333 return typeof v.isOpen === "boolean" && typeof v.zIndex === "number" && typeof v.corner === "string" && VALID_PANEL_CORNERS.has(v.corner) && typeof size.inlineSize === "number" && typeof size.blockSize === "number" && typeof position.insetInlineStart === "number" && typeof position.insetInlineEnd === "number" && typeof position.insetBlockStart === "number" && typeof position.insetBlockEnd === "number";
334 }
335
336 //#endregion
337 //#region packages/packages/core/editor-floating-panels/src/sync.ts
338 var PERSIST_DEBOUNCE_MS = 250;
339 var localStorageAdapter = {
340 read: () => {
341 try {
342 return globalThis.localStorage?.getItem("elementor_floating_panels_state") ?? null;
343 } catch {
344 return null;
345 }
346 },
347 write: (value) => {
348 try {
349 globalThis.localStorage?.setItem(PERSISTENCE_STORAGE_KEY, value);
350 } catch {}
351 }
352 };
353 var cachedPersistedState = {};
354 var isSyncInitialized = false;
355 var persistenceTimer = null;
356 var persistenceUnsubscribe = null;
357 var persistenceSession = 0;
358 function isFloatingPanelsSyncInitialized() {
359 return isSyncInitialized;
360 }
361 function sync(storage = localStorageAdapter) {
362 isSyncInitialized = true;
363 cachedPersistedState = decodePersistedState(storage.read());
364 schedulePersistence(storage);
365 }
366 function getPersistedState(id) {
367 return cachedPersistedState[id];
368 }
369 var STORE_READY_POLL_MS = 16;
370 function clearPersistenceTimer() {
371 if (persistenceTimer) {
372 clearTimeout(persistenceTimer);
373 persistenceTimer = null;
374 }
375 }
376 function schedulePersistence(storage) {
377 clearPersistenceTimer();
378 persistenceUnsubscribe?.();
379 persistenceUnsubscribe = null;
380 const session = ++persistenceSession;
381 const subscribe = () => {
382 if (session !== persistenceSession) return;
383 persistenceUnsubscribe = (0, _elementor_store.__subscribeWithSelector)((state) => state.floatingPanels.byId, (byId) => {
384 clearPersistenceTimer();
385 persistenceTimer = setTimeout(() => {
386 if (session !== persistenceSession) return;
387 cachedPersistedState = {
388 ...cachedPersistedState,
389 ...byId
390 };
391 storage.write(encodePersistedState(cachedPersistedState));
392 }, PERSIST_DEBOUNCE_MS);
393 });
394 };
395 const waitForStore = () => {
396 if (session !== persistenceSession) return;
397 if ((0, _elementor_store.__getStore)()) {
398 subscribe();
399 return;
400 }
401 setTimeout(waitForStore, STORE_READY_POLL_MS);
402 };
403 waitForStore();
404 }
405
406 //#endregion
407 //#region packages/packages/core/editor-floating-panels/src/api.ts
408 function createFloatingPanel(declaration) {
409 const persisted = isFloatingPanelsSyncInitialized() ? getPersistedState(declaration.id) : decodePersistedState(localStorageAdapter.read())[declaration.id];
410 (0, _elementor_store.__dispatch)(slice.actions.register({
411 id: declaration.id,
412 title: declaration.title,
413 isDraggable: declaration.isDraggable,
414 isResizable: declaration.isResizable,
415 defaults: declaration.defaults,
416 persisted
417 }));
418 return {
419 panel: declaration,
420 useFloatingPanelStatus: () => useFloatingPanelStatus(declaration.id),
421 useFloatingPanelActions: () => useFloatingPanelActions(declaration.id)
422 };
423 }
424 function registerFloatingPanel(declaration) {
425 injectIntoFloatingPanels({
426 id: declaration.id,
427 component: declaration.component
428 });
429 }
430
431 //#endregion
432 //#region packages/packages/core/editor-floating-panels/src/components/external/floating-panel.tsx
433 function FloatingPanel({ children }) {
434 return /* @__PURE__ */ react.createElement(react.Fragment, null, children);
435 }
436
437 //#endregion
438 //#region packages/packages/core/editor-floating-panels/src/components/external/floating-panel-body.tsx
439 function FloatingPanelBody(props) {
440 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
441 ...props,
442 sx: {
443 flex: 1,
444 overflowY: "auto",
445 ...props.sx ?? {}
446 }
447 });
448 }
449
450 //#endregion
451 //#region packages/packages/core/editor-floating-panels/src/components/external/floating-panel-footer.tsx
452 function FloatingPanelFooter({ children, sx, ...props }) {
453 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
454 ...props,
455 sx: {
456 px: 2,
457 py: 1.5,
458 borderTop: 1,
459 borderColor: "var(--e-a-border-color)",
460 display: "flex",
461 alignItems: "center",
462 gap: 1,
463 ...sx ?? {}
464 }
465 }, children);
466 }
467
468 //#endregion
469 //#region packages/packages/core/editor-floating-panels/src/hooks/use-floating-panel-z-index.ts
470 function useFloatingPanelZIndex(panelId) {
471 return (0, _elementor_store.__useSelector)((state) => resolveOverlayZIndex(state, panelId));
472 }
473
474 //#endregion
475 //#region packages/packages/core/editor-floating-panels/src/utils/direction.ts
476 function isRtl() {
477 return (document?.documentElement?.dir ?? "").toLowerCase() === "rtl";
478 }
479
480 //#endregion
481 //#region packages/packages/core/editor-floating-panels/src/utils/clamp.ts
482 function clamp(value, min, max) {
483 return Math.min(Math.max(min, value), Math.max(min, max));
484 }
485
486 //#endregion
487 //#region packages/packages/core/editor-floating-panels/src/utils/drag-math.ts
488 function physicalToLogicalDelta(delta, isRtl) {
489 return {
490 inlineDelta: isRtl ? -delta.dx : delta.dx,
491 blockDelta: delta.dy
492 };
493 }
494 function applyDragDelta(corner, position, delta, bounds) {
495 const [inlineKey, blockKey] = getActiveInsetKeys(corner);
496 const inlineDelta = usesInlineStart(corner) ? delta.inlineDelta : -delta.inlineDelta;
497 const blockDelta = usesBlockStart(corner) ? delta.blockDelta : -delta.blockDelta;
498 const inlineBounds = inlineKey === "insetInlineStart" ? {
499 min: bounds.minInlineStart,
500 max: bounds.maxInlineStart
501 } : {
502 min: bounds.minInlineEnd,
503 max: bounds.maxInlineEnd
504 };
505 const blockBounds = blockKey === "insetBlockStart" ? {
506 min: bounds.minBlockStart,
507 max: bounds.maxBlockStart
508 } : {
509 min: bounds.minBlockEnd,
510 max: bounds.maxBlockEnd
511 };
512 return {
513 ...position,
514 [inlineKey]: clamp(position[inlineKey] + inlineDelta, inlineBounds.min, inlineBounds.max),
515 [blockKey]: clamp(position[blockKey] + blockDelta, blockBounds.min, blockBounds.max)
516 };
517 }
518
519 //#endregion
520 //#region packages/packages/core/editor-floating-panels/src/utils/viewport-bounds.ts
521 var SIDE_PANEL_SELECTOR = "#elementor-panel";
522 function getSidePanelInlineSize() {
523 return document.querySelector(SIDE_PANEL_SELECTOR)?.getBoundingClientRect().width ?? 0;
524 }
525
526 //#endregion
527 //#region packages/packages/core/editor-floating-panels/src/hooks/use-floating-panel-drag.ts
528 function useFloatingPanelDrag(id) {
529 const sessionRef = (0, react.useRef)(null);
530 const { corner, position, size } = useFloatingPanelStatus(id);
531 const { setPosition } = useFloatingPanelActions(id);
532 const onPointerDown = (0, react.useCallback)((event) => {
533 if (!corner || !position || !size) return;
534 event.currentTarget.setPointerCapture(event.pointerId);
535 sessionRef.current = {
536 pointerId: event.pointerId,
537 startClientX: event.clientX,
538 startClientY: event.clientY,
539 startPosition: position,
540 lastDispatchedPosition: position,
541 bounds: getDragBounds(size, {
542 width: window.innerWidth,
543 height: window.innerHeight
544 }, getSidePanelInlineSize(), 48),
545 corner,
546 isRtl: isRtl()
547 };
548 }, [
549 corner,
550 position,
551 size
552 ]);
553 const onPointerMove = (0, react.useCallback)((event) => {
554 const session = sessionRef.current;
555 if (!session || session.pointerId !== event.pointerId) return;
556 const logical = physicalToLogicalDelta({
557 dx: event.clientX - session.startClientX,
558 dy: event.clientY - session.startClientY
559 }, session.isRtl);
560 const nextPosition = applyDragDelta(session.corner, session.startPosition, logical, session.bounds);
561 if (activePositionChanged(session.corner, session.lastDispatchedPosition, nextPosition)) {
562 setPosition(nextPosition);
563 session.lastDispatchedPosition = nextPosition;
564 }
565 }, [setPosition]);
566 const clearSession = (0, react.useCallback)((event) => {
567 const session = sessionRef.current;
568 if (!session || session.pointerId !== event.pointerId) return;
569 sessionRef.current = null;
570 }, []);
571 return {
572 onPointerDown,
573 onPointerMove,
574 onPointerUp: clearSession,
575 onPointerCancel: clearSession
576 };
577 }
578
579 //#endregion
580 //#region packages/packages/core/editor-floating-panels/src/components/internal/drag-handle.tsx
581 function DragHandle({ panelId, children }) {
582 const { onPointerDown, onPointerMove, onPointerUp, onPointerCancel } = useFloatingPanelDrag(panelId);
583 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
584 role: "button",
585 "aria-label": (0, _wordpress_i18n.__)("Drag to reposition", "elementor"),
586 onPointerDown,
587 onPointerMove,
588 onPointerUp,
589 onPointerCancel,
590 sx: {
591 cursor: "move",
592 touchAction: "none",
593 flex: 1
594 }
595 }, children);
596 }
597
598 //#endregion
599 //#region packages/packages/core/editor-floating-panels/src/components/external/floating-panel-header.tsx
600 function HeaderAction({ icon: Icon, label, onClick, panelZIndex, disabled = false }) {
601 return /* @__PURE__ */ react.createElement(_elementor_ui.Tooltip, {
602 title: label,
603 placement: "top",
604 PopperProps: { sx: { zIndex: panelZIndex } }
605 }, /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
606 component: "span",
607 "aria-label": void 0
608 }, /* @__PURE__ */ react.createElement(_elementor_ui.IconButton, {
609 size: "small",
610 color: "inherit",
611 "aria-label": label,
612 disabled,
613 onClick: disabled ? void 0 : onClick,
614 sx: {
615 borderRadius: 0,
616 p: 1
617 }
618 }, /* @__PURE__ */ react.createElement(Icon, null))));
619 }
620 function FloatingPanelHeader({ panelId, title, icon: Icon, actions, badge, titleVariant }) {
621 const { close } = useFloatingPanelActions(panelId);
622 const isDraggable = (0, _elementor_store.__useSelector)((state) => selectIsDraggable(state, panelId));
623 const hasActions = Boolean(actions?.length);
624 const panelZIndex = useFloatingPanelZIndex(panelId);
625 const hasBadge = Boolean(badge);
626 const titleContent = /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: {
627 display: "flex",
628 alignItems: "center",
629 justifyContent: hasBadge ? "flex-start" : "center",
630 gap: 1,
631 height: "100%",
632 pl: hasBadge ? 2 : 0
633 } }, Icon ? /* @__PURE__ */ react.createElement(Icon, null) : null, /* @__PURE__ */ react.createElement(_elementor_ui.Typography, {
634 component: "h2",
635 variant: titleVariant,
636 sx: {
637 textAlign: hasBadge ? "left" : "center",
638 ...!titleVariant && {
639 fontSize: "13px",
640 fontWeight: 400
641 }
642 }
643 }, title), badge ? /* @__PURE__ */ react.createElement(_elementor_ui.Chip, {
644 label: badge,
645 size: "tiny",
646 variant: "standard"
647 }) : null);
648 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: {
649 display: "flex",
650 alignItems: "stretch",
651 borderBottom: 1,
652 borderColor: "var(--e-a-border-color)",
653 overflow: "visible"
654 } }, hasActions ? /* @__PURE__ */ react.createElement(_elementor_ui.Stack, {
655 direction: "row",
656 alignItems: "center",
657 sx: {
658 flexShrink: 0,
659 overflow: "visible"
660 }
661 }, actions?.map((action) => /* @__PURE__ */ react.createElement(HeaderAction, {
662 key: action.id,
663 panelZIndex,
664 ...action
665 }))) : null, isDraggable ? /* @__PURE__ */ react.createElement(DragHandle, { panelId }, titleContent) : /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: { flex: 1 } }, titleContent), /* @__PURE__ */ react.createElement(_elementor_ui.IconButton, {
666 size: "small",
667 color: "inherit",
668 "aria-label": (0, _wordpress_i18n.__)("Close panel", "elementor"),
669 onClick: close,
670 sx: {
671 borderRadius: 0,
672 p: 1
673 }
674 }, /* @__PURE__ */ react.createElement(_elementor_icons.XIcon, { fontSize: "small" })));
675 }
676
677 //#endregion
678 //#region packages/packages/core/editor-floating-panels/src/utils/resize-math.ts
679 function applyInlineEndResize(size, inlineDelta, bounds) {
680 return {
681 inlineSize: clamp(size.inlineSize + inlineDelta, bounds.minInlineSize, bounds.maxInlineSize),
682 blockSize: size.blockSize
683 };
684 }
685 function applyBlockEndResize(size, blockDelta, bounds) {
686 return {
687 inlineSize: size.inlineSize,
688 blockSize: clamp(size.blockSize + blockDelta, bounds.minBlockSize, bounds.maxBlockSize)
689 };
690 }
691 function applyInlineStartResize(position, size, inlineDelta, bounds) {
692 const anchorInlineEnd = position.insetInlineStart + size.inlineSize;
693 const lowBound = Math.max(bounds.minInlineStart, anchorInlineEnd - bounds.maxInlineSize);
694 const highBound = anchorInlineEnd - bounds.minInlineSize;
695 const nextInlineStart = clamp(position.insetInlineStart + inlineDelta, lowBound, highBound);
696 return {
697 position: {
698 ...position,
699 insetInlineStart: nextInlineStart
700 },
701 size: {
702 ...size,
703 inlineSize: anchorInlineEnd - nextInlineStart
704 }
705 };
706 }
707 function applyBlockStartResize(position, size, blockDelta, bounds) {
708 const anchorBlockEnd = position.insetBlockStart + size.blockSize;
709 const lowBound = Math.max(bounds.minBlockStart, anchorBlockEnd - bounds.maxBlockSize);
710 const highBound = anchorBlockEnd - bounds.minBlockSize;
711 const nextBlockStart = clamp(position.insetBlockStart + blockDelta, lowBound, highBound);
712 return {
713 position: {
714 ...position,
715 insetBlockStart: nextBlockStart
716 },
717 size: {
718 ...size,
719 blockSize: anchorBlockEnd - nextBlockStart
720 }
721 };
722 }
723 function applyResize(direction, position, size, inlineDelta, blockDelta, bounds) {
724 if (direction === "inline-end") return {
725 position,
726 size: applyInlineEndResize(size, inlineDelta, bounds)
727 };
728 if (direction === "block-end") return {
729 position,
730 size: applyBlockEndResize(size, blockDelta, bounds)
731 };
732 if (direction === "inline-start") return applyInlineStartResize(position, size, inlineDelta, bounds);
733 if (direction === "block-start") return applyBlockStartResize(position, size, blockDelta, bounds);
734 let next = {
735 position,
736 size
737 };
738 if (direction.includes("inline-start")) next = applyInlineStartResize(next.position, next.size, inlineDelta, bounds);
739 else next = {
740 position: next.position,
741 size: applyInlineEndResize(next.size, inlineDelta, bounds)
742 };
743 if (direction.includes("block-start")) next = applyBlockStartResize(next.position, next.size, blockDelta, bounds);
744 else next = {
745 position: next.position,
746 size: applyBlockEndResize(next.size, blockDelta, bounds)
747 };
748 return next;
749 }
750
751 //#endregion
752 //#region packages/packages/core/editor-floating-panels/src/hooks/use-floating-panel-resize.ts
753 function getResizeBounds(corner, position, currentSize, minSize) {
754 const startAnchored = toStartAnchoredPosition(corner, position, currentSize, {
755 width: window.innerWidth,
756 height: window.innerHeight
757 });
758 return {
759 minBlockSize: minSize.blockSize,
760 maxBlockSize: window.innerHeight - startAnchored.insetBlockStart,
761 minInlineSize: minSize.inlineSize,
762 maxInlineSize: window.innerWidth - startAnchored.insetInlineStart,
763 minInlineStart: getSidePanelInlineSize(),
764 minBlockStart: 48
765 };
766 }
767 function usePanelResizeInteraction(id) {
768 const sessionRef = (0, react.useRef)(null);
769 const { corner, position, size } = useFloatingPanelStatus(id);
770 const minSize = (0, _elementor_store.__useSelector)((state) => selectMinSize(state, id));
771 const { setPosition, setSize } = useFloatingPanelActions(id);
772 const onPointerDown = (0, react.useCallback)((direction, event) => {
773 if (!corner || !position || !size || !minSize) return;
774 event.currentTarget.setPointerCapture(event.pointerId);
775 sessionRef.current = {
776 pointerId: event.pointerId,
777 direction,
778 startClientX: event.clientX,
779 startClientY: event.clientY,
780 startPosition: position,
781 startSize: size,
782 lastPosition: position,
783 lastSize: size,
784 bounds: getResizeBounds(corner, position, size, minSize),
785 corner,
786 isRtl: isRtl()
787 };
788 }, [
789 corner,
790 position,
791 size,
792 minSize
793 ]);
794 const onPointerMove = (0, react.useCallback)((event) => {
795 const session = sessionRef.current;
796 if (!session || session.pointerId !== event.pointerId) return;
797 const logical = physicalToLogicalDelta({
798 dx: event.clientX - session.startClientX,
799 dy: event.clientY - session.startClientY
800 }, session.isRtl);
801 const viewport = {
802 width: window.innerWidth,
803 height: window.innerHeight
804 };
805 const startAnchoredPosition = toStartAnchoredPosition(session.corner, session.startPosition, session.startSize, viewport);
806 const resizeInput = {
807 ...session.startPosition,
808 ...startAnchoredPosition
809 };
810 const next = applyResize(session.direction, resizeInput, session.startSize, logical.inlineDelta, logical.blockDelta, session.bounds);
811 const nextPosition = fromStartAnchoredPosition(session.corner, {
812 insetBlockStart: next.position.insetBlockStart,
813 insetInlineStart: next.position.insetInlineStart
814 }, next.size, viewport);
815 if (activePositionChanged(session.corner, session.lastPosition, nextPosition)) {
816 setPosition(nextPosition);
817 session.lastPosition = nextPosition;
818 }
819 if (next.size.inlineSize !== session.lastSize.inlineSize || next.size.blockSize !== session.lastSize.blockSize) {
820 setSize(next.size);
821 session.lastSize = next.size;
822 }
823 }, [setPosition, setSize]);
824 const clearSession = (0, react.useCallback)((event) => {
825 const session = sessionRef.current;
826 if (!session || session.pointerId !== event.pointerId) return;
827 sessionRef.current = null;
828 }, []);
829 return { getResizeHandleProps: (0, react.useCallback)((direction) => {
830 return {
831 onPointerDown: (event) => onPointerDown(direction, event),
832 onPointerMove,
833 onPointerUp: clearSession,
834 onPointerCancel: clearSession
835 };
836 }, [
837 onPointerDown,
838 onPointerMove,
839 clearSession
840 ]) };
841 }
842
843 //#endregion
844 //#region packages/packages/core/editor-floating-panels/src/components/internal/corner-resize-handle.tsx
845 var HANDLE_SIZE_PX = 8;
846 var CORNER_POSITION = {
847 "block-start-inline-start": {
848 insetBlockStart: 0,
849 insetInlineStart: 0
850 },
851 "block-start-inline-end": {
852 insetBlockStart: 0,
853 insetInlineEnd: 0
854 },
855 "block-end-inline-start": {
856 insetBlockEnd: 0,
857 insetInlineStart: 0
858 },
859 "block-end-inline-end": {
860 insetBlockEnd: 0,
861 insetInlineEnd: 0
862 }
863 };
864 var LTR_CURSORS = {
865 "block-start-inline-start": "nwse-resize",
866 "block-start-inline-end": "nesw-resize",
867 "block-end-inline-start": "nesw-resize",
868 "block-end-inline-end": "nwse-resize"
869 };
870 var RTL_CURSORS = {
871 "block-start-inline-start": "nesw-resize",
872 "block-start-inline-end": "nwse-resize",
873 "block-end-inline-start": "nwse-resize",
874 "block-end-inline-end": "nesw-resize"
875 };
876 function CornerResizeHandle({ corner, onPointerDown, onPointerMove, onPointerUp, onPointerCancel }) {
877 const cursor = isRtl() ? RTL_CURSORS[corner] : LTR_CURSORS[corner];
878 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
879 "data-resize-corner": corner,
880 "aria-hidden": "true",
881 onPointerDown,
882 onPointerMove,
883 onPointerUp,
884 onPointerCancel,
885 sx: {
886 position: "absolute",
887 touchAction: "none",
888 zIndex: 2,
889 inlineSize: `${HANDLE_SIZE_PX}px`,
890 blockSize: `${HANDLE_SIZE_PX}px`,
891 cursor,
892 ...CORNER_POSITION[corner]
893 }
894 });
895 }
896
897 //#endregion
898 //#region packages/packages/core/editor-floating-panels/src/components/internal/resize-handle.tsx
899 var HANDLE_THICKNESS_PX = 8;
900 var EDGE_SX = {
901 "inline-start": {
902 insetBlockStart: 0,
903 insetBlockEnd: 0,
904 insetInlineStart: 0,
905 inlineSize: `${HANDLE_THICKNESS_PX}px`,
906 cursor: "ew-resize"
907 },
908 "inline-end": {
909 insetBlockStart: 0,
910 insetBlockEnd: 0,
911 insetInlineEnd: 0,
912 inlineSize: `${HANDLE_THICKNESS_PX}px`,
913 cursor: "ew-resize"
914 },
915 "block-start": {
916 insetInlineStart: 0,
917 insetInlineEnd: 0,
918 insetBlockStart: 0,
919 blockSize: `${HANDLE_THICKNESS_PX}px`,
920 cursor: "ns-resize"
921 },
922 "block-end": {
923 insetInlineStart: 0,
924 insetInlineEnd: 0,
925 insetBlockEnd: 0,
926 blockSize: `${HANDLE_THICKNESS_PX}px`,
927 cursor: "ns-resize"
928 }
929 };
930 function ResizeHandle({ edge, onPointerDown, onPointerMove, onPointerUp, onPointerCancel }) {
931 return /* @__PURE__ */ react.createElement(_elementor_ui.Box, {
932 "data-resize-edge": edge,
933 "aria-hidden": "true",
934 onPointerDown,
935 onPointerMove,
936 onPointerUp,
937 onPointerCancel,
938 sx: {
939 position: "absolute",
940 touchAction: "none",
941 zIndex: 1,
942 ...EDGE_SX[edge]
943 }
944 });
945 }
946
947 //#endregion
948 //#region packages/packages/core/editor-floating-panels/src/components/internal/panel-window.tsx
949 var FADE_ENTER_MS = 225;
950 var FADE_EXIT_MS = 195;
951 var RESIZE_EDGES = [
952 "inline-start",
953 "inline-end",
954 "block-start",
955 "block-end"
956 ];
957 var RESIZE_CORNERS = [
958 "block-start-inline-start",
959 "block-start-inline-end",
960 "block-end-inline-start",
961 "block-end-inline-end"
962 ];
963 function PanelResizeHandles({ panelId }) {
964 const { getResizeHandleProps } = usePanelResizeInteraction(panelId);
965 return /* @__PURE__ */ react.createElement(react.Fragment, null, RESIZE_EDGES.map((edge) => /* @__PURE__ */ react.createElement(ResizeHandle, {
966 key: edge,
967 edge,
968 ...getResizeHandleProps(edge)
969 })), RESIZE_CORNERS.map((corner) => /* @__PURE__ */ react.createElement(CornerResizeHandle, {
970 key: corner,
971 corner,
972 ...getResizeHandleProps(corner)
973 })));
974 }
975 function PanelWindow({ panelId, corner, position, size, title, zIndex, visible, onFocus, children }) {
976 const isResizable = (0, _elementor_store.__useSelector)((state) => selectIsResizable(state, panelId));
977 return /* @__PURE__ */ react.createElement(_elementor_ui.Fade, {
978 in: visible,
979 timeout: {
980 enter: FADE_ENTER_MS,
981 exit: FADE_EXIT_MS
982 }
983 }, /* @__PURE__ */ react.createElement(_elementor_ui.Paper, {
984 component: "aside",
985 "data-floating-panel": panelId,
986 elevation: 0,
987 "aria-label": title || panelId,
988 "aria-hidden": !visible,
989 inert: !visible ? "" : void 0,
990 onMouseDown: onFocus,
991 onFocusCapture: onFocus,
992 sx: {
993 position: "fixed",
994 ...positionToCssInsets(corner, position),
995 inlineSize: `${size.inlineSize}px`,
996 blockSize: `${size.blockSize}px`,
997 zIndex,
998 display: "flex",
999 flexDirection: "column",
1000 pointerEvents: visible ? "auto" : "none",
1001 bgcolor: "var(--e-a-bg-default)",
1002 color: "var(--e-a-color-txt)",
1003 border: "var(--e-a-border)",
1004 boxShadow: `0 2px 20px 0 rgba(0, 0, 0, 0.1)`
1005 }
1006 }, /* @__PURE__ */ react.createElement(_elementor_editor_ui.ThemeProvider, null, /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: {
1007 display: "flex",
1008 flexDirection: "column",
1009 height: "100%"
1010 } }, children)), isResizable && /* @__PURE__ */ react.createElement(PanelResizeHandles, { panelId })));
1011 }
1012
1013 //#endregion
1014 //#region packages/packages/core/editor-floating-panels/src/components/internal/host.tsx
1015 function FloatingPanelsHost() {
1016 const openIds = (0, _elementor_store.__useSelector)(selectOpenPanelIds);
1017 const injections = useFloatingPanelsInjections();
1018 const dispatch = (0, _elementor_store.__useDispatch)();
1019 const isPreviewMode = (0, _elementor_editor_v1_adapters.useEditMode)() === "preview";
1020 const declarationById = (0, react.useMemo)(() => {
1021 return Object.fromEntries(injections.map((inj) => [inj.id, inj]));
1022 }, [injections]);
1023 return /* @__PURE__ */ react.createElement(react.Fragment, null, openIds.map((id) => {
1024 const declaration = declarationById[id];
1025 if (!declaration) return null;
1026 const Component = declaration.component;
1027 return /* @__PURE__ */ react.createElement(HostedPanel, {
1028 key: id,
1029 id,
1030 visible: !isPreviewMode,
1031 onFocus: () => dispatch(slice.actions.bringToFront(id))
1032 }, /* @__PURE__ */ react.createElement(Component, null));
1033 }));
1034 }
1035 function HostedPanel({ id, children, onFocus, visible }) {
1036 const panel = (0, _elementor_store.__useSelector)((state) => selectPanelState(state, id));
1037 const title = (0, _elementor_store.__useSelector)((state) => selectPanelTitle(state, id));
1038 const zIndex = (0, _elementor_store.__useSelector)((state) => resolvePanelZIndex(state, id));
1039 if (!panel) return null;
1040 return /* @__PURE__ */ react.createElement(PanelWindow, {
1041 panelId: id,
1042 corner: panel.corner,
1043 position: panel.position,
1044 size: panel.size,
1045 zIndex,
1046 visible,
1047 onFocus,
1048 title
1049 }, children);
1050 }
1051
1052 //#endregion
1053 //#region packages/packages/core/editor-floating-panels/src/init.ts
1054 function init() {
1055 sync();
1056 (0, _elementor_store.__registerSlice)(slice);
1057 (0, _elementor_editor.injectIntoTop)({
1058 id: "floating-panels",
1059 component: FloatingPanelsHost
1060 });
1061 }
1062
1063 //#endregion
1064 //#region packages/packages/core/editor-floating-panels/src/index.ts
1065 var src_exports = /* @__PURE__ */ __exportAll({
1066 FloatingPanel: () => FloatingPanel,
1067 FloatingPanelBody: () => FloatingPanelBody,
1068 FloatingPanelFooter: () => FloatingPanelFooter,
1069 FloatingPanelHeader: () => FloatingPanelHeader,
1070 createFloatingPanel: () => createFloatingPanel,
1071 init: () => init,
1072 registerFloatingPanel: () => registerFloatingPanel,
1073 useFloatingPanelActions: () => useFloatingPanelActions,
1074 useFloatingPanelStatus: () => useFloatingPanelStatus,
1075 useFloatingPanelZIndex: () => useFloatingPanelZIndex
1076 });
1077
1078 //#endregion
1079 //#region \0elementor-package-library-entry
1080 (window.elementorV2 = window.elementorV2 || {}).editorFloatingPanels = src_exports;
1081
1082 //#endregion
1083 })(elementorV2.store, elementorV2.locations, React, elementorV2.ui, elementorV2.icons, wp.i18n, elementorV2.editor, elementorV2.editorV1Adapters, elementorV2.editorUi);
1084 window.elementorV2.editorFloatingPanels?.init?.();
1085 //# sourceMappingURL=editor-floating-panels.js.map