@elementor/editor-editing-panel 1.10.0 → 1.11.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 (35) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/index.js +680 -685
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +632 -641
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +18 -15
  7. package/src/components/css-classes/css-class-item.tsx +130 -0
  8. package/src/components/css-classes/css-class-menu.tsx +151 -0
  9. package/src/components/{css-class-selector.tsx → css-classes/css-class-selector.tsx} +23 -154
  10. package/src/components/style-sections/layout-section/display-field.tsx +9 -1
  11. package/src/components/style-sections/layout-section/flex-order-field.tsx +5 -5
  12. package/src/components/style-sections/layout-section/flex-size-field.tsx +1 -1
  13. package/src/components/style-sections/layout-section/gap-control-field.tsx +0 -2
  14. package/src/components/style-sections/position-section/dimensions-field.tsx +1 -1
  15. package/src/components/style-sections/position-section/position-section.tsx +1 -1
  16. package/src/components/style-sections/typography-section/font-weight-field.tsx +9 -5
  17. package/src/components/style-sections/typography-section/text-alignment-field.tsx +16 -8
  18. package/src/components/style-sections/typography-section/transform-field.tsx +12 -3
  19. package/src/components/style-tab.tsx +1 -1
  20. package/src/controls-registry/controls-registry.tsx +3 -1
  21. package/src/controls-registry/settings-field.tsx +8 -1
  22. package/src/dynamics/components/dynamic-selection.tsx +1 -1
  23. package/src/dynamics/dynamic-control.tsx +1 -1
  24. package/src/dynamics/types.ts +2 -2
  25. package/src/dynamics/utils.ts +2 -2
  26. package/src/hooks/use-persist-dynamic-value.ts +1 -1
  27. package/src/hooks/use-styles-fields.ts +113 -9
  28. package/src/index.ts +1 -1
  29. package/src/init.ts +2 -2
  30. package/src/sync/types.ts +4 -3
  31. package/src/components/collapsible-field.tsx +0 -36
  32. package/src/components/css-class-menu.tsx +0 -101
  33. package/src/components/editable-field.tsx +0 -166
  34. package/src/hooks/use-session-storage.ts +0 -46
  35. package/src/sync/enqueue-font.ts +0 -7
@@ -1,33 +1,41 @@
1
1
  import * as React from 'react';
2
2
  import { ControlLabel, type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-controls';
3
3
  import { AlignCenterIcon, AlignJustifiedIcon, AlignLeftIcon, AlignRightIcon } from '@elementor/icons';
4
- import { Grid } from '@elementor/ui';
4
+ import { Grid, withDirection } from '@elementor/ui';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { StylesField } from '../../../controls-registry/styles-field';
8
+ import { RotatedIcon } from '../layout-section/utils/rotated-icon';
8
9
 
9
- type Alignments = 'left' | 'center' | 'right' | 'justify';
10
+ type Alignments = 'start' | 'center' | 'end' | 'justify';
11
+
12
+ const StartIcon = withDirection( AlignLeftIcon );
13
+ const EndIcon = withDirection( AlignRightIcon );
10
14
 
11
15
  const options: ToggleButtonGroupItem< Alignments >[] = [
12
16
  {
13
- value: 'left',
14
- label: __( 'Left', 'elementor' ),
15
- renderContent: ( { size } ) => <AlignLeftIcon fontSize={ size } />,
17
+ value: 'start',
18
+ label: __( 'Start', 'elementor' ),
19
+ renderContent: () => <RotatedIcon icon={ StartIcon } size="tiny" />,
20
+ showTooltip: true,
16
21
  },
17
22
  {
18
23
  value: 'center',
19
24
  label: __( 'Center', 'elementor' ),
20
25
  renderContent: ( { size } ) => <AlignCenterIcon fontSize={ size } />,
26
+ showTooltip: true,
21
27
  },
22
28
  {
23
- value: 'right',
24
- label: __( 'Right', 'elementor' ),
25
- renderContent: ( { size } ) => <AlignRightIcon fontSize={ size } />,
29
+ value: 'end',
30
+ label: __( 'End', 'elementor' ),
31
+ renderContent: () => <RotatedIcon icon={ EndIcon } size="tiny" />,
32
+ showTooltip: true,
26
33
  },
27
34
  {
28
35
  value: 'justify',
29
36
  label: __( 'Justify', 'elementor' ),
30
37
  renderContent: ( { size } ) => <AlignJustifiedIcon fontSize={ size } />,
38
+ showTooltip: true,
31
39
  },
32
40
  ];
33
41
 
@@ -1,28 +1,37 @@
1
1
  import * as React from 'react';
2
2
  import { ControlLabel, type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-controls';
3
- import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon } from '@elementor/icons';
3
+ import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon, MinusIcon } from '@elementor/icons';
4
4
  import { Grid } from '@elementor/ui';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { StylesField } from '../../../controls-registry/styles-field';
8
8
 
9
- type Transforms = 'capitalize' | 'uppercase' | 'lowercase';
9
+ type Transforms = 'none' | 'capitalize' | 'uppercase' | 'lowercase';
10
10
 
11
11
  const options: ToggleButtonGroupItem< Transforms >[] = [
12
+ {
13
+ value: 'none',
14
+ label: __( 'None', 'elementor' ),
15
+ renderContent: ( { size } ) => <MinusIcon fontSize={ size } />,
16
+ showTooltip: true,
17
+ },
12
18
  {
13
19
  value: 'capitalize',
14
20
  label: __( 'Capitalize', 'elementor' ),
15
21
  renderContent: ( { size } ) => <LetterCaseIcon fontSize={ size } />,
22
+ showTooltip: true,
16
23
  },
17
24
  {
18
25
  value: 'uppercase',
19
26
  label: __( 'Uppercase', 'elementor' ),
20
27
  renderContent: ( { size } ) => <LetterCaseUpperIcon fontSize={ size } />,
28
+ showTooltip: true,
21
29
  },
22
30
  {
23
31
  value: 'lowercase',
24
32
  label: __( 'Lowercase', 'elementor' ),
25
33
  renderContent: ( { size } ) => <LetterCaseLowerIcon fontSize={ size } />,
34
+ showTooltip: true,
26
35
  },
27
36
  ];
28
37
 
@@ -30,7 +39,7 @@ export const TransformField = () => (
30
39
  <StylesField bind={ 'text-transform' }>
31
40
  <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
32
41
  <Grid item xs={ 6 }>
33
- <ControlLabel>{ __( 'Transform', 'elementor' ) }</ControlLabel>
42
+ <ControlLabel>{ __( 'Text Transform', 'elementor' ) }</ControlLabel>
34
43
  </Grid>
35
44
  <Grid item xs={ 6 } display="flex" justifyContent="end">
36
45
  <ToggleControl options={ options } />
@@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
11
11
  import { ClassesPropProvider } from '../contexts/classes-prop-context';
12
12
  import { useElement } from '../contexts/element-context';
13
13
  import { StyleProvider } from '../contexts/style-context';
14
- import { CssClassSelector } from './css-class-selector';
14
+ import { CssClassSelector } from './css-classes/css-class-selector';
15
15
  import { Section } from './section';
16
16
  import { SectionsList } from './sections-list';
17
17
  import { BackgroundSection } from './style-sections/background-section/background-section';
@@ -4,6 +4,7 @@ import {
4
4
  LinkControl,
5
5
  SelectControl,
6
6
  SizeControl,
7
+ SvgMediaControl,
7
8
  TextAreaControl,
8
9
  TextControl,
9
10
  UrlControl,
@@ -15,7 +16,8 @@ type ControlRegistry = Record< string, { component: ControlComponent; layout: Co
15
16
 
16
17
  const controlTypes = {
17
18
  image: { component: ImageControl, layout: 'full' },
18
- text: { component: TextControl, layout: 'two-columns' },
19
+ 'svg-media': { component: SvgMediaControl, layout: 'full' },
20
+ text: { component: TextControl, layout: 'full' },
19
21
  textarea: { component: TextAreaControl, layout: 'full' },
20
22
  size: { component: SizeControl, layout: 'two-columns' },
21
23
  select: { component: SelectControl, layout: 'two-columns' },
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { PropKeyProvider, PropProvider } from '@elementor/editor-controls';
3
3
  import { updateElementSettings, useElementSetting } from '@elementor/editor-elements';
4
- import { type PropKey, type PropValue } from '@elementor/editor-props';
4
+ import { type LinkPropValue, type PropKey, type PropValue } from '@elementor/editor-props';
5
5
 
6
6
  import { useElement } from '../contexts/element-context';
7
7
  import { createTopLevelOjectType } from './create-top-level-object-type';
@@ -15,10 +15,17 @@ export const SettingsField = ( { bind, children }: Props ) => {
15
15
  const { element, elementType } = useElement();
16
16
 
17
17
  const settingsValue = useElementSetting< PropValue >( element.id, bind );
18
+
19
+ const linkValue = useElementSetting< PropValue >( element.id, 'link' ) as LinkPropValue;
20
+
18
21
  const value = { [ bind ]: settingsValue };
19
22
 
20
23
  const propType = createTopLevelOjectType( { schema: elementType.propsSchema } );
21
24
 
25
+ if ( bind === 'tag' && linkValue?.value && 'div-block' === elementType.key ) {
26
+ return null;
27
+ }
28
+
22
29
  const setValue = ( newValue: Record< string, PropValue > ) => {
23
30
  updateElementSettings( {
24
31
  id: element.id,
@@ -30,7 +30,7 @@ type OptionEntry = [ string, Option[] ];
30
30
 
31
31
  const SIZE = 'tiny';
32
32
 
33
- export type DynamicSelectionProps = {
33
+ type DynamicSelectionProps = {
34
34
  onSelect?: () => void;
35
35
  };
36
36
 
@@ -6,7 +6,7 @@ import { createTopLevelOjectType } from '../controls-registry/create-top-level-o
6
6
  import { useDynamicTag } from './hooks/use-dynamic-tag';
7
7
  import { dynamicPropTypeUtil, type DynamicPropValue } from './utils';
8
8
 
9
- export type DynamicControlProps = React.PropsWithChildren< {
9
+ type DynamicControlProps = React.PropsWithChildren< {
10
10
  bind: PropKey;
11
11
  } >;
12
12
 
@@ -1,5 +1,5 @@
1
- import { type ControlItem, type PropsSchema } from '@elementor/editor-elements';
2
- import { type TransformablePropType, type TransformablePropValue } from '@elementor/editor-props';
1
+ import { type ControlItem } from '@elementor/editor-elements';
2
+ import { type PropsSchema, type TransformablePropType, type TransformablePropValue } from '@elementor/editor-props';
3
3
 
4
4
  export type ExtendedWindow = Window & {
5
5
  elementor?: {
@@ -9,9 +9,9 @@ import { z } from '@elementor/schema';
9
9
 
10
10
  import { type DynamicPropType } from './types';
11
11
 
12
- export const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
12
+ const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
13
13
 
14
- export const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
14
+ const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
15
15
  prop.key === DYNAMIC_PROP_TYPE_KEY;
16
16
 
17
17
  export const getDynamicPropType = ( propType: PropType ): DynamicPropType | null => {
@@ -1,8 +1,8 @@
1
1
  import { type PropValue } from '@elementor/editor-props';
2
+ import { useSessionStorage } from '@elementor/session';
2
3
 
3
4
  import { useElement } from '../contexts/element-context';
4
5
  import { type DynamicPropValue } from '../dynamics/types';
5
- import { useSessionStorage } from './use-session-storage';
6
6
 
7
7
  export const usePersistDynamicValue = < T extends DynamicPropValue | PropValue >( propKey: string ) => {
8
8
  const { element } = useElement();
@@ -1,8 +1,16 @@
1
- import { useEffect, useReducer } from 'react';
2
- import { createElementStyle, type ElementID } from '@elementor/editor-elements';
1
+ import { useEffect, useMemo, useReducer } from 'react';
2
+ import {
3
+ createElementStyle,
4
+ type CreateElementStyleArgs,
5
+ deleteElementStyle,
6
+ type ElementID,
7
+ getElementLabel,
8
+ } from '@elementor/editor-elements';
3
9
  import type { Props } from '@elementor/editor-props';
4
10
  import { getVariantByMeta, type StyleDefinition, type StyleDefinitionVariant } from '@elementor/editor-styles';
5
11
  import { type StylesProvider } from '@elementor/editor-styles-repository';
12
+ import { LOCAL_STYLES_RESERVED_LABEL } from '@elementor/editor-styles-repository';
13
+ import { undoable } from '@elementor/editor-v1-adapters';
6
14
  import { __ } from '@wordpress/i18n';
7
15
 
8
16
  import { useClassesProp } from '../contexts/classes-prop-context';
@@ -15,6 +23,9 @@ export function useStylesFields< T extends Props >( propNames: ( keyof T & strin
15
23
  const { id, meta, provider } = useStyle();
16
24
  const classesProp = useClassesProp();
17
25
 
26
+ const undoableUpdateStyle = useUndoableUpdateStyle();
27
+ const undoableCreateElementStyle = useUndoableCreateElementStyle();
28
+
18
29
  const [ , reRender ] = useReducer( ( p ) => ! p, false );
19
30
 
20
31
  useEffect( () => provider?.subscribe( reRender ), [ provider ] );
@@ -29,22 +40,23 @@ export function useStylesFields< T extends Props >( propNames: ( keyof T & strin
29
40
 
30
41
  const setValue = ( props: T ) => {
31
42
  if ( id === null ) {
32
- createElementStyle( {
43
+ undoableCreateElementStyle( {
33
44
  elementId: element.id,
34
45
  classesProp,
35
46
  meta,
36
47
  props,
37
- label: __( 'local', 'elementor' ),
38
48
  } );
39
49
 
40
50
  return;
41
51
  }
42
52
 
43
- if ( ! provider.actions.updateProps ) {
44
- throw new StylesProviderCannotUpdatePropsError( { context: { providerKey: provider.key } } );
45
- }
46
-
47
- provider.actions.updateProps( { id, meta, props }, { elementId: element.id } );
53
+ undoableUpdateStyle( {
54
+ elementId: element.id,
55
+ styleId: id,
56
+ provider,
57
+ meta,
58
+ props,
59
+ } );
48
60
  };
49
61
 
50
62
  return [ value, setValue ] as const;
@@ -79,3 +91,95 @@ function getProps< T extends Props >( { styleId, elementId, provider, meta, prop
79
91
  propNames.map( ( key ) => [ key, variant?.props[ key ] ?? null ] )
80
92
  ) as NullableValues< T >;
81
93
  }
94
+
95
+ type UndoableCreateElementStyleArgs = Omit< CreateElementStyleArgs, 'label' >;
96
+
97
+ function useUndoableCreateElementStyle() {
98
+ return useMemo( () => {
99
+ return undoable(
100
+ {
101
+ do: ( payload: UndoableCreateElementStyleArgs ) => {
102
+ return createElementStyle( {
103
+ ...payload,
104
+ label: LOCAL_STYLES_RESERVED_LABEL,
105
+ } );
106
+ },
107
+
108
+ undo: ( { elementId }, styleId ) => {
109
+ deleteElementStyle( elementId, styleId );
110
+ },
111
+
112
+ redo: ( payload, styleId ) => {
113
+ return createElementStyle( {
114
+ ...payload,
115
+ styleId,
116
+ label: LOCAL_STYLES_RESERVED_LABEL,
117
+ } );
118
+ },
119
+ },
120
+ {
121
+ title: ( { elementId } ) => getElementLabel( elementId ),
122
+ subtitle: __( 'Style edited', 'elementor' ),
123
+ }
124
+ );
125
+ }, [] );
126
+ }
127
+
128
+ type UndoableUpdateStyleArgs = {
129
+ elementId: ElementID;
130
+ styleId: StyleDefinition[ 'id' ];
131
+ provider: StylesProvider;
132
+ meta: StyleDefinitionVariant[ 'meta' ];
133
+ props: Props;
134
+ };
135
+
136
+ function useUndoableUpdateStyle() {
137
+ return useMemo( () => {
138
+ return undoable(
139
+ {
140
+ do: ( { elementId, styleId, provider, meta, props }: UndoableUpdateStyleArgs ) => {
141
+ if ( ! provider.actions.updateProps ) {
142
+ throw new StylesProviderCannotUpdatePropsError( {
143
+ context: { providerKey: provider.key },
144
+ } );
145
+ }
146
+
147
+ const style = provider.actions.getById( styleId, { elementId } );
148
+
149
+ const prevProps = getCurrentProps( style, meta );
150
+
151
+ provider.actions.updateProps(
152
+ {
153
+ id: styleId,
154
+ meta,
155
+ props,
156
+ },
157
+ { elementId }
158
+ );
159
+
160
+ return prevProps;
161
+ },
162
+
163
+ undo: ( { elementId, styleId, meta, provider }, prevProps ) => {
164
+ provider.actions.updateProps?.( { id: styleId, meta, props: prevProps }, { elementId } );
165
+ },
166
+ },
167
+ {
168
+ title: ( { elementId } ) => getElementLabel( elementId ),
169
+ subtitle: __( 'Style edited', 'elementor' ),
170
+ }
171
+ );
172
+ }, [] );
173
+ }
174
+
175
+ function getCurrentProps( style: StyleDefinition | null, meta: StyleDefinitionVariant[ 'meta' ] ) {
176
+ if ( ! style ) {
177
+ return {};
178
+ }
179
+
180
+ const variant = getVariantByMeta( style, meta );
181
+
182
+ const props = variant?.props ?? {};
183
+
184
+ return structuredClone( props );
185
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { useBoundProp } from '@elementor/editor-controls';
2
2
  export type { PopoverActionProps } from './popover-action';
3
3
  export { replaceControl } from './control-replacement';
4
- export { injectIntoClassSelectorActions } from './components/css-class-selector';
4
+ export { injectIntoClassSelectorActions } from './components/css-classes/css-class-selector';
5
5
  export { usePanelActions, usePanelStatus } from './panel';
6
6
 
7
7
  import init from './init';
package/src/init.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { injectIntoLogic } from '@elementor/editor';
2
2
  import { __registerPanel as registerPanel } from '@elementor/editor-panels';
3
- import { __privateBlockDataCommand as blockDataCommand } from '@elementor/editor-v1-adapters';
3
+ import { blockCommand } from '@elementor/editor-v1-adapters';
4
4
 
5
5
  import { EditingPanelHooks } from './components/editing-panel-hooks';
6
6
  import { init as initDynamics } from './dynamics/init';
@@ -21,7 +21,7 @@ export default function init() {
21
21
  }
22
22
 
23
23
  const blockV1Panel = () => {
24
- blockDataCommand( {
24
+ blockCommand( {
25
25
  command: 'panel/editor/open',
26
26
  condition: isAtomicWidgetSelected,
27
27
  } );
package/src/sync/types.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { type ControlItem, type PropsSchema, type V1Element } from '@elementor/editor-elements';
1
+ import { type ControlItem, type V1Element } from '@elementor/editor-elements';
2
+ import { type PropsSchema } from '@elementor/editor-props';
2
3
 
3
- export type SupportedFonts = 'system' | 'googlefonts' | 'customfonts';
4
+ type SupportedFonts = 'system' | 'googlefonts' | 'customfonts';
4
5
 
5
- export type EnqueueFont = ( fontFamily: string, context?: 'preview' | 'editor' ) => void;
6
+ type EnqueueFont = ( fontFamily: string, context?: 'preview' | 'editor' ) => void;
6
7
 
7
8
  export type ExtendedWindow = Window & {
8
9
  elementor?: {
@@ -1,36 +0,0 @@
1
- import * as React from 'react';
2
- import { useState } from 'react';
3
- import { MinusIcon, PlusIcon } from '@elementor/icons';
4
- import { Collapse, IconButton, Stack } from '@elementor/ui';
5
- import { __ } from '@wordpress/i18n';
6
-
7
- type CollapsibleFieldProps = React.PropsWithChildren< {
8
- label: React.ReactNode;
9
- defaultOpen?: boolean;
10
- } >;
11
-
12
- export const CollapsibleField = ( { label, children, defaultOpen = false }: CollapsibleFieldProps ) => {
13
- const [ open, setOpen ] = useState( defaultOpen );
14
-
15
- const handleToggle = () => {
16
- setOpen( ( prevOpen ) => ! prevOpen );
17
- };
18
-
19
- return (
20
- <Stack gap={ 1.5 }>
21
- <Stack direction="row" justifyContent="space-between" alignItems="center" sx={ { py: 0.5 } }>
22
- { label }
23
- <IconButton
24
- onClick={ handleToggle }
25
- size="tiny"
26
- aria-label={ open ? __( 'Close', 'elementor' ) : __( 'Expand', 'elementor' ) }
27
- >
28
- { open ? <MinusIcon fontSize="tiny" /> : <PlusIcon fontSize="tiny" /> }
29
- </IconButton>
30
- </Stack>
31
- <Collapse in={ open } unmountOnExit>
32
- { children }
33
- </Collapse>
34
- </Stack>
35
- );
36
- };
@@ -1,101 +0,0 @@
1
- import * as React from 'react';
2
- import { type StyleDefinitionState } from '@elementor/editor-styles';
3
- import { CheckIcon } from '@elementor/icons';
4
- import {
5
- bindMenu,
6
- Divider,
7
- ListItemIcon,
8
- ListItemText,
9
- ListSubheader,
10
- Menu,
11
- MenuItem,
12
- type PopupState,
13
- styled,
14
- } from '@elementor/ui';
15
- import { __ } from '@wordpress/i18n';
16
-
17
- import { useStyle } from '../contexts/style-context';
18
- import { useUnapplyClass } from '../hooks/use-unapply-class';
19
-
20
- const STATES: NonNullable< StyleDefinitionState >[] = [ 'hover', 'focus', 'active' ];
21
-
22
- type CssClassMenuProps = { styleId: string; isFixed: boolean; popupState: PopupState };
23
-
24
- export function CssClassMenu( { styleId, isFixed = false, popupState }: CssClassMenuProps ) {
25
- const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
26
- e.stopPropagation();
27
- };
28
-
29
- return (
30
- <Menu
31
- MenuListProps={ { dense: true } }
32
- { ...bindMenu( popupState ) }
33
- anchorOrigin={ {
34
- vertical: 'top',
35
- horizontal: 'right',
36
- } }
37
- onKeyDown={ handleKeyDown }
38
- >
39
- { /* It has to be an array since MUI menu doesn't accept a Fragment as a child, and wrapping the items with an HTML element disrupts keyboard navigation */ }
40
- { ! isFixed && [
41
- <UnapplyClassMenuItem key="unapply-class" styleId={ styleId } />,
42
- <Divider key="global-class-items-divider" />,
43
- ] }
44
- <ListSubheader>{ __( 'Add a pseudo selector', 'elementor' ) }</ListSubheader>
45
- <StateMenuItem key="normal" state={ null } styleId={ styleId } />
46
- { STATES.map( ( state ) => {
47
- return <StateMenuItem key={ state } state={ state } styleId={ styleId } />;
48
- } ) }
49
- </Menu>
50
- );
51
- }
52
-
53
- type StateMenuItemProps = {
54
- state: StyleDefinitionState;
55
- styleId: string;
56
- };
57
-
58
- function StateMenuItem( { state, styleId, ...props }: StateMenuItemProps ) {
59
- const { id: activeId, setId: setActiveId, setMetaState: setActiveMetaState, meta } = useStyle();
60
- const { state: activeState } = meta;
61
-
62
- const isActive = styleId === activeId;
63
- const isSelected = state === activeState && isActive;
64
-
65
- return (
66
- <StyledMenuItem
67
- { ...props }
68
- selected={ isSelected }
69
- onClick={ () => {
70
- if ( ! isActive ) {
71
- setActiveId( styleId );
72
- }
73
-
74
- setActiveMetaState( state );
75
- } }
76
- >
77
- { isSelected && (
78
- <ListItemIcon>
79
- <CheckIcon />
80
- </ListItemIcon>
81
- ) }
82
- <ListItemText primary={ state ? `:${ state }` : 'Normal' } />
83
- </StyledMenuItem>
84
- );
85
- }
86
-
87
- function UnapplyClassMenuItem( { styleId, ...props }: { styleId: string } ) {
88
- const unapplyClass = useUnapplyClass( styleId );
89
-
90
- return (
91
- <StyledMenuItem { ...props } onClick={ unapplyClass }>
92
- <ListItemText primary="Remove" />
93
- </StyledMenuItem>
94
- );
95
- }
96
-
97
- const StyledMenuItem = styled( MenuItem )( {
98
- '&:hover': {
99
- color: 'text.primary', // Overriding global CSS from the editor.
100
- },
101
- } );