@elementor/editor-interactions 4.0.0-552 → 4.0.0-573
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/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +176 -103
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -104
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/components/controls/replay.tsx +22 -2
- package/src/components/field.tsx +19 -0
- package/src/components/interaction-details.tsx +119 -131
- package/src/index.ts +1 -0
- package/src/init.ts +9 -0
- package/src/types.ts +2 -0
- package/src/ui/interactions-promotion-chip.tsx +39 -0
- package/src/utils/resolve-direction.ts +20 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { Divider, Grid } from '@elementor/ui';
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
import { PopoverContent } from '@elementor/editor-controls';
|
|
4
|
+
import { Box, Divider, Grid } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
7
|
import { getInteractionsControl } from '../interactions-controls-registry';
|
|
@@ -13,11 +13,12 @@ import {
|
|
|
13
13
|
extractSize,
|
|
14
14
|
extractString,
|
|
15
15
|
} from '../utils/prop-value-utils';
|
|
16
|
+
import { resolveDirection } from '../utils/resolve-direction';
|
|
16
17
|
import { parseSizeValue } from '../utils/size-transform-utils';
|
|
17
18
|
import { Direction } from './controls/direction';
|
|
18
|
-
import { Effect } from './controls/effect';
|
|
19
19
|
import { EffectType } from './controls/effect-type';
|
|
20
20
|
import { TimeFrameIndicator } from './controls/time-frame-indicator';
|
|
21
|
+
import { Field } from './field';
|
|
21
22
|
|
|
22
23
|
type InteractionDetailsProps = {
|
|
23
24
|
interaction: InteractionItemValue;
|
|
@@ -39,7 +40,7 @@ const DEFAULT_VALUES = {
|
|
|
39
40
|
offsetBottom: 85,
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
const TRIGGERS_WITHOUT_REPLAY = [ 'load', 'scrollOn' ];
|
|
43
|
+
const TRIGGERS_WITHOUT_REPLAY = [ 'load', 'scrollOn', 'hover', 'click' ];
|
|
43
44
|
|
|
44
45
|
type InteractionsControlType =
|
|
45
46
|
| 'trigger'
|
|
@@ -130,6 +131,7 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
|
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
const TriggerControl = useControlComponent( 'trigger', true );
|
|
134
|
+
const EffectControl = useControlComponent( 'effect' );
|
|
133
135
|
const ReplayControl = useControlComponent( 'replay', controlVisibilityConfig.replay( interactionValues ) );
|
|
134
136
|
const RelativeToControl = useControlComponent(
|
|
135
137
|
'relativeTo',
|
|
@@ -143,16 +145,7 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
|
|
|
143
145
|
|
|
144
146
|
const EasingControl = useControlComponent( 'easing' );
|
|
145
147
|
|
|
146
|
-
const
|
|
147
|
-
if ( newEffect === 'slide' && ! newDirection ) {
|
|
148
|
-
return 'top';
|
|
149
|
-
}
|
|
150
|
-
// Why? - New direction can be undefined when the effect is not slide, so if the updates object includes direction, we take it always!
|
|
151
|
-
if ( hasDirection ) {
|
|
152
|
-
return newDirection;
|
|
153
|
-
}
|
|
154
|
-
return direction;
|
|
155
|
-
};
|
|
148
|
+
const containerRef = useRef< HTMLDivElement >( null );
|
|
156
149
|
|
|
157
150
|
const updateInteraction = (
|
|
158
151
|
updates: Partial< {
|
|
@@ -169,7 +162,13 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
|
|
|
169
162
|
offsetBottom: SizeStringValue;
|
|
170
163
|
} >
|
|
171
164
|
): void => {
|
|
172
|
-
const resolvedDirectionValue = resolveDirection(
|
|
165
|
+
const resolvedDirectionValue = resolveDirection(
|
|
166
|
+
'direction' in updates,
|
|
167
|
+
updates.effect,
|
|
168
|
+
updates.direction,
|
|
169
|
+
direction,
|
|
170
|
+
effect
|
|
171
|
+
);
|
|
173
172
|
|
|
174
173
|
const updatedInteraction = {
|
|
175
174
|
...interaction,
|
|
@@ -199,131 +198,120 @@ export const InteractionDetails = ( { interaction, onChange, onPlayInteraction }
|
|
|
199
198
|
};
|
|
200
199
|
|
|
201
200
|
return (
|
|
202
|
-
<
|
|
203
|
-
<
|
|
204
|
-
{
|
|
205
|
-
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
<Box ref={ containerRef }>
|
|
202
|
+
<PopoverContent p={ 1.5 }>
|
|
203
|
+
<Grid container spacing={ 1.5 }>
|
|
204
|
+
{ TriggerControl && (
|
|
205
|
+
<Field label={ __( 'Trigger', 'elementor' ) }>
|
|
206
|
+
<TriggerControl
|
|
207
|
+
value={ trigger }
|
|
208
|
+
onChange={ ( v ) => updateInteraction( { trigger: v } ) }
|
|
209
|
+
/>
|
|
210
|
+
</Field>
|
|
211
|
+
) }
|
|
212
|
+
|
|
213
|
+
{ ReplayControl && (
|
|
214
|
+
<Field label={ __( 'Replay', 'elementor' ) }>
|
|
215
|
+
<ReplayControl
|
|
216
|
+
value={ replay }
|
|
217
|
+
onChange={ ( v ) => updateInteraction( { replay: v } ) }
|
|
218
|
+
disabled={ true }
|
|
219
|
+
anchorRef={ containerRef }
|
|
220
|
+
/>
|
|
221
|
+
</Field>
|
|
222
|
+
) }
|
|
223
|
+
</Grid>
|
|
209
224
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
<Divider />
|
|
222
|
-
|
|
223
|
-
<Grid container spacing={ 1.5 }>
|
|
224
|
-
<Field label={ __( 'Effect', 'elementor' ) }>
|
|
225
|
-
<Effect value={ effect } onChange={ ( v ) => updateInteraction( { effect: v } ) } />
|
|
226
|
-
</Field>
|
|
227
|
-
|
|
228
|
-
<Field label={ __( 'Type', 'elementor' ) }>
|
|
229
|
-
<EffectType value={ type } onChange={ ( v ) => updateInteraction( { type: v } ) } />
|
|
230
|
-
</Field>
|
|
231
|
-
|
|
232
|
-
<Field label={ __( 'Direction', 'elementor' ) }>
|
|
233
|
-
<Direction
|
|
234
|
-
value={ direction }
|
|
235
|
-
onChange={ ( v ) => updateInteraction( { direction: v } ) }
|
|
236
|
-
interactionType={ type }
|
|
237
|
-
/>
|
|
238
|
-
</Field>
|
|
239
|
-
|
|
240
|
-
{ controlVisibilityConfig.duration( interactionValues ) && (
|
|
241
|
-
<Field label={ __( 'Duration', 'elementor' ) }>
|
|
242
|
-
<TimeFrameIndicator
|
|
243
|
-
value={ String( duration ) }
|
|
244
|
-
onChange={ ( v ) => updateInteraction( { duration: v as SizeStringValue } ) }
|
|
245
|
-
defaultValue={ DEFAULT_VALUES.duration as SizeStringValue }
|
|
246
|
-
/>
|
|
225
|
+
<Divider />
|
|
226
|
+
|
|
227
|
+
<Grid container spacing={ 1.5 }>
|
|
228
|
+
{ EffectControl && (
|
|
229
|
+
<Field label={ __( 'Effect', 'elementor' ) }>
|
|
230
|
+
<EffectControl value={ effect } onChange={ ( v ) => updateInteraction( { effect: v } ) } />
|
|
231
|
+
</Field>
|
|
232
|
+
) }
|
|
233
|
+
|
|
234
|
+
<Field label={ __( 'Type', 'elementor' ) }>
|
|
235
|
+
<EffectType value={ type } onChange={ ( v ) => updateInteraction( { type: v } ) } />
|
|
247
236
|
</Field>
|
|
248
|
-
) }
|
|
249
237
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
defaultValue={ DEFAULT_VALUES.delay as SizeStringValue }
|
|
238
|
+
<Field label={ __( 'Direction', 'elementor' ) }>
|
|
239
|
+
<Direction
|
|
240
|
+
value={ direction }
|
|
241
|
+
onChange={ ( v ) => updateInteraction( { direction: v } ) }
|
|
242
|
+
interactionType={ type }
|
|
256
243
|
/>
|
|
257
244
|
</Field>
|
|
258
|
-
) }
|
|
259
|
-
</Grid>
|
|
260
245
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
value={ relativeTo }
|
|
268
|
-
onChange={ ( v ) => updateInteraction( { relativeTo: v } ) }
|
|
246
|
+
{ controlVisibilityConfig.duration( interactionValues ) && (
|
|
247
|
+
<Field label={ __( 'Duration', 'elementor' ) }>
|
|
248
|
+
<TimeFrameIndicator
|
|
249
|
+
value={ String( duration ) }
|
|
250
|
+
onChange={ ( v ) => updateInteraction( { duration: v as SizeStringValue } ) }
|
|
251
|
+
defaultValue={ DEFAULT_VALUES.duration as SizeStringValue }
|
|
269
252
|
/>
|
|
270
253
|
</Field>
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
254
|
+
) }
|
|
255
|
+
|
|
256
|
+
{ controlVisibilityConfig.delay( interactionValues ) && (
|
|
257
|
+
<Field label={ __( 'Delay', 'elementor' ) }>
|
|
258
|
+
<TimeFrameIndicator
|
|
259
|
+
value={ String( delay ) }
|
|
260
|
+
onChange={ ( v ) => updateInteraction( { delay: v as SizeStringValue } ) }
|
|
261
|
+
defaultValue={ DEFAULT_VALUES.delay as SizeStringValue }
|
|
262
|
+
/>
|
|
263
|
+
</Field>
|
|
264
|
+
) }
|
|
265
|
+
</Grid>
|
|
266
|
+
|
|
267
|
+
{ controlVisibilityConfig.relativeTo( interactionValues ) && RelativeToControl && (
|
|
268
|
+
<>
|
|
269
|
+
<Divider />
|
|
270
|
+
<Grid container spacing={ 1.5 }>
|
|
271
|
+
<Field label={ __( 'Relative To', 'elementor' ) }>
|
|
272
|
+
<RelativeToControl
|
|
273
|
+
value={ relativeTo }
|
|
274
|
+
onChange={ ( v ) => updateInteraction( { relativeTo: v } ) }
|
|
288
275
|
/>
|
|
289
276
|
</Field>
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
277
|
+
{ OffsetTopControl && (
|
|
278
|
+
<Field label={ __( 'Offset Top', 'elementor' ) }>
|
|
279
|
+
<OffsetTopControl
|
|
280
|
+
value={ String( parseSizeValue( offsetTop, [ '%' ] ).size ) }
|
|
281
|
+
onChange={ ( v: string ) =>
|
|
282
|
+
updateInteraction( { offsetTop: v as SizeStringValue } )
|
|
283
|
+
}
|
|
284
|
+
/>
|
|
285
|
+
</Field>
|
|
286
|
+
) }
|
|
287
|
+
{ OffsetBottomControl && (
|
|
288
|
+
<Field label={ __( 'Offset Bottom', 'elementor' ) }>
|
|
289
|
+
<OffsetBottomControl
|
|
290
|
+
value={ String( parseSizeValue( offsetBottom, [ '%' ] ).size ) }
|
|
291
|
+
onChange={ ( v: string ) =>
|
|
292
|
+
updateInteraction( { offsetBottom: v as SizeStringValue } )
|
|
293
|
+
}
|
|
294
|
+
/>
|
|
295
|
+
</Field>
|
|
296
|
+
) }
|
|
297
|
+
</Grid>
|
|
298
|
+
<Divider />
|
|
299
|
+
</>
|
|
300
|
+
) }
|
|
295
301
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
302
|
+
{ EasingControl && (
|
|
303
|
+
<Grid container spacing={ 1.5 }>
|
|
304
|
+
<Field label={ __( 'Easing', 'elementor' ) }>
|
|
305
|
+
<EasingControl
|
|
306
|
+
value={ easing }
|
|
307
|
+
onChange={ ( v ) => {
|
|
308
|
+
updateInteraction( { easing: v } );
|
|
309
|
+
} }
|
|
310
|
+
/>
|
|
311
|
+
</Field>
|
|
312
|
+
</Grid>
|
|
313
|
+
) }
|
|
314
|
+
</PopoverContent>
|
|
315
|
+
</Box>
|
|
309
316
|
);
|
|
310
317
|
};
|
|
311
|
-
|
|
312
|
-
type FieldProps = {
|
|
313
|
-
label: string;
|
|
314
|
-
} & PropsWithChildren;
|
|
315
|
-
|
|
316
|
-
function Field( { label, children }: FieldProps ) {
|
|
317
|
-
return (
|
|
318
|
-
<Grid item xs={ 12 }>
|
|
319
|
-
<PopoverGridContainer>
|
|
320
|
-
<Grid item xs={ 6 }>
|
|
321
|
-
<ControlFormLabel>{ label }</ControlFormLabel>
|
|
322
|
-
</Grid>
|
|
323
|
-
<Grid item xs={ 6 }>
|
|
324
|
-
{ children }
|
|
325
|
-
</Grid>
|
|
326
|
-
</PopoverGridContainer>
|
|
327
|
-
</Grid>
|
|
328
|
-
);
|
|
329
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -12,3 +12,4 @@ export {
|
|
|
12
12
|
export { ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX } from './providers/document-elements-interactions-provider';
|
|
13
13
|
export { init } from './init';
|
|
14
14
|
export { registerInteractionsControl } from './interactions-controls-registry';
|
|
15
|
+
export type { InteractionItemPropValue, FieldProps } from './types';
|
package/src/init.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Easing } from './components/controls/easing';
|
|
2
|
+
import { Effect } from './components/controls/effect';
|
|
2
3
|
import { Replay } from './components/controls/replay';
|
|
3
4
|
import { Trigger } from './components/controls/trigger';
|
|
4
5
|
import { initCleanInteractionIdsOnDuplicate } from './hooks/on-duplicate';
|
|
@@ -9,7 +10,9 @@ import { documentElementsInteractionsProvider } from './providers/document-eleme
|
|
|
9
10
|
export function init() {
|
|
10
11
|
try {
|
|
11
12
|
interactionsRepository.register( documentElementsInteractionsProvider );
|
|
13
|
+
|
|
12
14
|
initCleanInteractionIdsOnDuplicate();
|
|
15
|
+
|
|
13
16
|
registerInteractionsControl( {
|
|
14
17
|
type: 'trigger',
|
|
15
18
|
component: Trigger,
|
|
@@ -21,11 +24,17 @@ export function init() {
|
|
|
21
24
|
component: Easing,
|
|
22
25
|
options: [ 'easeIn' ],
|
|
23
26
|
} );
|
|
27
|
+
|
|
24
28
|
registerInteractionsControl( {
|
|
25
29
|
type: 'replay',
|
|
26
30
|
component: Replay,
|
|
27
31
|
options: [ 'true', 'false' ],
|
|
28
32
|
} );
|
|
33
|
+
registerInteractionsControl( {
|
|
34
|
+
type: 'effect',
|
|
35
|
+
component: Effect,
|
|
36
|
+
options: [ 'fade', 'slide', 'scale' ],
|
|
37
|
+
} );
|
|
29
38
|
} catch ( error ) {
|
|
30
39
|
throw error;
|
|
31
40
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
1
2
|
import { type Unit } from '@elementor/editor-controls';
|
|
2
3
|
import type {
|
|
3
4
|
AnimationPresetPropValue,
|
|
@@ -53,6 +54,7 @@ export type ReplayFieldProps = {
|
|
|
53
54
|
value: boolean;
|
|
54
55
|
onChange: ( value: boolean ) => void;
|
|
55
56
|
disabled?: boolean;
|
|
57
|
+
anchorRef?: RefObject< HTMLElement | null >;
|
|
56
58
|
};
|
|
57
59
|
export type DirectionFieldProps = FieldProps & {
|
|
58
60
|
interactionType: string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MouseEvent, type RefObject, useState } from 'react';
|
|
3
|
+
import { PromotionChip, PromotionPopover, useCanvasClickHandler } from '@elementor/editor-ui';
|
|
4
|
+
import { Box } from '@elementor/ui';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
6
|
+
|
|
7
|
+
export type InteractionsPromotionChipProps = {
|
|
8
|
+
content: string;
|
|
9
|
+
upgradeUrl: string;
|
|
10
|
+
anchorRef?: RefObject< HTMLElement | null >;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function InteractionsPromotionChip( { content, upgradeUrl, anchorRef }: InteractionsPromotionChipProps ) {
|
|
14
|
+
const [ isOpen, setIsOpen ] = useState( false );
|
|
15
|
+
|
|
16
|
+
useCanvasClickHandler( isOpen, () => setIsOpen( false ) );
|
|
17
|
+
|
|
18
|
+
const handleToggle = ( e: MouseEvent ) => {
|
|
19
|
+
e.stopPropagation();
|
|
20
|
+
setIsOpen( ( prev ) => ! prev );
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<PromotionPopover
|
|
25
|
+
open={ isOpen }
|
|
26
|
+
title={ __( 'Interactions', 'elementor' ) }
|
|
27
|
+
content={ content }
|
|
28
|
+
ctaText={ __( 'Upgrade now', 'elementor' ) }
|
|
29
|
+
ctaUrl={ upgradeUrl }
|
|
30
|
+
anchorRef={ anchorRef }
|
|
31
|
+
placement={ anchorRef ? 'right-start' : undefined }
|
|
32
|
+
onClose={ handleToggle }
|
|
33
|
+
>
|
|
34
|
+
<Box onClick={ handleToggle } sx={ { cursor: 'pointer', display: 'inline-flex', mr: 1 } }>
|
|
35
|
+
<PromotionChip />
|
|
36
|
+
</Box>
|
|
37
|
+
</PromotionPopover>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const resolveDirection = (
|
|
2
|
+
hasDirection: boolean,
|
|
3
|
+
newEffect?: string,
|
|
4
|
+
newDirection?: string,
|
|
5
|
+
currentDirection?: string,
|
|
6
|
+
currentEffect?: string
|
|
7
|
+
) => {
|
|
8
|
+
if ( newEffect === 'slide' && ! newDirection ) {
|
|
9
|
+
return 'top';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if ( currentEffect === 'slide' && hasDirection ) {
|
|
13
|
+
return newDirection ?? 'top';
|
|
14
|
+
}
|
|
15
|
+
// Why? - New direction can be undefined when the effect is not slide, so if the updates object includes direction, we take it always!
|
|
16
|
+
if ( hasDirection ) {
|
|
17
|
+
return newDirection;
|
|
18
|
+
}
|
|
19
|
+
return currentDirection;
|
|
20
|
+
};
|