@elementor/editor-editing-panel 0.4.1 → 0.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.
Files changed (28) hide show
  1. package/CHANGELOG.md +12 -22
  2. package/dist/index.js +98 -88
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +97 -87
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +43 -43
  7. package/src/__tests__/utils.ts +2 -2
  8. package/src/components/__tests__/editing-panel.test.tsx +2 -6
  9. package/src/components/controls/__tests__/settings-control.test.tsx +19 -15
  10. package/src/components/controls/control-types/__tests__/select-control.test.tsx +1 -1
  11. package/src/components/controls/control-types/__tests__/{text-control.test.tsx → text-area-control.test.tsx} +4 -4
  12. package/src/components/controls/control-types/select-control.tsx +9 -9
  13. package/src/components/controls/control-types/text-area-control.tsx +25 -0
  14. package/src/components/controls/settings-control.tsx +12 -32
  15. package/src/components/editing-panel.tsx +23 -24
  16. package/src/contexts/control-context.tsx +45 -0
  17. package/src/contexts/{settings-controls.tsx → element-context.tsx} +4 -8
  18. package/src/hooks/__tests__/use-widget-settings.test.ts +3 -1
  19. package/src/hooks/use-open-editor-panel.ts +4 -7
  20. package/src/hooks/use-selected-elements.ts +1 -4
  21. package/src/panel.ts +1 -5
  22. package/src/sync/get-selected-elements.ts +1 -1
  23. package/src/sync/types.ts +20 -17
  24. package/src/sync/update-settings.ts +1 -1
  25. package/src/types.ts +17 -17
  26. package/src/components/controls/control-context.ts +0 -20
  27. package/src/components/controls/control-types/text-control.tsx +0 -19
  28. /package/src/{components/controls → contexts}/__tests__/control-context.test.tsx +0 -0
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import { TextareaAutosize } from '@elementor/ui';
3
+ import { useControl } from '../../../contexts/control-context';
4
+
5
+ type Props = {
6
+ placeholder?: string;
7
+ };
8
+
9
+ export const TextAreaControl = ( { placeholder }: Props ) => {
10
+ const { value, setValue } = useControl< string >( '' );
11
+
12
+ const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
13
+ setValue( event.target.value );
14
+ };
15
+
16
+ return (
17
+ <TextareaAutosize
18
+ size="tiny"
19
+ minRows={ 3 }
20
+ value={ value }
21
+ onChange={ handleChange }
22
+ placeholder={ placeholder }
23
+ />
24
+ );
25
+ };
@@ -1,40 +1,14 @@
1
1
  import * as React from 'react';
2
- import { ControlContext } from './control-context';
2
+ import { ControlContextProvider } from '../../contexts/control-context';
3
3
  import { Stack, Typography } from '@elementor/ui';
4
- import { updateSettings } from '../../sync/update-settings';
5
- import { useWidgetSettings } from '../../hooks/use-widget-settings';
6
- import { PropKey, PropValue } from '../../types';
4
+ import { PropKey } from '../../types';
7
5
 
8
6
  type Props = {
9
7
  bind: PropKey;
10
8
  children: React.ReactNode;
11
- elementID: Element['id'];
12
- }
13
-
14
- const SettingsControl = ( { bind, children, elementID }: Props ) => {
15
- const value = useWidgetSettings( { id: elementID, bind } );
16
-
17
- const setValue = ( newValue: PropValue ) => {
18
- updateSettings( {
19
- id: elementID,
20
- props: {
21
- [ bind ]: newValue,
22
- },
23
- } );
24
- };
25
-
26
- return (
27
- <ControlContext.Provider value={ { setValue, value, bind } }>
28
- { children }
29
- </ControlContext.Provider>
30
- );
31
- };
32
-
33
- const Label = ( { children }: { children: React.ReactNode } ) => {
34
- return <Typography component="label" variant="caption">{ children }</Typography>;
35
9
  };
36
10
 
37
- const Container = ( { children }: { children: React.ReactNode} ) => (
11
+ const SettingsControl = ( { children, bind }: Props ) => (
38
12
  <Stack
39
13
  spacing={ 1 }
40
14
  flexDirection="row"
@@ -43,11 +17,17 @@ const Container = ( { children }: { children: React.ReactNode} ) => (
43
17
  flexWrap="wrap"
44
18
  sx={ { px: 2 } }
45
19
  >
46
- { children }
20
+ <ControlContextProvider bind={ bind }>{ children }</ControlContextProvider>
47
21
  </Stack>
48
22
  );
49
23
 
50
- SettingsControl.Label = Label;
51
- SettingsControl.Container = Container;
24
+ const Label = ( { children }: { children: React.ReactNode } ) => {
25
+ return (
26
+ <Typography component="label" variant="caption">
27
+ { children }
28
+ </Typography>
29
+ );
30
+ };
52
31
 
32
+ SettingsControl.Label = Label;
53
33
  export { SettingsControl };
@@ -4,20 +4,20 @@ import useSelectedElements from '../hooks/use-selected-elements';
4
4
  import useElementType from '../hooks/use-element-type';
5
5
  import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from '@elementor/editor-panels';
6
6
  import { SelectControl } from './controls/control-types/select-control';
7
- import { TextControl } from './controls/control-types/text-control';
7
+ import { TextAreaControl } from './controls/control-types/text-area-control';
8
8
  import { SettingsControl } from '../components/controls/settings-control';
9
9
  import { Stack } from '@elementor/ui';
10
- import { ElementContext } from '../contexts/settings-controls';
10
+ import { ElementContext } from '../contexts/element-context';
11
11
 
12
12
  const controlTypes = {
13
13
  select: SelectControl,
14
- text: TextControl,
14
+ textarea: TextAreaControl,
15
15
  };
16
16
 
17
17
  export const EditingPanel = () => {
18
18
  const elements = useSelectedElements();
19
19
 
20
- const selectedElement = elements[ 0 ];
20
+ const [ selectedElement ] = elements;
21
21
 
22
22
  const elementType = useElementType( selectedElement?.type );
23
23
 
@@ -36,29 +36,28 @@ export const EditingPanel = () => {
36
36
  <PanelBody>
37
37
  <ElementContext element={ selectedElement }>
38
38
  <Stack spacing={ 2 }>
39
- {
40
- elementType.controls.map( ( control ) => {
41
- if ( control.type === 'control' ) {
42
- const ControlComponent = controlTypes[ control.value.type as keyof typeof controlTypes ];
39
+ { elementType.controls.map( ( control ) => {
40
+ if ( control.type === 'control' ) {
41
+ const ControlComponent =
42
+ controlTypes[ control.value.type as keyof typeof controlTypes ];
43
43
 
44
- if ( ! ControlComponent ) {
45
- return null;
46
- }
47
-
48
- return (
49
- <SettingsControl key={ control.value.bind } bind={ control.value.bind } elementID={ elements[ 0 ].id }>
50
- <SettingsControl.Container>
51
- <SettingsControl.Label>{ control.value.label }</SettingsControl.Label>
52
- { /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ }
53
- <ControlComponent { ...control.value.props as any } />
54
- </SettingsControl.Container>
55
- </SettingsControl>
56
- );
44
+ if ( ! ControlComponent ) {
45
+ return null;
57
46
  }
58
47
 
59
- return null;
60
- } )
61
- }
48
+ return (
49
+ <SettingsControl key={ control.value.bind } bind={ control.value.bind }>
50
+ <SettingsControl.Label>{ control.value.label }</SettingsControl.Label>
51
+ <ControlComponent
52
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
53
+ { ...( control.value.props as any ) }
54
+ />
55
+ </SettingsControl>
56
+ );
57
+ }
58
+
59
+ return null;
60
+ } ) }
62
61
  </Stack>
63
62
  </ElementContext>
64
63
  </PanelBody>
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import { createContext, useContext } from 'react';
3
+ import { PropKey, PropValue } from '../types';
4
+ import { useElementContext } from './element-context';
5
+ import { useWidgetSettings } from '../hooks/use-widget-settings';
6
+ import { updateSettings } from '../sync/update-settings';
7
+
8
+ export type ControlContext< T extends PropValue > = null | {
9
+ bind: PropKey;
10
+ setValue: ( value: T ) => void;
11
+ value: T;
12
+ };
13
+
14
+ export const ControlContext = createContext< ControlContext< PropValue > >( null );
15
+
16
+ export function useControl< T extends PropValue >( defaultValue?: T ) {
17
+ const controlContext = useContext< ControlContext< T > >( ControlContext as never );
18
+
19
+ if ( ! controlContext ) {
20
+ throw new Error( 'useControl must be used within a ControlContext' );
21
+ }
22
+
23
+ return { ...controlContext, value: controlContext.value ?? defaultValue };
24
+ }
25
+
26
+ type Props = {
27
+ bind: PropKey;
28
+ children: React.ReactNode;
29
+ };
30
+
31
+ export const ControlContextProvider = ( { bind, children }: Props ) => {
32
+ const { element } = useElementContext();
33
+ const value = useWidgetSettings( { id: element.id, bind } );
34
+
35
+ const setValue = ( newValue: PropValue ) => {
36
+ updateSettings( {
37
+ id: element.id,
38
+ props: {
39
+ [ bind ]: newValue,
40
+ },
41
+ } );
42
+ };
43
+
44
+ return <ControlContext.Provider value={ { setValue, value, bind } }>{ children }</ControlContext.Provider>;
45
+ };
@@ -4,21 +4,17 @@ import { Element } from '../types';
4
4
 
5
5
  type ContextValue = {
6
6
  element: Element;
7
- }
7
+ };
8
8
 
9
- const Context = createContext<ContextValue | null>( null );
9
+ const Context = createContext< ContextValue | null >( null );
10
10
 
11
11
  type Props = {
12
12
  element: Element;
13
13
  children?: ReactNode;
14
- }
14
+ };
15
15
 
16
16
  export function ElementContext( { children, element }: Props ) {
17
- return (
18
- <Context.Provider value={ { element } }>
19
- { children }
20
- </Context.Provider>
21
- );
17
+ return <Context.Provider value={ { element } }>{ children }</Context.Provider>;
22
18
  }
23
19
 
24
20
  export function useElementContext() {
@@ -71,7 +71,9 @@ describe( 'useWidgetSettings', () => {
71
71
 
72
72
  // Act.
73
73
  act( () => {
74
- jest.mocked( getContainer ).mockReturnValue( mockV1Element( { settings: { [ bind ]: 'Goodbye, World!' } } ) );
74
+ jest.mocked( getContainer ).mockReturnValue(
75
+ mockV1Element( { settings: { [ bind ]: 'Goodbye, World!' } } )
76
+ );
75
77
  dispatchCommandAfter( 'document/elements/settings' );
76
78
  } );
77
79
 
@@ -7,13 +7,10 @@ export const useOpenEditorPanel = () => {
7
7
  const { open } = usePanelActions();
8
8
 
9
9
  useEffect( () => {
10
- return listenTo(
11
- commandStartEvent( 'panel/editor/open' ),
12
- () => {
13
- if ( shouldUseV2Panel() ) {
14
- open();
15
- }
10
+ return listenTo( commandStartEvent( 'panel/editor/open' ), () => {
11
+ if ( shouldUseV2Panel() ) {
12
+ open();
16
13
  }
17
- );
14
+ } );
18
15
  }, [] ); // eslint-disable-line react-hooks/exhaustive-deps
19
16
  };
@@ -3,10 +3,7 @@ import getSelectedElements from '../sync/get-selected-elements';
3
3
 
4
4
  export default function useSelectedElements() {
5
5
  return useListenTo(
6
- [
7
- commandEndEvent( 'document/elements/select' ),
8
- commandEndEvent( 'document/elements/deselect' ),
9
- ],
6
+ [ commandEndEvent( 'document/elements/select' ), commandEndEvent( 'document/elements/deselect' ) ],
10
7
  () => getSelectedElements()
11
8
  );
12
9
  }
package/src/panel.ts CHANGED
@@ -1,11 +1,7 @@
1
1
  import { __createPanel as createPanel } from '@elementor/editor-panels';
2
2
  import { EditingPanel } from './components/editing-panel';
3
3
 
4
- export const {
5
- panel,
6
- usePanelActions,
7
- usePanelStatus,
8
- } = createPanel( {
4
+ export const { panel, usePanelActions, usePanelStatus } = createPanel( {
9
5
  id: 'editing-panel',
10
6
  component: EditingPanel,
11
7
  } );
@@ -6,7 +6,7 @@ export default function getSelectedElements(): Element[] {
6
6
 
7
7
  const selectedElements = extendedWindow.elementor?.selection?.getElements?.() ?? [];
8
8
 
9
- return selectedElements.reduce<Element[]>( ( acc, el ) => {
9
+ return selectedElements.reduce< Element[] >( ( acc, el ) => {
10
10
  const type = el.model.get( 'widgetType' ) || el.model.get( 'elType' );
11
11
 
12
12
  if ( type ) {
package/src/sync/types.ts CHANGED
@@ -4,29 +4,32 @@ export type ExtendedWindow = Window & {
4
4
  elementor?: {
5
5
  selection?: {
6
6
  getElements: () => V1Element[];
7
- },
8
- widgetsCache?: Record<string, {
9
- atomic_controls?: AtomicControl[],
10
- controls: object,
11
- title: string,
12
- }>,
13
- getContainer?: ( id: string ) => V1Element
14
- }
15
- }
7
+ };
8
+ widgetsCache?: Record<
9
+ string,
10
+ {
11
+ atomic_controls?: AtomicControl[];
12
+ controls: object;
13
+ title: string;
14
+ }
15
+ >;
16
+ getContainer?: ( id: string ) => V1Element;
17
+ };
18
+ };
16
19
 
17
20
  export type V1Element = {
18
- model: V1Model<V1ElementModelProps>,
19
- settings?: V1Model<V1ElementSettingsProps>,
20
- }
21
+ model: V1Model< V1ElementModelProps >;
22
+ settings?: V1Model< V1ElementSettingsProps >;
23
+ };
21
24
 
22
25
  export type V1ElementModelProps = {
23
26
  widgetType?: string;
24
27
  elType: string;
25
28
  id: string;
26
- }
29
+ };
27
30
 
28
- export type V1ElementSettingsProps = Record<string, PropValue>;
31
+ export type V1ElementSettingsProps = Record< string, PropValue >;
29
32
 
30
- type V1Model<T> = {
31
- get: <K extends keyof T>( key: K ) => T[K],
32
- }
33
+ type V1Model< T > = {
34
+ get: < K extends keyof T >( key: K ) => T[ K ];
35
+ };
@@ -2,7 +2,7 @@ import { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters
2
2
  import { Props } from '../types';
3
3
  import getContainer from './get-container';
4
4
 
5
- export const updateSettings = ( { id, props }: { id: string, props: Props } ) => {
5
+ export const updateSettings = ( { id, props }: { id: string; props: Props } ) => {
6
6
  const container = getContainer( id );
7
7
 
8
8
  runCommand( 'document/elements/settings', {
package/src/types.ts CHANGED
@@ -1,38 +1,38 @@
1
1
  export type Element = {
2
2
  id: string;
3
3
  type: string;
4
- }
4
+ };
5
5
 
6
6
  export type ElementType = {
7
7
  key: string;
8
8
  controls: AtomicControl[];
9
9
  title: string;
10
- }
10
+ };
11
11
 
12
12
  export type AtomicControl = {
13
- type: 'control',
13
+ type: 'control';
14
14
  value: {
15
- bind: string,
16
- label: string,
17
- description?: string,
18
- type: string,
19
- props: Record<string, unknown>,
20
- },
21
- }
15
+ bind: string;
16
+ label: string;
17
+ description?: string;
18
+ type: string;
19
+ props: Record< string, unknown >;
20
+ };
21
+ };
22
22
 
23
- type MaybeArray<T> = T | T[];
23
+ type MaybeArray< T > = T | T[];
24
24
 
25
25
  type TransformablePropValue = {
26
- $$type: string,
27
- value: unknown,
28
- }
26
+ $$type: string;
27
+ value: unknown;
28
+ };
29
29
 
30
- export type PlainPropValue = MaybeArray<string | number | boolean | object | null | undefined>;
30
+ export type PlainPropValue = MaybeArray< string | number | boolean | object | null | undefined >;
31
31
 
32
32
  export type PropValue = PlainPropValue | TransformablePropValue;
33
33
 
34
34
  export type PropKey = string;
35
35
 
36
- export type Props = Record<PropKey, PropValue>;
36
+ export type Props = Record< PropKey, PropValue >;
37
37
 
38
- export type PlainProps = Record<PropKey, PlainPropValue>;
38
+ export type PlainProps = Record< PropKey, PlainPropValue >;
@@ -1,20 +0,0 @@
1
- import { createContext, useContext } from 'react';
2
- import { PropKey, PropValue } from '../../types';
3
-
4
- export type ControlContext<T extends PropValue> = null | {
5
- bind: PropKey;
6
- setValue: ( value: T ) => void;
7
- value: T;
8
- };
9
-
10
- export const ControlContext = createContext<ControlContext<PropValue>>( null );
11
-
12
- export function useControl<T extends PropValue>( defaultValue?: T ) {
13
- const controlContext = useContext<ControlContext<T>>( ControlContext as never );
14
-
15
- if ( ! controlContext ) {
16
- throw new Error( 'useControl must be used within a ControlContext' );
17
- }
18
-
19
- return { ...controlContext, value: controlContext.value ?? defaultValue };
20
- }
@@ -1,19 +0,0 @@
1
- import * as React from 'react';
2
- import { TextareaAutosize } from '@elementor/ui';
3
- import { useControl } from '../control-context';
4
-
5
- export type TextControlProps = {
6
- placeholder?: string;
7
- }
8
-
9
- export const TextControl = ( { placeholder }: TextControlProps ) => {
10
- const { value, setValue } = useControl<string>( '' );
11
-
12
- const handleChange = ( event: React.ChangeEvent<HTMLInputElement> ) => {
13
- setValue( event.target.value );
14
- };
15
-
16
- return (
17
- <TextareaAutosize size="tiny" minRows={ 3 }value={ value } onChange={ handleChange } placeholder={ placeholder } />
18
- );
19
- };