@unif/react-native-design 0.31.1 → 0.31.2
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/lib/module/components/ui/BorderBeam/BorderBeam.js +6 -4
- package/lib/module/components/ui/BorderBeam/BorderBeam.js.map +1 -1
- package/lib/module/components/ui/BorderBeam/BorderBeam.web.js +19 -11
- package/lib/module/components/ui/BorderBeam/BorderBeam.web.js.map +1 -1
- package/lib/module/components/ui/BorderBeam/shared.js +30 -0
- package/lib/module/components/ui/BorderBeam/shared.js.map +1 -1
- package/lib/typescript/src/components/ui/BorderBeam/BorderBeam.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/BorderBeam/BorderBeam.web.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/BorderBeam/shared.d.ts +10 -0
- package/lib/typescript/src/components/ui/BorderBeam/shared.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/BorderBeam/BorderBeam.tsx +27 -18
- package/src/components/ui/BorderBeam/BorderBeam.web.tsx +42 -27
- package/src/components/ui/BorderBeam/shared.ts +21 -0
|
@@ -7,7 +7,7 @@ import Svg, { Rect } from 'react-native-svg';
|
|
|
7
7
|
import { radius, useColors, usePrefersReducedMotion } from "../../../theme/index.js";
|
|
8
8
|
import { A11Y_HIDDEN_PROPS } from "../shared/a11y.js";
|
|
9
9
|
import { normalizeBorderBeam } from "./normalizeBorderBeam.js";
|
|
10
|
-
import { borderBeamGeometry, EMPTY_BORDER_BEAM_LAYOUT } from "./shared.js";
|
|
10
|
+
import { borderBeamGeometry, borderBeamTrail, EMPTY_BORDER_BEAM_LAYOUT } from "./shared.js";
|
|
11
11
|
import { styles } from "./styles.js";
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
@@ -42,6 +42,7 @@ export function BorderBeam({
|
|
|
42
42
|
layout,
|
|
43
43
|
...normalized
|
|
44
44
|
});
|
|
45
|
+
const trail = borderBeamTrail(geometry.beamLength);
|
|
45
46
|
const dashOffset = useSharedValue(0);
|
|
46
47
|
const showVisual = active && !reducedMotion && geometry.perimeter > 0;
|
|
47
48
|
useEffect(() => {
|
|
@@ -79,7 +80,7 @@ export function BorderBeam({
|
|
|
79
80
|
children: /*#__PURE__*/_jsx(Svg, {
|
|
80
81
|
width: layout.width,
|
|
81
82
|
height: layout.height,
|
|
82
|
-
children: /*#__PURE__*/_jsx(AnimatedRect, {
|
|
83
|
+
children: trail.map(layer => /*#__PURE__*/_jsx(AnimatedRect, {
|
|
83
84
|
animatedProps: animatedProps,
|
|
84
85
|
x: normalized.lineWidth / 2,
|
|
85
86
|
y: normalized.lineWidth / 2,
|
|
@@ -89,10 +90,11 @@ export function BorderBeam({
|
|
|
89
90
|
ry: geometry.radius,
|
|
90
91
|
fill: "none",
|
|
91
92
|
stroke: color ?? colors.primary,
|
|
93
|
+
strokeOpacity: layer.opacity,
|
|
92
94
|
strokeWidth: normalized.lineWidth,
|
|
93
95
|
strokeLinecap: "round",
|
|
94
|
-
strokeDasharray: [
|
|
95
|
-
})
|
|
96
|
+
strokeDasharray: [layer.length, Math.max(0, geometry.perimeter - layer.length)]
|
|
97
|
+
}, `${layer.length}-${layer.opacity}`))
|
|
96
98
|
})
|
|
97
99
|
}) : null]
|
|
98
100
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useState","View","Animated","cancelAnimation","Easing","ReduceMotion","useAnimatedProps","useSharedValue","withRepeat","withTiming","Svg","Rect","radius","useColors","usePrefersReducedMotion","A11Y_HIDDEN_PROPS","normalizeBorderBeam","borderBeamGeometry","EMPTY_BORDER_BEAM_LAYOUT","styles","jsx","_jsx","jsxs","_jsxs","AnimatedRect","createAnimatedComponent","BorderBeam","children","active","color","duration","lineWidth","size","borderRadius","md","style","testID","colors","reducedMotion","layout","setLayout","normalized","geometry","dashOffset","showVisual","perimeter","value","easing","linear","reduceMotion","System","undefined","animatedProps","strokeDashoffset","handleLayout","event","width","Math","max","nativeEvent","height","current","onLayout","container","pointerEvents","visual","x","y","rectWidth","rectHeight","rx","ry","fill","stroke","primary","strokeWidth","strokeLinecap","strokeDasharray","
|
|
1
|
+
{"version":3,"names":["React","useEffect","useState","View","Animated","cancelAnimation","Easing","ReduceMotion","useAnimatedProps","useSharedValue","withRepeat","withTiming","Svg","Rect","radius","useColors","usePrefersReducedMotion","A11Y_HIDDEN_PROPS","normalizeBorderBeam","borderBeamGeometry","borderBeamTrail","EMPTY_BORDER_BEAM_LAYOUT","styles","jsx","_jsx","jsxs","_jsxs","AnimatedRect","createAnimatedComponent","BorderBeam","children","active","color","duration","lineWidth","size","borderRadius","md","style","testID","colors","reducedMotion","layout","setLayout","normalized","geometry","trail","beamLength","dashOffset","showVisual","perimeter","value","easing","linear","reduceMotion","System","undefined","animatedProps","strokeDashoffset","handleLayout","event","width","Math","max","nativeEvent","height","current","onLayout","container","pointerEvents","visual","map","layer","x","y","rectWidth","rectHeight","rx","ry","fill","stroke","primary","strokeOpacity","opacity","strokeWidth","strokeLinecap","strokeDasharray","length"],"sourceRoot":"../../../../../src","sources":["components/ui/BorderBeam/BorderBeam.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -6,7 +6,7 @@ import Svg, { Rect } from 'react-native-svg';
|
|
|
6
6
|
import { radius, useColors, usePrefersReducedMotion } from "../../../theme/index.js";
|
|
7
7
|
import { A11Y_HIDDEN_PROPS } from "../shared/a11y.js";
|
|
8
8
|
import { normalizeBorderBeam } from "./normalizeBorderBeam.js";
|
|
9
|
-
import { borderBeamGeometry, EMPTY_BORDER_BEAM_LAYOUT } from "./shared.js";
|
|
9
|
+
import { borderBeamGeometry, borderBeamTrail, EMPTY_BORDER_BEAM_LAYOUT } from "./shared.js";
|
|
10
10
|
import { styles } from "./styles.js";
|
|
11
11
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
const KEYFRAMES_ID = 'unif-border-beam-keyframes';
|
|
@@ -35,7 +35,7 @@ export function BorderBeam({
|
|
|
35
35
|
const colors = useColors();
|
|
36
36
|
const reducedMotion = usePrefersReducedMotion();
|
|
37
37
|
const [layout, setLayout] = useState(EMPTY_BORDER_BEAM_LAYOUT);
|
|
38
|
-
const
|
|
38
|
+
const rectRefs = useRef([]);
|
|
39
39
|
const normalized = normalizeBorderBeam({
|
|
40
40
|
duration,
|
|
41
41
|
lineWidth,
|
|
@@ -46,16 +46,21 @@ export function BorderBeam({
|
|
|
46
46
|
layout,
|
|
47
47
|
...normalized
|
|
48
48
|
});
|
|
49
|
+
const trail = borderBeamTrail(geometry.beamLength);
|
|
49
50
|
const showVisual = active && !reducedMotion && geometry.perimeter > 0;
|
|
50
51
|
useEffect(() => {
|
|
51
52
|
if (!showVisual) return;
|
|
52
53
|
ensureKeyframes();
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
const nodes = rectRefs.current.filter(node => node?.style);
|
|
55
|
+
if (nodes.length === 0) return;
|
|
56
|
+
nodes.forEach(node => {
|
|
57
|
+
node.style.setProperty('--unif-border-beam-path', `${geometry.perimeter}px`);
|
|
58
|
+
node.style.animation = `unif-border-beam-flow ${normalized.duration}ms linear infinite`;
|
|
59
|
+
});
|
|
57
60
|
return () => {
|
|
58
|
-
node
|
|
61
|
+
nodes.forEach(node => {
|
|
62
|
+
node.style.animation = '';
|
|
63
|
+
});
|
|
59
64
|
};
|
|
60
65
|
}, [geometry.perimeter, normalized.duration, showVisual]);
|
|
61
66
|
const handleLayout = event => {
|
|
@@ -79,8 +84,10 @@ export function BorderBeam({
|
|
|
79
84
|
children: /*#__PURE__*/_jsx(Svg, {
|
|
80
85
|
width: layout.width,
|
|
81
86
|
height: layout.height,
|
|
82
|
-
children: /*#__PURE__*/_jsx(Rect, {
|
|
83
|
-
ref:
|
|
87
|
+
children: trail.map((layer, index) => /*#__PURE__*/_jsx(Rect, {
|
|
88
|
+
ref: node => {
|
|
89
|
+
rectRefs.current[index] = node;
|
|
90
|
+
},
|
|
84
91
|
x: normalized.lineWidth / 2,
|
|
85
92
|
y: normalized.lineWidth / 2,
|
|
86
93
|
width: geometry.rectWidth,
|
|
@@ -89,10 +96,11 @@ export function BorderBeam({
|
|
|
89
96
|
ry: geometry.radius,
|
|
90
97
|
fill: "none",
|
|
91
98
|
stroke: color ?? colors.primary,
|
|
99
|
+
strokeOpacity: layer.opacity,
|
|
92
100
|
strokeWidth: normalized.lineWidth,
|
|
93
101
|
strokeLinecap: "round",
|
|
94
|
-
strokeDasharray: [
|
|
95
|
-
})
|
|
102
|
+
strokeDasharray: [layer.length, Math.max(0, geometry.perimeter - layer.length)]
|
|
103
|
+
}, `${layer.length}-${layer.opacity}`))
|
|
96
104
|
})
|
|
97
105
|
}) : null]
|
|
98
106
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useRef","useState","View","Svg","Rect","radius","useColors","usePrefersReducedMotion","A11Y_HIDDEN_PROPS","normalizeBorderBeam","borderBeamGeometry","EMPTY_BORDER_BEAM_LAYOUT","styles","jsx","_jsx","jsxs","_jsxs","KEYFRAMES_ID","win","globalThis","ensureKeyframes","document","getElementById","sheet","createElement","id","textContent","head","appendChild","BorderBeam","children","active","color","duration","lineWidth","size","borderRadius","md","style","testID","colors","reducedMotion","layout","setLayout","
|
|
1
|
+
{"version":3,"names":["React","useEffect","useRef","useState","View","Svg","Rect","radius","useColors","usePrefersReducedMotion","A11Y_HIDDEN_PROPS","normalizeBorderBeam","borderBeamGeometry","borderBeamTrail","EMPTY_BORDER_BEAM_LAYOUT","styles","jsx","_jsx","jsxs","_jsxs","KEYFRAMES_ID","win","globalThis","ensureKeyframes","document","getElementById","sheet","createElement","id","textContent","head","appendChild","BorderBeam","children","active","color","duration","lineWidth","size","borderRadius","md","style","testID","colors","reducedMotion","layout","setLayout","rectRefs","normalized","geometry","trail","beamLength","showVisual","perimeter","nodes","current","filter","node","length","forEach","setProperty","animation","handleLayout","event","width","Math","max","nativeEvent","height","onLayout","container","pointerEvents","visual","map","layer","index","ref","x","y","rectWidth","rectHeight","rx","ry","fill","stroke","primary","strokeOpacity","opacity","strokeWidth","strokeLinecap","strokeDasharray"],"sourceRoot":"../../../../../src","sources":["components/ui/BorderBeam/BorderBeam.web.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,6 +4,36 @@ export const EMPTY_BORDER_BEAM_LAYOUT = {
|
|
|
4
4
|
width: 0,
|
|
5
5
|
height: 0
|
|
6
6
|
};
|
|
7
|
+
const BORDER_BEAM_TRAIL = [{
|
|
8
|
+
lengthRatio: 1,
|
|
9
|
+
opacity: 0.12
|
|
10
|
+
}, {
|
|
11
|
+
lengthRatio: 0.75,
|
|
12
|
+
opacity: 0.24
|
|
13
|
+
}, {
|
|
14
|
+
lengthRatio: 0.5,
|
|
15
|
+
opacity: 0.42
|
|
16
|
+
}, {
|
|
17
|
+
lengthRatio: 0.25,
|
|
18
|
+
opacity: 0.88
|
|
19
|
+
}];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 把单色线段拆成由淡到亮的叠加尾迹。
|
|
23
|
+
*
|
|
24
|
+
* 所有层共享同一动画相位,较短且更亮的层叠在前端,形成接近渐变的彗星头;
|
|
25
|
+
* 同时避免 SVG gradient 在 Native/Web 上的实现差异。
|
|
26
|
+
*/
|
|
27
|
+
export function borderBeamTrail(beamLength) {
|
|
28
|
+
const safeLength = Math.max(0, beamLength);
|
|
29
|
+
return BORDER_BEAM_TRAIL.map(({
|
|
30
|
+
lengthRatio,
|
|
31
|
+
opacity
|
|
32
|
+
}) => ({
|
|
33
|
+
length: safeLength * lengthRatio,
|
|
34
|
+
opacity
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
7
37
|
export function borderBeamGeometry(input) {
|
|
8
38
|
const {
|
|
9
39
|
layout,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["EMPTY_BORDER_BEAM_LAYOUT","width","height","
|
|
1
|
+
{"version":3,"names":["EMPTY_BORDER_BEAM_LAYOUT","width","height","BORDER_BEAM_TRAIL","lengthRatio","opacity","borderBeamTrail","beamLength","safeLength","Math","max","map","length","borderBeamGeometry","input","layout","lineWidth","rectWidth","rectHeight","perimeter","min","size","radius","borderRadius"],"sourceRoot":"../../../../../src","sources":["components/ui/BorderBeam/shared.ts"],"mappings":";;AAEA,OAAO,MAAMA,wBAA0C,GAAG;EACxDC,KAAK,EAAE,CAAC;EACRC,MAAM,EAAE;AACV,CAAC;AAED,MAAMC,iBAAiB,GAAG,CACxB;EAAEC,WAAW,EAAE,CAAC;EAAEC,OAAO,EAAE;AAAK,CAAC,EACjC;EAAED,WAAW,EAAE,IAAI;EAAEC,OAAO,EAAE;AAAK,CAAC,EACpC;EAAED,WAAW,EAAE,GAAG;EAAEC,OAAO,EAAE;AAAK,CAAC,EACnC;EAAED,WAAW,EAAE,IAAI;EAAEC,OAAO,EAAE;AAAK,CAAC,CAC5B;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAACC,UAAkB,EAAE;EAClD,MAAMC,UAAU,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEH,UAAU,CAAC;EAC1C,OAAOJ,iBAAiB,CAACQ,GAAG,CAAC,CAAC;IAAEP,WAAW;IAAEC;EAAQ,CAAC,MAAM;IAC1DO,MAAM,EAAEJ,UAAU,GAAGJ,WAAW;IAChCC;EACF,CAAC,CAAC,CAAC;AACL;AAEA,OAAO,SAASQ,kBAAkBA,CAACC,KAKlC,EAAE;EACD,MAAM;IAAEC,MAAM;IAAEC;EAAU,CAAC,GAAGF,KAAK;EACnC,MAAMG,SAAS,GAAGR,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEK,MAAM,CAACd,KAAK,GAAGe,SAAS,CAAC;EACvD,MAAME,UAAU,GAAGT,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEK,MAAM,CAACb,MAAM,GAAGc,SAAS,CAAC;EACzD,MAAMG,SAAS,GAAGV,IAAI,CAACC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAIO,SAAS,GAAGC,UAAU,CAAC,CAAC;EAC3D,MAAMX,UAAU,GAAGE,IAAI,CAACW,GAAG,CAACN,KAAK,CAACO,IAAI,EAAEF,SAAS,GAAG,CAAC,CAAC;EACtD,OAAO;IACLZ,UAAU;IACVY,SAAS;IACTD,UAAU;IACVD,SAAS;IACTK,MAAM,EAAEb,IAAI,CAACW,GAAG,CAACN,KAAK,CAACS,YAAY,EAAEN,SAAS,GAAG,CAAC,EAAEC,UAAU,GAAG,CAAC;EACpE,CAAC;AACH","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BorderBeam.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/BorderBeam.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"BorderBeam.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/BorderBeam.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAuBnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI/C;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,MAAa,EACb,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,YAAwB,EACxB,KAAK,EACL,MAAM,GACP,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAsFrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BorderBeam.web.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/BorderBeam.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"BorderBeam.web.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/BorderBeam.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAc3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAe/C,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,MAAa,EACb,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,YAAwB,EACxB,KAAK,EACL,MAAM,GACP,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAsFrC"}
|
|
@@ -3,6 +3,16 @@ export type BorderBeamLayout = Readonly<{
|
|
|
3
3
|
height: number;
|
|
4
4
|
}>;
|
|
5
5
|
export declare const EMPTY_BORDER_BEAM_LAYOUT: BorderBeamLayout;
|
|
6
|
+
/**
|
|
7
|
+
* 把单色线段拆成由淡到亮的叠加尾迹。
|
|
8
|
+
*
|
|
9
|
+
* 所有层共享同一动画相位,较短且更亮的层叠在前端,形成接近渐变的彗星头;
|
|
10
|
+
* 同时避免 SVG gradient 在 Native/Web 上的实现差异。
|
|
11
|
+
*/
|
|
12
|
+
export declare function borderBeamTrail(beamLength: number): {
|
|
13
|
+
length: number;
|
|
14
|
+
opacity: 0.12 | 0.24 | 0.42 | 0.88;
|
|
15
|
+
}[];
|
|
6
16
|
export declare function borderBeamGeometry(input: {
|
|
7
17
|
layout: BorderBeamLayout;
|
|
8
18
|
lineWidth: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/shared.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3E,eAAO,MAAM,wBAAwB,EAAE,gBAGtC,CAAC;
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BorderBeam/shared.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3E,eAAO,MAAM,wBAAwB,EAAE,gBAGtC,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM;;;IAMjD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;;;;;;EAaA"}
|
package/package.json
CHANGED
|
@@ -15,7 +15,11 @@ import Svg, { Rect } from 'react-native-svg';
|
|
|
15
15
|
import { radius, useColors, usePrefersReducedMotion } from '../../../theme';
|
|
16
16
|
import { A11Y_HIDDEN_PROPS } from '../shared/a11y';
|
|
17
17
|
import { normalizeBorderBeam } from './normalizeBorderBeam';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
borderBeamGeometry,
|
|
20
|
+
borderBeamTrail,
|
|
21
|
+
EMPTY_BORDER_BEAM_LAYOUT,
|
|
22
|
+
} from './shared';
|
|
19
23
|
import { styles } from './styles';
|
|
20
24
|
import type { BorderBeamProps } from './types';
|
|
21
25
|
|
|
@@ -48,6 +52,7 @@ export function BorderBeam({
|
|
|
48
52
|
borderRadius,
|
|
49
53
|
});
|
|
50
54
|
const geometry = borderBeamGeometry({ layout, ...normalized });
|
|
55
|
+
const trail = borderBeamTrail(geometry.beamLength);
|
|
51
56
|
const dashOffset = useSharedValue(0);
|
|
52
57
|
const showVisual = active && !reducedMotion && geometry.perimeter > 0;
|
|
53
58
|
|
|
@@ -96,23 +101,27 @@ export function BorderBeam({
|
|
|
96
101
|
{showVisual ? (
|
|
97
102
|
<View pointerEvents="none" style={styles.visual} {...A11Y_HIDDEN_PROPS}>
|
|
98
103
|
<Svg width={layout.width} height={layout.height}>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
{trail.map((layer) => (
|
|
105
|
+
<AnimatedRect
|
|
106
|
+
key={`${layer.length}-${layer.opacity}`}
|
|
107
|
+
animatedProps={animatedProps}
|
|
108
|
+
x={normalized.lineWidth / 2}
|
|
109
|
+
y={normalized.lineWidth / 2}
|
|
110
|
+
width={geometry.rectWidth}
|
|
111
|
+
height={geometry.rectHeight}
|
|
112
|
+
rx={geometry.radius}
|
|
113
|
+
ry={geometry.radius}
|
|
114
|
+
fill="none"
|
|
115
|
+
stroke={color ?? colors.primary}
|
|
116
|
+
strokeOpacity={layer.opacity}
|
|
117
|
+
strokeWidth={normalized.lineWidth}
|
|
118
|
+
strokeLinecap="round"
|
|
119
|
+
strokeDasharray={[
|
|
120
|
+
layer.length,
|
|
121
|
+
Math.max(0, geometry.perimeter - layer.length),
|
|
122
|
+
]}
|
|
123
|
+
/>
|
|
124
|
+
))}
|
|
116
125
|
</Svg>
|
|
117
126
|
</View>
|
|
118
127
|
) : null}
|
|
@@ -6,7 +6,11 @@ import Svg, { Rect } from 'react-native-svg';
|
|
|
6
6
|
import { radius, useColors, usePrefersReducedMotion } from '../../../theme';
|
|
7
7
|
import { A11Y_HIDDEN_PROPS } from '../shared/a11y';
|
|
8
8
|
import { normalizeBorderBeam } from './normalizeBorderBeam';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
borderBeamGeometry,
|
|
11
|
+
borderBeamTrail,
|
|
12
|
+
EMPTY_BORDER_BEAM_LAYOUT,
|
|
13
|
+
} from './shared';
|
|
10
14
|
import { styles } from './styles';
|
|
11
15
|
import type { BorderBeamProps } from './types';
|
|
12
16
|
|
|
@@ -38,7 +42,7 @@ export function BorderBeam({
|
|
|
38
42
|
const colors = useColors();
|
|
39
43
|
const reducedMotion = usePrefersReducedMotion();
|
|
40
44
|
const [layout, setLayout] = useState(EMPTY_BORDER_BEAM_LAYOUT);
|
|
41
|
-
const
|
|
45
|
+
const rectRefs = useRef<any[]>([]);
|
|
42
46
|
const normalized = normalizeBorderBeam({
|
|
43
47
|
duration,
|
|
44
48
|
lineWidth,
|
|
@@ -46,20 +50,25 @@ export function BorderBeam({
|
|
|
46
50
|
borderRadius,
|
|
47
51
|
});
|
|
48
52
|
const geometry = borderBeamGeometry({ layout, ...normalized });
|
|
53
|
+
const trail = borderBeamTrail(geometry.beamLength);
|
|
49
54
|
const showVisual = active && !reducedMotion && geometry.perimeter > 0;
|
|
50
55
|
|
|
51
56
|
useEffect(() => {
|
|
52
57
|
if (!showVisual) return;
|
|
53
58
|
ensureKeyframes();
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const nodes = rectRefs.current.filter((node) => node?.style);
|
|
60
|
+
if (nodes.length === 0) return;
|
|
61
|
+
nodes.forEach((node) => {
|
|
62
|
+
node.style.setProperty(
|
|
63
|
+
'--unif-border-beam-path',
|
|
64
|
+
`${geometry.perimeter}px`
|
|
65
|
+
);
|
|
66
|
+
node.style.animation = `unif-border-beam-flow ${normalized.duration}ms linear infinite`;
|
|
67
|
+
});
|
|
61
68
|
return () => {
|
|
62
|
-
node
|
|
69
|
+
nodes.forEach((node) => {
|
|
70
|
+
node.style.animation = '';
|
|
71
|
+
});
|
|
63
72
|
};
|
|
64
73
|
}, [geometry.perimeter, normalized.duration, showVisual]);
|
|
65
74
|
|
|
@@ -87,23 +96,29 @@ export function BorderBeam({
|
|
|
87
96
|
{showVisual ? (
|
|
88
97
|
<View pointerEvents="none" style={styles.visual} {...A11Y_HIDDEN_PROPS}>
|
|
89
98
|
<Svg width={layout.width} height={layout.height}>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
{trail.map((layer, index) => (
|
|
100
|
+
<Rect
|
|
101
|
+
key={`${layer.length}-${layer.opacity}`}
|
|
102
|
+
ref={(node) => {
|
|
103
|
+
rectRefs.current[index] = node;
|
|
104
|
+
}}
|
|
105
|
+
x={normalized.lineWidth / 2}
|
|
106
|
+
y={normalized.lineWidth / 2}
|
|
107
|
+
width={geometry.rectWidth}
|
|
108
|
+
height={geometry.rectHeight}
|
|
109
|
+
rx={geometry.radius}
|
|
110
|
+
ry={geometry.radius}
|
|
111
|
+
fill="none"
|
|
112
|
+
stroke={color ?? colors.primary}
|
|
113
|
+
strokeOpacity={layer.opacity}
|
|
114
|
+
strokeWidth={normalized.lineWidth}
|
|
115
|
+
strokeLinecap="round"
|
|
116
|
+
strokeDasharray={[
|
|
117
|
+
layer.length,
|
|
118
|
+
Math.max(0, geometry.perimeter - layer.length),
|
|
119
|
+
]}
|
|
120
|
+
/>
|
|
121
|
+
))}
|
|
107
122
|
</Svg>
|
|
108
123
|
</View>
|
|
109
124
|
) : null}
|
|
@@ -5,6 +5,27 @@ export const EMPTY_BORDER_BEAM_LAYOUT: BorderBeamLayout = {
|
|
|
5
5
|
height: 0,
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
const BORDER_BEAM_TRAIL = [
|
|
9
|
+
{ lengthRatio: 1, opacity: 0.12 },
|
|
10
|
+
{ lengthRatio: 0.75, opacity: 0.24 },
|
|
11
|
+
{ lengthRatio: 0.5, opacity: 0.42 },
|
|
12
|
+
{ lengthRatio: 0.25, opacity: 0.88 },
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 把单色线段拆成由淡到亮的叠加尾迹。
|
|
17
|
+
*
|
|
18
|
+
* 所有层共享同一动画相位,较短且更亮的层叠在前端,形成接近渐变的彗星头;
|
|
19
|
+
* 同时避免 SVG gradient 在 Native/Web 上的实现差异。
|
|
20
|
+
*/
|
|
21
|
+
export function borderBeamTrail(beamLength: number) {
|
|
22
|
+
const safeLength = Math.max(0, beamLength);
|
|
23
|
+
return BORDER_BEAM_TRAIL.map(({ lengthRatio, opacity }) => ({
|
|
24
|
+
length: safeLength * lengthRatio,
|
|
25
|
+
opacity,
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
|
|
8
29
|
export function borderBeamGeometry(input: {
|
|
9
30
|
layout: BorderBeamLayout;
|
|
10
31
|
lineWidth: number;
|