@elementor/editor-interactions 4.1.0-714 → 4.1.0-715

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-interactions",
3
- "version": "4.1.0-714",
3
+ "version": "4.1.0-715",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,19 +39,19 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor-controls": "4.1.0-714",
43
- "@elementor/editor-elements": "4.1.0-714",
44
- "@elementor/editor-mcp": "4.1.0-714",
45
- "@elementor/editor-props": "4.1.0-714",
46
- "@elementor/editor-responsive": "4.1.0-714",
47
- "@elementor/editor-ui": "4.1.0-714",
48
- "@elementor/editor-v1-adapters": "4.1.0-714",
42
+ "@elementor/editor-controls": "4.1.0-715",
43
+ "@elementor/editor-elements": "4.1.0-715",
44
+ "@elementor/editor-mcp": "4.1.0-715",
45
+ "@elementor/editor-props": "4.1.0-715",
46
+ "@elementor/editor-responsive": "4.1.0-715",
47
+ "@elementor/editor-ui": "4.1.0-715",
48
+ "@elementor/editor-v1-adapters": "4.1.0-715",
49
49
  "@elementor/icons": "^1.68.0",
50
- "@elementor/schema": "4.1.0-714",
51
- "@elementor/session": "4.1.0-714",
50
+ "@elementor/schema": "4.1.0-715",
51
+ "@elementor/session": "4.1.0-715",
52
52
  "@elementor/ui": "1.36.17",
53
- "@elementor/utils": "4.1.0-714",
54
- "@elementor/events": "4.1.0-714",
53
+ "@elementor/utils": "4.1.0-715",
54
+ "@elementor/events": "4.1.0-715",
55
55
  "@wordpress/i18n": "^5.13.0"
56
56
  },
57
57
  "peerDependencies": {
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ import { useRef } from 'react';
3
+ import { type ToggleButtonGroupItem, ToggleButtonGroupUi } from '@elementor/editor-controls';
4
+ import { Number123Icon, RepeatIcon } from '@elementor/icons';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ import { InteractionsPromotionChip } from '../../ui/interactions-promotion-chip';
8
+ import { PromotionOverlayLayout } from '../../ui/promotion-overlay-layout';
9
+
10
+ const TRACKING_DATA = { target_name: 'interactions_repeat', location_l2: 'interactions' } as const;
11
+
12
+ export const REPEAT_OPTIONS = {
13
+ times: __( 'times', 'elementor' ),
14
+ loop: __( 'loop', 'elementor' ),
15
+ };
16
+
17
+ export const REPEAT_TOOLTIPS = {
18
+ times: __( 'Enable number', 'elementor' ),
19
+ loop: __( 'Infinite repeat', 'elementor' ),
20
+ };
21
+
22
+ export function Repeat() {
23
+ const repeatContainerRef = useRef< HTMLDivElement >( null );
24
+
25
+ const options: ToggleButtonGroupItem< string >[] = [
26
+ {
27
+ value: REPEAT_OPTIONS.times,
28
+ disabled: true,
29
+ label: REPEAT_TOOLTIPS.times,
30
+ renderContent: ( { size } ) => <Number123Icon fontSize={ size } />,
31
+ showTooltip: true,
32
+ },
33
+ {
34
+ value: REPEAT_OPTIONS.loop,
35
+ disabled: true,
36
+ label: REPEAT_TOOLTIPS.loop,
37
+ renderContent: ( { size } ) => <RepeatIcon fontSize={ size } />,
38
+ showTooltip: true,
39
+ },
40
+ ];
41
+
42
+ return (
43
+ <PromotionOverlayLayout
44
+ ref={ repeatContainerRef }
45
+ promotionChip={
46
+ <InteractionsPromotionChip
47
+ content={ __( 'Upgrade to control how many times the animation repeats.', 'elementor' ) }
48
+ upgradeUrl={ 'https://go.elementor.com/go-pro-interactions-repeat-modal/' }
49
+ anchorRef={ repeatContainerRef }
50
+ trackingData={ TRACKING_DATA }
51
+ />
52
+ }
53
+ >
54
+ <ToggleButtonGroupUi items={ options } exclusive onChange={ () => {} } value={ '' } />
55
+ </PromotionOverlayLayout>
56
+ );
57
+ }
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
+ import { useRef } from 'react';
2
3
  import { type ToggleButtonGroupItem, ToggleButtonGroupUi } from '@elementor/editor-controls';
3
4
  import { CheckIcon, MinusIcon } from '@elementor/icons';
4
- import { Box } from '@elementor/ui';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { type ReplayFieldProps } from '../../types';
8
8
  import { InteractionsPromotionChip } from '../../ui/interactions-promotion-chip';
9
+ import { PromotionOverlayLayout } from '../../ui/promotion-overlay-layout';
9
10
 
10
11
  const TRACKING_DATA = { target_name: 'interactions_replay', location_l2: 'interactions' } as const;
11
12
 
@@ -16,10 +17,8 @@ export const REPLAY_OPTIONS = {
16
17
 
17
18
  export const BASE_REPLAY: string[] = [ 'no' ];
18
19
 
19
- const OVERLAY_GRID = '1 / 1';
20
- const CHIP_OFFSET = '50%';
21
-
22
- export function Replay( { onChange, anchorRef }: ReplayFieldProps ) {
20
+ export function Replay( { onChange }: ReplayFieldProps ) {
21
+ const replayContainerRef = useRef< HTMLDivElement >( null );
23
22
  const options: ToggleButtonGroupItem< boolean >[] = [
24
23
  {
25
24
  value: false,
@@ -38,18 +37,18 @@ export function Replay( { onChange, anchorRef }: ReplayFieldProps ) {
38
37
  ];
39
38
 
40
39
  return (
41
- <Box sx={ { display: 'grid', alignItems: 'center' } }>
42
- <Box sx={ { gridArea: OVERLAY_GRID } }>
43
- <ToggleButtonGroupUi items={ options } exclusive onChange={ onChange } value={ false } />
44
- </Box>
45
- <Box sx={ { gridArea: OVERLAY_GRID, marginInlineEnd: CHIP_OFFSET, justifySelf: 'end' } }>
40
+ <PromotionOverlayLayout
41
+ ref={ replayContainerRef }
42
+ promotionChip={
46
43
  <InteractionsPromotionChip
47
44
  content={ __( 'Upgrade to run the animation every time its trigger occurs.', 'elementor' ) }
48
45
  upgradeUrl={ 'https://go.elementor.com/go-pro-interactions-replay-modal/' }
49
- anchorRef={ anchorRef }
46
+ anchorRef={ replayContainerRef }
50
47
  trackingData={ TRACKING_DATA }
51
48
  />
52
- </Box>
53
- </Box>
49
+ }
50
+ >
51
+ <ToggleButtonGroupUi items={ options } exclusive onChange={ onChange } value={ false } />
52
+ </PromotionOverlayLayout>
54
53
  );
55
54
  }
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { type ComponentType, useMemo, useRef } from 'react';
2
+ import { type ComponentType, useMemo } from 'react';
3
3
  import { PopoverContent } from '@elementor/editor-controls';
4
4
  import { type PropValue } from '@elementor/editor-props';
5
- import { Box, Divider, Grid } from '@elementor/ui';
5
+ import { Divider, Grid } from '@elementor/ui';
6
6
  import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { getInteractionsControl } from '../interactions-controls-registry';
@@ -182,8 +182,6 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
182
182
  ) as ComponentType< FieldProps< number > >;
183
183
  const EasingControl = useControlComponent( 'easing' );
184
184
 
185
- const containerRef = useRef< HTMLDivElement >( null );
186
-
187
185
  const updateInteraction = (
188
186
  updates: Partial< {
189
187
  trigger: string;
@@ -241,150 +239,142 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
241
239
  };
242
240
 
243
241
  return (
244
- <Box ref={ containerRef }>
245
- <PopoverContent p={ 1.5 }>
246
- <Grid container spacing={ 1.5 }>
247
- { TriggerControl && (
248
- <Field label={ __( 'Trigger', 'elementor' ) }>
249
- <TriggerControl
250
- value={ trigger }
251
- onChange={ ( v ) => updateInteraction( { trigger: v } ) }
252
- />
253
- </Field>
254
- ) }
255
-
256
- { ReplayControl && (
257
- <Field label={ __( 'Replay', 'elementor' ) }>
258
- <ReplayControl
259
- value={ replay }
260
- onChange={ ( v ) => updateInteraction( { replay: v } ) }
261
- disabled={ true }
262
- anchorRef={ containerRef }
263
- />
264
- </Field>
265
- ) }
266
- </Grid>
242
+ <PopoverContent p={ 1.5 }>
243
+ <Grid container spacing={ 1.5 }>
244
+ { TriggerControl && (
245
+ <Field label={ __( 'Trigger', 'elementor' ) }>
246
+ <TriggerControl value={ trigger } onChange={ ( v ) => updateInteraction( { trigger: v } ) } />
247
+ </Field>
248
+ ) }
267
249
 
268
- <Divider />
250
+ { ReplayControl && (
251
+ <Field label={ __( 'Replay', 'elementor' ) }>
252
+ <ReplayControl
253
+ value={ replay }
254
+ onChange={ ( v ) => updateInteraction( { replay: v } ) }
255
+ disabled={ true }
256
+ />
257
+ </Field>
258
+ ) }
259
+ </Grid>
269
260
 
270
- <Grid container spacing={ 1.5 }>
271
- { EffectControl && (
272
- <Field label={ __( 'Effect', 'elementor' ) }>
273
- <EffectControl value={ effect } onChange={ ( v ) => updateInteraction( { effect: v } ) } />
274
- </Field>
275
- ) }
261
+ <Divider />
276
262
 
277
- { CustomEffectControl && (
278
- <Field label={ __( 'Custom Effect', 'elementor' ) }>
279
- <CustomEffectControl
280
- value={ customEffects }
281
- onChange={ ( v: PropValue ) => updateInteraction( { customEffects: v } ) }
282
- />
283
- </Field>
284
- ) }
263
+ <Grid container spacing={ 1.5 }>
264
+ { EffectControl && (
265
+ <Field label={ __( 'Effect', 'elementor' ) }>
266
+ <EffectControl value={ effect } onChange={ ( v ) => updateInteraction( { effect: v } ) } />
267
+ </Field>
268
+ ) }
285
269
 
286
- { EffectTypeControl && (
287
- <Field label={ __( 'Type', 'elementor' ) }>
288
- <EffectTypeControl value={ type } onChange={ ( v ) => updateInteraction( { type: v } ) } />
289
- </Field>
290
- ) }
291
-
292
- { DirectionControl && (
293
- <Field label={ __( 'Direction', 'elementor' ) }>
294
- <DirectionControl
295
- value={ direction }
296
- onChange={ ( v ) => updateInteraction( { direction: v } ) }
297
- interactionType={ type }
298
- />
299
- </Field>
300
- ) }
270
+ { CustomEffectControl && (
271
+ <Field label={ __( 'Custom Effect', 'elementor' ) }>
272
+ <CustomEffectControl
273
+ value={ customEffects }
274
+ onChange={ ( v: PropValue ) => updateInteraction( { customEffects: v } ) }
275
+ />
276
+ </Field>
277
+ ) }
301
278
 
302
- { RepeatControl && (
303
- <Field label={ __( 'Repeat', 'elementor' ) }>
304
- <RepeatControl value={ repeat } onChange={ ( v ) => updateInteraction( { repeat: v } ) } />
305
- </Field>
306
- ) }
307
-
308
- { TimesControl && (
309
- <Field label={ __( 'Times', 'elementor' ) }>
310
- <TimesControl
311
- value={ times }
312
- onChange={ ( v ) =>
313
- updateInteraction( {
314
- times: normalizeTimesValue( v, DEFAULT_VALUES.times ),
315
- } )
316
- }
317
- />
318
- </Field>
319
- ) }
320
-
321
- { controlVisibilityConfig.duration( interactionValues ) && (
322
- <Field label={ __( 'Duration', 'elementor' ) }>
323
- <TimeFrameIndicator
324
- value={ String( duration ) }
325
- onChange={ ( v ) => updateInteraction( { duration: v as SizeStringValue } ) }
326
- defaultValue={ DEFAULT_VALUES.duration as SizeStringValue }
327
- />
328
- </Field>
329
- ) }
330
-
331
- { controlVisibilityConfig.delay( interactionValues ) && (
332
- <Field label={ __( 'Delay', 'elementor' ) }>
333
- <TimeFrameIndicator
334
- value={ String( delay ) }
335
- onChange={ ( v ) => updateInteraction( { delay: v as SizeStringValue } ) }
336
- defaultValue={ DEFAULT_VALUES.delay as SizeStringValue }
337
- />
338
- </Field>
339
- ) }
340
- </Grid>
279
+ { EffectTypeControl && (
280
+ <Field label={ __( 'Type', 'elementor' ) }>
281
+ <EffectTypeControl value={ type } onChange={ ( v ) => updateInteraction( { type: v } ) } />
282
+ </Field>
283
+ ) }
341
284
 
342
- { controlVisibilityConfig.relativeTo( interactionValues ) && RelativeToControl && (
343
- <>
344
- <Divider />
345
- <Grid container spacing={ 1.5 }>
346
- { StartControl && (
347
- <Field label={ __( 'Start', 'elementor' ) }>
348
- <StartControl
349
- value={ parseSizeValue( start, [ '%' ] ).size?.toString() ?? '' }
350
- onChange={ ( v: string ) =>
351
- updateInteraction( { start: v as SizeStringValue } )
352
- }
353
- />
354
- </Field>
355
- ) }
356
- { EndControl && (
357
- <Field label={ __( 'End', 'elementor' ) }>
358
- <EndControl
359
- value={ parseSizeValue( end, [ '%' ] ).size?.toString() ?? '' }
360
- onChange={ ( v: string ) => updateInteraction( { end: v as SizeStringValue } ) }
361
- />
362
- </Field>
363
- ) }
364
- <Field label={ __( 'Relative To', 'elementor' ) }>
365
- <RelativeToControl
366
- value={ relativeTo }
367
- onChange={ ( v ) => updateInteraction( { relativeTo: v } ) }
368
- />
369
- </Field>
370
- </Grid>
371
- <Divider />
372
- </>
285
+ { DirectionControl && (
286
+ <Field label={ __( 'Direction', 'elementor' ) }>
287
+ <DirectionControl
288
+ value={ direction }
289
+ onChange={ ( v ) => updateInteraction( { direction: v } ) }
290
+ interactionType={ type }
291
+ />
292
+ </Field>
293
+ ) }
294
+
295
+ { RepeatControl && (
296
+ <Field label={ __( 'Repeat', 'elementor' ) }>
297
+ <RepeatControl value={ repeat } onChange={ ( v ) => updateInteraction( { repeat: v } ) } />
298
+ </Field>
299
+ ) }
300
+
301
+ { TimesControl && (
302
+ <Field label={ __( 'Times', 'elementor' ) }>
303
+ <TimesControl
304
+ value={ times }
305
+ onChange={ ( v ) =>
306
+ updateInteraction( {
307
+ times: normalizeTimesValue( v, DEFAULT_VALUES.times ),
308
+ } )
309
+ }
310
+ />
311
+ </Field>
312
+ ) }
313
+
314
+ { controlVisibilityConfig.duration( interactionValues ) && (
315
+ <Field label={ __( 'Duration', 'elementor' ) }>
316
+ <TimeFrameIndicator
317
+ value={ String( duration ) }
318
+ onChange={ ( v ) => updateInteraction( { duration: v as SizeStringValue } ) }
319
+ defaultValue={ DEFAULT_VALUES.duration as SizeStringValue }
320
+ />
321
+ </Field>
322
+ ) }
323
+
324
+ { controlVisibilityConfig.delay( interactionValues ) && (
325
+ <Field label={ __( 'Delay', 'elementor' ) }>
326
+ <TimeFrameIndicator
327
+ value={ String( delay ) }
328
+ onChange={ ( v ) => updateInteraction( { delay: v as SizeStringValue } ) }
329
+ defaultValue={ DEFAULT_VALUES.delay as SizeStringValue }
330
+ />
331
+ </Field>
373
332
  ) }
333
+ </Grid>
374
334
 
375
- { EasingControl && (
335
+ { controlVisibilityConfig.relativeTo( interactionValues ) && RelativeToControl && (
336
+ <>
337
+ <Divider />
376
338
  <Grid container spacing={ 1.5 }>
377
- <Field label={ __( 'Easing', 'elementor' ) }>
378
- <EasingControl
379
- value={ easing }
380
- onChange={ ( v ) => {
381
- updateInteraction( { easing: v } );
382
- } }
339
+ { StartControl && (
340
+ <Field label={ __( 'Start', 'elementor' ) }>
341
+ <StartControl
342
+ value={ parseSizeValue( start, [ '%' ] ).size?.toString() ?? '' }
343
+ onChange={ ( v: string ) => updateInteraction( { start: v as SizeStringValue } ) }
344
+ />
345
+ </Field>
346
+ ) }
347
+ { EndControl && (
348
+ <Field label={ __( 'End', 'elementor' ) }>
349
+ <EndControl
350
+ value={ parseSizeValue( end, [ '%' ] ).size?.toString() ?? '' }
351
+ onChange={ ( v: string ) => updateInteraction( { end: v as SizeStringValue } ) }
352
+ />
353
+ </Field>
354
+ ) }
355
+ <Field label={ __( 'Relative To', 'elementor' ) }>
356
+ <RelativeToControl
357
+ value={ relativeTo }
358
+ onChange={ ( v ) => updateInteraction( { relativeTo: v } ) }
383
359
  />
384
360
  </Field>
385
361
  </Grid>
386
- ) }
387
- </PopoverContent>
388
- </Box>
362
+ <Divider />
363
+ </>
364
+ ) }
365
+
366
+ { EasingControl && (
367
+ <Grid container spacing={ 1.5 }>
368
+ <Field label={ __( 'Easing', 'elementor' ) }>
369
+ <EasingControl
370
+ value={ easing }
371
+ onChange={ ( v ) => {
372
+ updateInteraction( { easing: v } );
373
+ } }
374
+ />
375
+ </Field>
376
+ </Grid>
377
+ ) }
378
+ </PopoverContent>
389
379
  );
390
380
  };
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export { TRIGGER_OPTIONS, BASE_TRIGGERS } from './components/controls/trigger';
16
16
  export { EASING_OPTIONS, BASE_EASINGS } from './components/controls/easing';
17
17
  export { REPLAY_OPTIONS, BASE_REPLAY } from './components/controls/replay';
18
18
  export { EFFECT_OPTIONS, BASE_EFFECTS } from './components/controls/effect';
19
+ export { REPEAT_OPTIONS, REPEAT_TOOLTIPS } from './components/controls/repeat';
19
20
 
20
21
  export {
21
22
  createString,
package/src/init.ts CHANGED
@@ -3,6 +3,7 @@ import { Direction } from './components/controls/direction';
3
3
  import { Easing } from './components/controls/easing';
4
4
  import { Effect } from './components/controls/effect';
5
5
  import { EffectType } from './components/controls/effect-type';
6
+ import { Repeat } from './components/controls/repeat';
6
7
  import { Replay } from './components/controls/replay';
7
8
  import { Trigger } from './components/controls/trigger';
8
9
  import { initCleanInteractionIdsOnDuplicate } from './hooks/on-duplicate';
@@ -54,6 +55,11 @@ export function init() {
54
55
  options: [ 'fade', 'slide', 'scale' ],
55
56
  } );
56
57
 
58
+ registerInteractionsControl( {
59
+ type: 'repeat',
60
+ component: Repeat,
61
+ } );
62
+
57
63
  initMcpInteractions();
58
64
  } catch ( error ) {
59
65
  throw error;
@@ -64,5 +64,3 @@ export const InteractionsPromotionChip = forwardRef< InteractionsPromotionChipRe
64
64
  );
65
65
  }
66
66
  );
67
-
68
- InteractionsPromotionChip.displayName = 'InteractionsPromotionChip';
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { forwardRef, type ReactNode } from 'react';
3
+ import { Box } from '@elementor/ui';
4
+
5
+ const OVERLAY_GRID = '1 / 1';
6
+ const CHIP_OFFSET = '50%';
7
+
8
+ type PromotionOverlayLayoutProps = {
9
+ children: ReactNode;
10
+ promotionChip: ReactNode;
11
+ };
12
+
13
+ export const PromotionOverlayLayout = forwardRef< HTMLDivElement, PromotionOverlayLayoutProps >(
14
+ ( { children, promotionChip }, ref ) => (
15
+ <Box ref={ ref } sx={ { display: 'grid', alignItems: 'center' } }>
16
+ <Box sx={ { gridArea: OVERLAY_GRID } }>{ children }</Box>
17
+ <Box sx={ { gridArea: OVERLAY_GRID, marginInlineEnd: CHIP_OFFSET, justifySelf: 'end' } }>
18
+ { promotionChip }
19
+ </Box>
20
+ </Box>
21
+ )
22
+ );