@elementor/editor-controls 3.33.0-99 → 3.35.0-324

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 (94) hide show
  1. package/dist/index.d.mts +276 -85
  2. package/dist/index.d.ts +276 -85
  3. package/dist/index.js +2491 -1783
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +2304 -1592
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +31 -17
  8. package/src/bound-prop-context/prop-context.tsx +7 -1
  9. package/src/bound-prop-context/use-bound-prop.ts +19 -5
  10. package/src/components/autocomplete.tsx +34 -3
  11. package/src/components/conditional-control-infotip.tsx +64 -0
  12. package/src/components/{unstable-repeater → control-repeater}/actions/disable-item-action.tsx +2 -2
  13. package/src/components/{unstable-repeater → control-repeater}/actions/duplicate-item-action.tsx +10 -4
  14. package/src/components/{unstable-repeater → control-repeater}/actions/remove-item-action.tsx +2 -2
  15. package/src/components/control-repeater/context/item-context.tsx +8 -0
  16. package/src/components/{unstable-repeater → control-repeater}/context/repeater-context.tsx +24 -15
  17. package/src/components/control-repeater/control-repeater.tsx +29 -0
  18. package/src/components/{unstable-repeater → control-repeater}/index.ts +1 -2
  19. package/src/components/{unstable-repeater → control-repeater}/items/edit-item-popover.tsx +6 -20
  20. package/src/components/control-repeater/items/item.tsx +75 -0
  21. package/src/components/{unstable-repeater → control-repeater}/items/items-container.tsx +8 -13
  22. package/src/components/{unstable-repeater → control-repeater}/locations.ts +0 -4
  23. package/src/components/{unstable-repeater → control-repeater}/types.ts +1 -2
  24. package/src/components/control-toggle-button-group.tsx +79 -69
  25. package/src/components/enable-unfiltered-modal.tsx +1 -26
  26. package/src/components/icon-buttons/clear-icon-button.tsx +23 -0
  27. package/src/components/inline-editor-toolbar.tsx +137 -0
  28. package/src/components/inline-editor.tsx +111 -0
  29. package/src/components/item-selector.tsx +10 -4
  30. package/src/components/{unstable-repeater/header/header.tsx → repeater/repeater-header.tsx} +4 -12
  31. package/src/components/repeater/repeater-popover.tsx +19 -0
  32. package/src/components/repeater/repeater-tag.tsx +16 -0
  33. package/src/components/repeater/repeater.tsx +405 -0
  34. package/src/components/{sortable.tsx → repeater/sortable.tsx} +1 -1
  35. package/src/components/size-control/size-input.tsx +20 -14
  36. package/src/components/size-control/text-field-inner-selection.tsx +15 -2
  37. package/src/control-adornments/control-adornments-context.tsx +5 -4
  38. package/src/control-replacements.tsx +12 -47
  39. package/src/controls/background-control/background-control.tsx +43 -12
  40. package/src/controls/background-control/background-gradient-color-control.tsx +5 -8
  41. package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +18 -13
  42. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +25 -16
  43. package/src/controls/box-shadow-repeater-control.tsx +38 -21
  44. package/src/controls/color-control.tsx +3 -1
  45. package/src/controls/date-time-control.tsx +108 -0
  46. package/src/controls/filter-control/drop-shadow/drop-shadow-item-content.tsx +1 -0
  47. package/src/controls/filter-control/drop-shadow/drop-shadow-item-label.tsx +10 -6
  48. package/src/controls/filter-control/filter-content.tsx +1 -1
  49. package/src/controls/filter-control/filter-repeater-control.tsx +24 -21
  50. package/src/controls/filter-control/single-size/single-size-item-content.tsx +1 -1
  51. package/src/controls/filter-control/single-size/single-size-item-label.tsx +2 -1
  52. package/src/controls/font-family-control/font-family-control.tsx +66 -55
  53. package/src/controls/html-tag-control.tsx +90 -0
  54. package/src/controls/image-media-control.tsx +2 -2
  55. package/src/controls/inline-editing-control.tsx +18 -0
  56. package/src/controls/key-value-control.tsx +8 -2
  57. package/src/controls/link-control.tsx +23 -123
  58. package/src/controls/query-control.tsx +168 -0
  59. package/src/controls/repeatable-control.tsx +62 -27
  60. package/src/controls/select-control-wrapper.tsx +57 -0
  61. package/src/controls/select-control.tsx +9 -5
  62. package/src/controls/selection-size-control.tsx +13 -2
  63. package/src/controls/size-control.tsx +43 -25
  64. package/src/controls/svg-media-control.tsx +33 -10
  65. package/src/controls/text-area-control.tsx +5 -1
  66. package/src/controls/text-control.tsx +5 -0
  67. package/src/controls/toggle-control.tsx +11 -2
  68. package/src/controls/transform-control/functions/axis-row.tsx +1 -0
  69. package/src/controls/transform-control/transform-icon.tsx +2 -2
  70. package/src/controls/transform-control/transform-label.tsx +15 -32
  71. package/src/controls/transform-control/transform-repeater-control.tsx +42 -36
  72. package/src/controls/transform-control/{transform-base-control.tsx → transform-settings-control.tsx} +2 -2
  73. package/src/controls/transform-control/use-transform-tabs-history.tsx +1 -1
  74. package/src/controls/transition-control/data.ts +16 -1
  75. package/src/controls/transition-control/trainsition-events.ts +2 -2
  76. package/src/controls/transition-control/transition-repeater-control.tsx +137 -13
  77. package/src/controls/transition-control/transition-selector.tsx +37 -14
  78. package/src/controls/url-control.tsx +21 -16
  79. package/src/create-control.tsx +3 -2
  80. package/src/hooks/use-filtered-items-list.ts +3 -2
  81. package/src/hooks/use-repeatable-control-context.ts +3 -0
  82. package/src/hooks/use-sync-external-state.tsx +0 -1
  83. package/src/index.ts +21 -5
  84. package/src/utils/convert-toggle-options-to-atomic.tsx +33 -0
  85. package/src/utils/escape-html-attr.ts +11 -0
  86. package/src/components/css-code-editor/css-editor.styles.ts +0 -52
  87. package/src/components/css-code-editor/css-editor.tsx +0 -142
  88. package/src/components/css-code-editor/css-validation.ts +0 -75
  89. package/src/components/css-code-editor/resize-handle.tsx +0 -55
  90. package/src/components/css-code-editor/visual-content-change-protection.ts +0 -69
  91. package/src/components/repeater.tsx +0 -343
  92. package/src/components/unstable-repeater/items/item.tsx +0 -77
  93. package/src/components/unstable-repeater/unstable-repeater.tsx +0 -26
  94. /package/src/components/{unstable-repeater → control-repeater}/actions/tooltip-add-item-action.tsx +0 -0
@@ -1,343 +0,0 @@
1
- import * as React from 'react';
2
- import { useEffect, useState } from 'react';
3
- import { type PropKey, type PropTypeUtil } from '@elementor/editor-props';
4
- import { CopyIcon, EyeIcon, EyeOffIcon, PlusIcon, XIcon } from '@elementor/icons';
5
- import {
6
- bindPopover,
7
- bindTrigger,
8
- Box,
9
- IconButton,
10
- Popover,
11
- Stack,
12
- Tooltip,
13
- Typography,
14
- UnstableTag,
15
- type UnstableTagProps,
16
- usePopupState,
17
- } from '@elementor/ui';
18
- import { __ } from '@wordpress/i18n';
19
-
20
- import { ControlAdornments } from '../control-adornments/control-adornments';
21
- import { useSyncExternalState } from '../hooks/use-sync-external-state';
22
- import { SectionContent } from './section-content';
23
- import { SortableItem, SortableProvider } from './sortable';
24
- import { RepeaterItemIconSlot, RepeaterItemLabelSlot } from './unstable-repeater/locations';
25
-
26
- const SIZE = 'tiny';
27
-
28
- type AnchorEl = HTMLElement | null;
29
-
30
- type Item< T > = {
31
- disabled?: boolean;
32
- } & T;
33
- export type CollectionPropUtil< T > = PropTypeUtil< PropKey, T[] >;
34
-
35
- type RepeaterItemContentProps< T > = {
36
- anchorEl: AnchorEl;
37
- bind: PropKey;
38
- value: T;
39
- collectionPropUtil?: CollectionPropUtil< T >;
40
- };
41
-
42
- type RepeaterItemContent< T > = React.ComponentType< RepeaterItemContentProps< T > >;
43
-
44
- type RepeaterProps< T > = {
45
- label: string;
46
- values?: T[];
47
- addToBottom?: boolean;
48
- openOnAdd?: boolean;
49
- setValues: ( newValue: T[] ) => void;
50
- disabled?: boolean;
51
- itemSettings: {
52
- initialValues: T;
53
- Label: React.ComponentType< { value: T } >;
54
- Icon: React.ComponentType< { value: T } >;
55
- Content: RepeaterItemContent< T >;
56
- };
57
- showDuplicate?: boolean;
58
- showToggle?: boolean;
59
- isSortable?: boolean;
60
- collectionPropUtil?: CollectionPropUtil< T >;
61
- };
62
-
63
- const EMPTY_OPEN_ITEM = -1;
64
-
65
- export const Repeater = < T, >( {
66
- label,
67
- itemSettings,
68
- disabled = false,
69
- openOnAdd = false,
70
- addToBottom = false,
71
- values: repeaterValues = [],
72
- setValues: setRepeaterValues,
73
- showDuplicate = true,
74
- showToggle = true,
75
- isSortable = true,
76
- collectionPropUtil,
77
- }: RepeaterProps< Item< T > > ) => {
78
- const [ openItem, setOpenItem ] = useState( EMPTY_OPEN_ITEM );
79
-
80
- const [ items, setItems ] = useSyncExternalState( {
81
- external: repeaterValues,
82
- // @ts-expect-error - as long as persistWhen => true, value will never be null
83
- setExternal: setRepeaterValues,
84
- persistWhen: () => true,
85
- } );
86
-
87
- const [ uniqueKeys, setUniqueKeys ] = useState( items.map( ( _, index ) => index ) );
88
-
89
- const generateNextKey = ( source: number[] ) => {
90
- return 1 + Math.max( 0, ...source );
91
- };
92
-
93
- const addRepeaterItem = () => {
94
- const newItem = structuredClone( itemSettings.initialValues );
95
- const newKey = generateNextKey( uniqueKeys );
96
-
97
- if ( addToBottom ) {
98
- setItems( [ ...items, newItem ] );
99
- setUniqueKeys( [ ...uniqueKeys, newKey ] );
100
- } else {
101
- setItems( [ newItem, ...items ] );
102
- setUniqueKeys( [ newKey, ...uniqueKeys ] );
103
- }
104
-
105
- if ( openOnAdd ) {
106
- setOpenItem( newKey );
107
- }
108
- };
109
-
110
- const duplicateRepeaterItem = ( index: number ) => {
111
- const newItem = structuredClone( items[ index ] );
112
- const newKey = generateNextKey( uniqueKeys );
113
-
114
- // Insert the new (cloned item) at the next spot (after the current index)
115
- const atPosition = 1 + index;
116
-
117
- setItems( [ ...items.slice( 0, atPosition ), newItem, ...items.slice( atPosition ) ] );
118
- setUniqueKeys( [ ...uniqueKeys.slice( 0, atPosition ), newKey, ...uniqueKeys.slice( atPosition ) ] );
119
- };
120
-
121
- const removeRepeaterItem = ( index: number ) => {
122
- setUniqueKeys(
123
- uniqueKeys.filter( ( _, pos ) => {
124
- return pos !== index;
125
- } )
126
- );
127
-
128
- setItems(
129
- items.filter( ( _, pos ) => {
130
- return pos !== index;
131
- } )
132
- );
133
- };
134
-
135
- const toggleDisableRepeaterItem = ( index: number ) => {
136
- setItems(
137
- items.map( ( value, pos ) => {
138
- if ( pos === index ) {
139
- const { disabled: propDisabled, ...rest } = value;
140
-
141
- // If the items should not be disabled, remove the disabled property.
142
- return { ...rest, ...( propDisabled ? {} : { disabled: true } ) } as Item< T >;
143
- }
144
-
145
- return value;
146
- } )
147
- );
148
- };
149
-
150
- const onChangeOrder = ( reorderedKeys: number[] ) => {
151
- setUniqueKeys( reorderedKeys );
152
- setItems( ( prevItems ) => {
153
- return reorderedKeys.map( ( keyValue ) => {
154
- const index = uniqueKeys.indexOf( keyValue );
155
- return prevItems[ index ];
156
- } );
157
- } );
158
- };
159
-
160
- return (
161
- <SectionContent>
162
- <Stack
163
- direction="row"
164
- justifyContent="start"
165
- alignItems="center"
166
- gap={ 1 }
167
- sx={ { marginInlineEnd: -0.75 } }
168
- >
169
- <Typography component="label" variant="caption" color="text.secondary">
170
- { label }
171
- </Typography>
172
- <ControlAdornments />
173
- <IconButton
174
- size={ SIZE }
175
- sx={ { ml: 'auto' } }
176
- disabled={ disabled }
177
- onClick={ addRepeaterItem }
178
- aria-label={ __( 'Add item', 'elementor' ) }
179
- >
180
- <PlusIcon fontSize={ SIZE } />
181
- </IconButton>
182
- </Stack>
183
- { 0 < uniqueKeys.length && (
184
- <SortableProvider value={ uniqueKeys } onChange={ onChangeOrder }>
185
- { uniqueKeys.map( ( key, index ) => {
186
- const value = items[ index ];
187
-
188
- if ( ! value ) {
189
- return null;
190
- }
191
-
192
- return (
193
- <SortableItem id={ key } key={ `sortable-${ key }` } disabled={ ! isSortable }>
194
- <RepeaterItem
195
- disabled={ disabled }
196
- propDisabled={ value?.disabled }
197
- label={
198
- <RepeaterItemLabelSlot value={ value }>
199
- <itemSettings.Label value={ value } />
200
- </RepeaterItemLabelSlot>
201
- }
202
- startIcon={
203
- <RepeaterItemIconSlot value={ value }>
204
- <itemSettings.Icon value={ value } />
205
- </RepeaterItemIconSlot>
206
- }
207
- removeItem={ () => removeRepeaterItem( index ) }
208
- duplicateItem={ () => duplicateRepeaterItem( index ) }
209
- toggleDisableItem={ () => toggleDisableRepeaterItem( index ) }
210
- openOnMount={ openOnAdd && openItem === key }
211
- onOpen={ () => setOpenItem( EMPTY_OPEN_ITEM ) }
212
- showDuplicate={ showDuplicate }
213
- showToggle={ showToggle }
214
- collectionPropUtil={ collectionPropUtil }
215
- >
216
- { ( props ) => (
217
- <itemSettings.Content { ...props } value={ value } bind={ String( index ) } />
218
- ) }
219
- </RepeaterItem>
220
- </SortableItem>
221
- );
222
- } ) }
223
- </SortableProvider>
224
- ) }
225
- </SectionContent>
226
- );
227
- };
228
-
229
- type RepeaterItemProps< T > = {
230
- label: React.ReactNode;
231
- propDisabled?: boolean;
232
- startIcon: UnstableTagProps[ 'startIcon' ];
233
- removeItem: () => void;
234
- duplicateItem: () => void;
235
- toggleDisableItem: () => void;
236
- children: ( props: Pick< RepeaterItemContentProps< T >, 'anchorEl' | 'collectionPropUtil' > ) => React.ReactNode;
237
- openOnMount: boolean;
238
- onOpen: () => void;
239
- showDuplicate: boolean;
240
- showToggle: boolean;
241
- disabled?: boolean;
242
- collectionPropUtil?: CollectionPropUtil< T >;
243
- };
244
-
245
- const RepeaterItem = < T, >( {
246
- label,
247
- propDisabled,
248
- startIcon,
249
- children,
250
- removeItem,
251
- duplicateItem,
252
- toggleDisableItem,
253
- openOnMount,
254
- onOpen,
255
- showDuplicate,
256
- showToggle,
257
- disabled,
258
- collectionPropUtil,
259
- }: RepeaterItemProps< T > ) => {
260
- const [ anchorEl, setAnchorEl ] = useState< AnchorEl >( null );
261
- const { popoverState, popoverProps, ref, setRef } = usePopover( openOnMount, onOpen );
262
-
263
- const duplicateLabel = __( 'Duplicate', 'elementor' );
264
- const toggleLabel = propDisabled ? __( 'Show', 'elementor' ) : __( 'Hide', 'elementor' );
265
- const removeLabel = __( 'Remove', 'elementor' );
266
-
267
- return (
268
- <>
269
- <UnstableTag
270
- disabled={ disabled }
271
- label={ label }
272
- showActionsOnHover
273
- fullWidth
274
- ref={ setRef }
275
- variant="outlined"
276
- aria-label={ __( 'Open item', 'elementor' ) }
277
- { ...bindTrigger( popoverState ) }
278
- startIcon={ startIcon }
279
- actions={
280
- <>
281
- { showDuplicate && (
282
- <Tooltip title={ duplicateLabel } placement="top">
283
- <IconButton size={ SIZE } onClick={ duplicateItem } aria-label={ duplicateLabel }>
284
- <CopyIcon fontSize={ SIZE } />
285
- </IconButton>
286
- </Tooltip>
287
- ) }
288
- { showToggle && (
289
- <Tooltip title={ toggleLabel } placement="top">
290
- <IconButton size={ SIZE } onClick={ toggleDisableItem } aria-label={ toggleLabel }>
291
- { propDisabled ? <EyeOffIcon fontSize={ SIZE } /> : <EyeIcon fontSize={ SIZE } /> }
292
- </IconButton>
293
- </Tooltip>
294
- ) }
295
- <Tooltip title={ removeLabel } placement="top">
296
- <IconButton size={ SIZE } onClick={ removeItem } aria-label={ removeLabel }>
297
- <XIcon fontSize={ SIZE } />
298
- </IconButton>
299
- </Tooltip>
300
- </>
301
- }
302
- />
303
- <Popover
304
- disablePortal
305
- slotProps={ {
306
- paper: {
307
- ref: setAnchorEl,
308
- sx: { mt: 0.5, width: ref?.getBoundingClientRect().width },
309
- },
310
- } }
311
- anchorOrigin={ { vertical: 'bottom', horizontal: 'left' } }
312
- { ...popoverProps }
313
- anchorEl={ ref }
314
- >
315
- <Box>{ children( { anchorEl, collectionPropUtil } ) }</Box>
316
- </Popover>
317
- </>
318
- );
319
- };
320
-
321
- const usePopover = ( openOnMount: boolean, onOpen: () => void ) => {
322
- const [ ref, setRef ] = useState< HTMLElement | null >( null );
323
-
324
- const popoverState = usePopupState( { variant: 'popover' } );
325
-
326
- const popoverProps = bindPopover( popoverState );
327
-
328
- useEffect( () => {
329
- if ( openOnMount && ref ) {
330
- popoverState.open( ref );
331
- onOpen?.();
332
- }
333
- // eslint-disable-next-line react-compiler/react-compiler
334
- // eslint-disable-next-line react-hooks/exhaustive-deps
335
- }, [ ref ] );
336
-
337
- return {
338
- popoverState,
339
- ref,
340
- setRef,
341
- popoverProps,
342
- };
343
- };
@@ -1,77 +0,0 @@
1
- import * as React from 'react';
2
- import { bindTrigger, UnstableTag } from '@elementor/ui';
3
- import { __ } from '@wordpress/i18n';
4
-
5
- import { SlotChildren } from '../../../control-replacements';
6
- import { DisableItemAction } from '../actions/disable-item-action';
7
- import { DuplicateItemAction } from '../actions/duplicate-item-action';
8
- import { RemoveItemAction } from '../actions/remove-item-action';
9
- import { useRepeaterContext } from '../context/repeater-context';
10
- import { RepeaterItemActionsSlot, RepeaterItemIconSlot, RepeaterItemLabelSlot } from '../locations';
11
- import { type ItemProps, type RepeatablePropValue } from '../types';
12
-
13
- export const Item = < T extends RepeatablePropValue >( {
14
- Label,
15
- Icon,
16
- value,
17
- index = -1,
18
- children,
19
- }: React.PropsWithChildren< ItemProps< T > > ) => {
20
- const { items, popoverState, setRowRef, openItemIndex, setOpenItemIndex } = useRepeaterContext();
21
- const triggerProps = bindTrigger( popoverState );
22
- const key = items[ index ].key ?? -1;
23
-
24
- const onClick = ( ev: React.MouseEvent ) => {
25
- triggerProps.onClick( ev );
26
- setOpenItemIndex( index );
27
- };
28
-
29
- const setRef = ( ref: HTMLDivElement | null ) => {
30
- if ( ! ref || openItemIndex !== index || ref === popoverState.anchorEl ) {
31
- return;
32
- }
33
-
34
- setRowRef( ref );
35
- popoverState.setAnchorEl( ref );
36
- };
37
-
38
- return (
39
- <>
40
- <UnstableTag
41
- key={ key }
42
- disabled={ false }
43
- label={
44
- <RepeaterItemLabelSlot value={ value }>
45
- <Label value={ value as T } />
46
- </RepeaterItemLabelSlot>
47
- }
48
- showActionsOnHover
49
- fullWidth
50
- ref={ setRef }
51
- variant="outlined"
52
- aria-label={ __( 'Open item', 'elementor' ) }
53
- sx={ { minHeight: ( theme ) => theme.spacing( 4 ) } }
54
- { ...triggerProps }
55
- onClick={ onClick }
56
- startIcon={
57
- <RepeaterItemIconSlot value={ value }>
58
- <Icon value={ value as T } />
59
- </RepeaterItemIconSlot>
60
- }
61
- actions={
62
- <>
63
- <RepeaterItemActionsSlot index={ index ?? -1 } />
64
-
65
- <SlotChildren
66
- whitelist={ [ DuplicateItemAction, DisableItemAction, RemoveItemAction ] as React.FC[] }
67
- props={ { index } }
68
- sorted
69
- >
70
- { children }
71
- </SlotChildren>
72
- </>
73
- }
74
- />
75
- </>
76
- );
77
- };
@@ -1,26 +0,0 @@
1
- import * as React from 'react';
2
- import { type PropTypeUtil } from '@elementor/editor-props';
3
-
4
- import { SlotChildren } from '../../control-replacements';
5
- import { SectionContent } from '../section-content';
6
- import { RepeaterContextProvider } from './context/repeater-context';
7
- import { Header } from './header/header';
8
- import { EditItemPopover } from './items/edit-item-popover';
9
- import { ItemsContainer } from './items/items-container';
10
- import { type RepeatablePropValue } from './types';
11
-
12
- export const UnstableRepeater = < T extends RepeatablePropValue >( {
13
- children,
14
- initial,
15
- propTypeUtil,
16
- }: React.PropsWithChildren< { initial: T; propTypeUtil: PropTypeUtil< string, T[] > } > ) => {
17
- return (
18
- <SectionContent>
19
- <RepeaterContextProvider initial={ initial } propTypeUtil={ propTypeUtil }>
20
- <SlotChildren whitelist={ [ Header, ItemsContainer, EditItemPopover ] as React.FC[] } sorted>
21
- { children }
22
- </SlotChildren>
23
- </RepeaterContextProvider>
24
- </SectionContent>
25
- );
26
- };