@wix/editor-react-components 1.2210.0 → 1.2212.0

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.
@@ -53,6 +53,17 @@ const manifest = {
53
53
  displayName: DisplayNames.root.data.duration,
54
54
  defaultValue: DEFAULT_ANIMATION_DURATION
55
55
  },
56
+ trigger: {
57
+ dataType: DATA.DATA_TYPE.textEnum,
58
+ displayName: "Animation trigger",
59
+ [DATA.DATA_TYPE.textEnum]: {
60
+ options: [
61
+ { value: "hover", displayName: "Hover" },
62
+ { value: "click", displayName: "Click" }
63
+ ]
64
+ },
65
+ defaultValue: "hover"
66
+ },
56
67
  svgCustomAnimationStart: {
57
68
  dataType: DATA.DATA_TYPE.vectorArt,
58
69
  [DATA.DATA_TYPE.vectorArt]: {}
@@ -122,7 +133,8 @@ const manifest = {
122
133
  "svgCustomAnimationSelected",
123
134
  "svgLastStaticSelected",
124
135
  "svgLastAnimatedSelected",
125
- "duration"
136
+ "duration",
137
+ "trigger"
126
138
  ]
127
139
  }
128
140
  },
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ import { TriggerTypeEnum } from '../constants';
3
+ import { Translations } from '../translations/consts';
4
+ interface TriggerSectionProps {
5
+ trigger: TriggerTypeEnum;
6
+ onTriggerChange: (trigger: TriggerTypeEnum) => Promise<void> | void;
7
+ translations: Translations;
8
+ dataHook?: string;
9
+ }
10
+ declare const TriggerSection: React.FC<TriggerSectionProps>;
11
+ export default TriggerSection;
@@ -2,6 +2,10 @@ export declare enum IconTypeEnum {
2
2
  Static = "static",
3
3
  Animated = "animated"
4
4
  }
5
+ export declare enum TriggerTypeEnum {
6
+ Hover = "hover",
7
+ Click = "click"
8
+ }
5
9
  export declare const DURATION_CONSTANTS: {
6
10
  readonly DEFAULT_ANIMATION_DURATION: 0.2;
7
11
  readonly DURATION_STEP: 0.1;
@@ -4,10 +4,12 @@ export declare const CUSTOMIZE_ICON_PANEL_DATA_HOOKS: {
4
4
  SVG_DISPLAY_SECTION: string;
5
5
  CREATE_ANIMATED_SECTION: string;
6
6
  DURATION_SECTION: string;
7
+ TRIGGER_SECTION: string;
7
8
  CHOOSE_ICON_BUTTON: string;
8
9
  CREATE_ANIMATED_BUTTON: string;
9
10
  DURATION_SLIDER: string;
10
11
  DURATION_INPUT: string;
12
+ TRIGGER_TOGGLE: string;
11
13
  CREATION_PANEL: string;
12
14
  CREATION_BACK: string;
13
15
  CREATION_START_ICON: string;
@@ -15,6 +15,10 @@ export declare const TranslationKeys: {
15
15
  readonly endIconLabel: "custompanel_animatedicon_sidePanel_endIcon_label";
16
16
  readonly sidePanelTitle: "custompanel_animatedicon_sidePanel_title";
17
17
  readonly startIconLabel: "custompanel_animatedicon_sidePanel_startIcon_label";
18
+ readonly triggerFieldLabel: "custompanel_animatedicon_trigger_field_label";
19
+ readonly triggerHoverOption: "custompanel_animatedicon_trigger_toggle_hover_label";
20
+ readonly triggerClickOption: "custompanel_animatedicon_trigger_toggle_click_label";
21
+ readonly triggerTooltip: "custompanel_animatedicon_trigger_tooltip_description";
18
22
  };
19
23
  export type Translations = Record<keyof typeof TranslationKeys, string>;
20
24
  export declare const DefaultTranslations: Translations;
@@ -1,9 +1,11 @@
1
+ import { TriggerTypeEnum } from './constants';
1
2
  export interface SvgData {
2
3
  uri: string;
3
4
  type: string;
4
5
  }
5
6
  export interface AnimatedIconData {
6
7
  duration?: number;
8
+ trigger?: TriggerTypeEnum;
7
9
  svg?: SvgData;
8
10
  svgCustomAnimationStart?: SvgData;
9
11
  svgCustomAnimationEnd?: SvgData;
@@ -20,6 +22,7 @@ export declare const fetchSvg: (svgId: string) => Promise<string>;
20
22
  export declare const openMediaManager: (category: string) => Promise<any>;
21
23
  type Data = {
22
24
  duration: number;
25
+ trigger: TriggerTypeEnum | null;
23
26
  svg: SvgData | null;
24
27
  svgLastAnimatedSelected: SvgData | null;
25
28
  svgLastStaticSelected: SvgData | null;
@@ -28,6 +31,6 @@ type Data = {
28
31
  svgCustomAnimationEnd: SvgData | null;
29
32
  };
30
33
  export declare const getData: () => Promise<Data>;
31
- export declare const setData: (data: any) => Promise<void>;
34
+ export declare const setData: (data: Partial<Data>) => Promise<void>;
32
35
  export declare const generateAnimatedSvgInMediaManager: (startSvg: string, endSvg: string) => Promise<any>;
33
36
  export {};
@@ -4,6 +4,7 @@ export type AnimatedSvgRef = {
4
4
  runAnimationBackward: () => void;
5
5
  };
6
6
  export type { VectorArt } from '@wix/editor-react-types';
7
+ export type TriggerType = 'hover' | 'click';
7
8
  export interface AnimatedSvgProps {
8
9
  svgContent: string;
9
10
  reducedMotion?: boolean;
@@ -20,6 +21,7 @@ export interface AnimatedIconBuilderProps {
20
21
  className?: string;
21
22
  'data-testid'?: string;
22
23
  reducedMotion?: boolean;
24
+ trigger?: TriggerType;
23
25
  }
24
26
  export interface AnimatedSvgEditorProps {
25
27
  animatedSvgId: string;
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ import { AnimatedSvgRef, TriggerType } from './types';
3
+ export declare function useAnimatedIconInteraction(trigger?: TriggerType, ref?: React.Ref<AnimatedSvgRef>): {
4
+ actualRef: ((instance: AnimatedSvgRef | null) => void) | React.RefObject<AnimatedSvgRef>;
5
+ isClickable: boolean;
6
+ } | {
7
+ onClick: () => void;
8
+ onMouseEnter?: undefined;
9
+ onMouseLeave?: undefined;
10
+ actualRef: React.RefObject<AnimatedSvgRef>;
11
+ isClickable: boolean;
12
+ } | {
13
+ onMouseEnter: () => void;
14
+ onMouseLeave: () => void;
15
+ onClick?: undefined;
16
+ actualRef: React.RefObject<AnimatedSvgRef>;
17
+ isClickable: boolean;
18
+ };
@@ -1,6 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { VectorArt, A11y, Direction } from '@wix/editor-react-types';
3
3
  import { AriaProps } from '../../../types/vendored/editor-elements-types-a11y';
4
+ import { TriggerType } from '../AnimatedIcon/types';
4
5
  export interface ButtonLinkProps {
5
6
  href?: string;
6
7
  target?: '_blank' | '_self';
@@ -12,7 +13,8 @@ export interface ButtonLinkProps {
12
13
  anchorCompId?: string;
13
14
  }
14
15
  export declare enum IconAnimationTriggers {
15
- HOVER = "hover"
16
+ HOVER = "hover",
17
+ CLICK = "click"
16
18
  }
17
19
  export type IStylableButtonCorvidStyleStateProps = {
18
20
  hasBackgroundColor?: boolean;
@@ -41,6 +43,7 @@ export type AnimatedSvgRef = {
41
43
  export interface AnimatedIconElementProps {
42
44
  svg?: VectorArt;
43
45
  duration?: number;
46
+ trigger?: TriggerType;
44
47
  }
45
48
  export interface ElementProps {
46
49
  animatedIcon?: AnimatedIconElementProps;
@@ -1,4 +1,4 @@
1
1
  export { useIconAnimation } from './useIconAnimation';
2
- export { useHoverState } from './useHoverState';
2
+ export { useButtonInteractionState } from './useButtonInteractionState';
3
3
  export { useButtonEventHandlers } from './useButtonEventHandlers';
4
4
  export { useButtonA11y } from './useButtonA11y';
@@ -8,11 +8,12 @@ type UseButtonEventHandlersParams = {
8
8
  reportBiOnClick?: React.MouseEventHandler;
9
9
  onMouseEnter: MouseEventHandler;
10
10
  onMouseLeave: MouseEventHandler;
11
+ onIconAnimationClick?: MouseEventHandler;
11
12
  onDblClick?: React.MouseEventHandler;
12
13
  onFocus?: (event: React.FocusEvent) => void;
13
14
  onBlur?: (event: React.FocusEvent) => void;
14
15
  };
15
- export declare function useButtonEventHandlers({ isDisabled, link, propsOnClick, preventLinkNavigation, reportBiOnClick, onMouseEnter, onMouseLeave, onDblClick, onFocus, onBlur, }: UseButtonEventHandlersParams): {
16
+ export declare function useButtonEventHandlers({ isDisabled, link, propsOnClick, preventLinkNavigation, reportBiOnClick, onMouseEnter, onMouseLeave, onIconAnimationClick, onDblClick, onFocus, onBlur, }: UseButtonEventHandlersParams): {
16
17
  isLink: boolean;
17
18
  eventHandlers: {
18
19
  onClick: React.MouseEventHandler;
@@ -0,0 +1,10 @@
1
+ import { MouseEventHandler } from 'react';
2
+ import { IconAnimationTriggers } from '../Button.types';
3
+ interface UseButtonInteractionStateResult {
4
+ active: boolean;
5
+ onMouseEnter: MouseEventHandler;
6
+ onMouseLeave: MouseEventHandler;
7
+ onIconAnimationClick?: MouseEventHandler;
8
+ }
9
+ export declare function useButtonInteractionState(iconAnimationTriggers: Array<IconAnimationTriggers>, onAnimationForward: () => void, onAnimationBackward: () => void, propsOnMouseEnter?: MouseEventHandler, propsOnMouseLeave?: MouseEventHandler): UseButtonInteractionStateResult;
10
+ export {};
@@ -352,7 +352,10 @@ const stylableButtonSDKFactory = withValidation(
352
352
  type: ["array"],
353
353
  items: {
354
354
  type: ["string"],
355
- enum: [IconAnimationTriggers.HOVER]
355
+ enum: [
356
+ IconAnimationTriggers.HOVER,
357
+ IconAnimationTriggers.CLICK
358
+ ]
356
359
  },
357
360
  name: "iconAnimationTrigger"
358
361
  }
@@ -81,30 +81,32 @@ const animatedIcon = "animatedIcon__3o5ii";
81
81
  const styles = {
82
82
  animatedIcon
83
83
  };
84
- function useDefaultHoverBehavior(ref) {
84
+ function useAnimatedIconInteraction(trigger = "hover", ref) {
85
85
  const internalRef = useRef(null);
86
- const actualRef = ref || internalRef;
87
- const handleMouseEnter = () => {
88
- var _a;
89
- if (typeof actualRef === "function") {
90
- return;
86
+ const actualRef = ref ?? internalRef;
87
+ const isForwardRef = useRef(false);
88
+ const handleClick = useCallback(() => {
89
+ var _a, _b;
90
+ if (isForwardRef.current) {
91
+ (_a = actualRef.current) == null ? void 0 : _a.runAnimationBackward();
92
+ } else {
93
+ (_b = actualRef.current) == null ? void 0 : _b.runAnimationForward();
91
94
  }
92
- (_a = actualRef == null ? void 0 : actualRef.current) == null ? void 0 : _a.runAnimationForward();
93
- };
94
- const handleMouseLeave = () => {
95
+ isForwardRef.current = !isForwardRef.current;
96
+ }, [actualRef]);
97
+ const handleMouseEnter = useCallback(() => {
95
98
  var _a;
96
- if (typeof actualRef === "function") {
97
- return;
98
- }
99
- (_a = actualRef == null ? void 0 : actualRef.current) == null ? void 0 : _a.runAnimationBackward();
100
- };
101
- return {
102
- actualRef,
103
- ...!ref && {
104
- onMouseEnter: handleMouseEnter,
105
- onMouseLeave: handleMouseLeave
106
- }
107
- };
99
+ (_a = actualRef.current) == null ? void 0 : _a.runAnimationForward();
100
+ }, [actualRef]);
101
+ const handleMouseLeave = useCallback(() => {
102
+ var _a;
103
+ (_a = actualRef.current) == null ? void 0 : _a.runAnimationBackward();
104
+ }, [actualRef]);
105
+ if (typeof ref === "function" || ref && typeof ref === "object") {
106
+ return { actualRef: ref, isClickable: false };
107
+ }
108
+ const triggerProps = trigger === "click" ? { onClick: handleClick } : { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave };
109
+ return { actualRef, isClickable: trigger === "click", ...triggerProps };
108
110
  }
109
111
  const AnimatedIcon = forwardRef(
110
112
  (props, ref) => {
@@ -114,38 +116,40 @@ const AnimatedIcon = forwardRef(
114
116
  className,
115
117
  id,
116
118
  "data-testid": dataTestId,
117
- reducedMotion
119
+ reducedMotion,
120
+ trigger
118
121
  } = props;
119
122
  const svgContent = svg == null ? void 0 : svg.svgContent;
120
123
  const processedSvg = useMemo(
121
124
  () => addAttributesToStringSvg(svgContent || "", duration),
122
125
  [svgContent, duration]
123
126
  );
124
- const { actualRef, ...mouseEventProps } = useDefaultHoverBehavior(ref);
127
+ const { actualRef, isClickable, ...eventProps } = useAnimatedIconInteraction(trigger, ref);
125
128
  if (svgContent) {
126
- return /* @__PURE__ */ jsx(
127
- "div",
129
+ const commonProps = {
130
+ className: cn(
131
+ styles.animatedIcon,
132
+ "animatedIcon",
133
+ "icon",
134
+ className
135
+ ),
136
+ id,
137
+ "data-testid": dataTestId,
138
+ ...eventProps
139
+ };
140
+ const animatedIcon2 = /* @__PURE__ */ jsx(
141
+ AnimatedSvg,
128
142
  {
129
- className: cn(
130
- styles.animatedIcon,
131
- "animatedIcon",
132
- "icon",
133
- className
134
- ),
135
- id,
136
- "data-testid": dataTestId,
137
- ...mouseEventProps,
138
- children: /* @__PURE__ */ jsx(
139
- AnimatedSvg,
140
- {
141
- ref: actualRef,
142
- svgContent: processedSvg,
143
- reducedMotion,
144
- duration
145
- }
146
- )
143
+ ref: actualRef,
144
+ svgContent: processedSvg,
145
+ reducedMotion,
146
+ duration
147
147
  }
148
148
  );
149
+ if (isClickable) {
150
+ return /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Animated icon", ...commonProps, children: animatedIcon2 });
151
+ }
152
+ return /* @__PURE__ */ jsx("div", { ...commonProps, children: animatedIcon2 });
149
153
  }
150
154
  return null;
151
155
  }
@@ -48,11 +48,21 @@ function useIconAnimation(isDisabled) {
48
48
  }, [isDisabled]);
49
49
  return { iconAnimatedRef, onAnimationForward, onAnimationBackward };
50
50
  }
51
- function useHoverState(iconAnimationTriggers, onAnimationForward, onAnimationBackward, propsOnMouseEnter, propsOnMouseLeave) {
51
+ function useButtonInteractionState(iconAnimationTriggers, onAnimationForward, onAnimationBackward, propsOnMouseEnter, propsOnMouseLeave) {
52
52
  const [active2, setActive] = useState(false);
53
53
  const animationTimeoutRef = useRef(
54
54
  null
55
55
  );
56
+ const isForwardRef = useRef(false);
57
+ const hasHoverTrigger = iconAnimationTriggers.includes(
58
+ IconAnimationTriggers.HOVER
59
+ );
60
+ const hasClickTrigger = iconAnimationTriggers.includes(
61
+ IconAnimationTriggers.CLICK
62
+ );
63
+ useEffect(() => {
64
+ isForwardRef.current = false;
65
+ }, [hasClickTrigger, hasHoverTrigger]);
56
66
  useEffect(() => {
57
67
  return () => {
58
68
  if (animationTimeoutRef.current) {
@@ -67,26 +77,42 @@ function useHoverState(iconAnimationTriggers, onAnimationForward, onAnimationBac
67
77
  animationTimeoutRef.current = null;
68
78
  }
69
79
  setActive(true);
70
- if (iconAnimationTriggers.includes(IconAnimationTriggers.HOVER)) {
80
+ if (hasHoverTrigger) {
71
81
  onAnimationForward();
72
82
  }
73
83
  propsOnMouseEnter == null ? void 0 : propsOnMouseEnter(event);
74
84
  },
75
- [iconAnimationTriggers, onAnimationForward, propsOnMouseEnter]
85
+ [hasHoverTrigger, onAnimationForward, propsOnMouseEnter]
76
86
  );
77
87
  const onMouseLeave = useCallback(
78
88
  (event) => {
79
89
  animationTimeoutRef.current = setTimeout(() => {
80
90
  setActive(false);
81
91
  }, TRANSITION_DURATION);
82
- if (iconAnimationTriggers.includes(IconAnimationTriggers.HOVER)) {
92
+ if (hasHoverTrigger) {
83
93
  onAnimationBackward();
84
94
  }
85
95
  propsOnMouseLeave == null ? void 0 : propsOnMouseLeave(event);
86
96
  },
87
- [iconAnimationTriggers, onAnimationBackward, propsOnMouseLeave]
97
+ [hasHoverTrigger, onAnimationBackward, propsOnMouseLeave]
88
98
  );
89
- return { active: active2, onMouseEnter, onMouseLeave };
99
+ const onIconAnimationClick = useCallback(() => {
100
+ if (!hasClickTrigger) {
101
+ return;
102
+ }
103
+ if (isForwardRef.current) {
104
+ onAnimationBackward();
105
+ } else {
106
+ onAnimationForward();
107
+ }
108
+ isForwardRef.current = !isForwardRef.current;
109
+ }, [hasClickTrigger, onAnimationBackward, onAnimationForward]);
110
+ return {
111
+ active: active2,
112
+ onMouseEnter,
113
+ onMouseLeave,
114
+ onIconAnimationClick: hasClickTrigger ? onIconAnimationClick : void 0
115
+ };
90
116
  }
91
117
  const useAnalyticsReportClicks = ({
92
118
  reportBiOnClick,
@@ -108,6 +134,7 @@ function useButtonEventHandlers({
108
134
  reportBiOnClick,
109
135
  onMouseEnter,
110
136
  onMouseLeave,
137
+ onIconAnimationClick,
111
138
  onDblClick,
112
139
  onFocus,
113
140
  onBlur
@@ -117,9 +144,12 @@ function useButtonEventHandlers({
117
144
  const shouldHaveOnClick = !isDisabled && propsOnClick || shouldPreventLinkNavigation;
118
145
  const onClick = useAnalyticsReportClicks({
119
146
  reportBiOnClick,
120
- onClick: shouldHaveOnClick ? (event) => {
121
- shouldPreventLinkNavigation && event.preventDefault();
122
- !isDisabled && (propsOnClick == null ? void 0 : propsOnClick());
147
+ onClick: shouldHaveOnClick || onIconAnimationClick ? (event) => {
148
+ onIconAnimationClick == null ? void 0 : onIconAnimationClick(event);
149
+ if (shouldHaveOnClick) {
150
+ shouldPreventLinkNavigation && event.preventDefault();
151
+ !isDisabled && (propsOnClick == null ? void 0 : propsOnClick());
152
+ }
123
153
  } : void 0
124
154
  });
125
155
  const eventHandlers = useMemo(
@@ -196,10 +226,12 @@ const Button = (props) => {
196
226
  wix
197
227
  } = props;
198
228
  const presetsWrapperProps = (wix == null ? void 0 : wix.presetsWrapperProps) || {};
199
- const { iconAnimationTriggers = [IconAnimationTriggers.HOVER] } = corvid || {};
200
229
  const animatedIconProps = elementProps == null ? void 0 : elementProps.animatedIcon;
230
+ const corvidIconAnimationTriggers = (corvid == null ? void 0 : corvid.iconAnimationTriggers) ?? [];
231
+ const defaultTrigger = (animatedIconProps == null ? void 0 : animatedIconProps.trigger) === IconAnimationTriggers.CLICK ? IconAnimationTriggers.CLICK : IconAnimationTriggers.HOVER;
232
+ const iconAnimationTriggers = corvidIconAnimationTriggers.length > 0 ? corvidIconAnimationTriggers : [defaultTrigger];
201
233
  const { iconAnimatedRef, onAnimationForward, onAnimationBackward } = useIconAnimation(isDisabled);
202
- const { active: active2, onMouseEnter, onMouseLeave } = useHoverState(
234
+ const { active: active2, onMouseEnter, onMouseLeave, onIconAnimationClick } = useButtonInteractionState(
203
235
  iconAnimationTriggers,
204
236
  onAnimationForward,
205
237
  onAnimationBackward,
@@ -234,6 +266,7 @@ const Button = (props) => {
234
266
  reportBiOnClick,
235
267
  onMouseEnter,
236
268
  onMouseLeave,
269
+ onIconAnimationClick,
237
270
  onDblClick,
238
271
  onFocus,
239
272
  onBlur
@@ -1,5 +1,6 @@
1
1
  var IconAnimationTriggers = /* @__PURE__ */ ((IconAnimationTriggers2) => {
2
2
  IconAnimationTriggers2["HOVER"] = "hover";
3
+ IconAnimationTriggers2["CLICK"] = "click";
3
4
  return IconAnimationTriggers2;
4
5
  })(IconAnimationTriggers || {});
5
6
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/editor-react-components",
3
- "version": "1.2210.0",
3
+ "version": "1.2212.0",
4
4
  "description": "React components for the Wix Editor",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -188,5 +188,5 @@
188
188
  "registry": "https://registry.npmjs.org/",
189
189
  "access": "public"
190
190
  },
191
- "falconPackageHash": "4438c33ccf024b6c1f78aea0b993496c17457af84edba516269366b7"
191
+ "falconPackageHash": "8b09327c266bf7d5fb1bfdc564f3c00fd92b340332e7b8425098f3e7"
192
192
  }
@@ -1,7 +0,0 @@
1
- import { default as React } from 'react';
2
- import { AnimatedSvgRef } from './types';
3
- export declare function useDefaultHoverBehavior(ref?: React.Ref<AnimatedSvgRef>): {
4
- onMouseEnter?: (() => void) | undefined;
5
- onMouseLeave?: (() => void) | undefined;
6
- actualRef: ((instance: AnimatedSvgRef | null) => void) | React.RefObject<AnimatedSvgRef>;
7
- };
@@ -1,7 +0,0 @@
1
- import { MouseEventHandler } from 'react';
2
- import { IconAnimationTriggers } from '../Button.types';
3
- export declare function useHoverState(iconAnimationTriggers: Array<IconAnimationTriggers>, onAnimationForward: () => void, onAnimationBackward: () => void, propsOnMouseEnter?: MouseEventHandler, propsOnMouseLeave?: MouseEventHandler): {
4
- active: boolean;
5
- onMouseEnter: MouseEventHandler;
6
- onMouseLeave: MouseEventHandler;
7
- };