@elementor/editor-interactions 4.0.0-manual → 4.0.1

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 (36) hide show
  1. package/dist/index.d.mts +123 -5
  2. package/dist/index.d.ts +123 -5
  3. package/dist/index.js +861 -334
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +823 -312
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +12 -11
  8. package/src/commands/get-clipboard-elements.ts +11 -0
  9. package/src/commands/paste-interactions.ts +136 -0
  10. package/src/components/controls/easing.tsx +3 -0
  11. package/src/components/controls/effect.tsx +3 -0
  12. package/src/components/controls/repeat.tsx +57 -0
  13. package/src/components/controls/replay.tsx +15 -13
  14. package/src/components/controls/trigger.tsx +3 -0
  15. package/src/components/interaction-details.tsx +162 -120
  16. package/src/components/interactions-list.tsx +16 -3
  17. package/src/components/interactions-tab.tsx +4 -1
  18. package/src/contexts/interactions-context.tsx +4 -1
  19. package/src/hooks/use-element-interactions.ts +26 -0
  20. package/src/index.ts +26 -0
  21. package/src/init.ts +13 -3
  22. package/src/interactions-controls-registry.ts +15 -3
  23. package/src/mcp/constants.ts +58 -0
  24. package/src/mcp/index.ts +15 -69
  25. package/src/mcp/tools/manage-element-interaction-tool.ts +40 -5
  26. package/src/mcp/tools/schema.ts +1 -1
  27. package/src/types.ts +6 -1
  28. package/src/ui/interactions-promotion-chip.tsx +14 -6
  29. package/src/ui/promotion-overlay-layout.tsx +22 -0
  30. package/src/ui/promotion-select.tsx +4 -0
  31. package/src/utils/custom-effect-to-prop-value.ts +145 -0
  32. package/src/utils/filter-interactions.ts +9 -0
  33. package/src/utils/get-interactions-config.ts +1 -11
  34. package/src/utils/is-supported-interaction-item.ts +39 -0
  35. package/src/utils/prop-value-utils.ts +59 -34
  36. package/src/utils/tracking.ts +42 -0
@@ -17,6 +17,8 @@ import {
17
17
  type TimingConfigPropValue,
18
18
  } from '../types';
19
19
  import { formatSizeValue, parseSizeValue } from '../utils/size-transform-utils';
20
+ import { type PlainCustomEffect, toCustomEffectPropValue } from './custom-effect-to-prop-value';
21
+ import { getInteractionsConfig } from './get-interactions-config';
20
22
  import { generateTempInteractionId } from './temp-id-utils';
21
23
 
22
24
  export const createString = ( value: string ): StringPropValue => ( {
@@ -45,25 +47,32 @@ export const createBoolean = ( value: boolean ): BooleanPropValue => ( {
45
47
  export const createConfig = ( {
46
48
  replay,
47
49
  easing = 'easeIn',
48
- relativeTo = '',
50
+ relativeTo = 'viewport',
51
+ repeat = '',
52
+ times = 1,
49
53
  start = 85,
50
54
  end = 15,
51
55
  }: {
52
56
  replay: boolean;
53
57
  easing?: string;
54
58
  relativeTo?: string;
59
+ repeat?: string;
60
+ times?: number;
55
61
  start?: SizeStringValue;
56
62
  end?: SizeStringValue;
57
- } ): ConfigPropValue => ( {
58
- $$type: 'config',
59
- value: {
60
- replay: createBoolean( replay ),
61
- easing: createString( easing ),
62
- relativeTo: createString( relativeTo ),
63
- start: createSize( start, '%' ),
64
- end: createSize( end, '%' ),
65
- },
66
- } );
63
+ } ): ConfigPropValue =>
64
+ ( {
65
+ $$type: 'config',
66
+ value: {
67
+ replay: createBoolean( replay ),
68
+ easing: createString( easing ),
69
+ relativeTo: createString( relativeTo ),
70
+ repeat: createString( repeat ),
71
+ times: createNumber( times ),
72
+ start: createSize( start, '%' ),
73
+ end: createSize( end, '%' ),
74
+ },
75
+ } ) as ConfigPropValue;
67
76
 
68
77
  const createSize = ( value?: SizeStringValue, defaultUnit?: Unit, defaultValue?: SizeStringValue ) => {
69
78
  if ( ! value ) {
@@ -102,6 +111,8 @@ export const createAnimationPreset = ( {
102
111
  replay = false,
103
112
  easing = 'easeIn',
104
113
  relativeTo,
114
+ repeat,
115
+ times,
105
116
  start,
106
117
  end,
107
118
  customEffects,
@@ -114,26 +125,33 @@ export const createAnimationPreset = ( {
114
125
  replay: boolean;
115
126
  easing?: string;
116
127
  relativeTo?: string;
128
+ repeat?: string;
129
+ times?: number;
117
130
  start?: SizeStringValue;
118
131
  end?: SizeStringValue;
119
- customEffects?: PropValue;
120
- } ): AnimationPresetPropValue => ( {
121
- $$type: 'animation-preset-props',
122
- value: {
123
- effect: createString( effect ),
124
- custom_effect: customEffects,
125
- type: createString( type ),
126
- direction: createString( direction ?? '' ),
127
- timing_config: createTimingConfig( duration, delay ),
128
- config: createConfig( {
129
- replay,
130
- easing,
131
- relativeTo,
132
- start,
133
- end,
134
- } ),
135
- },
136
- } );
132
+ customEffects?: PropValue | PlainCustomEffect;
133
+ } ): AnimationPresetPropValue => {
134
+ const customEffectProp = toCustomEffectPropValue( customEffects );
135
+ return {
136
+ $$type: 'animation-preset-props',
137
+ value: {
138
+ effect: createString( effect ),
139
+ ...( customEffectProp !== undefined && { custom_effect: customEffectProp } ),
140
+ type: createString( type ),
141
+ direction: createString( direction ?? '' ),
142
+ timing_config: createTimingConfig( duration, delay ),
143
+ config: createConfig( {
144
+ replay,
145
+ easing,
146
+ relativeTo,
147
+ repeat,
148
+ times,
149
+ start,
150
+ end,
151
+ } ),
152
+ },
153
+ };
154
+ };
137
155
 
138
156
  export const createInteractionItem = ( {
139
157
  trigger,
@@ -146,6 +164,8 @@ export const createInteractionItem = ( {
146
164
  replay = false,
147
165
  easing = 'easeIn',
148
166
  relativeTo,
167
+ repeat,
168
+ times,
149
169
  start,
150
170
  end,
151
171
  excludedBreakpoints,
@@ -161,10 +181,12 @@ export const createInteractionItem = ( {
161
181
  replay?: boolean;
162
182
  easing?: string;
163
183
  relativeTo?: string;
184
+ repeat?: string;
185
+ times?: number;
164
186
  start?: number;
165
187
  end?: number;
166
188
  excludedBreakpoints?: string[];
167
- customEffects?: PropValue;
189
+ customEffects?: PropValue | PlainCustomEffect;
168
190
  } ): InteractionItemPropValue => ( {
169
191
  $$type: 'interaction-item',
170
192
  value: {
@@ -179,6 +201,8 @@ export const createInteractionItem = ( {
179
201
  replay,
180
202
  easing,
181
203
  relativeTo,
204
+ repeat,
205
+ times,
182
206
  start,
183
207
  end,
184
208
  customEffects,
@@ -191,14 +215,15 @@ export const createInteractionItem = ( {
191
215
  } );
192
216
 
193
217
  export const createDefaultInteractionItem = (): InteractionItemPropValue => {
218
+ const { constants } = getInteractionsConfig();
194
219
  return createInteractionItem( {
195
220
  trigger: 'load',
196
221
  effect: 'fade',
197
222
  type: 'in',
198
- duration: 600,
199
- delay: 0,
223
+ duration: constants.defaultDuration,
224
+ delay: constants.defaultDelay,
200
225
  replay: false,
201
- easing: 'easeIn',
226
+ easing: constants.defaultEasing,
202
227
  interactionId: generateTempInteractionId(),
203
228
  } );
204
229
  };
@@ -238,7 +263,7 @@ export const buildDisplayLabel = ( item: InteractionItemValue ): string => {
238
263
 
239
264
  const triggerLabel = TRIGGER_LABELS[ trigger ] || capitalize( trigger );
240
265
  const effectLabel = capitalize( effect );
241
- const typeLabel = capitalize( type );
266
+ const typeLabel = 'custom' === effect ? '' : capitalize( type );
242
267
 
243
268
  return `${ triggerLabel }: ${ effectLabel } ${ typeLabel }`;
244
269
  };
@@ -0,0 +1,42 @@
1
+ import { getElementLabel } from '@elementor/editor-elements';
2
+ import { getMixpanel } from '@elementor/events';
3
+
4
+ import type { InteractionItemPropValue } from '../types';
5
+ import { extractString } from './prop-value-utils';
6
+
7
+ const TRIGGER_LABELS: Record< string, string > = {
8
+ load: 'On page load',
9
+ scrollIn: 'Scroll into view',
10
+ scrollOut: 'Scroll out of view',
11
+ scrollOn: 'While scrolling',
12
+ hover: 'Hover',
13
+ click: 'Click',
14
+ };
15
+
16
+ const capitalize = ( s: string ) => s.charAt( 0 ).toUpperCase() + s.slice( 1 );
17
+
18
+ export const trackInteractionCreated = ( elementId: string, item: InteractionItemPropValue ) => {
19
+ const { dispatchEvent, config } = getMixpanel();
20
+ if ( ! config?.names?.interactions?.created ) {
21
+ return;
22
+ }
23
+
24
+ const trigger = extractString( item.value.trigger );
25
+ const effect = extractString( item.value.animation.value.effect );
26
+ const type = extractString( item.value.animation.value.type );
27
+
28
+ dispatchEvent?.( config.names.interactions.created, {
29
+ app_type: config?.appTypes?.editor,
30
+ window_name: config?.appTypes?.editor,
31
+ interaction_type: config?.triggers?.click,
32
+ target_name: getElementLabel( elementId ),
33
+ interaction_result: 'interaction_created',
34
+ target_location: config?.locations?.widgetPanel,
35
+ location_l1: getElementLabel( elementId ),
36
+ location_l2: 'interactions',
37
+ interaction_description: 'interaction_created',
38
+ interaction_trigger: TRIGGER_LABELS[ trigger ] ?? capitalize( trigger ),
39
+ interaction_effect:
40
+ effect === 'custom' ? capitalize( effect ) : `${ capitalize( effect ) } ${ capitalize( type ) }`,
41
+ } );
42
+ };