@elementor/editor-floating-panels 4.3.0-970

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +117 -0
  3. package/dist/index.d.mts +159 -0
  4. package/dist/index.d.ts +159 -0
  5. package/dist/index.js +1108 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +1062 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +58 -0
  10. package/src/api.ts +36 -0
  11. package/src/components/external/floating-panel-body.tsx +15 -0
  12. package/src/components/external/floating-panel-footer.tsx +22 -0
  13. package/src/components/external/floating-panel-header.tsx +100 -0
  14. package/src/components/external/floating-panel.tsx +10 -0
  15. package/src/components/external/index.ts +4 -0
  16. package/src/components/internal/corner-resize-handle.tsx +69 -0
  17. package/src/components/internal/drag-handle.tsx +29 -0
  18. package/src/components/internal/host.tsx +86 -0
  19. package/src/components/internal/panel-window.tsx +100 -0
  20. package/src/components/internal/resize-handle.tsx +60 -0
  21. package/src/constants.ts +1 -0
  22. package/src/hooks/use-floating-panel-actions.ts +26 -0
  23. package/src/hooks/use-floating-panel-drag.ts +85 -0
  24. package/src/hooks/use-floating-panel-resize.ts +166 -0
  25. package/src/hooks/use-floating-panel-status.ts +17 -0
  26. package/src/hooks/use-floating-panel-z-index.ts +7 -0
  27. package/src/index.ts +15 -0
  28. package/src/init.ts +14 -0
  29. package/src/location.ts +3 -0
  30. package/src/persistence.ts +76 -0
  31. package/src/store/index.ts +2 -0
  32. package/src/store/selectors.ts +61 -0
  33. package/src/store/slice.ts +113 -0
  34. package/src/sync.ts +104 -0
  35. package/src/types.ts +64 -0
  36. package/src/utils/clamp.ts +3 -0
  37. package/src/utils/corner-position.ts +149 -0
  38. package/src/utils/direction.ts +3 -0
  39. package/src/utils/drag-math.ts +49 -0
  40. package/src/utils/resize-math.ts +107 -0
  41. package/src/utils/viewport-bounds.ts +7 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api.ts","../src/hooks/use-floating-panel-actions.ts","../src/store/selectors.ts","../src/constants.ts","../src/store/slice.ts","../src/utils/corner-position.ts","../src/hooks/use-floating-panel-status.ts","../src/location.ts","../src/persistence.ts","../src/sync.ts","../src/components/external/floating-panel.tsx","../src/components/external/floating-panel-body.tsx","../src/components/external/floating-panel-footer.tsx","../src/components/external/floating-panel-header.tsx","../src/hooks/use-floating-panel-z-index.ts","../src/components/internal/drag-handle.tsx","../src/hooks/use-floating-panel-drag.ts","../src/utils/direction.ts","../src/utils/clamp.ts","../src/utils/drag-math.ts","../src/utils/viewport-bounds.ts","../src/init.ts","../src/components/internal/host.tsx","../src/components/internal/panel-window.tsx","../src/hooks/use-floating-panel-resize.ts","../src/utils/resize-math.ts","../src/components/internal/corner-resize-handle.tsx","../src/components/internal/resize-handle.tsx"],"sourcesContent":["import { __dispatch as dispatch } from '@elementor/store';\n\nimport { useFloatingPanelActions } from './hooks/use-floating-panel-actions';\nimport { useFloatingPanelStatus } from './hooks/use-floating-panel-status';\nimport { injectIntoFloatingPanels } from './location';\nimport { decodePersistedState } from './persistence';\nimport { slice } from './store/slice';\nimport { getPersistedState, isFloatingPanelsSyncInitialized, localStorageAdapter } from './sync';\nimport { type FloatingPanelDeclaration } from './types';\n\nexport function createFloatingPanel( declaration: FloatingPanelDeclaration ) {\n\tconst persisted = isFloatingPanelsSyncInitialized()\n\t\t? getPersistedState( declaration.id )\n\t\t: decodePersistedState( localStorageAdapter.read() )[ declaration.id ];\n\n\tdispatch(\n\t\tslice.actions.register( {\n\t\t\tid: declaration.id,\n\t\t\ttitle: declaration.title,\n\t\t\tisDraggable: declaration.isDraggable,\n\t\t\tisResizable: declaration.isResizable,\n\t\t\tdefaults: declaration.defaults,\n\t\t\tpersisted,\n\t\t} )\n\t);\n\n\treturn {\n\t\tpanel: declaration,\n\t\tuseFloatingPanelStatus: () => useFloatingPanelStatus( declaration.id ),\n\t\tuseFloatingPanelActions: () => useFloatingPanelActions( declaration.id ),\n\t};\n}\n\nexport function registerFloatingPanel( declaration: Pick< FloatingPanelDeclaration, 'id' | 'component' > ): void {\n\tinjectIntoFloatingPanels( { id: declaration.id, component: declaration.component } );\n}\n","import { __useDispatch as useDispatch, __useSelector as useSelector } from '@elementor/store';\n\nimport { type GlobalState, selectIsOpen } from '../store/selectors';\nimport { slice } from '../store/slice';\nimport { type LogicalPosition, type LogicalSize } from '../types';\n\nexport function useFloatingPanelActions( id: string ) {\n\tconst dispatch = useDispatch();\n\tconst isOpen = useSelector( ( state: GlobalState ) => selectIsOpen( state, id ) );\n\n\tconst open = () => {\n\t\tdispatch( slice.actions.open( id ) );\n\t\tdispatch( slice.actions.bringToFront( id ) );\n\t};\n\n\tconst close = () => dispatch( slice.actions.close( id ) );\n\n\treturn {\n\t\topen,\n\t\tclose,\n\t\ttoggle: () => ( isOpen ? close() : open() ),\n\t\tsetPosition: ( position: LogicalPosition ) => dispatch( slice.actions.setPosition( { id, position } ) ),\n\t\tsetSize: ( size: LogicalSize ) => dispatch( slice.actions.setSize( { id, size } ) ),\n\t\tfocus: () => dispatch( slice.actions.bringToFront( id ) ),\n\t};\n}\n","import { __createSelector } from '@elementor/store';\n\nimport { FLOATING_PANEL_Z_INDEX_BASE } from '../constants';\nimport { type FloatingPanelsSliceState } from './slice';\n\nexport type GlobalState = { floatingPanels: FloatingPanelsSliceState };\n\nexport function selectPanelState( state: GlobalState, id: string ) {\n\treturn state.floatingPanels.byId[ id ];\n}\n\nexport function resolvePanelZIndex( state: GlobalState, id: string ): number {\n\treturn FLOATING_PANEL_Z_INDEX_BASE + ( state.floatingPanels.byId[ id ]?.zIndex ?? 0 );\n}\n\nexport function resolveOverlayZIndex( state: GlobalState, id: string ): number {\n\treturn resolvePanelZIndex( state, id ) + 1;\n}\n\nexport function selectIsOpen( state: GlobalState, id: string ): boolean {\n\treturn state.floatingPanels.byId[ id ]?.isOpen ?? false;\n}\n\nexport function selectCorner( state: GlobalState, id: string ) {\n\treturn state.floatingPanels.byId[ id ]?.corner;\n}\n\nexport function selectPosition( state: GlobalState, id: string ) {\n\treturn state.floatingPanels.byId[ id ]?.position;\n}\n\nexport function selectSize( state: GlobalState, id: string ) {\n\treturn state.floatingPanels.byId[ id ]?.size;\n}\n\nexport function selectMinSize( state: GlobalState, id: string ) {\n\treturn state.floatingPanels.minSizeById[ id ];\n}\n\nexport function selectIsDraggable( state: GlobalState, id: string ): boolean {\n\treturn state.floatingPanels.isDraggableById[ id ] ?? false;\n}\n\nexport function selectIsResizable( state: GlobalState, id: string ): boolean {\n\treturn state.floatingPanels.isResizableById[ id ] ?? false;\n}\n\nexport function selectPanelTitle( state: GlobalState, id: string ): string | undefined {\n\treturn state.floatingPanels.titlesById[ id ];\n}\n\nexport function selectTopZIndex( state: GlobalState ): number {\n\treturn state.floatingPanels.topZIndex;\n}\n\nexport const selectOpenPanelIds = __createSelector( [ ( state: GlobalState ) => state.floatingPanels.byId ], ( byId ) =>\n\tObject.entries( byId )\n\t\t.filter( ( [ , panel ] ) => panel.isOpen )\n\t\t.sort( ( [ , a ], [ , b ] ) => a.zIndex - b.zIndex )\n\t\t.map( ( [ id ] ) => id )\n);\n","export const FLOATING_PANEL_Z_INDEX_BASE = 1000;\n","import { __createSlice, type PayloadAction } from '@elementor/store';\n\nimport { type FloatingPanelDefaults, type FloatingPanelState, type LogicalPosition, type LogicalSize } from '../types';\nimport { buildInitialPosition, type PanelCorner } from '../utils/corner-position';\n\ntype SliceState = {\n\tbyId: Record< string, FloatingPanelState >;\n\tminSizeById: Record< string, LogicalSize >;\n\ttitlesById: Record< string, string >;\n\tisDraggableById: Record< string, boolean >;\n\tisResizableById: Record< string, boolean >;\n\ttopZIndex: number;\n};\n\nconst DEFAULT_CORNER: PanelCorner = 'block-start-inline-start';\n\nconst initialState: SliceState = {\n\tbyId: {},\n\tminSizeById: {},\n\ttitlesById: {},\n\tisDraggableById: {},\n\tisResizableById: {},\n\ttopZIndex: 0,\n};\n\nexport const slice = __createSlice( {\n\tname: 'floatingPanels',\n\tinitialState,\n\treducers: {\n\t\tregister(\n\t\t\tstate,\n\t\t\taction: PayloadAction< {\n\t\t\t\tid: string;\n\t\t\t\tdefaults: FloatingPanelDefaults;\n\t\t\t\ttitle?: string;\n\t\t\t\tisDraggable?: boolean;\n\t\t\t\tisResizable?: boolean;\n\t\t\t\tpersisted?: FloatingPanelState;\n\t\t\t} >\n\t\t) {\n\t\t\tconst { id, defaults, title, isDraggable, isResizable, persisted } = action.payload;\n\n\t\t\tstate.minSizeById[ id ] = { inlineSize: defaults.minWidth, blockSize: defaults.minHeight };\n\t\t\tstate.isDraggableById[ id ] = isDraggable ?? false;\n\t\t\tstate.isResizableById[ id ] = isResizable ?? false;\n\n\t\t\tif ( title !== undefined ) {\n\t\t\t\tstate.titlesById[ id ] = title;\n\t\t\t}\n\n\t\t\tif ( state.byId[ id ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst corner = defaults.corner ?? DEFAULT_CORNER;\n\t\t\tconst canReusePersisted = persisted && persisted.corner === corner;\n\n\t\t\tstate.byId[ id ] = canReusePersisted\n\t\t\t\t? persisted\n\t\t\t\t: {\n\t\t\t\t\t\tisOpen: false,\n\t\t\t\t\t\tcorner,\n\t\t\t\t\t\tposition: buildInitialPosition( corner, defaults.initialPosition ),\n\t\t\t\t\t\tsize: { inlineSize: defaults.width, blockSize: defaults.height },\n\t\t\t\t\t\tzIndex: 0,\n\t\t\t\t };\n\n\t\t\tif ( persisted && persisted.zIndex > state.topZIndex ) {\n\t\t\t\tstate.topZIndex = persisted.zIndex;\n\t\t\t}\n\t\t},\n\t\topen( state, action: PayloadAction< string > ) {\n\t\t\tconst panel = state.byId[ action.payload ];\n\n\t\t\tif ( panel ) {\n\t\t\t\tpanel.isOpen = true;\n\t\t\t}\n\t\t},\n\t\tclose( state, action: PayloadAction< string > ) {\n\t\t\tconst panel = state.byId[ action.payload ];\n\n\t\t\tif ( panel ) {\n\t\t\t\tpanel.isOpen = false;\n\t\t\t}\n\t\t},\n\t\tsetPosition( state, action: PayloadAction< { id: string; position: LogicalPosition } > ) {\n\t\t\tconst panel = state.byId[ action.payload.id ];\n\n\t\t\tif ( panel ) {\n\t\t\t\tpanel.position = action.payload.position;\n\t\t\t}\n\t\t},\n\t\tsetSize( state, action: PayloadAction< { id: string; size: LogicalSize } > ) {\n\t\t\tconst panel = state.byId[ action.payload.id ];\n\n\t\t\tif ( panel ) {\n\t\t\t\tpanel.size = action.payload.size;\n\t\t\t}\n\t\t},\n\t\tbringToFront( state, action: PayloadAction< string > ) {\n\t\t\tconst panel = state.byId[ action.payload ];\n\n\t\t\tif ( ! panel ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstate.topZIndex += 1;\n\t\t\tpanel.zIndex = state.topZIndex;\n\t\t},\n\t},\n} );\n\nexport type FloatingPanelsSliceState = SliceState;\n","import type { LogicalPosition, LogicalSize } from '../types';\n\nexport type PanelCorner =\n\t| 'block-start-inline-start'\n\t| 'block-start-inline-end'\n\t| 'block-end-inline-start'\n\t| 'block-end-inline-end';\n\nexport const DEFAULT_INSET_BLOCK_PX = 80;\nexport const DEFAULT_INSET_INLINE_PX = 24;\n\ntype InsetKey = keyof LogicalPosition;\n\nconst ACTIVE_INSETS: Record< PanelCorner, [ InsetKey, InsetKey ] > = {\n\t'block-start-inline-start': [ 'insetInlineStart', 'insetBlockStart' ],\n\t'block-start-inline-end': [ 'insetInlineEnd', 'insetBlockStart' ],\n\t'block-end-inline-start': [ 'insetInlineStart', 'insetBlockEnd' ],\n\t'block-end-inline-end': [ 'insetInlineEnd', 'insetBlockEnd' ],\n};\n\nconst CORNER_DEFAULTS: Record< PanelCorner, Partial< LogicalPosition > > = {\n\t'block-start-inline-start': { insetInlineStart: DEFAULT_INSET_INLINE_PX, insetBlockStart: DEFAULT_INSET_BLOCK_PX },\n\t'block-start-inline-end': { insetInlineEnd: DEFAULT_INSET_INLINE_PX, insetBlockStart: DEFAULT_INSET_BLOCK_PX },\n\t'block-end-inline-start': { insetInlineStart: DEFAULT_INSET_INLINE_PX, insetBlockEnd: DEFAULT_INSET_BLOCK_PX },\n\t'block-end-inline-end': { insetInlineEnd: DEFAULT_INSET_INLINE_PX, insetBlockEnd: DEFAULT_INSET_BLOCK_PX },\n};\n\nconst EMPTY_POSITION: LogicalPosition = {\n\tinsetBlockStart: 0,\n\tinsetBlockEnd: 0,\n\tinsetInlineStart: 0,\n\tinsetInlineEnd: 0,\n};\n\nexport function getActiveInsetKeys( corner: PanelCorner ): [ InsetKey, InsetKey ] {\n\treturn ACTIVE_INSETS[ corner ];\n}\n\nexport function usesInlineStart( corner: PanelCorner ): boolean {\n\treturn corner.endsWith( 'inline-start' );\n}\n\nexport function usesBlockStart( corner: PanelCorner ): boolean {\n\treturn corner.startsWith( 'block-start' );\n}\n\nexport function buildInitialPosition( corner: PanelCorner, overrides?: Partial< LogicalPosition > ): LogicalPosition {\n\tconst [ inlineKey, blockKey ] = getActiveInsetKeys( corner );\n\tconst defaults = CORNER_DEFAULTS[ corner ];\n\n\treturn {\n\t\t...EMPTY_POSITION,\n\t\t[ inlineKey ]: overrides?.[ inlineKey ] ?? defaults[ inlineKey ] ?? 0,\n\t\t[ blockKey ]: overrides?.[ blockKey ] ?? defaults[ blockKey ] ?? 0,\n\t};\n}\n\nexport function positionToCssInsets(\n\tcorner: PanelCorner,\n\tposition: LogicalPosition\n): Partial< Record< InsetKey, string > > {\n\tconst [ inlineKey, blockKey ] = getActiveInsetKeys( corner );\n\n\treturn {\n\t\t[ inlineKey ]: `${ position[ inlineKey ] }px`,\n\t\t[ blockKey ]: `${ position[ blockKey ] }px`,\n\t};\n}\n\nexport function toStartAnchoredPosition(\n\tcorner: PanelCorner,\n\tposition: LogicalPosition,\n\tsize: LogicalSize,\n\tviewport: { width: number; height: number }\n): Pick< LogicalPosition, 'insetInlineStart' | 'insetBlockStart' > {\n\treturn {\n\t\tinsetInlineStart: usesInlineStart( corner )\n\t\t\t? position.insetInlineStart\n\t\t\t: viewport.width - position.insetInlineEnd - size.inlineSize,\n\t\tinsetBlockStart: usesBlockStart( corner )\n\t\t\t? position.insetBlockStart\n\t\t\t: viewport.height - position.insetBlockEnd - size.blockSize,\n\t};\n}\n\nexport function fromStartAnchoredPosition(\n\tcorner: PanelCorner,\n\tstartAnchored: Pick< LogicalPosition, 'insetInlineStart' | 'insetBlockStart' >,\n\tsize: LogicalSize,\n\tviewport: { width: number; height: number }\n): LogicalPosition {\n\tif ( usesInlineStart( corner ) && usesBlockStart( corner ) ) {\n\t\treturn {\n\t\t\t...EMPTY_POSITION,\n\t\t\tinsetInlineStart: startAnchored.insetInlineStart,\n\t\t\tinsetBlockStart: startAnchored.insetBlockStart,\n\t\t};\n\t}\n\n\tconst position = { ...EMPTY_POSITION };\n\n\tif ( usesInlineStart( corner ) ) {\n\t\tposition.insetInlineStart = startAnchored.insetInlineStart;\n\t\tposition.insetBlockEnd = viewport.height - startAnchored.insetBlockStart - size.blockSize;\n\t} else if ( usesBlockStart( corner ) ) {\n\t\tposition.insetInlineEnd = viewport.width - startAnchored.insetInlineStart - size.inlineSize;\n\t\tposition.insetBlockStart = startAnchored.insetBlockStart;\n\t} else {\n\t\tposition.insetInlineEnd = viewport.width - startAnchored.insetInlineStart - size.inlineSize;\n\t\tposition.insetBlockEnd = viewport.height - startAnchored.insetBlockStart - size.blockSize;\n\t}\n\n\treturn position;\n}\n\nexport function activePositionChanged( corner: PanelCorner, before: LogicalPosition, after: LogicalPosition ): boolean {\n\tconst [ inlineKey, blockKey ] = getActiveInsetKeys( corner );\n\n\treturn before[ inlineKey ] !== after[ inlineKey ] || before[ blockKey ] !== after[ blockKey ];\n}\n\nexport type DragBounds = {\n\tminInlineStart: number;\n\tmaxInlineStart: number;\n\tminInlineEnd: number;\n\tmaxInlineEnd: number;\n\tminBlockStart: number;\n\tmaxBlockStart: number;\n\tminBlockEnd: number;\n\tmaxBlockEnd: number;\n};\n\nexport function getDragBounds(\n\tsize: LogicalSize,\n\tviewport: { width: number; height: number },\n\tsidePanelInlineSize: number,\n\tappBarHeight: number\n): DragBounds {\n\treturn {\n\t\tminInlineStart: sidePanelInlineSize,\n\t\tmaxInlineStart: viewport.width - size.inlineSize,\n\t\tminInlineEnd: 0,\n\t\tmaxInlineEnd: viewport.width - sidePanelInlineSize - size.inlineSize,\n\t\tminBlockStart: appBarHeight,\n\t\tmaxBlockStart: viewport.height - size.blockSize,\n\t\tminBlockEnd: 0,\n\t\tmaxBlockEnd: viewport.height - appBarHeight - size.blockSize,\n\t};\n}\n","import { __createSelector, __useSelector as useSelector } from '@elementor/store';\n\nimport { type GlobalState, selectCorner, selectIsOpen, selectPosition, selectSize } from '../store/selectors';\n\nconst selectStatus = __createSelector(\n\t[\n\t\t( state: GlobalState, id: string ) => selectIsOpen( state, id ),\n\t\t( state: GlobalState, id: string ) => selectCorner( state, id ),\n\t\t( state: GlobalState, id: string ) => selectPosition( state, id ),\n\t\t( state: GlobalState, id: string ) => selectSize( state, id ),\n\t],\n\t( isOpen, corner, position, size ) => ( { isOpen, corner, position, size } )\n);\n\nexport function useFloatingPanelStatus( id: string ) {\n\treturn useSelector( ( state: GlobalState ) => selectStatus( state, id ) );\n}\n","import { createLocation } from '@elementor/locations';\n\nexport const { inject: injectIntoFloatingPanels, useInjections: useFloatingPanelsInjections } = createLocation();\n","import { type FloatingPanelState, type PanelCorner } from './types';\n\nexport const PERSISTENCE_STORAGE_KEY = 'elementor_floating_panels_state';\n\nconst VALID_PANEL_CORNERS = new Set< PanelCorner >( [\n\t'block-start-inline-start',\n\t'block-start-inline-end',\n\t'block-end-inline-start',\n\t'block-end-inline-end',\n] );\n\ntype PersistedState = Record< string, FloatingPanelState >;\n\nexport function encodePersistedState( state: PersistedState ): string {\n\treturn JSON.stringify( state );\n}\n\nexport function decodePersistedState( raw: string | null | undefined ): PersistedState {\n\tif ( ! raw ) {\n\t\treturn {};\n\t}\n\n\tlet parsed: unknown;\n\n\ttry {\n\t\tparsed = JSON.parse( raw );\n\t} catch {\n\t\treturn {};\n\t}\n\n\tif ( typeof parsed !== 'object' || parsed === null ) {\n\t\treturn {};\n\t}\n\n\tconst result: PersistedState = {};\n\n\tfor ( const [ id, value ] of Object.entries( parsed as Record< string, unknown > ) ) {\n\t\tif ( isPanelState( value ) ) {\n\t\t\tresult[ id ] = value;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction isPanelState( value: unknown ): value is FloatingPanelState {\n\tif ( typeof value !== 'object' || value === null ) {\n\t\treturn false;\n\t}\n\n\tconst v = value as Record< string, unknown >;\n\n\tif ( typeof v.size !== 'object' || v.size === null ) {\n\t\treturn false;\n\t}\n\n\tif ( typeof v.position !== 'object' || v.position === null ) {\n\t\treturn false;\n\t}\n\n\tconst size = v.size as Record< string, unknown >;\n\tconst position = v.position as Record< string, unknown >;\n\n\treturn (\n\t\ttypeof v.isOpen === 'boolean' &&\n\t\ttypeof v.zIndex === 'number' &&\n\t\ttypeof v.corner === 'string' &&\n\t\tVALID_PANEL_CORNERS.has( v.corner as PanelCorner ) &&\n\t\ttypeof size.inlineSize === 'number' &&\n\t\ttypeof size.blockSize === 'number' &&\n\t\ttypeof position.insetInlineStart === 'number' &&\n\t\ttypeof position.insetInlineEnd === 'number' &&\n\t\ttypeof position.insetBlockStart === 'number' &&\n\t\ttypeof position.insetBlockEnd === 'number'\n\t);\n}\n","import { __getStore, __subscribeWithSelector } from '@elementor/store';\n\nimport { decodePersistedState, encodePersistedState, PERSISTENCE_STORAGE_KEY } from './persistence';\nimport { type GlobalState } from './store/selectors';\nimport { type FloatingPanelState } from './types';\n\nconst PERSIST_DEBOUNCE_MS = 250;\n\nexport interface PanelStateStorage {\n\tread: () => string | null;\n\twrite: ( value: string ) => void;\n}\n\nexport const localStorageAdapter: PanelStateStorage = {\n\tread: () => {\n\t\ttry {\n\t\t\treturn globalThis.localStorage?.getItem( PERSISTENCE_STORAGE_KEY ) ?? null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t},\n\twrite: ( value ) => {\n\t\ttry {\n\t\t\tglobalThis.localStorage?.setItem( PERSISTENCE_STORAGE_KEY, value );\n\t\t} catch {\n\t\t\t// Best-effort: storage may be full, blocked, or unavailable.\n\t\t}\n\t},\n};\n\nlet cachedPersistedState: Record< string, FloatingPanelState > = {};\nlet isSyncInitialized = false;\nlet persistenceTimer: ReturnType< typeof setTimeout > | null = null;\nlet persistenceUnsubscribe: ( () => void ) | null = null;\nlet persistenceSession = 0;\n\nexport function isFloatingPanelsSyncInitialized(): boolean {\n\treturn isSyncInitialized;\n}\n\nexport function sync( storage: PanelStateStorage = localStorageAdapter ): void {\n\tisSyncInitialized = true;\n\tcachedPersistedState = decodePersistedState( storage.read() );\n\n\tschedulePersistence( storage );\n}\n\nexport function getPersistedState( id: string ): FloatingPanelState | undefined {\n\treturn cachedPersistedState[ id ];\n}\n\nconst STORE_READY_POLL_MS = 16;\n\nfunction clearPersistenceTimer(): void {\n\tif ( persistenceTimer ) {\n\t\tclearTimeout( persistenceTimer );\n\t\tpersistenceTimer = null;\n\t}\n}\n\nfunction schedulePersistence( storage: PanelStateStorage ): void {\n\tclearPersistenceTimer();\n\tpersistenceUnsubscribe?.();\n\tpersistenceUnsubscribe = null;\n\n\tconst session = ++persistenceSession;\n\n\tconst subscribe = () => {\n\t\tif ( session !== persistenceSession ) {\n\t\t\treturn;\n\t\t}\n\n\t\tpersistenceUnsubscribe = __subscribeWithSelector(\n\t\t\t( state: GlobalState ) => state.floatingPanels.byId,\n\t\t\t( byId ) => {\n\t\t\t\tclearPersistenceTimer();\n\n\t\t\t\tpersistenceTimer = setTimeout( () => {\n\t\t\t\t\tif ( session !== persistenceSession ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tcachedPersistedState = { ...cachedPersistedState, ...byId };\n\t\t\t\t\tstorage.write( encodePersistedState( cachedPersistedState ) );\n\t\t\t\t}, PERSIST_DEBOUNCE_MS );\n\t\t\t}\n\t\t);\n\t};\n\n\tconst waitForStore = () => {\n\t\tif ( session !== persistenceSession ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( __getStore() ) {\n\t\t\tsubscribe();\n\t\t\treturn;\n\t\t}\n\n\t\tsetTimeout( waitForStore, STORE_READY_POLL_MS );\n\t};\n\n\twaitForStore();\n}\n","import * as React from 'react';\nimport { type ReactNode } from 'react';\n\ntype Props = {\n\tchildren: ReactNode;\n};\n\nexport default function FloatingPanel( { children }: Props ) {\n\treturn <>{ children }</>;\n}\n","import * as React from 'react';\nimport { Box, type BoxProps } from '@elementor/ui';\n\nexport default function FloatingPanelBody( props: BoxProps ) {\n\treturn (\n\t\t<Box\n\t\t\t{ ...props }\n\t\t\tsx={ {\n\t\t\t\tflex: 1,\n\t\t\t\toverflowY: 'auto',\n\t\t\t\t...( props.sx ?? {} ),\n\t\t\t} }\n\t\t/>\n\t);\n}\n","import * as React from 'react';\nimport { Box, type BoxProps } from '@elementor/ui';\n\nexport default function FloatingPanelFooter( { children, sx, ...props }: BoxProps ) {\n\treturn (\n\t\t<Box\n\t\t\t{ ...props }\n\t\t\tsx={ {\n\t\t\t\tpx: 2,\n\t\t\t\tpy: 1.5,\n\t\t\t\tborderTop: 1,\n\t\t\t\tborderColor: 'var(--e-a-border-color)',\n\t\t\t\tdisplay: 'flex',\n\t\t\t\talignItems: 'center',\n\t\t\t\tgap: 1,\n\t\t\t\t...( sx ?? {} ),\n\t\t\t} }\n\t\t>\n\t\t\t{ children }\n\t\t</Box>\n\t);\n}\n","import * as React from 'react';\nimport { type ComponentType } from 'react';\nimport { XIcon } from '@elementor/icons';\nimport { __useSelector as useSelector } from '@elementor/store';\nimport { Box, IconButton, Stack, Tooltip, Typography } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { useFloatingPanelActions } from '../../hooks/use-floating-panel-actions';\nimport { useFloatingPanelZIndex } from '../../hooks/use-floating-panel-z-index';\nimport { type GlobalState, selectIsDraggable } from '../../store/selectors';\nimport { type FloatingPanelHeaderAction } from '../../types';\nimport DragHandle from '../internal/drag-handle';\n\ntype Props = {\n\tpanelId: string;\n\ttitle: string;\n\ticon?: ComponentType;\n\tactions?: FloatingPanelHeaderAction[];\n};\n\nfunction HeaderAction( {\n\ticon: Icon,\n\tlabel,\n\tonClick,\n\tpanelZIndex,\n\tdisabled = false,\n}: FloatingPanelHeaderAction & { panelZIndex: number } ) {\n\treturn (\n\t\t<Tooltip\n\t\t\ttitle={ label }\n\t\t\tplacement=\"top\"\n\t\t\tPopperProps={ {\n\t\t\t\tsx: { zIndex: panelZIndex },\n\t\t\t} }\n\t\t>\n\t\t\t<Box component=\"span\" aria-label={ undefined }>\n\t\t\t\t<IconButton\n\t\t\t\t\tsize=\"small\"\n\t\t\t\t\tcolor=\"inherit\"\n\t\t\t\t\taria-label={ label }\n\t\t\t\t\tdisabled={ disabled }\n\t\t\t\t\tonClick={ disabled ? undefined : onClick }\n\t\t\t\t\tsx={ { borderRadius: 0, p: 1 } }\n\t\t\t\t>\n\t\t\t\t\t<Icon />\n\t\t\t\t</IconButton>\n\t\t\t</Box>\n\t\t</Tooltip>\n\t);\n}\n\nexport default function FloatingPanelHeader( { panelId, title, icon: Icon, actions }: Props ) {\n\tconst { close } = useFloatingPanelActions( panelId );\n\tconst isDraggable = useSelector( ( state: GlobalState ) => selectIsDraggable( state, panelId ) );\n\tconst hasActions = Boolean( actions?.length );\n\tconst panelZIndex = useFloatingPanelZIndex( panelId );\n\n\tconst titleContent = (\n\t\t<Box sx={ { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 1, height: '100%' } }>\n\t\t\t{ Icon ? <Icon /> : null }\n\t\t\t<Typography component=\"h2\" sx={ { textAlign: 'center', fontSize: '13px', fontWeight: 400 } }>\n\t\t\t\t{ title }\n\t\t\t</Typography>\n\t\t</Box>\n\t);\n\n\treturn (\n\t\t<Box\n\t\t\tsx={ {\n\t\t\t\tdisplay: 'flex',\n\t\t\t\talignItems: 'stretch',\n\t\t\t\tborderBottom: 1,\n\t\t\t\tborderColor: 'var(--e-a-border-color)',\n\t\t\t\toverflow: 'visible',\n\t\t\t} }\n\t\t>\n\t\t\t{ hasActions ? (\n\t\t\t\t<Stack direction=\"row\" alignItems=\"center\" sx={ { flexShrink: 0, overflow: 'visible' } }>\n\t\t\t\t\t{ actions?.map( ( action ) => (\n\t\t\t\t\t\t<HeaderAction key={ action.id } panelZIndex={ panelZIndex } { ...action } />\n\t\t\t\t\t) ) }\n\t\t\t\t</Stack>\n\t\t\t) : null }\n\t\t\t{ isDraggable ? (\n\t\t\t\t<DragHandle panelId={ panelId }>{ titleContent }</DragHandle>\n\t\t\t) : (\n\t\t\t\t<Box sx={ { flex: 1 } }>{ titleContent }</Box>\n\t\t\t) }\n\t\t\t<IconButton\n\t\t\t\tsize=\"small\"\n\t\t\t\tcolor=\"inherit\"\n\t\t\t\taria-label={ __( 'Close panel', 'elementor' ) }\n\t\t\t\tonClick={ close }\n\t\t\t\tsx={ { borderRadius: 0, p: 1 } }\n\t\t\t>\n\t\t\t\t<XIcon fontSize=\"small\" />\n\t\t\t</IconButton>\n\t\t</Box>\n\t);\n}\n","import { __useSelector as useSelector } from '@elementor/store';\n\nimport { type GlobalState, resolveOverlayZIndex } from '../store/selectors';\n\nexport function useFloatingPanelZIndex( panelId: string ): number {\n\treturn useSelector( ( state: GlobalState ) => resolveOverlayZIndex( state, panelId ) );\n}\n","import * as React from 'react';\nimport { type ReactNode } from 'react';\nimport { Box } from '@elementor/ui';\nimport { __ } from '@wordpress/i18n';\n\nimport { useFloatingPanelDrag } from '../../hooks/use-floating-panel-drag';\n\ntype Props = {\n\tpanelId: string;\n\tchildren: ReactNode;\n};\n\nexport default function DragHandle( { panelId, children }: Props ) {\n\tconst { onPointerDown, onPointerMove, onPointerUp, onPointerCancel } = useFloatingPanelDrag( panelId );\n\n\treturn (\n\t\t<Box\n\t\t\trole=\"button\"\n\t\t\taria-label={ __( 'Drag to reposition', 'elementor' ) }\n\t\t\tonPointerDown={ onPointerDown }\n\t\t\tonPointerMove={ onPointerMove }\n\t\t\tonPointerUp={ onPointerUp }\n\t\t\tonPointerCancel={ onPointerCancel }\n\t\t\tsx={ { cursor: 'move', touchAction: 'none', flex: 1 } }\n\t\t>\n\t\t\t{ children }\n\t\t</Box>\n\t);\n}\n","import { type PointerEvent as ReactPointerEvent, useCallback, useRef } from 'react';\n\nimport { type LogicalPosition } from '../types';\nimport { activePositionChanged, getDragBounds, type PanelCorner } from '../utils/corner-position';\nimport { isRtl } from '../utils/direction';\nimport { applyDragDelta, type DragBounds, physicalToLogicalDelta } from '../utils/drag-math';\nimport { APP_BAR_HEIGHT_PX, getSidePanelInlineSize } from '../utils/viewport-bounds';\nimport { useFloatingPanelActions } from './use-floating-panel-actions';\nimport { useFloatingPanelStatus } from './use-floating-panel-status';\n\ntype DragSession = {\n\tpointerId: number;\n\tstartClientX: number;\n\tstartClientY: number;\n\tstartPosition: LogicalPosition;\n\tlastDispatchedPosition: LogicalPosition;\n\tbounds: DragBounds;\n\tcorner: PanelCorner;\n\tisRtl: boolean;\n};\n\nexport function useFloatingPanelDrag( id: string ) {\n\tconst sessionRef = useRef< DragSession | null >( null );\n\tconst { corner, position, size } = useFloatingPanelStatus( id );\n\tconst { setPosition } = useFloatingPanelActions( id );\n\n\tconst onPointerDown = useCallback(\n\t\t( event: ReactPointerEvent< HTMLElement > ) => {\n\t\t\tif ( ! corner || ! position || ! size ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tevent.currentTarget.setPointerCapture( event.pointerId );\n\n\t\t\tsessionRef.current = {\n\t\t\t\tpointerId: event.pointerId,\n\t\t\t\tstartClientX: event.clientX,\n\t\t\t\tstartClientY: event.clientY,\n\t\t\t\tstartPosition: position,\n\t\t\t\tlastDispatchedPosition: position,\n\t\t\t\tbounds: getDragBounds(\n\t\t\t\t\tsize,\n\t\t\t\t\t{ width: window.innerWidth, height: window.innerHeight },\n\t\t\t\t\tgetSidePanelInlineSize(),\n\t\t\t\t\tAPP_BAR_HEIGHT_PX\n\t\t\t\t),\n\t\t\t\tcorner,\n\t\t\t\tisRtl: isRtl(),\n\t\t\t};\n\t\t},\n\t\t[ corner, position, size ]\n\t);\n\n\tconst onPointerMove = useCallback(\n\t\t( event: ReactPointerEvent< HTMLElement > ) => {\n\t\t\tconst session = sessionRef.current;\n\n\t\t\tif ( ! session || session.pointerId !== event.pointerId ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst physical = { dx: event.clientX - session.startClientX, dy: event.clientY - session.startClientY };\n\t\t\tconst logical = physicalToLogicalDelta( physical, session.isRtl );\n\t\t\tconst nextPosition = applyDragDelta( session.corner, session.startPosition, logical, session.bounds );\n\n\t\t\tif ( activePositionChanged( session.corner, session.lastDispatchedPosition, nextPosition ) ) {\n\t\t\t\tsetPosition( nextPosition );\n\t\t\t\tsession.lastDispatchedPosition = nextPosition;\n\t\t\t}\n\t\t},\n\t\t[ setPosition ]\n\t);\n\n\tconst clearSession = useCallback( ( event: ReactPointerEvent< HTMLElement > ) => {\n\t\tconst session = sessionRef.current;\n\n\t\tif ( ! session || session.pointerId !== event.pointerId ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsessionRef.current = null;\n\t}, [] );\n\n\treturn { onPointerDown, onPointerMove, onPointerUp: clearSession, onPointerCancel: clearSession };\n}\n","export function isRtl(): boolean {\n\treturn ( document?.documentElement?.dir ?? '' ).toLowerCase() === 'rtl';\n}\n","export function clamp( value: number, min: number, max: number ): number {\n\treturn Math.min( Math.max( min, value ), Math.max( min, max ) );\n}\n","import { type LogicalPosition } from '../types';\nimport { clamp } from './clamp';\nimport {\n\ttype DragBounds,\n\tgetActiveInsetKeys,\n\ttype PanelCorner,\n\tusesBlockStart,\n\tusesInlineStart,\n} from './corner-position';\n\nexport type { DragBounds } from './corner-position';\n\nexport type PhysicalDelta = { dx: number; dy: number };\n\nexport type LogicalDelta = { inlineDelta: number; blockDelta: number };\n\nexport function physicalToLogicalDelta( delta: PhysicalDelta, isRtl: boolean ): LogicalDelta {\n\treturn {\n\t\tinlineDelta: isRtl ? -delta.dx : delta.dx,\n\t\tblockDelta: delta.dy,\n\t};\n}\n\nexport function applyDragDelta(\n\tcorner: PanelCorner,\n\tposition: LogicalPosition,\n\tdelta: LogicalDelta,\n\tbounds: DragBounds\n): LogicalPosition {\n\tconst [ inlineKey, blockKey ] = getActiveInsetKeys( corner );\n\tconst inlineDelta = usesInlineStart( corner ) ? delta.inlineDelta : -delta.inlineDelta;\n\tconst blockDelta = usesBlockStart( corner ) ? delta.blockDelta : -delta.blockDelta;\n\n\tconst inlineBounds =\n\t\tinlineKey === 'insetInlineStart'\n\t\t\t? { min: bounds.minInlineStart, max: bounds.maxInlineStart }\n\t\t\t: { min: bounds.minInlineEnd, max: bounds.maxInlineEnd };\n\n\tconst blockBounds =\n\t\tblockKey === 'insetBlockStart'\n\t\t\t? { min: bounds.minBlockStart, max: bounds.maxBlockStart }\n\t\t\t: { min: bounds.minBlockEnd, max: bounds.maxBlockEnd };\n\n\treturn {\n\t\t...position,\n\t\t[ inlineKey ]: clamp( position[ inlineKey ] + inlineDelta, inlineBounds.min, inlineBounds.max ),\n\t\t[ blockKey ]: clamp( position[ blockKey ] + blockDelta, blockBounds.min, blockBounds.max ),\n\t};\n}\n","export const APP_BAR_HEIGHT_PX = 48;\n\nconst SIDE_PANEL_SELECTOR = '#elementor-panel';\n\nexport function getSidePanelInlineSize(): number {\n\treturn document.querySelector< HTMLElement >( SIDE_PANEL_SELECTOR )?.getBoundingClientRect().width ?? 0;\n}\n","import { injectIntoTop } from '@elementor/editor';\nimport { __registerSlice } from '@elementor/store';\n\nimport FloatingPanelsHost from './components/internal/host';\nimport { slice } from './store/slice';\nimport { sync } from './sync';\n\nexport function init() {\n\tsync();\n\n\t__registerSlice( slice );\n\n\tinjectIntoTop( { id: 'floating-panels', component: FloatingPanelsHost } );\n}\n","import * as React from 'react';\nimport { type ReactNode, useMemo } from 'react';\nimport { useEditMode } from '@elementor/editor-v1-adapters';\nimport { __useDispatch as useDispatch, __useSelector as useSelector } from '@elementor/store';\n\nimport { useFloatingPanelsInjections } from '../../location';\nimport {\n\ttype GlobalState,\n\tresolvePanelZIndex,\n\tselectOpenPanelIds,\n\tselectPanelState,\n\tselectPanelTitle,\n} from '../../store/selectors';\nimport { slice } from '../../store/slice';\nimport PanelWindow from './panel-window';\n\nexport default function FloatingPanelsHost() {\n\tconst openIds = useSelector( selectOpenPanelIds );\n\tconst injections = useFloatingPanelsInjections();\n\tconst dispatch = useDispatch();\n\tconst isPreviewMode = useEditMode() === 'preview';\n\n\tconst declarationById = useMemo( () => {\n\t\treturn Object.fromEntries( injections.map( ( inj ) => [ inj.id, inj ] ) );\n\t}, [ injections ] );\n\n\treturn (\n\t\t<>\n\t\t\t{ openIds.map( ( id ) => {\n\t\t\t\tconst declaration = declarationById[ id ];\n\n\t\t\t\tif ( ! declaration ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst Component = declaration.component;\n\n\t\t\t\treturn (\n\t\t\t\t\t<HostedPanel\n\t\t\t\t\t\tkey={ id }\n\t\t\t\t\t\tid={ id }\n\t\t\t\t\t\tvisible={ ! isPreviewMode }\n\t\t\t\t\t\tonFocus={ () => dispatch( slice.actions.bringToFront( id ) ) }\n\t\t\t\t\t>\n\t\t\t\t\t\t<Component />\n\t\t\t\t\t</HostedPanel>\n\t\t\t\t);\n\t\t\t} ) }\n\t\t</>\n\t);\n}\n\nfunction HostedPanel( {\n\tid,\n\tchildren,\n\tonFocus,\n\tvisible,\n}: {\n\tid: string;\n\tchildren: ReactNode;\n\tonFocus: () => void;\n\tvisible: boolean;\n} ) {\n\tconst panel = useSelector( ( state: GlobalState ) => selectPanelState( state, id ) );\n\tconst title = useSelector( ( state: GlobalState ) => selectPanelTitle( state, id ) );\n\tconst zIndex = useSelector( ( state: GlobalState ) => resolvePanelZIndex( state, id ) );\n\n\tif ( ! panel ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<PanelWindow\n\t\t\tpanelId={ id }\n\t\t\tcorner={ panel.corner }\n\t\t\tposition={ panel.position }\n\t\t\tsize={ panel.size }\n\t\t\tzIndex={ zIndex }\n\t\t\tvisible={ visible }\n\t\t\tonFocus={ onFocus }\n\t\t\ttitle={ title }\n\t\t>\n\t\t\t{ children }\n\t\t</PanelWindow>\n\t);\n}\n","import * as React from 'react';\nimport { type ReactNode } from 'react';\nimport { ThemeProvider } from '@elementor/editor-ui';\nimport { __useSelector as useSelector } from '@elementor/store';\nimport { Box, Fade, Paper } from '@elementor/ui';\n\nimport { usePanelResizeInteraction } from '../../hooks/use-floating-panel-resize';\nimport { type GlobalState, selectIsResizable } from '../../store/selectors';\nimport { type LogicalPosition, type LogicalSize } from '../../types';\nimport { type PanelCorner, positionToCssInsets } from '../../utils/corner-position';\nimport { type ResizeCorner, type ResizeEdge } from '../../utils/resize-math';\nimport CornerResizeHandle from './corner-resize-handle';\nimport ResizeHandle from './resize-handle';\n\nconst FADE_ENTER_MS = 225;\nconst FADE_EXIT_MS = 195;\n\nconst RESIZE_EDGES: ResizeEdge[] = [ 'inline-start', 'inline-end', 'block-start', 'block-end' ];\n\nconst RESIZE_CORNERS: ResizeCorner[] = [\n\t'block-start-inline-start',\n\t'block-start-inline-end',\n\t'block-end-inline-start',\n\t'block-end-inline-end',\n];\n\ntype Props = {\n\tpanelId: string;\n\tcorner: PanelCorner;\n\tposition: LogicalPosition;\n\tsize: LogicalSize;\n\ttitle?: string;\n\tzIndex: number;\n\tvisible: boolean;\n\tonFocus: () => void;\n\tchildren: ReactNode;\n};\n\nfunction PanelResizeHandles( { panelId }: { panelId: string } ) {\n\tconst { getResizeHandleProps } = usePanelResizeInteraction( panelId );\n\n\treturn (\n\t\t<>\n\t\t\t{ RESIZE_EDGES.map( ( edge ) => (\n\t\t\t\t<ResizeHandle key={ edge } edge={ edge } { ...getResizeHandleProps( edge ) } />\n\t\t\t) ) }\n\t\t\t{ RESIZE_CORNERS.map( ( corner ) => (\n\t\t\t\t<CornerResizeHandle key={ corner } corner={ corner } { ...getResizeHandleProps( corner ) } />\n\t\t\t) ) }\n\t\t</>\n\t);\n}\n\nexport default function PanelWindow( {\n\tpanelId,\n\tcorner,\n\tposition,\n\tsize,\n\ttitle,\n\tzIndex,\n\tvisible,\n\tonFocus,\n\tchildren,\n}: Props ) {\n\tconst isResizable = useSelector( ( state: GlobalState ) => selectIsResizable( state, panelId ) );\n\n\treturn (\n\t\t<Fade in={ visible } timeout={ { enter: FADE_ENTER_MS, exit: FADE_EXIT_MS } }>\n\t\t\t<Paper\n\t\t\t\tcomponent=\"aside\"\n\t\t\t\tdata-floating-panel={ panelId }\n\t\t\t\televation={ 0 }\n\t\t\t\taria-label={ title || panelId }\n\t\t\t\taria-hidden={ ! visible }\n\t\t\t\tinert={ ! visible ? '' : undefined }\n\t\t\t\tonMouseDown={ onFocus }\n\t\t\t\tonFocusCapture={ onFocus }\n\t\t\t\tsx={ {\n\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\t...positionToCssInsets( corner, position ),\n\t\t\t\t\tinlineSize: `${ size.inlineSize }px`,\n\t\t\t\t\tblockSize: `${ size.blockSize }px`,\n\t\t\t\t\tzIndex,\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\tflexDirection: 'column',\n\t\t\t\t\tpointerEvents: visible ? 'auto' : 'none',\n\t\t\t\t\tbgcolor: 'var(--e-a-bg-default)',\n\t\t\t\t\tcolor: 'var(--e-a-color-txt)',\n\t\t\t\t\tborder: 'var(--e-a-border)',\n\t\t\t\t\tboxShadow: `0 2px 20px 0 rgba(0, 0, 0, 0.1)`,\n\t\t\t\t} }\n\t\t\t>\n\t\t\t\t<ThemeProvider>\n\t\t\t\t\t<Box sx={ { display: 'flex', flexDirection: 'column', height: '100%' } }>{ children }</Box>\n\t\t\t\t</ThemeProvider>\n\t\t\t\t{ isResizable && <PanelResizeHandles panelId={ panelId } /> }\n\t\t\t</Paper>\n\t\t</Fade>\n\t);\n}\n","import { type PointerEvent as ReactPointerEvent, useCallback, useRef } from 'react';\nimport { __useSelector as useSelector } from '@elementor/store';\n\nimport { type GlobalState, selectMinSize } from '../store/selectors';\nimport { type LogicalPosition, type LogicalSize } from '../types';\nimport {\n\tactivePositionChanged,\n\tfromStartAnchoredPosition,\n\ttype PanelCorner,\n\ttoStartAnchoredPosition,\n} from '../utils/corner-position';\nimport { isRtl } from '../utils/direction';\nimport { physicalToLogicalDelta } from '../utils/drag-math';\nimport { applyResize, type ResizeBounds, type ResizeDirection } from '../utils/resize-math';\nimport { APP_BAR_HEIGHT_PX, getSidePanelInlineSize } from '../utils/viewport-bounds';\nimport { useFloatingPanelActions } from './use-floating-panel-actions';\nimport { useFloatingPanelStatus } from './use-floating-panel-status';\n\ntype ResizeSession = {\n\tpointerId: number;\n\tdirection: ResizeDirection;\n\tstartClientX: number;\n\tstartClientY: number;\n\tstartPosition: LogicalPosition;\n\tstartSize: LogicalSize;\n\tlastPosition: LogicalPosition;\n\tlastSize: LogicalSize;\n\tbounds: ResizeBounds;\n\tcorner: PanelCorner;\n\tisRtl: boolean;\n};\n\nfunction getResizeBounds(\n\tcorner: PanelCorner,\n\tposition: LogicalPosition,\n\tcurrentSize: LogicalSize,\n\tminSize: LogicalSize\n): ResizeBounds {\n\tconst viewport = { width: window.innerWidth, height: window.innerHeight };\n\tconst startAnchored = toStartAnchoredPosition( corner, position, currentSize, viewport );\n\n\treturn {\n\t\tminBlockSize: minSize.blockSize,\n\t\tmaxBlockSize: window.innerHeight - startAnchored.insetBlockStart,\n\t\tminInlineSize: minSize.inlineSize,\n\t\tmaxInlineSize: window.innerWidth - startAnchored.insetInlineStart,\n\t\tminInlineStart: getSidePanelInlineSize(),\n\t\tminBlockStart: APP_BAR_HEIGHT_PX,\n\t};\n}\n\ntype ResizeHandlePointerHandlers = {\n\tonPointerDown: ( event: ReactPointerEvent< HTMLElement > ) => void;\n\tonPointerMove: ( event: ReactPointerEvent< HTMLElement > ) => void;\n\tonPointerUp: ( event: ReactPointerEvent< HTMLElement > ) => void;\n\tonPointerCancel: ( event: ReactPointerEvent< HTMLElement > ) => void;\n};\n\nexport function usePanelResizeInteraction( id: string ) {\n\tconst sessionRef = useRef< ResizeSession | null >( null );\n\tconst { corner, position, size } = useFloatingPanelStatus( id );\n\tconst minSize = useSelector( ( state: GlobalState ) => selectMinSize( state, id ) );\n\tconst { setPosition, setSize } = useFloatingPanelActions( id );\n\n\tconst onPointerDown = useCallback(\n\t\t( direction: ResizeDirection, event: ReactPointerEvent< HTMLElement > ) => {\n\t\t\tif ( ! corner || ! position || ! size || ! minSize ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tevent.currentTarget.setPointerCapture( event.pointerId );\n\n\t\t\tsessionRef.current = {\n\t\t\t\tpointerId: event.pointerId,\n\t\t\t\tdirection,\n\t\t\t\tstartClientX: event.clientX,\n\t\t\t\tstartClientY: event.clientY,\n\t\t\t\tstartPosition: position,\n\t\t\t\tstartSize: size,\n\t\t\t\tlastPosition: position,\n\t\t\t\tlastSize: size,\n\t\t\t\tbounds: getResizeBounds( corner, position, size, minSize ),\n\t\t\t\tcorner,\n\t\t\t\tisRtl: isRtl(),\n\t\t\t};\n\t\t},\n\t\t[ corner, position, size, minSize ]\n\t);\n\n\tconst onPointerMove = useCallback(\n\t\t( event: ReactPointerEvent< HTMLElement > ) => {\n\t\t\tconst session = sessionRef.current;\n\n\t\t\tif ( ! session || session.pointerId !== event.pointerId ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst physical = { dx: event.clientX - session.startClientX, dy: event.clientY - session.startClientY };\n\t\t\tconst logical = physicalToLogicalDelta( physical, session.isRtl );\n\t\t\tconst viewport = { width: window.innerWidth, height: window.innerHeight };\n\t\t\tconst startAnchoredPosition = toStartAnchoredPosition(\n\t\t\t\tsession.corner,\n\t\t\t\tsession.startPosition,\n\t\t\t\tsession.startSize,\n\t\t\t\tviewport\n\t\t\t);\n\t\t\tconst resizeInput = { ...session.startPosition, ...startAnchoredPosition };\n\t\t\tconst next = applyResize(\n\t\t\t\tsession.direction,\n\t\t\t\tresizeInput,\n\t\t\t\tsession.startSize,\n\t\t\t\tlogical.inlineDelta,\n\t\t\t\tlogical.blockDelta,\n\t\t\t\tsession.bounds\n\t\t\t);\n\t\t\tconst nextPosition = fromStartAnchoredPosition(\n\t\t\t\tsession.corner,\n\t\t\t\t{\n\t\t\t\t\tinsetBlockStart: next.position.insetBlockStart,\n\t\t\t\t\tinsetInlineStart: next.position.insetInlineStart,\n\t\t\t\t},\n\t\t\t\tnext.size,\n\t\t\t\tviewport\n\t\t\t);\n\n\t\t\tif ( activePositionChanged( session.corner, session.lastPosition, nextPosition ) ) {\n\t\t\t\tsetPosition( nextPosition );\n\t\t\t\tsession.lastPosition = nextPosition;\n\t\t\t}\n\n\t\t\tconst sizeChanged =\n\t\t\t\tnext.size.inlineSize !== session.lastSize.inlineSize ||\n\t\t\t\tnext.size.blockSize !== session.lastSize.blockSize;\n\n\t\t\tif ( sizeChanged ) {\n\t\t\t\tsetSize( next.size );\n\t\t\t\tsession.lastSize = next.size;\n\t\t\t}\n\t\t},\n\t\t[ setPosition, setSize ]\n\t);\n\n\tconst clearSession = useCallback( ( event: ReactPointerEvent< HTMLElement > ) => {\n\t\tconst session = sessionRef.current;\n\n\t\tif ( ! session || session.pointerId !== event.pointerId ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsessionRef.current = null;\n\t}, [] );\n\n\tconst getResizeHandleProps = useCallback(\n\t\t( direction: ResizeDirection ): ResizeHandlePointerHandlers => {\n\t\t\treturn {\n\t\t\t\tonPointerDown: ( event ) => onPointerDown( direction, event ),\n\t\t\t\tonPointerMove,\n\t\t\t\tonPointerUp: clearSession,\n\t\t\t\tonPointerCancel: clearSession,\n\t\t\t};\n\t\t},\n\t\t[ onPointerDown, onPointerMove, clearSession ]\n\t);\n\n\treturn { getResizeHandleProps };\n}\n","import { type LogicalPosition, type LogicalSize } from '../types';\nimport { clamp } from './clamp';\nimport { type PanelCorner } from './corner-position';\n\nexport type ResizeEdge = 'inline-start' | 'inline-end' | 'block-start' | 'block-end';\n\nexport type ResizeCorner = PanelCorner;\n\nexport type ResizeDirection = ResizeEdge | PanelCorner;\n\nexport type ResizeBounds = {\n\tminInlineSize: number;\n\tmaxInlineSize: number;\n\tminBlockSize: number;\n\tmaxBlockSize: number;\n\tminInlineStart: number;\n\tminBlockStart: number;\n};\n\nexport function applyInlineEndResize( size: LogicalSize, inlineDelta: number, bounds: ResizeBounds ): LogicalSize {\n\treturn {\n\t\tinlineSize: clamp( size.inlineSize + inlineDelta, bounds.minInlineSize, bounds.maxInlineSize ),\n\t\tblockSize: size.blockSize,\n\t};\n}\n\nexport function applyBlockEndResize( size: LogicalSize, blockDelta: number, bounds: ResizeBounds ): LogicalSize {\n\treturn {\n\t\tinlineSize: size.inlineSize,\n\t\tblockSize: clamp( size.blockSize + blockDelta, bounds.minBlockSize, bounds.maxBlockSize ),\n\t};\n}\n\nexport function applyInlineStartResize(\n\tposition: LogicalPosition,\n\tsize: LogicalSize,\n\tinlineDelta: number,\n\tbounds: ResizeBounds\n): { position: LogicalPosition; size: LogicalSize } {\n\tconst anchorInlineEnd = position.insetInlineStart + size.inlineSize;\n\tconst lowBound = Math.max( bounds.minInlineStart, anchorInlineEnd - bounds.maxInlineSize );\n\tconst highBound = anchorInlineEnd - bounds.minInlineSize;\n\tconst nextInlineStart = clamp( position.insetInlineStart + inlineDelta, lowBound, highBound );\n\n\treturn {\n\t\tposition: { ...position, insetInlineStart: nextInlineStart },\n\t\tsize: { ...size, inlineSize: anchorInlineEnd - nextInlineStart },\n\t};\n}\n\nexport function applyBlockStartResize(\n\tposition: LogicalPosition,\n\tsize: LogicalSize,\n\tblockDelta: number,\n\tbounds: ResizeBounds\n): { position: LogicalPosition; size: LogicalSize } {\n\tconst anchorBlockEnd = position.insetBlockStart + size.blockSize;\n\tconst lowBound = Math.max( bounds.minBlockStart, anchorBlockEnd - bounds.maxBlockSize );\n\tconst highBound = anchorBlockEnd - bounds.minBlockSize;\n\tconst nextBlockStart = clamp( position.insetBlockStart + blockDelta, lowBound, highBound );\n\n\treturn {\n\t\tposition: { ...position, insetBlockStart: nextBlockStart },\n\t\tsize: { ...size, blockSize: anchorBlockEnd - nextBlockStart },\n\t};\n}\n\nexport function applyResize(\n\tdirection: ResizeDirection,\n\tposition: LogicalPosition,\n\tsize: LogicalSize,\n\tinlineDelta: number,\n\tblockDelta: number,\n\tbounds: ResizeBounds\n): { position: LogicalPosition; size: LogicalSize } {\n\tif ( direction === 'inline-end' ) {\n\t\treturn { position, size: applyInlineEndResize( size, inlineDelta, bounds ) };\n\t}\n\n\tif ( direction === 'block-end' ) {\n\t\treturn { position, size: applyBlockEndResize( size, blockDelta, bounds ) };\n\t}\n\n\tif ( direction === 'inline-start' ) {\n\t\treturn applyInlineStartResize( position, size, inlineDelta, bounds );\n\t}\n\n\tif ( direction === 'block-start' ) {\n\t\treturn applyBlockStartResize( position, size, blockDelta, bounds );\n\t}\n\n\tlet next = { position, size };\n\n\tif ( direction.includes( 'inline-start' ) ) {\n\t\tnext = applyInlineStartResize( next.position, next.size, inlineDelta, bounds );\n\t} else {\n\t\tnext = { position: next.position, size: applyInlineEndResize( next.size, inlineDelta, bounds ) };\n\t}\n\n\tif ( direction.includes( 'block-start' ) ) {\n\t\tnext = applyBlockStartResize( next.position, next.size, blockDelta, bounds );\n\t} else {\n\t\tnext = { position: next.position, size: applyBlockEndResize( next.size, blockDelta, bounds ) };\n\t}\n\n\treturn next;\n}\n","import * as React from 'react';\nimport { type PointerEventHandler } from 'react';\nimport { Box } from '@elementor/ui';\n\nimport { isRtl } from '../../utils/direction';\nimport { type ResizeCorner } from '../../utils/resize-math';\n\nconst HANDLE_SIZE_PX = 8;\n\ntype CornerPosition = { insetBlockStart?: 0; insetBlockEnd?: 0; insetInlineStart?: 0; insetInlineEnd?: 0 };\n\nconst CORNER_POSITION: Record< ResizeCorner, CornerPosition > = {\n\t'block-start-inline-start': { insetBlockStart: 0, insetInlineStart: 0 },\n\t'block-start-inline-end': { insetBlockStart: 0, insetInlineEnd: 0 },\n\t'block-end-inline-start': { insetBlockEnd: 0, insetInlineStart: 0 },\n\t'block-end-inline-end': { insetBlockEnd: 0, insetInlineEnd: 0 },\n};\n\nconst LTR_CURSORS: Record< ResizeCorner, string > = {\n\t'block-start-inline-start': 'nwse-resize',\n\t'block-start-inline-end': 'nesw-resize',\n\t'block-end-inline-start': 'nesw-resize',\n\t'block-end-inline-end': 'nwse-resize',\n};\n\nconst RTL_CURSORS: Record< ResizeCorner, string > = {\n\t'block-start-inline-start': 'nesw-resize',\n\t'block-start-inline-end': 'nwse-resize',\n\t'block-end-inline-start': 'nwse-resize',\n\t'block-end-inline-end': 'nesw-resize',\n};\n\ntype Props = {\n\tcorner: ResizeCorner;\n\tonPointerDown: PointerEventHandler< HTMLElement >;\n\tonPointerMove: PointerEventHandler< HTMLElement >;\n\tonPointerUp: PointerEventHandler< HTMLElement >;\n\tonPointerCancel: PointerEventHandler< HTMLElement >;\n};\n\nexport default function CornerResizeHandle( {\n\tcorner,\n\tonPointerDown,\n\tonPointerMove,\n\tonPointerUp,\n\tonPointerCancel,\n}: Props ) {\n\tconst cursor = isRtl() ? RTL_CURSORS[ corner ] : LTR_CURSORS[ corner ];\n\n\treturn (\n\t\t<Box\n\t\t\tdata-resize-corner={ corner }\n\t\t\taria-hidden=\"true\"\n\t\t\tonPointerDown={ onPointerDown }\n\t\t\tonPointerMove={ onPointerMove }\n\t\t\tonPointerUp={ onPointerUp }\n\t\t\tonPointerCancel={ onPointerCancel }\n\t\t\tsx={ {\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttouchAction: 'none',\n\t\t\t\tzIndex: 2,\n\t\t\t\tinlineSize: `${ HANDLE_SIZE_PX }px`,\n\t\t\t\tblockSize: `${ HANDLE_SIZE_PX }px`,\n\t\t\t\tcursor,\n\t\t\t\t...CORNER_POSITION[ corner ],\n\t\t\t} }\n\t\t/>\n\t);\n}\n","import * as React from 'react';\nimport { type PointerEventHandler } from 'react';\nimport { Box } from '@elementor/ui';\n\nimport { type ResizeEdge } from '../../utils/resize-math';\n\nconst HANDLE_THICKNESS_PX = 8;\n\nconst EDGE_SX: Record< ResizeEdge, object > = {\n\t'inline-start': {\n\t\tinsetBlockStart: 0,\n\t\tinsetBlockEnd: 0,\n\t\tinsetInlineStart: 0,\n\t\tinlineSize: `${ HANDLE_THICKNESS_PX }px`,\n\t\tcursor: 'ew-resize',\n\t},\n\t'inline-end': {\n\t\tinsetBlockStart: 0,\n\t\tinsetBlockEnd: 0,\n\t\tinsetInlineEnd: 0,\n\t\tinlineSize: `${ HANDLE_THICKNESS_PX }px`,\n\t\tcursor: 'ew-resize',\n\t},\n\t'block-start': {\n\t\tinsetInlineStart: 0,\n\t\tinsetInlineEnd: 0,\n\t\tinsetBlockStart: 0,\n\t\tblockSize: `${ HANDLE_THICKNESS_PX }px`,\n\t\tcursor: 'ns-resize',\n\t},\n\t'block-end': {\n\t\tinsetInlineStart: 0,\n\t\tinsetInlineEnd: 0,\n\t\tinsetBlockEnd: 0,\n\t\tblockSize: `${ HANDLE_THICKNESS_PX }px`,\n\t\tcursor: 'ns-resize',\n\t},\n};\n\ntype Props = {\n\tedge: ResizeEdge;\n\tonPointerDown: PointerEventHandler< HTMLElement >;\n\tonPointerMove: PointerEventHandler< HTMLElement >;\n\tonPointerUp: PointerEventHandler< HTMLElement >;\n\tonPointerCancel: PointerEventHandler< HTMLElement >;\n};\n\nexport default function ResizeHandle( { edge, onPointerDown, onPointerMove, onPointerUp, onPointerCancel }: Props ) {\n\treturn (\n\t\t<Box\n\t\t\tdata-resize-edge={ edge }\n\t\t\taria-hidden=\"true\"\n\t\t\tonPointerDown={ onPointerDown }\n\t\t\tonPointerMove={ onPointerMove }\n\t\t\tonPointerUp={ onPointerUp }\n\t\t\tonPointerCancel={ onPointerCancel }\n\t\t\tsx={ { position: 'absolute', touchAction: 'none', zIndex: 1, ...EDGE_SX[ edge ] } }\n\t\t/>\n\t);\n}\n"],"mappings":"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","names":["dispatch","__createSelector","useSelector","__createSelector","useSelector","React","React","Box","React","useSelector","Box","__","useSelector","useSelector","React","Box","isRtl","Box","Box","useSelector","__","React","useDispatch","useSelector","React","useSelector","Box","useCallback","useRef","useSelector","useRef","useSelector","useCallback","React","Box","Box","React","Box","useSelector","Box","useSelector","dispatch","useDispatch"]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@elementor/editor-floating-panels",
3
+ "version": "4.3.0-970",
4
+ "private": false,
5
+ "author": "Elementor Team",
6
+ "homepage": "https://elementor.com/",
7
+ "license": "GPL-3.0-or-later",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.mjs",
15
+ "require": "./dist/index.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/elementor/elementor.git",
22
+ "directory": "packages/core/editor-floating-panels"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/elementor/elementor/issues"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "files": [
31
+ "README.md",
32
+ "CHANGELOG.md",
33
+ "/dist",
34
+ "/src",
35
+ "!**/__tests__"
36
+ ],
37
+ "scripts": {
38
+ "build": "tsup --config=../../tsup.build.ts",
39
+ "dev": "tsup --config=../../tsup.dev.ts"
40
+ },
41
+ "dependencies": {
42
+ "@elementor/editor": "4.3.0-970",
43
+ "@elementor/editor-ui": "4.3.0-970",
44
+ "@elementor/editor-v1-adapters": "4.3.0-970",
45
+ "@elementor/icons": "~1.75.1",
46
+ "@elementor/locations": "4.3.0-970",
47
+ "@elementor/store": "4.3.0-970",
48
+ "@elementor/ui": "1.37.5",
49
+ "@wordpress/i18n": "^5.13.0"
50
+ },
51
+ "peerDependencies": {
52
+ "react": "^18.3.1",
53
+ "react-dom": "^18.3.1"
54
+ },
55
+ "devDependencies": {
56
+ "tsup": "^8.3.5"
57
+ }
58
+ }
package/src/api.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { __dispatch as dispatch } from '@elementor/store';
2
+
3
+ import { useFloatingPanelActions } from './hooks/use-floating-panel-actions';
4
+ import { useFloatingPanelStatus } from './hooks/use-floating-panel-status';
5
+ import { injectIntoFloatingPanels } from './location';
6
+ import { decodePersistedState } from './persistence';
7
+ import { slice } from './store/slice';
8
+ import { getPersistedState, isFloatingPanelsSyncInitialized, localStorageAdapter } from './sync';
9
+ import { type FloatingPanelDeclaration } from './types';
10
+
11
+ export function createFloatingPanel( declaration: FloatingPanelDeclaration ) {
12
+ const persisted = isFloatingPanelsSyncInitialized()
13
+ ? getPersistedState( declaration.id )
14
+ : decodePersistedState( localStorageAdapter.read() )[ declaration.id ];
15
+
16
+ dispatch(
17
+ slice.actions.register( {
18
+ id: declaration.id,
19
+ title: declaration.title,
20
+ isDraggable: declaration.isDraggable,
21
+ isResizable: declaration.isResizable,
22
+ defaults: declaration.defaults,
23
+ persisted,
24
+ } )
25
+ );
26
+
27
+ return {
28
+ panel: declaration,
29
+ useFloatingPanelStatus: () => useFloatingPanelStatus( declaration.id ),
30
+ useFloatingPanelActions: () => useFloatingPanelActions( declaration.id ),
31
+ };
32
+ }
33
+
34
+ export function registerFloatingPanel( declaration: Pick< FloatingPanelDeclaration, 'id' | 'component' > ): void {
35
+ injectIntoFloatingPanels( { id: declaration.id, component: declaration.component } );
36
+ }
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { Box, type BoxProps } from '@elementor/ui';
3
+
4
+ export default function FloatingPanelBody( props: BoxProps ) {
5
+ return (
6
+ <Box
7
+ { ...props }
8
+ sx={ {
9
+ flex: 1,
10
+ overflowY: 'auto',
11
+ ...( props.sx ?? {} ),
12
+ } }
13
+ />
14
+ );
15
+ }
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { Box, type BoxProps } from '@elementor/ui';
3
+
4
+ export default function FloatingPanelFooter( { children, sx, ...props }: BoxProps ) {
5
+ return (
6
+ <Box
7
+ { ...props }
8
+ sx={ {
9
+ px: 2,
10
+ py: 1.5,
11
+ borderTop: 1,
12
+ borderColor: 'var(--e-a-border-color)',
13
+ display: 'flex',
14
+ alignItems: 'center',
15
+ gap: 1,
16
+ ...( sx ?? {} ),
17
+ } }
18
+ >
19
+ { children }
20
+ </Box>
21
+ );
22
+ }
@@ -0,0 +1,100 @@
1
+ import * as React from 'react';
2
+ import { type ComponentType } from 'react';
3
+ import { XIcon } from '@elementor/icons';
4
+ import { __useSelector as useSelector } from '@elementor/store';
5
+ import { Box, IconButton, Stack, Tooltip, Typography } from '@elementor/ui';
6
+ import { __ } from '@wordpress/i18n';
7
+
8
+ import { useFloatingPanelActions } from '../../hooks/use-floating-panel-actions';
9
+ import { useFloatingPanelZIndex } from '../../hooks/use-floating-panel-z-index';
10
+ import { type GlobalState, selectIsDraggable } from '../../store/selectors';
11
+ import { type FloatingPanelHeaderAction } from '../../types';
12
+ import DragHandle from '../internal/drag-handle';
13
+
14
+ type Props = {
15
+ panelId: string;
16
+ title: string;
17
+ icon?: ComponentType;
18
+ actions?: FloatingPanelHeaderAction[];
19
+ };
20
+
21
+ function HeaderAction( {
22
+ icon: Icon,
23
+ label,
24
+ onClick,
25
+ panelZIndex,
26
+ disabled = false,
27
+ }: FloatingPanelHeaderAction & { panelZIndex: number } ) {
28
+ return (
29
+ <Tooltip
30
+ title={ label }
31
+ placement="top"
32
+ PopperProps={ {
33
+ sx: { zIndex: panelZIndex },
34
+ } }
35
+ >
36
+ <Box component="span" aria-label={ undefined }>
37
+ <IconButton
38
+ size="small"
39
+ color="inherit"
40
+ aria-label={ label }
41
+ disabled={ disabled }
42
+ onClick={ disabled ? undefined : onClick }
43
+ sx={ { borderRadius: 0, p: 1 } }
44
+ >
45
+ <Icon />
46
+ </IconButton>
47
+ </Box>
48
+ </Tooltip>
49
+ );
50
+ }
51
+
52
+ export default function FloatingPanelHeader( { panelId, title, icon: Icon, actions }: Props ) {
53
+ const { close } = useFloatingPanelActions( panelId );
54
+ const isDraggable = useSelector( ( state: GlobalState ) => selectIsDraggable( state, panelId ) );
55
+ const hasActions = Boolean( actions?.length );
56
+ const panelZIndex = useFloatingPanelZIndex( panelId );
57
+
58
+ const titleContent = (
59
+ <Box sx={ { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 1, height: '100%' } }>
60
+ { Icon ? <Icon /> : null }
61
+ <Typography component="h2" sx={ { textAlign: 'center', fontSize: '13px', fontWeight: 400 } }>
62
+ { title }
63
+ </Typography>
64
+ </Box>
65
+ );
66
+
67
+ return (
68
+ <Box
69
+ sx={ {
70
+ display: 'flex',
71
+ alignItems: 'stretch',
72
+ borderBottom: 1,
73
+ borderColor: 'var(--e-a-border-color)',
74
+ overflow: 'visible',
75
+ } }
76
+ >
77
+ { hasActions ? (
78
+ <Stack direction="row" alignItems="center" sx={ { flexShrink: 0, overflow: 'visible' } }>
79
+ { actions?.map( ( action ) => (
80
+ <HeaderAction key={ action.id } panelZIndex={ panelZIndex } { ...action } />
81
+ ) ) }
82
+ </Stack>
83
+ ) : null }
84
+ { isDraggable ? (
85
+ <DragHandle panelId={ panelId }>{ titleContent }</DragHandle>
86
+ ) : (
87
+ <Box sx={ { flex: 1 } }>{ titleContent }</Box>
88
+ ) }
89
+ <IconButton
90
+ size="small"
91
+ color="inherit"
92
+ aria-label={ __( 'Close panel', 'elementor' ) }
93
+ onClick={ close }
94
+ sx={ { borderRadius: 0, p: 1 } }
95
+ >
96
+ <XIcon fontSize="small" />
97
+ </IconButton>
98
+ </Box>
99
+ );
100
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { type ReactNode } from 'react';
3
+
4
+ type Props = {
5
+ children: ReactNode;
6
+ };
7
+
8
+ export default function FloatingPanel( { children }: Props ) {
9
+ return <>{ children }</>;
10
+ }
@@ -0,0 +1,4 @@
1
+ export { default as FloatingPanel } from './floating-panel';
2
+ export { default as FloatingPanelBody } from './floating-panel-body';
3
+ export { default as FloatingPanelFooter } from './floating-panel-footer';
4
+ export { default as FloatingPanelHeader } from './floating-panel-header';
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { type PointerEventHandler } from 'react';
3
+ import { Box } from '@elementor/ui';
4
+
5
+ import { isRtl } from '../../utils/direction';
6
+ import { type ResizeCorner } from '../../utils/resize-math';
7
+
8
+ const HANDLE_SIZE_PX = 8;
9
+
10
+ type CornerPosition = { insetBlockStart?: 0; insetBlockEnd?: 0; insetInlineStart?: 0; insetInlineEnd?: 0 };
11
+
12
+ const CORNER_POSITION: Record< ResizeCorner, CornerPosition > = {
13
+ 'block-start-inline-start': { insetBlockStart: 0, insetInlineStart: 0 },
14
+ 'block-start-inline-end': { insetBlockStart: 0, insetInlineEnd: 0 },
15
+ 'block-end-inline-start': { insetBlockEnd: 0, insetInlineStart: 0 },
16
+ 'block-end-inline-end': { insetBlockEnd: 0, insetInlineEnd: 0 },
17
+ };
18
+
19
+ const LTR_CURSORS: Record< ResizeCorner, string > = {
20
+ 'block-start-inline-start': 'nwse-resize',
21
+ 'block-start-inline-end': 'nesw-resize',
22
+ 'block-end-inline-start': 'nesw-resize',
23
+ 'block-end-inline-end': 'nwse-resize',
24
+ };
25
+
26
+ const RTL_CURSORS: Record< ResizeCorner, string > = {
27
+ 'block-start-inline-start': 'nesw-resize',
28
+ 'block-start-inline-end': 'nwse-resize',
29
+ 'block-end-inline-start': 'nwse-resize',
30
+ 'block-end-inline-end': 'nesw-resize',
31
+ };
32
+
33
+ type Props = {
34
+ corner: ResizeCorner;
35
+ onPointerDown: PointerEventHandler< HTMLElement >;
36
+ onPointerMove: PointerEventHandler< HTMLElement >;
37
+ onPointerUp: PointerEventHandler< HTMLElement >;
38
+ onPointerCancel: PointerEventHandler< HTMLElement >;
39
+ };
40
+
41
+ export default function CornerResizeHandle( {
42
+ corner,
43
+ onPointerDown,
44
+ onPointerMove,
45
+ onPointerUp,
46
+ onPointerCancel,
47
+ }: Props ) {
48
+ const cursor = isRtl() ? RTL_CURSORS[ corner ] : LTR_CURSORS[ corner ];
49
+
50
+ return (
51
+ <Box
52
+ data-resize-corner={ corner }
53
+ aria-hidden="true"
54
+ onPointerDown={ onPointerDown }
55
+ onPointerMove={ onPointerMove }
56
+ onPointerUp={ onPointerUp }
57
+ onPointerCancel={ onPointerCancel }
58
+ sx={ {
59
+ position: 'absolute',
60
+ touchAction: 'none',
61
+ zIndex: 2,
62
+ inlineSize: `${ HANDLE_SIZE_PX }px`,
63
+ blockSize: `${ HANDLE_SIZE_PX }px`,
64
+ cursor,
65
+ ...CORNER_POSITION[ corner ],
66
+ } }
67
+ />
68
+ );
69
+ }
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { type ReactNode } from 'react';
3
+ import { Box } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ import { useFloatingPanelDrag } from '../../hooks/use-floating-panel-drag';
7
+
8
+ type Props = {
9
+ panelId: string;
10
+ children: ReactNode;
11
+ };
12
+
13
+ export default function DragHandle( { panelId, children }: Props ) {
14
+ const { onPointerDown, onPointerMove, onPointerUp, onPointerCancel } = useFloatingPanelDrag( panelId );
15
+
16
+ return (
17
+ <Box
18
+ role="button"
19
+ aria-label={ __( 'Drag to reposition', 'elementor' ) }
20
+ onPointerDown={ onPointerDown }
21
+ onPointerMove={ onPointerMove }
22
+ onPointerUp={ onPointerUp }
23
+ onPointerCancel={ onPointerCancel }
24
+ sx={ { cursor: 'move', touchAction: 'none', flex: 1 } }
25
+ >
26
+ { children }
27
+ </Box>
28
+ );
29
+ }
@@ -0,0 +1,86 @@
1
+ import * as React from 'react';
2
+ import { type ReactNode, useMemo } from 'react';
3
+ import { useEditMode } from '@elementor/editor-v1-adapters';
4
+ import { __useDispatch as useDispatch, __useSelector as useSelector } from '@elementor/store';
5
+
6
+ import { useFloatingPanelsInjections } from '../../location';
7
+ import {
8
+ type GlobalState,
9
+ resolvePanelZIndex,
10
+ selectOpenPanelIds,
11
+ selectPanelState,
12
+ selectPanelTitle,
13
+ } from '../../store/selectors';
14
+ import { slice } from '../../store/slice';
15
+ import PanelWindow from './panel-window';
16
+
17
+ export default function FloatingPanelsHost() {
18
+ const openIds = useSelector( selectOpenPanelIds );
19
+ const injections = useFloatingPanelsInjections();
20
+ const dispatch = useDispatch();
21
+ const isPreviewMode = useEditMode() === 'preview';
22
+
23
+ const declarationById = useMemo( () => {
24
+ return Object.fromEntries( injections.map( ( inj ) => [ inj.id, inj ] ) );
25
+ }, [ injections ] );
26
+
27
+ return (
28
+ <>
29
+ { openIds.map( ( id ) => {
30
+ const declaration = declarationById[ id ];
31
+
32
+ if ( ! declaration ) {
33
+ return null;
34
+ }
35
+
36
+ const Component = declaration.component;
37
+
38
+ return (
39
+ <HostedPanel
40
+ key={ id }
41
+ id={ id }
42
+ visible={ ! isPreviewMode }
43
+ onFocus={ () => dispatch( slice.actions.bringToFront( id ) ) }
44
+ >
45
+ <Component />
46
+ </HostedPanel>
47
+ );
48
+ } ) }
49
+ </>
50
+ );
51
+ }
52
+
53
+ function HostedPanel( {
54
+ id,
55
+ children,
56
+ onFocus,
57
+ visible,
58
+ }: {
59
+ id: string;
60
+ children: ReactNode;
61
+ onFocus: () => void;
62
+ visible: boolean;
63
+ } ) {
64
+ const panel = useSelector( ( state: GlobalState ) => selectPanelState( state, id ) );
65
+ const title = useSelector( ( state: GlobalState ) => selectPanelTitle( state, id ) );
66
+ const zIndex = useSelector( ( state: GlobalState ) => resolvePanelZIndex( state, id ) );
67
+
68
+ if ( ! panel ) {
69
+ return null;
70
+ }
71
+
72
+ return (
73
+ <PanelWindow
74
+ panelId={ id }
75
+ corner={ panel.corner }
76
+ position={ panel.position }
77
+ size={ panel.size }
78
+ zIndex={ zIndex }
79
+ visible={ visible }
80
+ onFocus={ onFocus }
81
+ title={ title }
82
+ >
83
+ { children }
84
+ </PanelWindow>
85
+ );
86
+ }