@windrun-huaiin/third-ui 29.2.1 → 30.1.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.
- package/dist/fuma/fuma-page-genarator.d.ts +2 -6
- package/dist/fuma/fuma-page-genarator.js +3 -2
- package/dist/fuma/fuma-page-genarator.mjs +3 -2
- package/dist/fuma/mdx/cheet-table.d.ts +13 -0
- package/dist/fuma/mdx/cheet-table.js +295 -0
- package/dist/fuma/mdx/cheet-table.mjs +293 -0
- package/dist/fuma/mdx/index.d.ts +1 -0
- package/dist/fuma/mdx/index.js +2 -0
- package/dist/fuma/mdx/index.mjs +1 -0
- package/dist/fuma/server/features/widgets.js +2 -0
- package/dist/fuma/server/features/widgets.mjs +2 -0
- package/dist/lib/fuma-schema-check-util.d.ts +1 -1
- package/dist/main/404-page.d.ts +12 -0
- package/dist/main/404-page.js +66 -0
- package/dist/main/404-page.mjs +64 -0
- package/dist/main/alert-dialog/confirm-dialog.js +1 -1
- package/dist/main/alert-dialog/confirm-dialog.mjs +2 -2
- package/dist/main/alert-dialog/dialog-loading-action.js +5 -2
- package/dist/main/alert-dialog/dialog-loading-action.mjs +5 -2
- package/dist/main/alert-dialog/dialog-styles.d.ts +4 -2
- package/dist/main/alert-dialog/dialog-styles.js +8 -4
- package/dist/main/alert-dialog/dialog-styles.mjs +7 -5
- package/dist/main/alert-dialog/high-priority-confirm-dialog.js +5 -5
- package/dist/main/alert-dialog/high-priority-confirm-dialog.mjs +6 -6
- package/dist/main/alert-dialog/info-dialog.js +1 -1
- package/dist/main/alert-dialog/info-dialog.mjs +2 -2
- package/dist/main/alert-dialog/undoable-confirm-dialog.js +2 -2
- package/dist/main/alert-dialog/undoable-confirm-dialog.mjs +3 -3
- package/dist/main/anime/anime-404-page.d.ts +14 -0
- package/dist/main/anime/anime-404-page.js +197 -0
- package/dist/main/anime/anime-404-page.mjs +195 -0
- package/dist/main/anime/anime-beam-frame.d.ts +3 -0
- package/dist/main/anime/anime-beam-frame.js +63 -0
- package/dist/main/anime/anime-beam-frame.mjs +61 -0
- package/dist/main/anime/anime-not-found-page.d.ts +7 -0
- package/dist/main/anime/anime-not-found-page.js +142 -0
- package/dist/main/anime/anime-not-found-page.mjs +140 -0
- package/dist/main/anime/anime-spiral-loading.d.ts +10 -0
- package/dist/main/anime/anime-spiral-loading.js +77 -0
- package/dist/main/anime/anime-spiral-loading.mjs +75 -0
- package/dist/main/anime/index.d.ts +3 -0
- package/dist/main/anime/index.js +12 -0
- package/dist/main/anime/index.mjs +4 -0
- package/dist/main/beam-frame/animate.d.ts +3 -0
- package/dist/main/beam-frame/animate.js +63 -0
- package/dist/main/beam-frame/animate.mjs +61 -0
- package/dist/main/beam-frame/beam-frame.d.ts +4 -0
- package/dist/main/beam-frame/beam-frame.js +262 -0
- package/dist/main/beam-frame/beam-frame.mjs +258 -0
- package/dist/main/beam-frame/index.d.ts +4 -0
- package/dist/main/beam-frame/index.js +11 -0
- package/dist/main/beam-frame/index.mjs +3 -0
- package/dist/main/beam-frame/motion.d.ts +3 -0
- package/dist/main/beam-frame/motion.js +61 -0
- package/dist/main/beam-frame/motion.mjs +59 -0
- package/dist/main/beam-frame/share-config.d.ts +54 -0
- package/dist/main/beam-frame/share-config.js +161 -0
- package/dist/main/beam-frame/share-config.mjs +152 -0
- package/dist/main/beam-frame-config.d.ts +54 -0
- package/dist/main/beam-frame-config.js +161 -0
- package/dist/main/beam-frame-config.mjs +152 -0
- package/dist/main/calendar/random-date-range-dialog.js +177 -51
- package/dist/main/calendar/random-date-range-dialog.mjs +178 -52
- package/dist/main/cta.js +17 -1
- package/dist/main/cta.mjs +18 -2
- package/dist/main/delayed-img.d.ts +1 -1
- package/dist/main/delayed-img.js +8 -5
- package/dist/main/delayed-img.mjs +8 -5
- package/dist/main/index.d.ts +1 -0
- package/dist/main/index.js +2 -0
- package/dist/main/index.mjs +1 -0
- package/dist/main/info-tooltip.js +70 -9
- package/dist/main/info-tooltip.mjs +70 -9
- package/dist/main/loading-frame/index.d.ts +1 -0
- package/dist/main/loading.d.ts +2 -1
- package/dist/main/loading.js +64 -26
- package/dist/main/loading.mjs +64 -26
- package/dist/main/motion/creative-left-panel.d.ts +7 -0
- package/dist/main/motion/creative-left-panel.js +11 -0
- package/dist/main/motion/creative-left-panel.mjs +9 -0
- package/dist/main/motion/creative-right-panel.d.ts +7 -0
- package/dist/main/motion/creative-right-panel.js +11 -0
- package/dist/main/motion/creative-right-panel.mjs +9 -0
- package/dist/main/motion/index.d.ts +1 -0
- package/dist/main/motion/index.js +9 -0
- package/dist/main/motion/index.mjs +2 -0
- package/dist/main/motion/motion-beam-frame.d.ts +3 -0
- package/dist/main/motion/motion-beam-frame.js +61 -0
- package/dist/main/motion/motion-beam-frame.mjs +59 -0
- package/dist/main/snake-loading-frame.d.ts +7 -3
- package/dist/main/snake-loading-frame.js +45 -252
- package/dist/main/snake-loading-frame.mjs +47 -254
- package/package.json +16 -5
- package/src/fuma/fuma-page-genarator.tsx +2 -22
- package/src/fuma/mdx/cheet-table.tsx +650 -0
- package/src/fuma/mdx/index.ts +1 -0
- package/src/fuma/server/features/widgets.tsx +2 -0
- package/src/main/404-page.tsx +162 -0
- package/src/main/alert-dialog/confirm-dialog.tsx +2 -1
- package/src/main/alert-dialog/dialog-loading-action.tsx +7 -5
- package/src/main/alert-dialog/dialog-styles.ts +13 -3
- package/src/main/alert-dialog/high-priority-confirm-dialog.tsx +26 -23
- package/src/main/alert-dialog/info-dialog.tsx +2 -1
- package/src/main/alert-dialog/undoable-confirm-dialog.tsx +18 -17
- package/src/main/anime/anime-404-page.tsx +344 -0
- package/src/main/anime/anime-beam-frame.tsx +128 -0
- package/src/main/anime/anime-spiral-loading.tsx +123 -0
- package/src/main/anime/index.ts +10 -0
- package/src/main/beam-frame-config.tsx +341 -0
- package/src/main/calendar/random-date-range-dialog.tsx +225 -69
- package/src/main/cta.tsx +50 -21
- package/src/main/delayed-img.tsx +9 -4
- package/src/main/index.ts +1 -0
- package/src/main/info-tooltip.tsx +116 -20
- package/src/main/loading-frame/index.ts +4 -0
- package/src/main/loading.tsx +75 -24
- package/src/main/motion/index.ts +8 -0
- package/src/main/motion/motion-beam-frame.tsx +137 -0
- package/src/main/snake-loading-frame.tsx +95 -496
- package/src/styles/cta.css +21 -4
- package/src/styles/third-ui.css +0 -20
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var React = require('react');
|
|
6
|
+
var react = require('motion/react');
|
|
7
|
+
var beamFrameConfig = require('../beam-frame-config.js');
|
|
8
|
+
|
|
9
|
+
function MotionAroundBeam({ isRunning, duration, radius, size, }) {
|
|
10
|
+
const auraGradientId = React.useId().replace(/:/g, '');
|
|
11
|
+
const softGlowFilterId = React.useId().replace(/:/g, '');
|
|
12
|
+
const beamGroupRef = React.useRef(null);
|
|
13
|
+
const controlsRef = React.useRef(null);
|
|
14
|
+
const hasStartedRef = React.useRef(false);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
var _a;
|
|
17
|
+
const node = beamGroupRef.current;
|
|
18
|
+
if (!node) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (isRunning) {
|
|
22
|
+
hasStartedRef.current = true;
|
|
23
|
+
}
|
|
24
|
+
node.style.opacity = isRunning || hasStartedRef.current ? 'var(--beam-frame-beam-opacity)' : '0';
|
|
25
|
+
if (!isRunning) {
|
|
26
|
+
(_a = controlsRef.current) === null || _a === void 0 ? void 0 : _a.pause();
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (controlsRef.current) {
|
|
30
|
+
controlsRef.current.speed = beamFrameConfig.BASE_DURATION_SECONDS / duration;
|
|
31
|
+
controlsRef.current.play();
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
controlsRef.current = react.animate(node, { strokeDashoffset: [0, -1] }, {
|
|
35
|
+
duration: beamFrameConfig.BASE_DURATION_SECONDS,
|
|
36
|
+
repeat: Infinity,
|
|
37
|
+
ease: 'linear',
|
|
38
|
+
});
|
|
39
|
+
controlsRef.current.speed = beamFrameConfig.BASE_DURATION_SECONDS / duration;
|
|
40
|
+
return undefined;
|
|
41
|
+
}, [duration, isRunning]);
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
return () => {
|
|
44
|
+
var _a;
|
|
45
|
+
(_a = controlsRef.current) === null || _a === void 0 ? void 0 : _a.stop();
|
|
46
|
+
controlsRef.current = null;
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
return (jsxRuntime.jsx(beamFrameConfig.BeamSvgLayer, { beamRef: beamGroupRef, auraGradientId: auraGradientId, softGlowFilterId: softGlowFilterId, radius: radius, size: size }));
|
|
50
|
+
}
|
|
51
|
+
function MotionBeamFrame(props) {
|
|
52
|
+
const { children, active = false, interactive = true, tone = 'theme', duration = beamFrameConfig.BASE_DURATION_SECONDS, radius, className, } = props;
|
|
53
|
+
const prefersReducedMotion = react.useReducedMotion();
|
|
54
|
+
const { isRunning, interactionProps } = beamFrameConfig.useInteractiveRunning(active, interactive);
|
|
55
|
+
const shouldRun = isRunning && !prefersReducedMotion;
|
|
56
|
+
const normalizedDuration = beamFrameConfig.normalizeDuration(duration);
|
|
57
|
+
const { ref, size } = beamFrameConfig.useMeasuredFrameSize();
|
|
58
|
+
return (jsxRuntime.jsx(beamFrameConfig.BeamFrameShell, { active: active, interactive: interactive, tone: tone, duration: normalizedDuration, radius: radius, className: className, isRunning: shouldRun, interactionProps: interactionProps, rootRef: ref, renderBeam: () => (jsxRuntime.jsx(MotionAroundBeam, { isRunning: shouldRun, duration: normalizedDuration, radius: radius, size: size })), children: children }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.MotionBeamFrame = MotionBeamFrame;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useId, useRef, useEffect } from 'react';
|
|
4
|
+
import { useReducedMotion, animate } from 'motion/react';
|
|
5
|
+
import { BASE_DURATION_SECONDS, useInteractiveRunning, useMeasuredFrameSize, BeamFrameShell, normalizeDuration, BeamSvgLayer } from '../beam-frame-config.mjs';
|
|
6
|
+
|
|
7
|
+
function MotionAroundBeam({ isRunning, duration, radius, size, }) {
|
|
8
|
+
const auraGradientId = useId().replace(/:/g, '');
|
|
9
|
+
const softGlowFilterId = useId().replace(/:/g, '');
|
|
10
|
+
const beamGroupRef = useRef(null);
|
|
11
|
+
const controlsRef = useRef(null);
|
|
12
|
+
const hasStartedRef = useRef(false);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
var _a;
|
|
15
|
+
const node = beamGroupRef.current;
|
|
16
|
+
if (!node) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (isRunning) {
|
|
20
|
+
hasStartedRef.current = true;
|
|
21
|
+
}
|
|
22
|
+
node.style.opacity = isRunning || hasStartedRef.current ? 'var(--beam-frame-beam-opacity)' : '0';
|
|
23
|
+
if (!isRunning) {
|
|
24
|
+
(_a = controlsRef.current) === null || _a === void 0 ? void 0 : _a.pause();
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
if (controlsRef.current) {
|
|
28
|
+
controlsRef.current.speed = BASE_DURATION_SECONDS / duration;
|
|
29
|
+
controlsRef.current.play();
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
controlsRef.current = animate(node, { strokeDashoffset: [0, -1] }, {
|
|
33
|
+
duration: BASE_DURATION_SECONDS,
|
|
34
|
+
repeat: Infinity,
|
|
35
|
+
ease: 'linear',
|
|
36
|
+
});
|
|
37
|
+
controlsRef.current.speed = BASE_DURATION_SECONDS / duration;
|
|
38
|
+
return undefined;
|
|
39
|
+
}, [duration, isRunning]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
return () => {
|
|
42
|
+
var _a;
|
|
43
|
+
(_a = controlsRef.current) === null || _a === void 0 ? void 0 : _a.stop();
|
|
44
|
+
controlsRef.current = null;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
return (jsx(BeamSvgLayer, { beamRef: beamGroupRef, auraGradientId: auraGradientId, softGlowFilterId: softGlowFilterId, radius: radius, size: size }));
|
|
48
|
+
}
|
|
49
|
+
function MotionBeamFrame(props) {
|
|
50
|
+
const { children, active = false, interactive = true, tone = 'theme', duration = BASE_DURATION_SECONDS, radius, className, } = props;
|
|
51
|
+
const prefersReducedMotion = useReducedMotion();
|
|
52
|
+
const { isRunning, interactionProps } = useInteractiveRunning(active, interactive);
|
|
53
|
+
const shouldRun = isRunning && !prefersReducedMotion;
|
|
54
|
+
const normalizedDuration = normalizeDuration(duration);
|
|
55
|
+
const { ref, size } = useMeasuredFrameSize();
|
|
56
|
+
return (jsx(BeamFrameShell, { active: active, interactive: interactive, tone: tone, duration: normalizedDuration, radius: radius, className: className, isRunning: shouldRun, interactionProps: interactionProps, rootRef: ref, renderBeam: () => (jsx(MotionAroundBeam, { isRunning: shouldRun, duration: normalizedDuration, radius: radius, size: size })), children: children }));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { MotionBeamFrame };
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { BeamFrameTone } from './beam-frame-config';
|
|
2
3
|
type SnakeShape = 'circle' | 'rounded-rect';
|
|
3
|
-
interface SnakeLoadingFrameProps {
|
|
4
|
+
export interface SnakeLoadingFrameProps {
|
|
4
5
|
shape: SnakeShape;
|
|
5
6
|
loading: boolean;
|
|
6
7
|
children: ReactNode;
|
|
8
|
+
paused?: boolean;
|
|
7
9
|
className?: string;
|
|
8
10
|
themeColor?: string;
|
|
11
|
+
tone?: BeamFrameTone;
|
|
9
12
|
strokeWidth?: number;
|
|
10
13
|
contentClassName?: string;
|
|
11
14
|
}
|
|
12
|
-
interface SnakeLoadingPreviewProps {
|
|
15
|
+
export interface SnakeLoadingPreviewProps {
|
|
13
16
|
shape: SnakeShape;
|
|
14
17
|
children: ReactNode;
|
|
15
18
|
className?: string;
|
|
16
19
|
themeColor?: string;
|
|
20
|
+
tone?: BeamFrameTone;
|
|
17
21
|
defaultProgress?: number;
|
|
18
22
|
strokeWidth?: number;
|
|
19
23
|
contentClassName?: string;
|
|
20
24
|
}
|
|
21
25
|
export declare function SnakeLoadingFrame(props: SnakeLoadingFrameProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
-
export declare function SnakeLoadingPreview({ shape, children, className, themeColor, defaultProgress, strokeWidth, contentClassName, }: SnakeLoadingPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare function SnakeLoadingPreview({ shape, children, className, themeColor, tone, defaultProgress, strokeWidth, contentClassName, }: SnakeLoadingPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
23
27
|
export {};
|
|
@@ -3,20 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var
|
|
6
|
+
var react = require('motion/react');
|
|
7
7
|
var utils = require('@windrun-huaiin/lib/utils');
|
|
8
|
+
var animeBeamFrame = require('./anime/anime-beam-frame.js');
|
|
9
|
+
require('animejs');
|
|
10
|
+
require('./anime/anime-404-page.js');
|
|
8
11
|
|
|
9
12
|
const DEFAULT_THEME_COLOR = '#3b82f6';
|
|
10
|
-
const TRACK_COLOR = 'rgba(148, 163, 184, 0.22)';
|
|
11
|
-
const BODY_LENGTH_RATIO = 0.26;
|
|
12
13
|
const EXIT_DURATION_MS = 260;
|
|
13
14
|
const LOOP_DURATION_SECONDS = 1.85;
|
|
14
15
|
const DEFAULT_CIRCLE_STROKE = 0.5;
|
|
15
16
|
const DEFAULT_RECT_STROKE = 1;
|
|
16
|
-
const MIN_FRAME_SIZE = 2;
|
|
17
|
-
const MIN_BODY_LENGTH = 24;
|
|
18
|
-
const MAX_BODY_LENGTH_RATIO = 0.36;
|
|
19
|
-
const RECT_MIN_STROKE_WIDTH = 1;
|
|
20
17
|
function clampProgress(progress) {
|
|
21
18
|
if (!Number.isFinite(progress)) {
|
|
22
19
|
return 0;
|
|
@@ -41,188 +38,45 @@ function createBodyTailColor(themeColor) {
|
|
|
41
38
|
}
|
|
42
39
|
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0.18)`;
|
|
43
40
|
}
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return { x: 0, y: 0 };
|
|
65
|
-
}
|
|
66
|
-
if (parts.length === 1) {
|
|
67
|
-
return { x: parts[0], y: parts[0] };
|
|
68
|
-
}
|
|
69
|
-
return { x: parts[0], y: parts[1] };
|
|
70
|
-
}
|
|
71
|
-
function clampCornerRadius(radius, maxX, maxY) {
|
|
72
|
-
return {
|
|
73
|
-
x: Math.max(0, Math.min(radius.x, maxX)),
|
|
74
|
-
y: Math.max(0, Math.min(radius.y, maxY)),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
function scaleHorizontalPair(start, end, limit) {
|
|
78
|
-
const sum = start.x + end.x;
|
|
79
|
-
if (sum <= limit || sum === 0) {
|
|
80
|
-
return [start, end];
|
|
81
|
-
}
|
|
82
|
-
const scale = limit / sum;
|
|
83
|
-
return [
|
|
84
|
-
Object.assign(Object.assign({}, start), { x: start.x * scale }),
|
|
85
|
-
Object.assign(Object.assign({}, end), { x: end.x * scale }),
|
|
86
|
-
];
|
|
87
|
-
}
|
|
88
|
-
function scaleVerticalPair(start, end, limit) {
|
|
89
|
-
const sum = start.y + end.y;
|
|
90
|
-
if (sum <= limit || sum === 0) {
|
|
91
|
-
return [start, end];
|
|
92
|
-
}
|
|
93
|
-
const scale = limit / sum;
|
|
94
|
-
return [
|
|
95
|
-
Object.assign(Object.assign({}, start), { y: start.y * scale }),
|
|
96
|
-
Object.assign(Object.assign({}, end), { y: end.y * scale }),
|
|
97
|
-
];
|
|
98
|
-
}
|
|
99
|
-
function normalizeRectRadii(width, height, input) {
|
|
100
|
-
let topLeft = clampCornerRadius(input.topLeft, width / 2, height / 2);
|
|
101
|
-
let topRight = clampCornerRadius(input.topRight, width / 2, height / 2);
|
|
102
|
-
let bottomRight = clampCornerRadius(input.bottomRight, width / 2, height / 2);
|
|
103
|
-
let bottomLeft = clampCornerRadius(input.bottomLeft, width / 2, height / 2);
|
|
104
|
-
[topLeft, topRight] = scaleHorizontalPair(topLeft, topRight, width);
|
|
105
|
-
[bottomLeft, bottomRight] = scaleHorizontalPair(bottomLeft, bottomRight, width);
|
|
106
|
-
[topLeft, bottomLeft] = scaleVerticalPair(topLeft, bottomLeft, height);
|
|
107
|
-
[topRight, bottomRight] = scaleVerticalPair(topRight, bottomRight, height);
|
|
108
|
-
return {
|
|
109
|
-
topLeft,
|
|
110
|
-
topRight,
|
|
111
|
-
bottomRight,
|
|
112
|
-
bottomLeft,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function buildRoundedRectPath(x, y, width, height, radii) {
|
|
116
|
-
const { topLeft, topRight, bottomRight, bottomLeft } = normalizeRectRadii(width, height, radii);
|
|
117
|
-
return [
|
|
118
|
-
`M ${x + topLeft.x} ${y}`,
|
|
119
|
-
`H ${x + Math.max(topLeft.x, width - topRight.x)}`,
|
|
120
|
-
topRight.x > 0 || topRight.y > 0
|
|
121
|
-
? `A ${topRight.x} ${topRight.y} 0 0 1 ${x + width} ${y + topRight.y}`
|
|
122
|
-
: `L ${x + width} ${y}`,
|
|
123
|
-
`V ${y + Math.max(topRight.y, height - bottomRight.y)}`,
|
|
124
|
-
bottomRight.x > 0 || bottomRight.y > 0
|
|
125
|
-
? `A ${bottomRight.x} ${bottomRight.y} 0 0 1 ${x + width - bottomRight.x} ${y + height}`
|
|
126
|
-
: `L ${x + width} ${y + height}`,
|
|
127
|
-
`H ${x + Math.min(width - bottomRight.x, bottomLeft.x)}`,
|
|
128
|
-
bottomLeft.x > 0 || bottomLeft.y > 0
|
|
129
|
-
? `A ${bottomLeft.x} ${bottomLeft.y} 0 0 1 ${x} ${y + height - bottomLeft.y}`
|
|
130
|
-
: `L ${x} ${y + height}`,
|
|
131
|
-
`V ${y + Math.min(height - bottomLeft.y, topLeft.y)}`,
|
|
132
|
-
topLeft.x > 0 || topLeft.y > 0
|
|
133
|
-
? `A ${topLeft.x} ${topLeft.y} 0 0 1 ${x + topLeft.x} ${y}`
|
|
134
|
-
: `L ${x} ${y}`,
|
|
135
|
-
'Z',
|
|
136
|
-
].join(' ');
|
|
137
|
-
}
|
|
138
|
-
function createCircleGeometry(width, height, strokeWidth) {
|
|
139
|
-
const safeWidth = Math.max(width, MIN_FRAME_SIZE);
|
|
140
|
-
const safeHeight = Math.max(height, MIN_FRAME_SIZE);
|
|
141
|
-
const radius = Math.max(0, Math.min(safeWidth, safeHeight) / 2 - strokeWidth / 2);
|
|
142
|
-
const centerX = safeWidth / 2;
|
|
143
|
-
const centerY = safeHeight / 2;
|
|
144
|
-
return {
|
|
145
|
-
viewBox: `0 0 ${safeWidth} ${safeHeight}`,
|
|
146
|
-
path: `M ${centerX} ${centerY - radius} A ${radius} ${radius} 0 1 1 ${centerX} ${centerY + radius} A ${radius} ${radius} 0 1 1 ${centerX} ${centerY - radius}`,
|
|
147
|
-
length: Math.max(0, 2 * Math.PI * radius),
|
|
148
|
-
strokeWidth,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
function createRoundedRectGeometry(width, height, strokeWidth, radii) {
|
|
152
|
-
const safeWidth = Math.max(width, MIN_FRAME_SIZE);
|
|
153
|
-
const safeHeight = Math.max(height, MIN_FRAME_SIZE);
|
|
154
|
-
const inset = strokeWidth / 2;
|
|
155
|
-
const innerWidth = Math.max(safeWidth - strokeWidth, MIN_FRAME_SIZE);
|
|
156
|
-
const innerHeight = Math.max(safeHeight - strokeWidth, MIN_FRAME_SIZE);
|
|
157
|
-
const adjustedRadii = normalizeRectRadii(innerWidth, innerHeight, {
|
|
158
|
-
topLeft: {
|
|
159
|
-
x: Math.max(0, radii.topLeft.x - inset),
|
|
160
|
-
y: Math.max(0, radii.topLeft.y - inset),
|
|
161
|
-
},
|
|
162
|
-
topRight: {
|
|
163
|
-
x: Math.max(0, radii.topRight.x - inset),
|
|
164
|
-
y: Math.max(0, radii.topRight.y - inset),
|
|
165
|
-
},
|
|
166
|
-
bottomRight: {
|
|
167
|
-
x: Math.max(0, radii.bottomRight.x - inset),
|
|
168
|
-
y: Math.max(0, radii.bottomRight.y - inset),
|
|
169
|
-
},
|
|
170
|
-
bottomLeft: {
|
|
171
|
-
x: Math.max(0, radii.bottomLeft.x - inset),
|
|
172
|
-
y: Math.max(0, radii.bottomLeft.y - inset),
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
return {
|
|
176
|
-
viewBox: `0 0 ${safeWidth} ${safeHeight}`,
|
|
177
|
-
path: buildRoundedRectPath(inset, inset, innerWidth, innerHeight, adjustedRadii),
|
|
178
|
-
length: 0,
|
|
179
|
-
strokeWidth,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function readRectRadii(element) {
|
|
183
|
-
const computedStyle = window.getComputedStyle(element);
|
|
184
|
-
return {
|
|
185
|
-
topLeft: parseRadiusValue(computedStyle.borderTopLeftRadius),
|
|
186
|
-
topRight: parseRadiusValue(computedStyle.borderTopRightRadius),
|
|
187
|
-
bottomRight: parseRadiusValue(computedStyle.borderBottomRightRadius),
|
|
188
|
-
bottomLeft: parseRadiusValue(computedStyle.borderBottomLeftRadius),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
function SnakeRingSvg({ containerRef, shape, themeColor, progressRatio, animate, strokeWidth, }) {
|
|
192
|
-
var _a, _b;
|
|
193
|
-
const gradientId = React.useId().replace(/:/g, '-');
|
|
194
|
-
createBodyTailColor(themeColor);
|
|
195
|
-
const headGlowColor = createHeadGlowColor(themeColor);
|
|
196
|
-
const sweepTailColor = createSweepTailColor(themeColor);
|
|
197
|
-
const [geometry, setGeometry] = React.useState(null);
|
|
198
|
-
const pathMeasureRef = React.useRef(null);
|
|
199
|
-
const measuredLengthRef = React.useRef(0);
|
|
41
|
+
function StaticProgressFrame({ shape, progress, themeColor, }) {
|
|
42
|
+
const trackColor = 'rgba(148, 163, 184, 0.22)';
|
|
43
|
+
const progressRatio = clampProgress(progress);
|
|
44
|
+
return (jsxRuntime.jsx("div", { "aria-hidden": "true", className: utils.cn('pointer-events-none absolute inset-0 p-px', shape === 'circle' ? 'rounded-full' : 'rounded-[inherit]'), style: {
|
|
45
|
+
background: `conic-gradient(${themeColor} 0% ${progressRatio}%, ${trackColor} ${progressRatio}% 100%)`,
|
|
46
|
+
mask: 'linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0)',
|
|
47
|
+
maskComposite: 'exclude',
|
|
48
|
+
WebkitMask: 'linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0)',
|
|
49
|
+
WebkitMaskComposite: 'xor',
|
|
50
|
+
} }));
|
|
51
|
+
}
|
|
52
|
+
function SnakeFrameBase({ shape, loading, children, paused = false, className, themeColor = DEFAULT_THEME_COLOR, tone = 'rainbow', previewProgress, strokeWidth, contentClassName, }) {
|
|
53
|
+
const containerRef = React.useRef(null);
|
|
54
|
+
const [frameRadius, setFrameRadius] = React.useState(shape === 'circle' ? 999 : undefined);
|
|
55
|
+
const [showOverlay, setShowOverlay] = React.useState(loading || previewProgress !== undefined);
|
|
56
|
+
const exitTimerRef = React.useRef(null);
|
|
57
|
+
const resolvedStrokeWidth = strokeWidth !== null && strokeWidth !== void 0 ? strokeWidth : (shape === 'circle' ? DEFAULT_CIRCLE_STROKE : DEFAULT_RECT_STROKE);
|
|
58
|
+
const circleContentInset = shape === 'circle' ? Math.max(6, resolvedStrokeWidth + 4) : 0;
|
|
59
|
+
const isPreview = previewProgress !== undefined;
|
|
60
|
+
const isActivelyLoading = loading && !paused && !isPreview;
|
|
200
61
|
React.useEffect(() => {
|
|
201
|
-
|
|
202
|
-
|
|
62
|
+
if (shape === 'circle') {
|
|
63
|
+
setFrameRadius(999);
|
|
203
64
|
return;
|
|
204
65
|
}
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
: createRoundedRectGeometry(rect.width, rect.height, resolvedStrokeWidth, readRectRadii(container));
|
|
214
|
-
measuredLengthRef.current = 0;
|
|
215
|
-
setGeometry(nextGeometry);
|
|
66
|
+
const node = containerRef.current;
|
|
67
|
+
if (!node) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const updateRadius = () => {
|
|
71
|
+
const computedStyle = window.getComputedStyle(node);
|
|
72
|
+
const nextRadius = Number.parseFloat(computedStyle.borderTopLeftRadius);
|
|
73
|
+
setFrameRadius(Number.isFinite(nextRadius) ? nextRadius : undefined);
|
|
216
74
|
};
|
|
217
|
-
|
|
218
|
-
const resizeObserver = new ResizeObserver(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
updateGeometry();
|
|
223
|
-
});
|
|
224
|
-
resizeObserver.observe(container);
|
|
225
|
-
mutationObserver.observe(container, {
|
|
75
|
+
updateRadius();
|
|
76
|
+
const resizeObserver = new ResizeObserver(updateRadius);
|
|
77
|
+
const mutationObserver = new MutationObserver(updateRadius);
|
|
78
|
+
resizeObserver.observe(node);
|
|
79
|
+
mutationObserver.observe(node, {
|
|
226
80
|
attributes: true,
|
|
227
81
|
attributeFilter: ['class', 'style'],
|
|
228
82
|
});
|
|
@@ -230,70 +84,9 @@ function SnakeRingSvg({ containerRef, shape, themeColor, progressRatio, animate,
|
|
|
230
84
|
resizeObserver.disconnect();
|
|
231
85
|
mutationObserver.disconnect();
|
|
232
86
|
};
|
|
233
|
-
}, [
|
|
234
|
-
React.useEffect(() => {
|
|
235
|
-
if (!geometry || shape === 'circle' || !pathMeasureRef.current) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
const measuredLength = pathMeasureRef.current.getTotalLength();
|
|
239
|
-
const normalizedLength = Number.isFinite(measuredLength)
|
|
240
|
-
? Math.max(0, measuredLength)
|
|
241
|
-
: 0;
|
|
242
|
-
if (normalizedLength <= 0) {
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
if (Math.abs(measuredLengthRef.current - normalizedLength) < 0.1) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
measuredLengthRef.current = normalizedLength;
|
|
249
|
-
setGeometry((current) => {
|
|
250
|
-
if (!current || current.path !== geometry.path) {
|
|
251
|
-
return current;
|
|
252
|
-
}
|
|
253
|
-
if (Math.abs(current.length - normalizedLength) < 0.1) {
|
|
254
|
-
return current;
|
|
255
|
-
}
|
|
256
|
-
return Object.assign(Object.assign({}, current), { length: normalizedLength });
|
|
257
|
-
});
|
|
258
|
-
}, [geometry, shape]);
|
|
259
|
-
const resolvedGeometry = React.useMemo(() => geometry, [geometry]);
|
|
260
|
-
if (!resolvedGeometry) {
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
const effectiveLength = resolvedGeometry.length > 0
|
|
264
|
-
? resolvedGeometry.length
|
|
265
|
-
: Math.max(1, 2 * Math.max(0, resolvedGeometry.strokeWidth), 2 *
|
|
266
|
-
(Math.max(0, Number.parseFloat((_a = resolvedGeometry.viewBox.split(' ')[2]) !== null && _a !== void 0 ? _a : '0')) +
|
|
267
|
-
Math.max(0, Number.parseFloat((_b = resolvedGeometry.viewBox.split(' ')[3]) !== null && _b !== void 0 ? _b : '0'))));
|
|
268
|
-
const [, , viewBoxWidthRaw, viewBoxHeightRaw] = resolvedGeometry.viewBox.split(' ');
|
|
269
|
-
const viewBoxWidth = Math.max(0, Number.parseFloat(viewBoxWidthRaw !== null && viewBoxWidthRaw !== void 0 ? viewBoxWidthRaw : '0'));
|
|
270
|
-
const viewBoxHeight = Math.max(0, Number.parseFloat(viewBoxHeightRaw !== null && viewBoxHeightRaw !== void 0 ? viewBoxHeightRaw : '0'));
|
|
271
|
-
const centerX = viewBoxWidth / 2;
|
|
272
|
-
const centerY = viewBoxHeight / 2;
|
|
273
|
-
const isCircle = shape === 'circle';
|
|
274
|
-
const tailTransparentStart = isCircle ? '18%' : '26%';
|
|
275
|
-
const tailColorStart = isCircle ? '39%' : '46%';
|
|
276
|
-
const tailTransparentEnd = isCircle ? '90%' : '82%';
|
|
277
|
-
const headTransparentStart = isCircle ? '32%' : '40%';
|
|
278
|
-
const headColorStart = isCircle ? '48%' : '53%';
|
|
279
|
-
const headTransparentEnd = isCircle ? '82%' : '73%';
|
|
280
|
-
const bodyLength = Math.min(effectiveLength * MAX_BODY_LENGTH_RATIO, Math.max(MIN_BODY_LENGTH, effectiveLength * BODY_LENGTH_RATIO));
|
|
281
|
-
const bodyDashArray = `${bodyLength} ${effectiveLength}`;
|
|
282
|
-
const staticDashOffset = effectiveLength * (1 - progressRatio);
|
|
283
|
-
const tailStrokeWidth = shape === 'circle'
|
|
284
|
-
? resolvedGeometry.strokeWidth + 1.2
|
|
285
|
-
: resolvedGeometry.strokeWidth + Math.min(1.2, resolvedGeometry.strokeWidth * 0.32);
|
|
286
|
-
return (jsxRuntime.jsxs("svg", { className: "pointer-events-none absolute inset-0 h-full w-full", viewBox: resolvedGeometry.viewBox, preserveAspectRatio: "none", "aria-hidden": "true", children: [shape === 'rounded-rect' ? (jsxRuntime.jsx("path", { ref: pathMeasureRef, d: resolvedGeometry.path, fill: "none", stroke: "transparent" })) : null, animate ? (jsxRuntime.jsxs("defs", { children: [jsxRuntime.jsxs("linearGradient", { id: `${gradientId}-sweep-tail`, x1: "0", y1: "0", x2: String(viewBoxWidth), y2: "0", gradientUnits: "userSpaceOnUse", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: tailTransparentStart, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: tailColorStart, stopColor: sweepTailColor }), jsxRuntime.jsx("stop", { offset: "64%", stopColor: headGlowColor }), jsxRuntime.jsx("stop", { offset: tailTransparentEnd, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: "transparent" }), jsxRuntime.jsx("animateTransform", { attributeName: "gradientTransform", type: "rotate", from: `0 ${centerX} ${centerY}`, to: `360 ${centerX} ${centerY}`, dur: `${LOOP_DURATION_SECONDS}s`, repeatCount: "indefinite" })] }), jsxRuntime.jsxs("linearGradient", { id: `${gradientId}-sweep-head`, x1: "0", y1: "0", x2: String(viewBoxWidth), y2: "0", gradientUnits: "userSpaceOnUse", children: [jsxRuntime.jsx("stop", { offset: "0%", stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: headTransparentStart, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: headColorStart, stopColor: themeColor }), jsxRuntime.jsx("stop", { offset: "63%", stopColor: headGlowColor }), jsxRuntime.jsx("stop", { offset: headTransparentEnd, stopColor: "transparent" }), jsxRuntime.jsx("stop", { offset: "100%", stopColor: "transparent" }), jsxRuntime.jsx("animateTransform", { attributeName: "gradientTransform", type: "rotate", from: `0 ${centerX} ${centerY}`, to: `360 ${centerX} ${centerY}`, dur: `${LOOP_DURATION_SECONDS}s`, repeatCount: "indefinite" })] })] })) : null, jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: TRACK_COLOR, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }), animate ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: `url(#${gradientId}-sweep-tail)`, strokeWidth: tailStrokeWidth, strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: `url(#${gradientId}-sweep-head)`, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" })] })) : null, !animate ? (jsxRuntime.jsx("path", { d: resolvedGeometry.path, fill: "none", stroke: themeColor, strokeWidth: resolvedGeometry.strokeWidth, strokeLinecap: "round", strokeLinejoin: "round", strokeDasharray: bodyDashArray, strokeDashoffset: staticDashOffset })) : null] }));
|
|
287
|
-
}
|
|
288
|
-
function SnakeFrameBase({ shape, loading, children, className, themeColor = DEFAULT_THEME_COLOR, previewProgress, strokeWidth, contentClassName, }) {
|
|
289
|
-
const containerRef = React.useRef(null);
|
|
290
|
-
const [showOverlay, setShowOverlay] = React.useState(loading || previewProgress !== undefined);
|
|
291
|
-
const exitTimerRef = React.useRef(null);
|
|
292
|
-
const resolvedStrokeWidth = strokeWidth !== null && strokeWidth !== void 0 ? strokeWidth : (shape === 'circle' ? DEFAULT_CIRCLE_STROKE : DEFAULT_RECT_STROKE);
|
|
293
|
-
const circleContentInset = shape === 'circle' ? Math.max(6, resolvedStrokeWidth + 4) : 0;
|
|
294
|
-
const progressRatio = clampProgress(previewProgress !== null && previewProgress !== void 0 ? previewProgress : 0) / 100;
|
|
87
|
+
}, [shape]);
|
|
295
88
|
React.useEffect(() => {
|
|
296
|
-
if (
|
|
89
|
+
if (isPreview) {
|
|
297
90
|
setShowOverlay(true);
|
|
298
91
|
return;
|
|
299
92
|
}
|
|
@@ -315,24 +108,24 @@ function SnakeFrameBase({ shape, loading, children, className, themeColor = DEFA
|
|
|
315
108
|
exitTimerRef.current = null;
|
|
316
109
|
}
|
|
317
110
|
};
|
|
318
|
-
}, [
|
|
111
|
+
}, [isPreview, loading]);
|
|
319
112
|
return (jsxRuntime.jsxs("div", { ref: containerRef, className: utils.cn('relative isolate', shape === 'circle' ? 'rounded-full' : 'rounded-none', className), children: [jsxRuntime.jsx("div", { className: utils.cn('relative z-0 overflow-hidden', shape === 'circle'
|
|
320
113
|
? 'absolute flex items-center justify-center rounded-full'
|
|
321
114
|
: 'h-full w-full', contentClassName), style: shape === 'circle'
|
|
322
115
|
? {
|
|
323
116
|
inset: circleContentInset,
|
|
324
117
|
}
|
|
325
|
-
: undefined, children: children }), showOverlay ? (jsxRuntime.jsx(
|
|
118
|
+
: undefined, children: children }), showOverlay ? (jsxRuntime.jsx(react.motion.div, { className: "pointer-events-none absolute inset-0 overflow-visible", initial: false, animate: { opacity: loading || isPreview ? 1 : 0 }, transition: { duration: EXIT_DURATION_MS / 1000, ease: 'easeOut' }, children: isPreview ? (jsxRuntime.jsx(StaticProgressFrame, { shape: shape, progress: previewProgress, themeColor: themeColor })) : (jsxRuntime.jsx(animeBeamFrame.AnimeBeamFrame, { active: isActivelyLoading, interactive: false, tone: tone, duration: LOOP_DURATION_SECONDS, radius: frameRadius, className: "absolute inset-0 h-full w-full", children: jsxRuntime.jsx("div", { className: "h-full w-full" }) })) })) : null] }));
|
|
326
119
|
}
|
|
327
120
|
function SnakeLoadingFrame(props) {
|
|
328
121
|
return jsxRuntime.jsx(SnakeFrameBase, Object.assign({}, props));
|
|
329
122
|
}
|
|
330
|
-
function SnakeLoadingPreview({ shape, children, className, themeColor = DEFAULT_THEME_COLOR, defaultProgress = 32, strokeWidth, contentClassName, }) {
|
|
123
|
+
function SnakeLoadingPreview({ shape, children, className, themeColor = DEFAULT_THEME_COLOR, tone = 'rainbow', defaultProgress = 32, strokeWidth, contentClassName, }) {
|
|
331
124
|
const [progress, setProgress] = React.useState(clampProgress(defaultProgress));
|
|
332
125
|
const sliderFillColor = themeColor;
|
|
333
126
|
const sliderGlowColor = createBodyTailColor(themeColor);
|
|
334
127
|
const sliderBackground = `linear-gradient(90deg, ${sliderGlowColor} 0%, ${sliderFillColor} ${progress}%, rgba(148, 163, 184, 0.24) ${progress}%, rgba(148, 163, 184, 0.24) 100%)`;
|
|
335
|
-
return (jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsx(SnakeFrameBase, { shape: shape, loading: true, previewProgress: progress, className: className, themeColor: themeColor, strokeWidth: strokeWidth, contentClassName: contentClassName, children: children }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-[11px] font-medium uppercase tracking-[0.14em] text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsx("span", { children: "Snake Preview" }), jsxRuntime.jsxs("span", { children: [progress, "%"] })] }), jsxRuntime.jsx("input", { type: "range", min: 0, max: 100, value: progress, onChange: (event) => {
|
|
128
|
+
return (jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsx(SnakeFrameBase, { shape: shape, loading: true, previewProgress: progress, className: className, themeColor: themeColor, tone: tone, strokeWidth: strokeWidth, contentClassName: contentClassName, children: children }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-[11px] font-medium uppercase tracking-[0.14em] text-slate-500 dark:text-slate-400", children: [jsxRuntime.jsx("span", { children: "Snake Preview" }), jsxRuntime.jsxs("span", { children: [progress, "%"] })] }), jsxRuntime.jsx("input", { type: "range", min: 0, max: 100, value: progress, onChange: (event) => {
|
|
336
129
|
setProgress(clampProgress(Number(event.target.value)));
|
|
337
130
|
}, className: "h-2 w-full cursor-pointer appearance-none rounded-full", style: {
|
|
338
131
|
background: sliderBackground,
|