@elementor/editor-editing-panel 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-editing-panel",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -40,14 +40,14 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@elementor/editor": "0.17.2",
43
- "@elementor/editor-controls": "0.3.0",
43
+ "@elementor/editor-controls": "0.4.0",
44
44
  "@elementor/editor-elements": "0.3.3",
45
45
  "@elementor/menus": "0.1.2",
46
46
  "@elementor/editor-props": "0.5.0",
47
47
  "@elementor/editor-panels": "0.10.2",
48
48
  "@elementor/editor-responsive": "0.12.4",
49
49
  "@elementor/editor-styles": "0.3.2",
50
- "@elementor/editor-styles-repository": "0.2.0",
50
+ "@elementor/editor-styles-repository": "0.3.0",
51
51
  "@elementor/editor-v1-adapters": "0.8.5",
52
52
  "@elementor/icons": "^1.20.0",
53
53
  "@elementor/schema": "0.1.2",
@@ -32,21 +32,27 @@ export const ConditionalTooltipWrapper = ( { maxWidth, title }: ConditionalToolt
32
32
  if ( isOverflown ) {
33
33
  return (
34
34
  <Tooltip title={ title } placement="top">
35
- <Content maxWidth={ maxWidth } ref={ elRef } title={ title } />
35
+ <Content maxWidth={ maxWidth } ref={ elRef }>
36
+ { title }
37
+ </Content>
36
38
  </Tooltip>
37
39
  );
38
40
  }
39
41
 
40
- return <Content maxWidth={ maxWidth } ref={ elRef } title={ title } />;
42
+ return (
43
+ <Content maxWidth={ maxWidth } ref={ elRef }>
44
+ { title }
45
+ </Content>
46
+ );
41
47
  };
42
48
 
43
- const Content = React.forwardRef( ( { maxWidth, title, ...rest }: ConditionalTooltipWrapperProps, ref ) => (
49
+ type ContentProps = React.PropsWithChildren< Omit< ConditionalTooltipWrapperProps, 'title' > >;
50
+
51
+ const Content = React.forwardRef( ( { maxWidth, ...tooltipProps }: ContentProps, ref ) => (
44
52
  <Box
45
53
  ref={ ref }
46
54
  position="relative"
47
55
  sx={ { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth } }
48
- { ...rest }
49
- >
50
- { title }
51
- </Box>
56
+ { ...tooltipProps }
57
+ />
52
58
  ) );
@@ -102,9 +102,7 @@ function useOptions() {
102
102
  }
103
103
 
104
104
  function useAppliedOptions( options: Option[], appliedIds: StyleDefinitionID[] ) {
105
- const applied = appliedIds
106
- .map( ( id ) => options.find( ( option ) => option.value === id ) )
107
- .filter( ( option ) => !! option );
105
+ const applied = options.filter( ( option ) => appliedIds.includes( option.value ) );
108
106
 
109
107
  const hasElementsProviderStyleApplied = applied.some(
110
108
  ( option ) => option.provider === ELEMENTS_STYLES_PROVIDER_KEY
@@ -1,17 +1,12 @@
1
1
  import * as React from 'react';
2
- import { BackgroundOverlayRepeaterControl } from '@elementor/editor-controls';
3
- import { Stack } from '@elementor/ui';
2
+ import { BackgroundControl } from '@elementor/editor-controls';
4
3
 
5
4
  import { StylesField } from '../../../controls-registry/styles-field';
6
- import { BackgroundColorField } from './background-color-field';
7
5
 
8
6
  export const BackgroundSection = () => {
9
7
  return (
10
- <Stack gap={ 1.5 }>
11
- <StylesField bind="background-image">
12
- <BackgroundOverlayRepeaterControl />
13
- </StylesField>
14
- <BackgroundColorField />
15
- </Stack>
8
+ <StylesField bind="background">
9
+ <BackgroundControl />
10
+ </StylesField>
16
11
  );
17
12
  };
@@ -1,9 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { ControlLabel } from '@elementor/editor-controls';
3
+ import { useParentElement } from '@elementor/editor-elements';
3
4
  import { type StringPropValue } from '@elementor/editor-props';
4
5
  import { Divider, Stack } from '@elementor/ui';
5
6
  import { __ } from '@wordpress/i18n';
6
7
 
8
+ import { useElement } from '../../../contexts/element-context';
9
+ import { useComputedStyle } from '../../../hooks/use-computed-style';
7
10
  import { useStylesField } from '../../../hooks/use-styles-field';
8
11
  import { AlignItemsField } from './align-items-field';
9
12
  import { AlignSelfChild } from './align-self-child-field';
@@ -17,11 +20,15 @@ import { WrapField } from './wrap-field';
17
20
 
18
21
  export const LayoutSection = () => {
19
22
  const [ display ] = useStylesField< StringPropValue >( 'display' );
23
+ const { element } = useElement();
24
+ const parent = useParentElement( element.id );
25
+ const parentStyle = useComputedStyle( parent?.id || null );
20
26
 
21
27
  return (
22
28
  <Stack gap={ 2 }>
23
29
  <DisplayField />
24
30
  { 'flex' === display?.value && <FlexFields /> }
31
+ { 'flex' === parentStyle?.display && <FlexChildFields /> }
25
32
  </Stack>
26
33
  );
27
34
  };
@@ -34,6 +41,11 @@ const FlexFields = () => (
34
41
  <Divider />
35
42
  <GapControlField />
36
43
  <WrapField />
44
+ </>
45
+ );
46
+
47
+ const FlexChildFields = () => (
48
+ <>
37
49
  <Divider />
38
50
  <ControlLabel>{ __( 'Flex child', 'elementor' ) }</ControlLabel>
39
51
  <AlignSelfChild />
@@ -12,7 +12,11 @@ const positionOptions = [
12
12
  { label: __( 'Fixed', 'elementor' ), value: 'fixed' },
13
13
  ];
14
14
 
15
- export const PositionField = () => {
15
+ type Props = {
16
+ onChange?: ( newValue: string | null, previousValue: string | null | undefined ) => void;
17
+ };
18
+
19
+ export const PositionField = ( { onChange }: Props ) => {
16
20
  return (
17
21
  <StylesField bind="position">
18
22
  <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
@@ -20,7 +24,7 @@ export const PositionField = () => {
20
24
  <ControlLabel>{ __( 'Position', 'elementor' ) }</ControlLabel>
21
25
  </Grid>
22
26
  <Grid item xs={ 6 }>
23
- <SelectControl options={ positionOptions } />
27
+ <SelectControl options={ positionOptions } onChange={ onChange } />
24
28
  </Grid>
25
29
  </Grid>
26
30
  </StylesField>
@@ -1,25 +1,65 @@
1
1
  import * as React from 'react';
2
- import { useCallback } from 'react';
3
- import type { PropValue, StringPropValue } from '@elementor/editor-props';
2
+ import { type StringPropValue } from '@elementor/editor-props';
4
3
  import { Stack } from '@elementor/ui';
5
4
 
6
- import { useStylePropsHistory } from '../../../hooks/use-style-prop-history';
5
+ import { useStyle } from '../../../contexts/style-context';
6
+ import { useSessionStorage } from '../../../hooks/use-session-storage';
7
7
  import { useStylesField } from '../../../hooks/use-styles-field';
8
+ import { useStylesFields } from '../../../hooks/use-styles-fields';
8
9
  import { DimensionsField } from './dimensions-field';
9
10
  import { PositionField } from './position-field';
10
11
  import { ZIndexField } from './z-index-field';
11
12
 
12
- const dimensionsPropKeys = [ 'top', 'bottom', 'left', 'right' ];
13
+ type DimensionValue =
14
+ | {
15
+ $$type: 'size';
16
+ value: number;
17
+ }
18
+ | undefined
19
+ | null;
20
+
21
+ type DimensionsValues = {
22
+ top: DimensionValue;
23
+ bottom: DimensionValue;
24
+ left: DimensionValue;
25
+ right: DimensionValue;
26
+ };
13
27
 
14
28
  export const PositionSection = () => {
15
29
  const [ positionValue ] = useStylesField< StringPropValue >( 'position' );
16
- usePositionChangeHandler();
30
+ const [ dimensionsValues, setDimensionsValues ] = useStylesFields< DimensionsValues >( [
31
+ 'top',
32
+ 'bottom',
33
+ 'left',
34
+ 'right',
35
+ ] );
36
+
37
+ const [ dimensionsValuesFromHistory, updateDimensionsHistory, clearDimensionsHistory ] = usePersistDimensions();
38
+
39
+ const onPositionChange = ( newPosition: string | null, previousPosition: string | null | undefined ) => {
40
+ if ( newPosition === 'static' ) {
41
+ if ( dimensionsValues ) {
42
+ updateDimensionsHistory( dimensionsValues );
43
+ setDimensionsValues( {
44
+ top: undefined,
45
+ bottom: undefined,
46
+ left: undefined,
47
+ right: undefined,
48
+ } );
49
+ }
50
+ } else if ( previousPosition === 'static' ) {
51
+ if ( dimensionsValuesFromHistory ) {
52
+ setDimensionsValues( dimensionsValuesFromHistory );
53
+ clearDimensionsHistory();
54
+ }
55
+ }
56
+ };
17
57
 
18
58
  const isNotStatic = positionValue && positionValue?.value !== 'static';
19
59
 
20
60
  return (
21
61
  <Stack gap={ 1.5 }>
22
- <PositionField />
62
+ <PositionField onChange={ onPositionChange } />
23
63
  { isNotStatic ? (
24
64
  <>
25
65
  <DimensionsField />
@@ -30,29 +70,10 @@ export const PositionSection = () => {
30
70
  );
31
71
  };
32
72
 
33
- const usePositionChangeHandler = () => {
34
- const dimensionsHistory = useStylePropsHistory( dimensionsPropKeys );
35
-
36
- const onPositionChange = useCallback(
37
- ( newPositionValue: PropValue, previousPosition: PropValue ) => {
38
- if ( ! dimensionsHistory ) {
39
- return;
40
- }
41
-
42
- const { saveStylePropsHistory, updateStylePropsFromHistory, clearCurrentStyleProps } = dimensionsHistory;
43
-
44
- if ( newPositionValue === 'static' ) {
45
- saveStylePropsHistory();
46
- clearCurrentStyleProps();
47
- } else if ( previousPosition === 'static' ) {
48
- updateStylePropsFromHistory();
49
- }
50
-
51
- previousPosition = newPositionValue;
52
- },
53
- [ dimensionsHistory ]
54
- );
73
+ const usePersistDimensions = () => {
74
+ const { id: styleDefID, meta } = useStyle();
75
+ const styleVariantPath = `styles/${ styleDefID }/${ meta.breakpoint || 'desktop' }/${ meta.state || 'null' }`;
76
+ const dimensionsPath = `${ styleVariantPath }/dimensions`;
55
77
 
56
- const [ , , registerChangeListener ] = useStylesField< PropValue >( 'position' );
57
- registerChangeListener?.( onPositionChange );
78
+ return useSessionStorage< DimensionsValues >( dimensionsPath );
58
79
  };
@@ -24,7 +24,7 @@ import { __ } from '@wordpress/i18n';
24
24
 
25
25
  import { Control as BaseControl } from '../../controls-registry/control';
26
26
  import { type ControlType, getControlByType } from '../../controls-registry/controls-registry';
27
- import { usePropValueHistory } from '../../hooks/use-prop-value-history';
27
+ import { usePersistDynamicValue } from '../../hooks/use-persist-dynamic-value';
28
28
  import { DynamicControl } from '../dynamic-control';
29
29
  import { useDynamicTag } from '../hooks/use-dynamic-tag';
30
30
  import { type DynamicTag } from '../types';
@@ -36,7 +36,7 @@ const SIZE = 'tiny';
36
36
  export const DynamicSelectionControl = () => {
37
37
  const { setValue: setAnyValue } = useBoundProp();
38
38
  const { bind, value } = useBoundProp( dynamicPropTypeUtil );
39
- const { getPropValue: getPropValueFromHistory } = usePropValueHistory();
39
+ const [ propValueFromHistory ] = usePersistDynamicValue( bind );
40
40
  const { name: tagName = '' } = value;
41
41
 
42
42
  const selectionPopoverId = useId();
@@ -45,9 +45,7 @@ export const DynamicSelectionControl = () => {
45
45
  const dynamicTag = useDynamicTag( bind, tagName );
46
46
 
47
47
  const removeDynamicTag = () => {
48
- const propValue = getPropValueFromHistory( bind );
49
-
50
- setAnyValue( propValue ?? null );
48
+ setAnyValue( propValueFromHistory ?? null );
51
49
  };
52
50
 
53
51
  if ( ! dynamicTag ) {
@@ -17,7 +17,7 @@ import {
17
17
  } from '@elementor/ui';
18
18
  import { __ } from '@wordpress/i18n';
19
19
 
20
- import { usePropValueHistory } from '../../hooks/use-prop-value-history';
20
+ import { usePersistDynamicValue } from '../../hooks/use-persist-dynamic-value';
21
21
  import { usePropDynamicTags } from '../hooks/use-prop-dynamic-tags';
22
22
  import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
23
23
  import { dynamicPropTypeUtil } from '../utils';
@@ -40,11 +40,11 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
40
40
  const { groups: dynamicGroups } = getAtomicDynamicTags() || {};
41
41
 
42
42
  const { value: anyValue } = useBoundProp();
43
- const { bind, value: dynamicvalue, setValue } = useBoundProp( dynamicPropTypeUtil );
43
+ const { bind, value: dynamicValue, setValue } = useBoundProp( dynamicPropTypeUtil );
44
44
 
45
- const { setPropValue: updatePropValueHistory } = usePropValueHistory();
45
+ const [ , updatePropValueHistory ] = usePersistDynamicValue( bind );
46
46
 
47
- const isCurrentValueDynamic = !! dynamicvalue;
47
+ const isCurrentValueDynamic = !! dynamicValue;
48
48
 
49
49
  const options = useFilteredOptions( bind, searchValue );
50
50
 
@@ -54,7 +54,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
54
54
 
55
55
  const handleSetDynamicTag = ( value: string ) => {
56
56
  if ( ! isCurrentValueDynamic ) {
57
- updatePropValueHistory( bind, anyValue );
57
+ updatePropValueHistory( anyValue );
58
58
  }
59
59
 
60
60
  setValue( { name: value, settings: {} } );
@@ -90,7 +90,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
90
90
  { dynamicGroups?.[ category ]?.title || category }
91
91
  </ListSubheader>
92
92
  { items.map( ( { value, label: tagLabel } ) => {
93
- const isSelected = isCurrentValueDynamic && value === dynamicvalue?.name;
93
+ const isSelected = isCurrentValueDynamic && value === dynamicValue?.name;
94
94
 
95
95
  return (
96
96
  <MenuItem
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { BoundPropProvider, useBoundProp } from '@elementor/editor-controls';
3
- import { isTransformable, type PropKey, type PropValue } from '@elementor/editor-props';
3
+ import { type PropKey, type PropValue } from '@elementor/editor-props';
4
4
 
5
5
  import { useDynamicTag } from './hooks/use-dynamic-tag';
6
6
  import { dynamicPropTypeUtil } from './utils';
@@ -27,8 +27,7 @@ export const DynamicControl = ( { bind, children }: DynamicControlProps ) => {
27
27
  name,
28
28
  settings: {
29
29
  ...settings,
30
- // The value inside the dynamic is not a transformable value, so we need to store the whole object.
31
- [ bind ]: isTransformable( newValue ) ? newValue.value : newValue,
30
+ [ bind ]: newValue,
32
31
  },
33
32
  } );
34
33
  };
@@ -0,0 +1,29 @@
1
+ import { __privateUseListenTo as useListenTo, commandEndEvent, windowEvent } from '@elementor/editor-v1-adapters';
2
+
3
+ import { type ExtendedWindow } from '../sync/types';
4
+
5
+ export function useComputedStyle( elementId: string | null ) {
6
+ return useListenTo(
7
+ [
8
+ windowEvent( 'elementor/device-mode/change' ),
9
+ commandEndEvent( 'document/elements/reset-style' ),
10
+ commandEndEvent( 'document/elements/settings' ),
11
+ commandEndEvent( 'document/elements/paste-style' ),
12
+ ],
13
+ () => {
14
+ if ( ! elementId ) {
15
+ return null;
16
+ }
17
+
18
+ const extendedWindow: ExtendedWindow = window;
19
+ const element = extendedWindow.elementor?.getContainer?.( elementId );
20
+
21
+ if ( ! element?.view?.el ) {
22
+ return null;
23
+ }
24
+
25
+ const resp = window.getComputedStyle( element.view.el );
26
+ return resp;
27
+ }
28
+ );
29
+ }
@@ -0,0 +1,11 @@
1
+ import { type PropValue } from '@elementor/editor-props';
2
+
3
+ import { useElement } from '../contexts/element-context';
4
+ import { type DynamicPropValue } from '../dynamics/types';
5
+ import { useSessionStorage } from './use-session-storage';
6
+
7
+ export const usePersistDynamicValue = < T extends DynamicPropValue | PropValue >( propKey: string ) => {
8
+ const { element } = useElement();
9
+ const prefixedKey = `dynamic/non-dynamic-values-history/${ element.id }/${ propKey }`;
10
+ return useSessionStorage< T >( prefixedKey );
11
+ };
@@ -0,0 +1,46 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { getSessionStorageItem, removeSessionStorageItem, setSessionStorageItem } from '@elementor/utils';
3
+
4
+ export const useSessionStorage = < T >( key: string ) => {
5
+ const prefixedKey = `elementor/${ key }`;
6
+
7
+ const [ value, setValue ] = useState< T | null >();
8
+
9
+ useEffect( () => {
10
+ return subscribeToSessionStorage< T | null >( prefixedKey, ( newValue ) => {
11
+ setValue( newValue ?? null );
12
+ } );
13
+ }, [ prefixedKey ] );
14
+
15
+ const saveValue = ( newValue: T ) => {
16
+ setSessionStorageItem( prefixedKey, newValue );
17
+ };
18
+
19
+ const removeValue = () => {
20
+ removeSessionStorageItem( prefixedKey );
21
+ };
22
+
23
+ return [ value, saveValue, removeValue ] as const;
24
+ };
25
+
26
+ const subscribeToSessionStorage = < T >( key: string, subscriber: ( value: T ) => void ) => {
27
+ subscriber( getSessionStorageItem( key ) as T );
28
+
29
+ const abortController = new AbortController();
30
+
31
+ window.addEventListener(
32
+ 'storage',
33
+ ( e ) => {
34
+ if ( e.key !== key || e.storageArea !== sessionStorage ) {
35
+ return;
36
+ }
37
+
38
+ subscriber( getSessionStorageItem( key ) as T );
39
+ },
40
+ { signal: abortController.signal }
41
+ );
42
+
43
+ return () => {
44
+ abortController.abort();
45
+ };
46
+ };
@@ -1,53 +1,17 @@
1
- import { useEffect, useRef } from 'react';
2
- import { updateStyle, useElementStyleProp } from '@elementor/editor-elements';
3
1
  import type { PropKey, PropValue } from '@elementor/editor-props';
4
- import { __ } from '@wordpress/i18n';
5
2
 
6
- import { useClassesProp } from '../contexts/classes-prop-context';
7
- import { useElement } from '../contexts/element-context';
8
- import { useStyle } from '../contexts/style-context';
3
+ import { useStylesFields } from './use-styles-fields';
9
4
 
10
- export const useStylesField = < T extends PropValue >(
11
- propName: PropKey
12
- ): [
13
- T | null,
14
- ( newValue: T ) => void,
15
- ( callback: ( newValue: T | null, previousValue: T | null ) => void ) => void,
16
- ] => {
17
- const { element } = useElement();
18
- const { id, meta } = useStyle();
19
- const classesProp = useClassesProp();
20
- const previousValue = useRef< T | null >( null );
21
- const onChangeCallbacks = useRef< Set< ( newValue: T | null, previousValue: T | null ) => void > >( new Set() );
5
+ export function useStylesField< T extends PropValue >( propName: PropKey ): [ T | null, ( newValue: T ) => void ] {
6
+ const [ values, setValues ] = useStylesFields< { [ k: typeof propName ]: T } >( [ propName ] );
22
7
 
23
- const value = useElementStyleProp< T >( {
24
- elementID: element.id,
25
- styleDefID: id,
26
- meta,
27
- propName,
28
- } );
8
+ const value = values?.[ propName ] ?? null;
29
9
 
30
10
  const setValue = ( newValue: T ) => {
31
- updateStyle( {
32
- elementID: element.id,
33
- styleDefID: id,
34
- props: { [ propName ]: newValue },
35
- meta,
36
- bind: classesProp,
37
- label: __( 'local', 'elementor' ),
11
+ setValues( {
12
+ [ propName ]: newValue,
38
13
  } );
39
14
  };
40
15
 
41
- const registerChangeListener = ( callback: ( newValue: T | null, previousValue: T | null ) => void ) => {
42
- onChangeCallbacks.current.add( callback );
43
- };
44
-
45
- useEffect( () => {
46
- onChangeCallbacks.current.forEach( ( cb ) => {
47
- cb( value, previousValue.current );
48
- } );
49
- previousValue.current = value;
50
- }, [ value ] );
51
-
52
- return [ value, setValue, registerChangeListener ];
53
- };
16
+ return [ value, setValue ];
17
+ }
@@ -0,0 +1,32 @@
1
+ import { updateStyle, useElementStyleProps } from '@elementor/editor-elements';
2
+ import type { Props } from '@elementor/editor-props';
3
+ import { __ } from '@wordpress/i18n';
4
+
5
+ import { useClassesProp } from '../contexts/classes-prop-context';
6
+ import { useElement } from '../contexts/element-context';
7
+ import { useStyle } from '../contexts/style-context';
8
+
9
+ export function useStylesFields< T extends Props >( propNames: ( keyof T & string )[] ) {
10
+ const { element } = useElement();
11
+ const { id, meta } = useStyle();
12
+ const classesProp = useClassesProp();
13
+
14
+ const value = useElementStyleProps( {
15
+ elementID: element.id,
16
+ styleDefID: id,
17
+ meta,
18
+ propNames,
19
+ } );
20
+
21
+ const setValue = ( newValues: T ) => {
22
+ updateStyle( {
23
+ elementID: element.id,
24
+ styleDefID: id,
25
+ props: newValues,
26
+ meta,
27
+ bind: classesProp,
28
+ label: __( 'local', 'elementor' ),
29
+ } );
30
+ };
31
+ return [ value, setValue ] as const;
32
+ }
@@ -1,21 +0,0 @@
1
- import * as React from 'react';
2
- import { ColorControl, ControlLabel } from '@elementor/editor-controls';
3
- import { Grid } from '@elementor/ui';
4
- import { __ } from '@wordpress/i18n';
5
-
6
- import { StylesField } from '../../../controls-registry/styles-field';
7
-
8
- export const BackgroundColorField = () => {
9
- return (
10
- <StylesField bind="background-color">
11
- <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
12
- <Grid item xs={ 6 }>
13
- <ControlLabel>{ __( 'Color', 'elementor' ) }</ControlLabel>
14
- </Grid>
15
- <Grid item xs={ 6 }>
16
- <ColorControl />
17
- </Grid>
18
- </Grid>
19
- </StylesField>
20
- );
21
- };
@@ -1,45 +0,0 @@
1
- import { useCallback, useMemo } from 'react';
2
- import { getSessionStorageItem, setSessionStorageItem } from '@elementor/utils';
3
-
4
- import { useElement } from '../contexts/element-context';
5
-
6
- export const PROPS_VALUES_HISTORY_PREFIX = 'elementor/editor-editing-panel/prop-value-history';
7
-
8
- export const usePropValueHistory = () => {
9
- const { element } = useElement();
10
- const elementKey = `${ PROPS_VALUES_HISTORY_PREFIX }/${ element.id }`;
11
-
12
- const getElementPropsHistory = useCallback( () => {
13
- return getSessionStorageItem< Record< string, unknown > >( elementKey );
14
- }, [ elementKey ] );
15
-
16
- const getPropValue = useCallback(
17
- < T >( propKey: string ) => {
18
- const elementPropValues = getElementPropsHistory();
19
- return ( elementPropValues?.[ propKey ] ?? null ) as T | null;
20
- },
21
- [ getElementPropsHistory ]
22
- );
23
-
24
- const setPropValue = useCallback(
25
- ( propKey: string, propValue: unknown ) => {
26
- const elementPropValues = getElementPropsHistory();
27
- const updatedElementPropValues = { ...elementPropValues, [ propKey ]: propValue };
28
- setSessionStorageItem( elementKey, updatedElementPropValues );
29
- },
30
- [ getElementPropsHistory, elementKey ]
31
- );
32
-
33
- const removeProp = useCallback(
34
- ( propKey: string ) => {
35
- const elementPropValues = getElementPropsHistory();
36
- const updatedElementPropValues = Object.fromEntries(
37
- Object.entries( elementPropValues || {} ).filter( ( [ key ] ) => key !== propKey )
38
- );
39
- setSessionStorageItem( elementKey, updatedElementPropValues );
40
- },
41
- [ getElementPropsHistory, elementKey ]
42
- );
43
-
44
- return useMemo( () => ( { getPropValue, setPropValue, removeProp } ), [ getPropValue, removeProp, setPropValue ] );
45
- };