@elementor/editor-interactions 4.0.0-498 → 4.0.0-500

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.
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { useCallback, useEffect, useMemo, useRef } from 'react';
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef } from 'react';
3
3
  import { Repeater } from '@elementor/editor-controls';
4
4
  import { InfoCircleFilledIcon, PlayerPlayIcon } from '@elementor/icons';
5
5
  import { Alert, AlertTitle, Box, IconButton, Tooltip } from '@elementor/ui';
@@ -17,6 +17,13 @@ export type InteractionListProps = {
17
17
  triggerCreateOnShowEmpty?: boolean;
18
18
  };
19
19
 
20
+ type InteractionItemContextValue = {
21
+ onInteractionChange: ( index: number, newInteractionValue: InteractionItemValue ) => void;
22
+ onPlayInteraction: ( interactionId: string ) => void;
23
+ };
24
+
25
+ const InteractionItemContext = createContext< InteractionItemContextValue | null >( null );
26
+
20
27
  export function InteractionsList( props: InteractionListProps ) {
21
28
  const { interactions, onSelectInteractions, onPlayInteraction, triggerCreateOnShowEmpty } = props;
22
29
 
@@ -85,44 +92,72 @@ export function InteractionsList( props: InteractionListProps ) {
85
92
  [ interactions, handleUpdateInteractions ]
86
93
  );
87
94
 
95
+ const contextValue = useMemo(
96
+ () => ( {
97
+ onInteractionChange: handleInteractionChange,
98
+ onPlayInteraction,
99
+ } ),
100
+ [ handleInteractionChange, onPlayInteraction ]
101
+ );
102
+
88
103
  return (
89
- <Repeater
90
- openOnAdd
91
- openItem={ triggerCreateOnShowEmpty ? 0 : undefined }
92
- label={ __( 'Interactions', 'elementor' ) }
93
- values={ interactions.items }
94
- setValues={ handleRepeaterChange }
95
- showDuplicate={ false }
96
- showToggle={ false }
97
- isSortable={ false }
98
- disableAddItemButton={ isMaxNumberOfInteractionsReached }
99
- addButtonInfotipContent={ infotipContent }
100
- itemSettings={ {
101
- initialValues: createDefaultInteractionItem(),
102
- Label: ( { value }: { value: InteractionItemPropValue } ) => buildDisplayLabel( value.value ),
103
- Icon: () => null,
104
- Content: ( { index, value }: { index: number; value: InteractionItemPropValue } ) => (
105
- <InteractionDetails
106
- key={ index }
107
- interaction={ value.value }
108
- onChange={ ( newInteractionValue: InteractionItemValue ) => {
109
- handleInteractionChange( index, newInteractionValue );
110
- } }
111
- onPlayInteraction={ onPlayInteraction }
112
- />
113
- ),
114
- actions: ( value: InteractionItemPropValue ) => (
115
- <Tooltip key="preview" placement="top" title={ __( 'Preview', 'elementor' ) }>
116
- <IconButton
117
- aria-label={ __( 'Play interaction', 'elementor' ) }
118
- size="tiny"
119
- onClick={ () => onPlayInteraction( extractString( value.value.interaction_id ) ) }
120
- >
121
- <PlayerPlayIcon fontSize="tiny" />
122
- </IconButton>
123
- </Tooltip>
124
- ),
125
- } }
126
- />
104
+ <InteractionItemContext.Provider value={ contextValue }>
105
+ <Repeater
106
+ openOnAdd
107
+ openItem={ triggerCreateOnShowEmpty ? 0 : undefined }
108
+ label={ __( 'Interactions', 'elementor' ) }
109
+ values={ interactions.items }
110
+ setValues={ handleRepeaterChange }
111
+ showDuplicate={ false }
112
+ showToggle={ false }
113
+ isSortable={ false }
114
+ disableAddItemButton={ isMaxNumberOfInteractionsReached }
115
+ addButtonInfotipContent={ infotipContent }
116
+ itemSettings={ {
117
+ initialValues: createDefaultInteractionItem(),
118
+ Label: ( { value }: { value: InteractionItemPropValue } ) => buildDisplayLabel( value.value ),
119
+ Icon: () => null,
120
+ Content,
121
+ actions: ( value: InteractionItemPropValue ) => (
122
+ <Tooltip key="preview" placement="top" title={ __( 'Preview', 'elementor' ) }>
123
+ <IconButton
124
+ aria-label={ __( 'Play interaction', 'elementor' ) }
125
+ size="tiny"
126
+ onClick={ () => onPlayInteraction( extractString( value.value.interaction_id ) ) }
127
+ >
128
+ <PlayerPlayIcon fontSize="tiny" />
129
+ </IconButton>
130
+ </Tooltip>
131
+ ),
132
+ } }
133
+ />
134
+ </InteractionItemContext.Provider>
127
135
  );
128
136
  }
137
+
138
+ const Content = ( { index, value }: { index: number; value: InteractionItemPropValue } ) => {
139
+ const context = useContext( InteractionItemContext );
140
+
141
+ const handleChange = useCallback(
142
+ ( newInteractionValue: InteractionItemValue ) => {
143
+ context?.onInteractionChange( index, newInteractionValue );
144
+ },
145
+ [ context, index ]
146
+ );
147
+
148
+ const handlePlayInteraction = useCallback(
149
+ ( interactionId: string ) => {
150
+ context?.onPlayInteraction( interactionId );
151
+ },
152
+ [ context ]
153
+ );
154
+
155
+ return (
156
+ <InteractionDetails
157
+ key={ index }
158
+ interaction={ value.value }
159
+ onChange={ handleChange }
160
+ onPlayInteraction={ handlePlayInteraction }
161
+ />
162
+ );
163
+ };
package/src/init.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Easing } from './components/controls/easing';
1
2
  import { Trigger } from './components/controls/trigger';
2
3
  import { initCleanInteractionIdsOnDuplicate } from './hooks/on-duplicate';
3
4
  import { registerInteractionsControl } from './interactions-controls-registry';
@@ -13,6 +14,12 @@ export function init() {
13
14
  component: Trigger,
14
15
  options: [ 'load', 'scrollIn' ],
15
16
  } );
17
+
18
+ registerInteractionsControl( {
19
+ type: 'easing',
20
+ component: Easing,
21
+ options: [ 'easeIn' ],
22
+ } );
16
23
  } catch ( error ) {
17
24
  throw error;
18
25
  }
@@ -10,6 +10,7 @@ type InteractionsControlType =
10
10
  | 'duration'
11
11
  | 'delay'
12
12
  | 'replay'
13
+ | 'easing'
13
14
  | 'relativeTo'
14
15
  | 'offsetTop'
15
16
  | 'offsetBottom';
@@ -22,6 +23,7 @@ type InteractionsControlPropsMap = {
22
23
  duration: FieldProps;
23
24
  delay: FieldProps;
24
25
  replay: ReplayFieldProps;
26
+ easing: FieldProps;
25
27
  relativeTo: FieldProps;
26
28
  offsetTop: FieldProps;
27
29
  offsetBottom: FieldProps;
@@ -34,18 +34,26 @@ export const createBoolean = ( value: boolean ): BooleanPropValue => ( {
34
34
  value,
35
35
  } );
36
36
 
37
- export const createConfig = (
38
- replay: boolean,
39
- relativeTo?: string,
40
- offsetTop?: number,
41
- offsetBottom?: number
42
- ): ConfigPropValue => ( {
37
+ export const createConfig = ( {
38
+ replay,
39
+ easing = 'easeIn',
40
+ relativeTo = '',
41
+ offsetTop = 0,
42
+ offsetBottom = 100,
43
+ }: {
44
+ replay: boolean;
45
+ easing?: string;
46
+ relativeTo?: string;
47
+ offsetTop?: number;
48
+ offsetBottom?: number;
49
+ } ): ConfigPropValue => ( {
43
50
  $$type: 'config',
44
51
  value: {
45
52
  replay: createBoolean( replay ),
46
- relativeTo: createString( relativeTo ?? '' ),
47
- offsetTop: createNumber( offsetTop ?? 0 ),
48
- offsetBottom: createNumber( offsetBottom ?? 100 ),
53
+ easing: createString( easing ),
54
+ relativeTo: createString( relativeTo ),
55
+ offsetTop: createNumber( offsetTop ),
56
+ offsetBottom: createNumber( offsetBottom ),
49
57
  },
50
58
  } );
51
59
 
@@ -60,6 +68,7 @@ export const createAnimationPreset = ( {
60
68
  duration,
61
69
  delay,
62
70
  replay = false,
71
+ easing = 'easeIn',
63
72
  relativeTo,
64
73
  offsetTop,
65
74
  offsetBottom,
@@ -70,6 +79,7 @@ export const createAnimationPreset = ( {
70
79
  duration: number;
71
80
  delay: number;
72
81
  replay: boolean;
82
+ easing?: string;
73
83
  relativeTo?: string;
74
84
  offsetTop?: number;
75
85
  offsetBottom?: number;
@@ -80,7 +90,13 @@ export const createAnimationPreset = ( {
80
90
  type: createString( type ),
81
91
  direction: createString( direction ?? '' ),
82
92
  timing_config: createTimingConfig( duration, delay ),
83
- config: createConfig( replay, relativeTo, offsetTop, offsetBottom ),
93
+ config: createConfig( {
94
+ replay,
95
+ easing,
96
+ relativeTo,
97
+ offsetTop,
98
+ offsetBottom,
99
+ } ),
84
100
  },
85
101
  } );
86
102
 
@@ -93,6 +109,7 @@ export const createInteractionItem = ( {
93
109
  delay,
94
110
  interactionId,
95
111
  replay = false,
112
+ easing = 'easeIn',
96
113
  relativeTo,
97
114
  offsetTop,
98
115
  offsetBottom,
@@ -105,6 +122,7 @@ export const createInteractionItem = ( {
105
122
  delay: number;
106
123
  interactionId?: string;
107
124
  replay: boolean;
125
+ easing?: string;
108
126
  relativeTo?: string;
109
127
  offsetTop?: number;
110
128
  offsetBottom?: number;
@@ -120,6 +138,7 @@ export const createInteractionItem = ( {
120
138
  duration,
121
139
  delay,
122
140
  replay,
141
+ easing,
123
142
  relativeTo,
124
143
  offsetTop,
125
144
  offsetBottom,
@@ -132,9 +151,10 @@ export const createDefaultInteractionItem = (): InteractionItemPropValue => {
132
151
  trigger: 'load',
133
152
  effect: 'fade',
134
153
  type: 'in',
135
- duration: 300,
154
+ duration: 600,
136
155
  delay: 0,
137
156
  replay: false,
157
+ easing: 'easeIn',
138
158
  interactionId: generateTempInteractionId(),
139
159
  } );
140
160
  };
@@ -152,17 +172,6 @@ export const extractNumber = ( prop: NumberPropValue | undefined, fallback = 0 )
152
172
  return prop?.value ?? fallback;
153
173
  };
154
174
 
155
- export const buildAnimationIdString = ( item: InteractionItemValue ): string => {
156
- const trigger = extractString( item.trigger );
157
- const effect = extractString( item.animation.value.effect );
158
- const type = extractString( item.animation.value.type );
159
- const direction = extractString( item.animation.value.direction );
160
- const duration = extractNumber( item.animation.value.timing_config.value.duration );
161
- const delay = extractNumber( item.animation.value.timing_config.value.delay );
162
-
163
- return [ trigger, effect, type, direction, duration, delay ].join( '-' );
164
- };
165
-
166
175
  const TRIGGER_LABELS: Record< string, string > = {
167
176
  load: 'On page load',
168
177
  scrollIn: 'Scroll into view',