@rxdrag/website-lib-core 0.0.103 → 0.0.105
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 +5 -5
- package/src/component-logic/index.ts +1 -8
- package/src/global.d.ts +7 -0
- package/src/index.ts +1 -3
- package/src/react/components/BackgroundHlsVideoPlayer.tsx +30 -1
- package/src/react/components/ContactForm/ContactForm.tsx +3 -2
- package/src/react/components/ContactForm/types.ts +1 -0
- package/src/react/components/ProductCard/ProductCta/index.tsx +5 -21
- package/src/react/components/Scroller.tsx +32 -4
- package/src/react/components/Share/socials.tsx +1 -2
- package/src/react/index.ts +1 -2
- package/src/component-logic/collapse.ts +0 -61
- package/src/component-logic/gsap.d.ts +0 -4
- package/src/component-logic/modal.ts +0 -45
- package/src/component-logic/motion.ts +0 -272
- package/src/component-logic/number.ts +0 -45
- package/src/component-logic/popover.ts +0 -51
- package/src/component-logic/tabs.ts +0 -10
- package/src/controller/AnimateController.ts +0 -138
- package/src/controller/AosController.ts +0 -240
- package/src/controller/CollapseController.ts +0 -130
- package/src/controller/FlipController.ts +0 -339
- package/src/controller/ModalController.ts +0 -127
- package/src/controller/NumberController.ts +0 -161
- package/src/controller/OpenableController.ts +0 -367
- package/src/controller/PageLoader.ts +0 -154
- package/src/controller/PopoverController.ts +0 -116
- package/src/controller/TabsController.ts +0 -271
- package/src/controller/applyAnimation.ts +0 -86
- package/src/controller/applyInitialState.ts +0 -79
- package/src/controller/consts.ts +0 -33
- package/src/controller/index.ts +0 -10
- package/src/controller/utils.ts +0 -48
- package/src/motion/consts.ts +0 -428
- package/src/motion/convertToGsapVars.ts +0 -102
- package/src/motion/index.ts +0 -6
- package/src/motion/normalizeAnimation.ts +0 -28
- package/src/motion/normalizeAosAnimation.ts +0 -22
- package/src/motion/normalizePopupAnimation.ts +0 -24
- package/src/motion/types.ts +0 -133
- package/src/react/hooks/index.ts +0 -1
- package/src/react/hooks/useScroll.ts +0 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxdrag/website-lib-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.105",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.ts"
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"@types/react-dom": "^19.1.0",
|
|
25
25
|
"eslint": "^7.32.0",
|
|
26
26
|
"typescript": "^5",
|
|
27
|
-
"@rxdrag/slate-preview": "1.2.63",
|
|
28
27
|
"@rxdrag/tsconfig": "0.2.0",
|
|
28
|
+
"@rxdrag/slate-preview": "1.2.63",
|
|
29
29
|
"@rxdrag/eslint-config-custom": "0.2.12"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
"gsap": "^3.12.7",
|
|
35
35
|
"hls.js": "^1.6.13",
|
|
36
36
|
"lodash-es": "^4.17.21",
|
|
37
|
-
"react": "^19.1.0",
|
|
38
|
-
"react-dom": "^19.1.0",
|
|
39
37
|
"@rxdrag/entify-lib": "0.0.23",
|
|
40
38
|
"@rxdrag/rxcms-models": "0.3.96"
|
|
41
39
|
},
|
|
42
40
|
"peerDependencies": {
|
|
43
|
-
"astro": "^4.0.0 || ^5.0.0"
|
|
41
|
+
"astro": "^4.0.0 || ^5.0.0",
|
|
42
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
43
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"lint": "eslint . --ext .ts,tsx",
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
export * from "./collapse";
|
|
2
|
-
export * from "./motion";
|
|
3
|
-
export * from "../controller/FlipController";
|
|
4
1
|
export * from "./link";
|
|
5
|
-
export * from "./link-client";
|
|
6
|
-
export * from "./popover";
|
|
7
|
-
export * from "./tabs";
|
|
8
|
-
export * from "./modal";
|
|
9
|
-
export * from "./number";
|
|
2
|
+
export * from "./link-client";
|
package/src/global.d.ts
ADDED
package/src/index.ts
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
import { useEffect, useRef, type VideoHTMLAttributes } from "react";
|
|
2
2
|
import Hls from "hls.js";
|
|
3
3
|
|
|
4
|
+
// 需要过滤掉的非 video 属性(Astro runtime 透传的方法/对象)
|
|
5
|
+
const FORBIDDEN_PROPS = new Set([
|
|
6
|
+
'createMetadata',
|
|
7
|
+
'createComponent',
|
|
8
|
+
'createAstro',
|
|
9
|
+
'renderComponent',
|
|
10
|
+
'renderSlot',
|
|
11
|
+
'render',
|
|
12
|
+
'addAttribute',
|
|
13
|
+
'spreadAttributes',
|
|
14
|
+
'defineStyleVars',
|
|
15
|
+
'defineScriptVars',
|
|
16
|
+
'Fragment',
|
|
17
|
+
'unescapeHTML',
|
|
18
|
+
'maybeRenderHead',
|
|
19
|
+
'renderHead',
|
|
20
|
+
'slots',
|
|
21
|
+
'props',
|
|
22
|
+
'children',
|
|
23
|
+
]);
|
|
24
|
+
|
|
4
25
|
export function BackgroundHlsVideoPlayer(
|
|
5
26
|
props: VideoHTMLAttributes<HTMLVideoElement>
|
|
6
27
|
) {
|
|
7
|
-
const { poster, src, className, ...
|
|
28
|
+
const { poster, src, className, ...rawRestProps } = props;
|
|
29
|
+
// 过滤掉 Astro runtime 透传的非 video 属性
|
|
30
|
+
const restProps: Record<string, unknown> = {};
|
|
31
|
+
for (const [k, v] of Object.entries(rawRestProps)) {
|
|
32
|
+
if (FORBIDDEN_PROPS.has(k)) continue;
|
|
33
|
+
if (k.startsWith('_')) continue;
|
|
34
|
+
if (typeof v === 'function') continue;
|
|
35
|
+
restProps[k] = v;
|
|
36
|
+
}
|
|
8
37
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
9
38
|
|
|
10
39
|
useEffect(() => {
|
|
@@ -2,7 +2,6 @@ import { forwardRef, useState } from "react";
|
|
|
2
2
|
import { Submit } from "./Submit";
|
|
3
3
|
import { type UploadedFile } from "./FileUpload2";
|
|
4
4
|
import clsx from "clsx";
|
|
5
|
-
import { modal } from "../../../controller";
|
|
6
5
|
import { encrypt } from "./funcs";
|
|
7
6
|
import { ContactFormProps, QuoteRequest } from "./types";
|
|
8
7
|
import { getControl, getFileUpload } from "./factory";
|
|
@@ -22,6 +21,7 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
|
|
|
22
21
|
fields = [],
|
|
23
22
|
className,
|
|
24
23
|
classNames,
|
|
24
|
+
fromCta,
|
|
25
25
|
...rest
|
|
26
26
|
} = props;
|
|
27
27
|
const [formData, setFormData] = useState<QuoteRequest>({
|
|
@@ -129,7 +129,8 @@ export const ContactForm = forwardRef<HTMLDivElement, ContactFormProps>(
|
|
|
129
129
|
method: "POST",
|
|
130
130
|
body: JSON.stringify({
|
|
131
131
|
...formData,
|
|
132
|
-
|
|
132
|
+
//TODO:后面改成从window 或者传入
|
|
133
|
+
fromCta: fromCta || window?.lastCta,
|
|
133
134
|
encryptedField: encrypt(formData.phone, formSalt),
|
|
134
135
|
}),
|
|
135
136
|
headers: {
|
|
@@ -1,41 +1,25 @@
|
|
|
1
1
|
import { Product } from "@rxdrag/rxcms-models";
|
|
2
2
|
import "./style.css";
|
|
3
|
-
import {
|
|
4
|
-
DATA_OPENABLE,
|
|
5
|
-
DATA_POPUP_CTA,
|
|
6
|
-
DATA_OPENABLE_ROLE,
|
|
7
|
-
popover,
|
|
8
|
-
OpenAble,
|
|
9
|
-
} from "../../../../controller";
|
|
10
|
-
import { useRef } from "react";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
11
4
|
|
|
12
5
|
//TODO: 跟询盘触发器同样的实现原理,给询盘对话框发消息
|
|
13
6
|
export function ProductCta(props: {
|
|
14
7
|
product?: Product;
|
|
15
8
|
openableKey?: string;
|
|
16
|
-
children?:
|
|
9
|
+
children?: ReactNode;
|
|
17
10
|
}) {
|
|
18
11
|
const { product, openableKey = "enquiry-modal", children } = props;
|
|
19
|
-
const ref = useRef<HTMLButtonElement>(null);
|
|
20
12
|
const roleProps = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
[DATA_OPENABLE]: openableKey,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const handleClick = () => {
|
|
27
|
-
if (ref.current) {
|
|
28
|
-
popover.open(openableKey, ref.current);
|
|
29
|
-
}
|
|
13
|
+
"data-modal-open": openableKey,
|
|
14
|
+
"data-call-to-action": `From RichText ProductCard-${product?.title}-${product?.id}`,
|
|
30
15
|
};
|
|
31
16
|
|
|
32
17
|
return (
|
|
33
18
|
<div className="flex justify-center items-center">
|
|
34
19
|
<button
|
|
35
|
-
ref={ref}
|
|
36
20
|
{...roleProps}
|
|
37
21
|
className="product-cta-button relative flex-1 mt-2 flex items-center justify-center rounded-md border border-transparent bg-sky-600 text-md font-smibold text-white hover:bg-sky-700"
|
|
38
|
-
|
|
22
|
+
type="button"
|
|
39
23
|
>
|
|
40
24
|
{children || "Get a quote"}
|
|
41
25
|
</button>
|
|
@@ -1,11 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
export const defaultThreshold = 10;
|
|
2
4
|
|
|
3
5
|
export type ScrollerProps = {
|
|
4
6
|
threshold?: number;
|
|
5
7
|
};
|
|
6
8
|
|
|
7
9
|
export function Scroller(props: ScrollerProps) {
|
|
8
|
-
const { threshold } = props;
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const { threshold = defaultThreshold } = props;
|
|
11
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
12
|
+
const [win, setWin] = useState<Window | null>(null);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (ref.current) {
|
|
16
|
+
setWin(ref.current.ownerDocument.defaultView);
|
|
17
|
+
}
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
const onScroll = useCallback(() => {
|
|
21
|
+
if (!win) return;
|
|
22
|
+
const scrolled = win.scrollY > threshold;
|
|
23
|
+
const doc = win.document;
|
|
24
|
+
|
|
25
|
+
if (scrolled) {
|
|
26
|
+
doc.body.classList.add("scrolled");
|
|
27
|
+
} else {
|
|
28
|
+
doc.body.classList.remove("scrolled");
|
|
29
|
+
}
|
|
30
|
+
}, [threshold, win]);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!win) return;
|
|
34
|
+
win.addEventListener("scroll", onScroll);
|
|
35
|
+
return () => win.removeEventListener("scroll", onScroll);
|
|
36
|
+
}, [onScroll, win]);
|
|
37
|
+
|
|
38
|
+
return <div ref={ref} style={{ display: "none" }} />;
|
|
11
39
|
}
|
package/src/react/index.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export * from "./components";
|
|
2
|
-
export * from "./hooks";
|
|
1
|
+
export * from "./components";
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { DATA_OPENABLE, DATA_OPENABLE_ROLE, OpenAble } from "../controller";
|
|
2
|
-
import { AnimationConfig, OpenableAnimationConfig } from "../motion";
|
|
3
|
-
import { HTMLElementsWithChildren, IMotionProps } from "./motion";
|
|
4
|
-
|
|
5
|
-
export type CollapseTriggerProps = IMotionProps & {
|
|
6
|
-
as?: HTMLElementsWithChildren;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const defaultCollapsePanelOpen: AnimationConfig = {
|
|
10
|
-
fromTo: {
|
|
11
|
-
from: {
|
|
12
|
-
height: 0,
|
|
13
|
-
opacity: 0,
|
|
14
|
-
},
|
|
15
|
-
to: {
|
|
16
|
-
height: "auto",
|
|
17
|
-
opacity: 1,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
duration: 0.6,
|
|
21
|
-
ease: "spring",
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const defaultCollapsePanelClose: AnimationConfig = {
|
|
25
|
-
fromTo: {
|
|
26
|
-
from: {
|
|
27
|
-
height: "auto",
|
|
28
|
-
opacity: 1,
|
|
29
|
-
},
|
|
30
|
-
to: {
|
|
31
|
-
height: 0,
|
|
32
|
-
opacity: 0,
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
duration: 0.25,
|
|
36
|
-
ease: "cubic-bezier(0.4, 0.0, 0.2, 1)",
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const defaultCollapsePanelAnimation: OpenableAnimationConfig = {
|
|
40
|
-
open: defaultCollapsePanelOpen,
|
|
41
|
-
close: defaultCollapsePanelClose,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export function getCollapseDataAttrs(openableKey: string = crypto.randomUUID()) {
|
|
45
|
-
return {
|
|
46
|
-
[DATA_OPENABLE]: openableKey,
|
|
47
|
-
[DATA_OPENABLE_ROLE]: OpenAble.CollapseContainer,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function getCollapseTriggerDataAttrs() {
|
|
52
|
-
return {
|
|
53
|
-
[DATA_OPENABLE_ROLE]: OpenAble.CollapseTrigger,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function getCollapsePanelDataAttrs() {
|
|
58
|
-
return {
|
|
59
|
-
[DATA_OPENABLE_ROLE]: OpenAble.CollapsePanel,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DATA_OPENABLE,
|
|
3
|
-
DATA_OPENABLE_ROLE,
|
|
4
|
-
DATA_POPUP_CTA,
|
|
5
|
-
OpenAble,
|
|
6
|
-
} from "../controller";
|
|
7
|
-
import { HTMLElementsWithChildren, IMotionProps } from "./motion";
|
|
8
|
-
|
|
9
|
-
export type ModalTriggerProps = IMotionProps & {
|
|
10
|
-
openableKey: string;
|
|
11
|
-
callToAction?: string;
|
|
12
|
-
as?: HTMLElementsWithChildren;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export function getModalDataAttrs(openableKey?: string) {
|
|
16
|
-
return {
|
|
17
|
-
[DATA_OPENABLE]: openableKey,
|
|
18
|
-
[DATA_OPENABLE_ROLE]: OpenAble.ModalContainer,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function getModalCloserDataAttrs(openableKey?: string) {
|
|
23
|
-
return {
|
|
24
|
-
[DATA_OPENABLE]: openableKey,
|
|
25
|
-
[DATA_OPENABLE_ROLE]: OpenAble.ModalCloser,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getModalPanelDataAttrs(openableKey?: string) {
|
|
30
|
-
return {
|
|
31
|
-
[DATA_OPENABLE]: openableKey,
|
|
32
|
-
[DATA_OPENABLE_ROLE]: OpenAble.ModalPanel,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function getModalTriggerDataAttrs(
|
|
37
|
-
openableKey: string | undefined,
|
|
38
|
-
callToAction?: string
|
|
39
|
-
) {
|
|
40
|
-
return {
|
|
41
|
-
[DATA_OPENABLE]: openableKey,
|
|
42
|
-
[DATA_OPENABLE_ROLE]: OpenAble.ModalTrigger,
|
|
43
|
-
[DATA_POPUP_CTA]: callToAction,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
normalizeAnimation,
|
|
3
|
-
DATA_MOTION,
|
|
4
|
-
DATA_MOTION_HOVER,
|
|
5
|
-
DATA_MOTION_INVIEW,
|
|
6
|
-
DATA_MOTION_TAP,
|
|
7
|
-
AnimationConfig,
|
|
8
|
-
AosAnimationConfig,
|
|
9
|
-
HoverAnimationConfig,
|
|
10
|
-
OpenableAnimationConfig,
|
|
11
|
-
DATA_MOTION_OPENABLE,
|
|
12
|
-
normalizePopupAnimation,
|
|
13
|
-
normalizeAosAnimation,
|
|
14
|
-
} from "../motion";
|
|
15
|
-
import { DATA_MOTION_SELECTION, DATA_MOTION_FLIP } from "./tabs";
|
|
16
|
-
import { CSSProperties } from "react";
|
|
17
|
-
|
|
18
|
-
// 排除不能包含子元素的标签
|
|
19
|
-
export type ExcludedElements =
|
|
20
|
-
| "img"
|
|
21
|
-
| "input"
|
|
22
|
-
| "br"
|
|
23
|
-
| "hr"
|
|
24
|
-
| "area"
|
|
25
|
-
| "base"
|
|
26
|
-
| "col"
|
|
27
|
-
| "embed"
|
|
28
|
-
| "link"
|
|
29
|
-
| "meta"
|
|
30
|
-
| "param"
|
|
31
|
-
| "source"
|
|
32
|
-
| "track"
|
|
33
|
-
| "wbr";
|
|
34
|
-
|
|
35
|
-
export type HTMLElementsWithChildren = Exclude<
|
|
36
|
-
keyof HTMLElementTagNameMap,
|
|
37
|
-
ExcludedElements
|
|
38
|
-
>;
|
|
39
|
-
|
|
40
|
-
// CSS 属性的单位处理映射
|
|
41
|
-
export const cssPropertyUnits = {
|
|
42
|
-
// 无单位的属性
|
|
43
|
-
opacity: "",
|
|
44
|
-
scale: "",
|
|
45
|
-
fontWeight: "",
|
|
46
|
-
lineHeight: "",
|
|
47
|
-
zIndex: "",
|
|
48
|
-
flex: "",
|
|
49
|
-
flexGrow: "",
|
|
50
|
-
flexShrink: "",
|
|
51
|
-
order: "",
|
|
52
|
-
// 使用px的属性
|
|
53
|
-
width: "px",
|
|
54
|
-
height: "px",
|
|
55
|
-
minWidth: "px",
|
|
56
|
-
minHeight: "px",
|
|
57
|
-
maxWidth: "px",
|
|
58
|
-
maxHeight: "px",
|
|
59
|
-
padding: "px",
|
|
60
|
-
margin: "px",
|
|
61
|
-
top: "px",
|
|
62
|
-
right: "px",
|
|
63
|
-
bottom: "px",
|
|
64
|
-
left: "px",
|
|
65
|
-
gap: "px",
|
|
66
|
-
columnGap: "px",
|
|
67
|
-
rowGap: "px",
|
|
68
|
-
// transform 相关的属性
|
|
69
|
-
x: "transform",
|
|
70
|
-
y: "transform",
|
|
71
|
-
z: "transform",
|
|
72
|
-
} as const;
|
|
73
|
-
|
|
74
|
-
export interface IMotionProps {
|
|
75
|
-
animate?: AnimationConfig | string;
|
|
76
|
-
whileHover?: HoverAnimationConfig | string;
|
|
77
|
-
whileInView?: AosAnimationConfig | string;
|
|
78
|
-
whileTap?: AnimationConfig | string;
|
|
79
|
-
whileOpenable?: OpenableAnimationConfig | string;
|
|
80
|
-
whileSelection?: AnimationConfig | string;
|
|
81
|
-
// 在flip的父元素中使用
|
|
82
|
-
flipTransition?: AnimationConfig | string;
|
|
83
|
-
class?: string;
|
|
84
|
-
style?: CSSProperties;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface MotionAttributes {
|
|
88
|
-
className?: string;
|
|
89
|
-
style?: CSSProperties;
|
|
90
|
-
class?: string;
|
|
91
|
-
[DATA_MOTION]?: string;
|
|
92
|
-
[DATA_MOTION_HOVER]?: string;
|
|
93
|
-
[DATA_MOTION_INVIEW]?: string;
|
|
94
|
-
[DATA_MOTION_TAP]?: string;
|
|
95
|
-
[DATA_MOTION_OPENABLE]?: string;
|
|
96
|
-
[DATA_MOTION_SELECTION]?: string;
|
|
97
|
-
[DATA_MOTION_FLIP]?: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function getMotionProps(props: IMotionProps): MotionAttributes {
|
|
101
|
-
const {
|
|
102
|
-
animate,
|
|
103
|
-
whileHover,
|
|
104
|
-
whileInView,
|
|
105
|
-
whileTap,
|
|
106
|
-
whileOpenable,
|
|
107
|
-
whileSelection,
|
|
108
|
-
flipTransition,
|
|
109
|
-
class: className,
|
|
110
|
-
style,
|
|
111
|
-
...rest
|
|
112
|
-
} = props;
|
|
113
|
-
const normalizedAnimate = normalizeAnimation(animate);
|
|
114
|
-
const normalizedWhileHover = normalizeAnimation(whileHover);
|
|
115
|
-
const normalizedWhileInView = normalizeAosAnimation(whileInView);
|
|
116
|
-
const normalizedWhileTap = normalizeAnimation(whileTap);
|
|
117
|
-
const normalizedWhilePopup = normalizePopupAnimation(whileOpenable);
|
|
118
|
-
const normalizedWhileSelection = normalizeAnimation(whileSelection);
|
|
119
|
-
|
|
120
|
-
const dataWhileHover = JSON.stringify(normalizedWhileHover);
|
|
121
|
-
const dataWhileInView = JSON.stringify(normalizedWhileInView);
|
|
122
|
-
const dataWhileTap = JSON.stringify(normalizedWhileTap);
|
|
123
|
-
const dataWhilePopup = JSON.stringify(normalizedWhilePopup);
|
|
124
|
-
const dataWhileSelection = JSON.stringify(normalizedWhileSelection);
|
|
125
|
-
const motions: Record<string, string> = {
|
|
126
|
-
[DATA_MOTION_HOVER]: dataWhileHover,
|
|
127
|
-
[DATA_MOTION_INVIEW]: dataWhileInView,
|
|
128
|
-
[DATA_MOTION_TAP]: dataWhileTap,
|
|
129
|
-
[DATA_MOTION_OPENABLE]: dataWhilePopup,
|
|
130
|
-
[DATA_MOTION_SELECTION]: dataWhileSelection,
|
|
131
|
-
[DATA_MOTION_FLIP]: JSON.stringify(flipTransition),
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
if (Object.keys(normalizedAnimate || {}).length > 0) {
|
|
135
|
-
motions[DATA_MOTION] = JSON.stringify(normalizedAnimate);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const newClassName = className || "";
|
|
139
|
-
const newProps = { ...motions, ...rest };
|
|
140
|
-
const mergedStyle = { ...style };
|
|
141
|
-
|
|
142
|
-
if (normalizedAnimate?.initial) {
|
|
143
|
-
// 处理特殊的transform属性 (x, y, z, rotation, scale等)
|
|
144
|
-
// 这些属性需要转换为CSS的transform属性
|
|
145
|
-
|
|
146
|
-
// 处理标准CSS属性
|
|
147
|
-
if (normalizedAnimate.initial.opacity !== undefined)
|
|
148
|
-
mergedStyle.opacity = String(normalizedAnimate.initial.opacity);
|
|
149
|
-
if (normalizedAnimate.initial.backgroundColor !== undefined)
|
|
150
|
-
mergedStyle.backgroundColor = normalizedAnimate.initial.backgroundColor;
|
|
151
|
-
if (normalizedAnimate.initial.color !== undefined)
|
|
152
|
-
mergedStyle.color = normalizedAnimate.initial.color;
|
|
153
|
-
if (normalizedAnimate.initial.width !== undefined) {
|
|
154
|
-
mergedStyle.width =
|
|
155
|
-
typeof normalizedAnimate.initial.width === "number"
|
|
156
|
-
? `${normalizedAnimate.initial.width}px`
|
|
157
|
-
: normalizedAnimate.initial.width;
|
|
158
|
-
}
|
|
159
|
-
if (normalizedAnimate.initial.height !== undefined) {
|
|
160
|
-
mergedStyle.height =
|
|
161
|
-
typeof normalizedAnimate.initial.height === "number"
|
|
162
|
-
? `${normalizedAnimate.initial.height}px`
|
|
163
|
-
: normalizedAnimate.initial.height;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// 处理transformOrigin
|
|
167
|
-
if (normalizedAnimate.initial.transformOrigin !== undefined) {
|
|
168
|
-
mergedStyle.transformOrigin = normalizedAnimate.initial.transformOrigin;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// 处理transform属性
|
|
172
|
-
const transforms: string[] = [];
|
|
173
|
-
|
|
174
|
-
// 注意:对于x和y,我们使用translateX和translateY,但要确保单位是正确的
|
|
175
|
-
if (normalizedAnimate.initial.x !== undefined) {
|
|
176
|
-
const value =
|
|
177
|
-
typeof normalizedAnimate.initial.x === "number"
|
|
178
|
-
? `${normalizedAnimate.initial.x}px`
|
|
179
|
-
: normalizedAnimate.initial.x;
|
|
180
|
-
transforms.push(`translateX(${value})`);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (normalizedAnimate.initial.y !== undefined) {
|
|
184
|
-
const value =
|
|
185
|
-
typeof normalizedAnimate.initial.y === "number"
|
|
186
|
-
? `${normalizedAnimate.initial.y}px`
|
|
187
|
-
: normalizedAnimate.initial.y;
|
|
188
|
-
transforms.push(`translateY(${value})`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (normalizedAnimate.initial.z !== undefined) {
|
|
192
|
-
const value =
|
|
193
|
-
typeof normalizedAnimate.initial.z === "number"
|
|
194
|
-
? `${normalizedAnimate.initial.z}px`
|
|
195
|
-
: normalizedAnimate.initial.z;
|
|
196
|
-
transforms.push(`translateZ(${value})`);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// 处理旋转
|
|
200
|
-
if (normalizedAnimate.initial.rotation !== undefined) {
|
|
201
|
-
transforms.push(`rotate(${normalizedAnimate.initial.rotation}deg)`);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (normalizedAnimate.initial.rotationX !== undefined) {
|
|
205
|
-
transforms.push(`rotateX(${normalizedAnimate.initial.rotationX}deg)`);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (normalizedAnimate.initial.rotationY !== undefined) {
|
|
209
|
-
transforms.push(`rotateY(${normalizedAnimate.initial.rotationY}deg)`);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (normalizedAnimate.initial.rotationZ !== undefined) {
|
|
213
|
-
transforms.push(`rotateZ(${normalizedAnimate.initial.rotationZ}deg)`);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 处理缩放
|
|
217
|
-
if (normalizedAnimate.initial.scale !== undefined) {
|
|
218
|
-
transforms.push(`scale(${normalizedAnimate.initial.scale})`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (normalizedAnimate.initial.scaleX !== undefined) {
|
|
222
|
-
transforms.push(`scaleX(${normalizedAnimate.initial.scaleX})`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (normalizedAnimate.initial.scaleY !== undefined) {
|
|
226
|
-
transforms.push(`scaleY(${normalizedAnimate.initial.scaleY})`);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// 如果有transform属性,合并它们
|
|
230
|
-
if (transforms.length > 0) {
|
|
231
|
-
mergedStyle.transform = transforms.join(" ");
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// 处理其他属性
|
|
235
|
-
const handledProps = [
|
|
236
|
-
"opacity",
|
|
237
|
-
"backgroundColor",
|
|
238
|
-
"color",
|
|
239
|
-
"width",
|
|
240
|
-
"height",
|
|
241
|
-
"transformOrigin",
|
|
242
|
-
"x",
|
|
243
|
-
"y",
|
|
244
|
-
"z",
|
|
245
|
-
"rotation",
|
|
246
|
-
"rotationX",
|
|
247
|
-
"rotationY",
|
|
248
|
-
"rotationZ",
|
|
249
|
-
"scale",
|
|
250
|
-
"scaleX",
|
|
251
|
-
"scaleY",
|
|
252
|
-
];
|
|
253
|
-
|
|
254
|
-
// 复制其他没有特殊处理的属性
|
|
255
|
-
for (const key in normalizedAnimate.initial) {
|
|
256
|
-
if (!handledProps.includes(key)) {
|
|
257
|
-
// @ts-expect-error - 允许动态属性赋值
|
|
258
|
-
mergedStyle[key] = normalizedAnimate.initial[key];
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// 将 styleProp 的定义移到条件块外部,确保它始终被定义
|
|
264
|
-
const styleProp =
|
|
265
|
-
Object.keys(mergedStyle).length > 0
|
|
266
|
-
? {
|
|
267
|
-
style: mergedStyle,
|
|
268
|
-
}
|
|
269
|
-
: undefined;
|
|
270
|
-
|
|
271
|
-
return { ...newProps, ...styleProp, class: newClassName };
|
|
272
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { DATA_MOTION_NUMBER, DATA_MOTION_NUMBER_ONCE } from "../motion/consts";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Animation options for GSAP animations
|
|
5
|
-
*/
|
|
6
|
-
export interface AnimationOptions {
|
|
7
|
-
/** Animation duration in seconds */
|
|
8
|
-
duration?: number;
|
|
9
|
-
/** GSAP easing function (e.g., "power1.out", "power2.in", "elastic.out") */
|
|
10
|
-
ease?: string;
|
|
11
|
-
/** Delay before animation starts in seconds */
|
|
12
|
-
delay?: number;
|
|
13
|
-
/** Repeat count (-1 for infinite) */
|
|
14
|
-
repeat?: number;
|
|
15
|
-
/** Whether to yoyo the animation (play in reverse after completion) */
|
|
16
|
-
yoyo?: boolean;
|
|
17
|
-
/** Stagger value for multiple animations */
|
|
18
|
-
stagger?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface AnimationNumberProps {
|
|
22
|
-
start?: number;
|
|
23
|
-
end?: number;
|
|
24
|
-
transition?: AnimationOptions;
|
|
25
|
-
class?: string;
|
|
26
|
-
sign?: string;
|
|
27
|
-
once?: boolean;
|
|
28
|
-
type?: "int" | "float" | "percentage" | "currency";
|
|
29
|
-
fractionDigits?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function getAnimationNumberDataAttrs(props: AnimationNumberProps) {
|
|
33
|
-
const { start, end, transition, type, fractionDigits } = props;
|
|
34
|
-
const motionValue = {
|
|
35
|
-
start,
|
|
36
|
-
end,
|
|
37
|
-
transition,
|
|
38
|
-
type,
|
|
39
|
-
fractionDigits,
|
|
40
|
-
};
|
|
41
|
-
return {
|
|
42
|
-
[DATA_MOTION_NUMBER]: JSON.stringify(motionValue),
|
|
43
|
-
[DATA_MOTION_NUMBER_ONCE]: props.once,
|
|
44
|
-
};
|
|
45
|
-
}
|