@elementor/editor-editing-panel 4.4.0-1121 → 4.4.0-1122

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": "4.4.0-1121",
3
+ "version": "4.4.0-1122",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,32 +39,32 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor": "4.4.0-1121",
43
- "@elementor/editor-canvas": "4.4.0-1121",
44
- "@elementor/editor-controls": "4.4.0-1121",
45
- "@elementor/editor-current-user": "4.4.0-1121",
46
- "@elementor/editor-documents": "4.4.0-1121",
47
- "@elementor/editor-elements": "4.4.0-1121",
48
- "@elementor/editor-interactions": "4.4.0-1121",
49
- "@elementor/editor-notifications": "4.4.0-1121",
50
- "@elementor/editor-panels": "4.4.0-1121",
51
- "@elementor/editor-props": "4.4.0-1121",
52
- "@elementor/editor-responsive": "4.4.0-1121",
53
- "@elementor/editor-styles": "4.4.0-1121",
54
- "@elementor/editor-styles-repository": "4.4.0-1121",
55
- "@elementor/editor-ui": "4.4.0-1121",
56
- "@elementor/editor-v1-adapters": "4.4.0-1121",
57
- "@elementor/http-client": "4.4.0-1121",
42
+ "@elementor/editor": "4.4.0-1122",
43
+ "@elementor/editor-canvas": "4.4.0-1122",
44
+ "@elementor/editor-controls": "4.4.0-1122",
45
+ "@elementor/editor-current-user": "4.4.0-1122",
46
+ "@elementor/editor-documents": "4.4.0-1122",
47
+ "@elementor/editor-elements": "4.4.0-1122",
48
+ "@elementor/editor-interactions": "4.4.0-1122",
49
+ "@elementor/editor-notifications": "4.4.0-1122",
50
+ "@elementor/editor-panels": "4.4.0-1122",
51
+ "@elementor/editor-props": "4.4.0-1122",
52
+ "@elementor/editor-responsive": "4.4.0-1122",
53
+ "@elementor/editor-styles": "4.4.0-1122",
54
+ "@elementor/editor-styles-repository": "4.4.0-1122",
55
+ "@elementor/editor-ui": "4.4.0-1122",
56
+ "@elementor/editor-v1-adapters": "4.4.0-1122",
57
+ "@elementor/http-client": "4.4.0-1122",
58
58
  "@elementor/icons": "~1.75.1",
59
- "@elementor/editor-variables": "4.4.0-1121",
60
- "@elementor/locations": "4.4.0-1121",
61
- "@elementor/menus": "4.4.0-1121",
62
- "@elementor/query": "4.4.0-1121",
63
- "@elementor/schema": "4.4.0-1121",
64
- "@elementor/session": "4.4.0-1121",
59
+ "@elementor/editor-variables": "4.4.0-1122",
60
+ "@elementor/locations": "4.4.0-1122",
61
+ "@elementor/menus": "4.4.0-1122",
62
+ "@elementor/query": "4.4.0-1122",
63
+ "@elementor/schema": "4.4.0-1122",
64
+ "@elementor/session": "4.4.0-1122",
65
65
  "@elementor/ui": "1.37.5",
66
- "@elementor/utils": "4.4.0-1121",
67
- "@elementor/wp-media": "4.4.0-1121",
66
+ "@elementor/utils": "4.4.0-1122",
67
+ "@elementor/wp-media": "4.4.0-1122",
68
68
  "@wordpress/i18n": "^5.13.0"
69
69
  },
70
70
  "peerDependencies": {
@@ -7,7 +7,7 @@ import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { useElement } from '../../../contexts/element-context';
9
9
  import { ACCORDION_ELEMENT_TYPE, ACCORDION_ITEM_ELEMENT_TYPE, type AccordionItem, useActions } from './use-actions';
10
- import { useShowIconWriteThrough } from './use-show-icon-write-through';
10
+ import { useDifferentOpenIconWriteThrough, useShowIconWriteThrough } from './use-show-icon-write-through';
11
11
 
12
12
  export const AccordionItemsControl = ( { label }: { label: string } ) => {
13
13
  const { element, settings } = useElement();
@@ -26,8 +26,10 @@ export const AccordionItemsControl = ( { label }: { label: string } ) => {
26
26
  // drive the write-through to every head - see `useShowIconWriteThrough` for why this can't live
27
27
  // inside the generic switch control itself.
28
28
  const showIcon = booleanPropTypeUtil.extract( settings.show_icon ) ?? true;
29
+ const differentOpenIcon = booleanPropTypeUtil.extract( settings.different_open_icon ) ?? false;
29
30
 
30
31
  useShowIconWriteThrough( element.id, showIcon );
32
+ useDifferentOpenIconWriteThrough( element.id, differentOpenIcon );
31
33
 
32
34
  const repeaterValues: RepeaterItem< AccordionItem >[] = items.map( ( item, index ) => {
33
35
  return {
@@ -50,6 +52,7 @@ export const AccordionItemsControl = ( { label }: { label: string } ) => {
50
52
  existingTitles: repeaterValues.map( ( { title } ) => title ),
51
53
  items: meta.action.payload,
52
54
  showIcon,
55
+ differentOpenIcon,
53
56
  } );
54
57
  }
55
58
 
@@ -78,7 +78,7 @@ const getNextItemNumber = ( existingTitles: ( string | undefined )[] ) => {
78
78
  // `V1ElementData` is the plain-object form of a model tree: nested `elements` are objects that
79
79
  // Backbone turns into models on `initialize`, and ids have to be generated here because only the
80
80
  // outermost model gets one from `document/elements/create`.
81
- const buildItemModel = ( position: number, showIcon: boolean ): V1ElementData => {
81
+ const buildItemModel = ( position: number, showIcon: boolean, differentOpenIcon: boolean ): V1ElementData => {
82
82
  const numberedTitle = getItemTitle( position );
83
83
 
84
84
  return {
@@ -94,7 +94,10 @@ const buildItemModel = ( position: number, showIcon: boolean ): V1ElementData =>
94
94
  // has already turned Show Icon off, a newly added item must start with its icon hidden
95
95
  // too, not re-show one just because the item itself is brand new. See the comment on
96
96
  // the mirrored prop in `Atomic_Accordion_Item_Header` for why this duplication exists.
97
- settings: { show_icon: booleanPropTypeUtil.create( showIcon ) },
97
+ settings: {
98
+ show_icon: booleanPropTypeUtil.create( showIcon ),
99
+ different_open_icon: booleanPropTypeUtil.create( differentOpenIcon ),
100
+ },
98
101
  elements: [
99
102
  {
100
103
  elType: ACCORDION_ITEM_TITLE_ELEMENT_TYPE,
@@ -142,6 +145,7 @@ export const useActions = () => {
142
145
  existingTitles,
143
146
  items,
144
147
  showIcon,
148
+ differentOpenIcon = false,
145
149
  }: {
146
150
  accordionId: string;
147
151
  existingTitles: ( string | undefined )[];
@@ -149,6 +153,7 @@ export const useActions = () => {
149
153
  // The root's *current* `show_icon` value, so the new item's header starts in sync with it
150
154
  // instead of the schema default - see the comment on `buildItemModel`.
151
155
  showIcon: boolean;
156
+ differentOpenIcon?: boolean;
152
157
  } ) => {
153
158
  const accordion = getContainer( accordionId );
154
159
 
@@ -175,7 +180,11 @@ export const useActions = () => {
175
180
  // *existing* element out of the document, not for describing one to create. A single
176
181
  // cast is enough (the two types overlap enough for TS to allow it directly); no
177
182
  // `unknown` escape hatch needed.
178
- model: buildItemModel( position, showIcon ) as CreateElementParams[ 'model' ],
183
+ model: buildItemModel(
184
+ position,
185
+ showIcon,
186
+ differentOpenIcon
187
+ ) as CreateElementParams[ 'model' ],
179
188
  },
180
189
  ],
181
190
  } );
@@ -110,6 +110,78 @@ function getAccordionHeaderIds( accordionId: string ): string[] {
110
110
  return headerContainers.map( ( header ) => header.id );
111
111
  }
112
112
 
113
+ type CascadeDifferentOpenIconPayload = {
114
+ accordionId: string;
115
+ differentOpenIcon: boolean;
116
+ };
117
+
118
+ type CascadeDifferentOpenIconResult = {
119
+ previous: Record< string, ReturnType< typeof booleanPropTypeUtil.create > | null | undefined >;
120
+ };
121
+
122
+ export const cascadeDifferentOpenIconToHeaders = undoable<
123
+ CascadeDifferentOpenIconPayload,
124
+ CascadeDifferentOpenIconResult,
125
+ undefined
126
+ >(
127
+ {
128
+ do: ( { accordionId, differentOpenIcon } ) => {
129
+ const headerIds = getAccordionHeaderIds( accordionId );
130
+
131
+ const previous = Object.fromEntries(
132
+ headerIds.map(
133
+ ( headerId ) =>
134
+ [
135
+ headerId,
136
+ getElementSettings< ReturnType< typeof booleanPropTypeUtil.create > >( headerId, [
137
+ 'different_open_icon',
138
+ ] ).different_open_icon,
139
+ ] as const
140
+ )
141
+ );
142
+
143
+ headerIds.forEach( ( headerId ) => {
144
+ updateElementSettings( {
145
+ id: headerId,
146
+ props: { different_open_icon: booleanPropTypeUtil.create( differentOpenIcon ) },
147
+ withHistory: false,
148
+ } );
149
+ } );
150
+
151
+ return { previous };
152
+ },
153
+ undo: ( _payload, { previous } ) => {
154
+ Object.entries( previous ).forEach( ( [ headerId, previousValue ] ) => {
155
+ updateElementSettings( {
156
+ id: headerId,
157
+ props: { different_open_icon: previousValue ?? null },
158
+ withHistory: false,
159
+ } );
160
+ } );
161
+ },
162
+ },
163
+ {
164
+ title: __( 'Accordion', 'elementor' ),
165
+ subtitle: __( 'Different icon when open', 'elementor' ),
166
+ debounce: { wait: HISTORY_DEBOUNCE_WAIT },
167
+ }
168
+ );
169
+
170
+ export function useDifferentOpenIconWriteThrough( accordionId: string, differentOpenIcon: boolean ): void {
171
+ const previousRef = useRef< { accordionId: string; differentOpenIcon: boolean } | null >( null );
172
+
173
+ useEffect( () => {
174
+ const previous = previousRef.current;
175
+ previousRef.current = { accordionId, differentOpenIcon };
176
+
177
+ if ( ! previous || previous.accordionId !== accordionId || previous.differentOpenIcon === differentOpenIcon ) {
178
+ return;
179
+ }
180
+
181
+ cascadeDifferentOpenIconToHeaders( { accordionId, differentOpenIcon } );
182
+ }, [ accordionId, differentOpenIcon ] );
183
+ }
184
+
113
185
  // Watches the root's *current* `show_icon` value (read reactively from the panel's element
114
186
  // settings) and cascades it to every header on change. Skips the very first render for a given
115
187
  // element so mounting the panel on an already-toggled-off accordion doesn't re-fire a no-op