@lobehub/ui 5.49.1 → 5.50.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/es/Empty/Empty.d.mts +1 -2
- package/es/Empty/Empty.mjs +107 -53
- package/es/Empty/Empty.mjs.map +1 -1
- package/es/Empty/style.mjs +48 -0
- package/es/Empty/style.mjs.map +1 -0
- package/es/Empty/type.d.mts +7 -8
- package/es/HtmlPreview/HtmlPreview.mjs +5 -2
- package/es/HtmlPreview/HtmlPreview.mjs.map +1 -1
- package/es/base-ui/Badge/Badge.d.mts +6 -0
- package/es/base-ui/Badge/Badge.mjs +73 -0
- package/es/base-ui/Badge/Badge.mjs.map +1 -0
- package/es/base-ui/Badge/index.d.mts +3 -0
- package/es/base-ui/Badge/style.mjs +112 -0
- package/es/base-ui/Badge/style.mjs.map +1 -0
- package/es/base-ui/Badge/type.d.mts +19 -0
- package/es/base-ui/Input/style.d.mts +2 -2
- package/es/base-ui/Pagination/Pagination.d.mts +6 -0
- package/es/base-ui/Pagination/Pagination.mjs +123 -0
- package/es/base-ui/Pagination/Pagination.mjs.map +1 -0
- package/es/base-ui/Pagination/helpers.mjs +18 -0
- package/es/base-ui/Pagination/helpers.mjs.map +1 -0
- package/es/base-ui/Pagination/index.d.mts +3 -0
- package/es/base-ui/Pagination/style.mjs +92 -0
- package/es/base-ui/Pagination/style.mjs.map +1 -0
- package/es/base-ui/Pagination/type.d.mts +22 -0
- package/es/base-ui/Progress/Progress.d.mts +6 -0
- package/es/base-ui/Progress/Progress.mjs +179 -0
- package/es/base-ui/Progress/Progress.mjs.map +1 -0
- package/es/base-ui/Progress/index.d.mts +3 -0
- package/es/base-ui/Progress/style.mjs +203 -0
- package/es/base-ui/Progress/style.mjs.map +1 -0
- package/es/base-ui/Progress/type.d.mts +24 -0
- package/es/base-ui/Result/Result.d.mts +6 -0
- package/es/base-ui/Result/Result.mjs +69 -0
- package/es/base-ui/Result/Result.mjs.map +1 -0
- package/es/base-ui/Result/index.d.mts +3 -0
- package/es/base-ui/Result/style.mjs +55 -0
- package/es/base-ui/Result/style.mjs.map +1 -0
- package/es/base-ui/Result/type.d.mts +14 -0
- package/es/base-ui/Spin/NetworkGlyph.mjs +70 -0
- package/es/base-ui/Spin/NetworkGlyph.mjs.map +1 -0
- package/es/base-ui/Spin/Spin.d.mts +6 -0
- package/es/base-ui/Spin/Spin.mjs +100 -0
- package/es/base-ui/Spin/Spin.mjs.map +1 -0
- package/es/base-ui/Spin/index.d.mts +3 -0
- package/es/base-ui/Spin/style.mjs +166 -0
- package/es/base-ui/Spin/style.mjs.map +1 -0
- package/es/base-ui/Spin/type.d.mts +18 -0
- package/es/base-ui/Upload/Upload.d.mts +6 -0
- package/es/base-ui/Upload/Upload.mjs +148 -0
- package/es/base-ui/Upload/Upload.mjs.map +1 -0
- package/es/base-ui/Upload/UploadDragger.d.mts +6 -0
- package/es/base-ui/Upload/UploadDragger.mjs +14 -0
- package/es/base-ui/Upload/UploadDragger.mjs.map +1 -0
- package/es/base-ui/Upload/helpers.mjs +17 -0
- package/es/base-ui/Upload/helpers.mjs.map +1 -0
- package/es/base-ui/Upload/index.d.mts +4 -0
- package/es/base-ui/Upload/style.mjs +74 -0
- package/es/base-ui/Upload/style.mjs.map +1 -0
- package/es/base-ui/Upload/type.d.mts +24 -0
- package/es/base-ui/index.d.mts +20 -1
- package/es/base-ui/index.mjs +10 -3
- package/es/index.d.mts +20 -4
- package/es/index.mjs +8 -2
- package/es/static-css/baseline.mjs +0 -1
- package/es/static-css/baseline.mjs.map +1 -1
- package/package.json +1 -1
- package/es/NeuralNetworkLoading/NeuralNetworkLoading.d.mts +0 -6
- package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs +0 -142
- package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs.map +0 -1
- package/es/NeuralNetworkLoading/index.d.mts +0 -3
- package/es/NeuralNetworkLoading/index.d.ts +0 -1
- package/es/NeuralNetworkLoading/index.js +0 -1
- package/es/NeuralNetworkLoading/index.mjs +0 -2
- package/es/NeuralNetworkLoading/type.d.mts +0 -11
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createStaticStyles, cssVar, keyframes } from "antd-style";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
//#region src/base-ui/Badge/style.ts
|
|
4
|
+
const pulse = keyframes`
|
|
5
|
+
to {
|
|
6
|
+
scale: 2.4;
|
|
7
|
+
opacity: 0;
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
11
|
+
pill: css`
|
|
12
|
+
display: inline-block;
|
|
13
|
+
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
min-width: 18px;
|
|
16
|
+
height: 18px;
|
|
17
|
+
padding-inline: 5px;
|
|
18
|
+
border-radius: 999px;
|
|
19
|
+
|
|
20
|
+
font-family: ${cssVar.fontFamilyCode};
|
|
21
|
+
font-size: 11px;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
font-variant-numeric: tabular-nums;
|
|
24
|
+
line-height: 18px;
|
|
25
|
+
color: ${cssVar.colorWhite};
|
|
26
|
+
text-align: center;
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
|
|
29
|
+
background: ${cssVar.colorError};
|
|
30
|
+
box-shadow: 0 0 0 1.5px ${cssVar.colorBgContainer};
|
|
31
|
+
`,
|
|
32
|
+
pillAbsolute: css`
|
|
33
|
+
position: absolute;
|
|
34
|
+
inset-block-start: 0;
|
|
35
|
+
inset-inline-end: 0;
|
|
36
|
+
translate: 50% -50%;
|
|
37
|
+
`,
|
|
38
|
+
pillDot: css`
|
|
39
|
+
width: 8px;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
height: 8px;
|
|
42
|
+
padding: 0;
|
|
43
|
+
|
|
44
|
+
box-shadow: none;
|
|
45
|
+
`,
|
|
46
|
+
pillSmall: css`
|
|
47
|
+
min-width: 14px;
|
|
48
|
+
height: 14px;
|
|
49
|
+
font-size: 11px;
|
|
50
|
+
line-height: 14px;
|
|
51
|
+
`,
|
|
52
|
+
statusDot: css`
|
|
53
|
+
position: relative;
|
|
54
|
+
|
|
55
|
+
flex-shrink: 0;
|
|
56
|
+
|
|
57
|
+
width: 6px;
|
|
58
|
+
height: 6px;
|
|
59
|
+
border-radius: 50%;
|
|
60
|
+
|
|
61
|
+
background: ${cssVar.colorTextQuaternary};
|
|
62
|
+
`,
|
|
63
|
+
statusDotProcessing: css`
|
|
64
|
+
&::after {
|
|
65
|
+
content: '';
|
|
66
|
+
|
|
67
|
+
position: absolute;
|
|
68
|
+
inset: -1px;
|
|
69
|
+
|
|
70
|
+
border: 1px solid currentcolor;
|
|
71
|
+
border-radius: 50%;
|
|
72
|
+
|
|
73
|
+
animation: ${pulse} 1.2s ease-out infinite;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media (prefers-reduced-motion: reduce) {
|
|
77
|
+
&::after {
|
|
78
|
+
animation: none;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`,
|
|
82
|
+
statusRoot: css`
|
|
83
|
+
display: inline-flex;
|
|
84
|
+
gap: 8px;
|
|
85
|
+
align-items: center;
|
|
86
|
+
`,
|
|
87
|
+
statusText: css`
|
|
88
|
+
color: ${cssVar.colorText};
|
|
89
|
+
`,
|
|
90
|
+
wrapper: css`
|
|
91
|
+
position: relative;
|
|
92
|
+
display: inline-block;
|
|
93
|
+
`
|
|
94
|
+
}));
|
|
95
|
+
const statusColor = {
|
|
96
|
+
default: cssVar.colorTextQuaternary,
|
|
97
|
+
error: cssVar.colorError,
|
|
98
|
+
processing: cssVar.colorInfo,
|
|
99
|
+
success: cssVar.colorSuccess,
|
|
100
|
+
warning: cssVar.colorWarning
|
|
101
|
+
};
|
|
102
|
+
const pillSize = cva(styles.pill, {
|
|
103
|
+
defaultVariants: { size: "default" },
|
|
104
|
+
variants: { size: {
|
|
105
|
+
default: null,
|
|
106
|
+
small: styles.pillSmall
|
|
107
|
+
} }
|
|
108
|
+
});
|
|
109
|
+
//#endregion
|
|
110
|
+
export { pillSize, statusColor, styles };
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=style.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Badge/style.ts"],"sourcesContent":["import { createStaticStyles, cssVar, keyframes } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nconst pulse = keyframes`\n to {\n scale: 2.4;\n opacity: 0;\n }\n`;\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n pill: css`\n display: inline-block;\n\n box-sizing: border-box;\n min-width: 18px;\n height: 18px;\n padding-inline: 5px;\n border-radius: 999px;\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 11px;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 18px;\n color: ${cssVar.colorWhite};\n text-align: center;\n white-space: nowrap;\n\n background: ${cssVar.colorError};\n box-shadow: 0 0 0 1.5px ${cssVar.colorBgContainer};\n `,\n pillAbsolute: css`\n position: absolute;\n inset-block-start: 0;\n inset-inline-end: 0;\n translate: 50% -50%;\n `,\n pillDot: css`\n width: 8px;\n min-width: 0;\n height: 8px;\n padding: 0;\n\n box-shadow: none;\n `,\n pillSmall: css`\n min-width: 14px;\n height: 14px;\n font-size: 11px;\n line-height: 14px;\n `,\n statusDot: css`\n position: relative;\n\n flex-shrink: 0;\n\n width: 6px;\n height: 6px;\n border-radius: 50%;\n\n background: ${cssVar.colorTextQuaternary};\n `,\n statusDotProcessing: css`\n &::after {\n content: '';\n\n position: absolute;\n inset: -1px;\n\n border: 1px solid currentcolor;\n border-radius: 50%;\n\n animation: ${pulse} 1.2s ease-out infinite;\n }\n\n @media (prefers-reduced-motion: reduce) {\n &::after {\n animation: none;\n }\n }\n `,\n statusRoot: css`\n display: inline-flex;\n gap: 8px;\n align-items: center;\n `,\n statusText: css`\n color: ${cssVar.colorText};\n `,\n wrapper: css`\n position: relative;\n display: inline-block;\n `,\n}));\n\nexport const statusColor: Record<string, string> = {\n default: cssVar.colorTextQuaternary,\n error: cssVar.colorError,\n processing: cssVar.colorInfo,\n success: cssVar.colorSuccess,\n warning: cssVar.colorWarning,\n};\n\nexport const pillSize = cva(styles.pill, {\n defaultVariants: {\n size: 'default',\n },\n variants: {\n size: {\n default: null,\n small: styles.pillSmall,\n },\n },\n});\n"],"mappings":";;;AAGA,MAAM,QAAQ,SAAS;;;;;;AAOvB,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,MAAM,GAAG;;;;;;;;;mBASQ,OAAO,eAAe;;;;;aAK5B,OAAO,WAAW;;;;kBAIb,OAAO,WAAW;8BACN,OAAO,iBAAiB;;CAEpD,cAAc,GAAG;;;;;;CAMjB,SAAS,GAAG;;;;;;;;CAQZ,WAAW,GAAG;;;;;;CAMd,WAAW,GAAG;;;;;;;;;kBASE,OAAO,oBAAoB;;CAE3C,qBAAqB,GAAG;;;;;;;;;;mBAUP,MAAM;;;;;;;;;CASvB,YAAY,GAAG;;;;;CAKf,YAAY,GAAG;aACJ,OAAO,UAAU;;CAE5B,SAAS,GAAG;;;;AAId,EAAE;AAEF,MAAa,cAAsC;CACjD,SAAS,OAAO;CAChB,OAAO,OAAO;CACd,YAAY,OAAO;CACnB,SAAS,OAAO;CAChB,SAAS,OAAO;AAClB;AAEA,MAAa,WAAW,IAAI,OAAO,MAAM;CACvC,iBAAiB,EACf,MAAM,UACR;CACA,UAAU,EACR,MAAM;EACJ,SAAS;EACT,OAAO,OAAO;CAChB,EACF;AACF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode, Ref } from "react";
|
|
2
|
+
//#region src/base-ui/Badge/type.d.ts
|
|
3
|
+
type BadgeStatus = 'success' | 'processing' | 'default' | 'error' | 'warning';
|
|
4
|
+
type BadgeSize = 'default' | 'small';
|
|
5
|
+
interface BadgeProps extends Omit<ComponentProps<'span'>, 'color'> {
|
|
6
|
+
color?: string;
|
|
7
|
+
count?: ReactNode;
|
|
8
|
+
dot?: boolean;
|
|
9
|
+
offset?: [number, number];
|
|
10
|
+
overflowCount?: number;
|
|
11
|
+
ref?: Ref<HTMLSpanElement>;
|
|
12
|
+
showZero?: boolean;
|
|
13
|
+
size?: BadgeSize;
|
|
14
|
+
status?: BadgeStatus;
|
|
15
|
+
text?: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { BadgeProps, BadgeSize, BadgeStatus };
|
|
19
|
+
//# sourceMappingURL=type.d.mts.map
|
|
@@ -23,8 +23,8 @@ declare const styles: {
|
|
|
23
23
|
};
|
|
24
24
|
declare const rootVariants: (props?: ({
|
|
25
25
|
shadow?: boolean | null | undefined;
|
|
26
|
-
size?: "
|
|
27
|
-
variant?: "
|
|
26
|
+
size?: "small" | "middle" | "large" | null | undefined;
|
|
27
|
+
variant?: "filled" | "borderless" | "outlined" | null | undefined;
|
|
28
28
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
29
29
|
//#endregion
|
|
30
30
|
export { rootVariants, styles };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PaginationProps } from "./type.mjs";
|
|
2
|
+
//#region src/base-ui/Pagination/Pagination.d.ts
|
|
3
|
+
declare const Pagination: import("react").NamedExoticComponent<PaginationProps>;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { Pagination as default };
|
|
6
|
+
//# sourceMappingURL=Pagination.d.mts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Select from "../Select/Select.mjs";
|
|
3
|
+
import { useEventCallback } from "../../hooks/useEventCallback.mjs";
|
|
4
|
+
import { clampPage, getPageCount, getPaginationItems } from "./helpers.mjs";
|
|
5
|
+
import { buttonVariants, ellipsisVariants, styles } from "./style.mjs";
|
|
6
|
+
import { memo, useEffect, useRef, useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { cx } from "antd-style";
|
|
9
|
+
import useMergeState from "use-merge-value";
|
|
10
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
11
|
+
//#region src/base-ui/Pagination/Pagination.tsx
|
|
12
|
+
const Pagination = memo(({ className, current, defaultCurrent = 1, defaultPageSize = 10, disabled, hideOnSinglePage, onChange, onPageSizeChange, pageSize, pageSizeOptions = [
|
|
13
|
+
10,
|
|
14
|
+
20,
|
|
15
|
+
50,
|
|
16
|
+
100
|
|
17
|
+
], ref, showSizeChanger = false, showTotal, size = "middle", style, total, ...rest }) => {
|
|
18
|
+
const [mergedPageSize, setMergedPageSize] = useMergeState(defaultPageSize, { value: pageSize });
|
|
19
|
+
const pageCount = getPageCount(total, mergedPageSize);
|
|
20
|
+
const [mergedCurrent, setMergedCurrent] = useMergeState(defaultCurrent, { value: current });
|
|
21
|
+
const onChangeStable = useEventCallback((nextCurrent, nextPageSize) => {
|
|
22
|
+
onChange?.(nextCurrent, nextPageSize);
|
|
23
|
+
});
|
|
24
|
+
const pendingNotifyRef = useRef(null);
|
|
25
|
+
const [prevPageCount, setPrevPageCount] = useState(pageCount);
|
|
26
|
+
if (pageCount !== prevPageCount) {
|
|
27
|
+
setPrevPageCount(pageCount);
|
|
28
|
+
if (mergedCurrent > pageCount && pageCount >= 1) {
|
|
29
|
+
setMergedCurrent(pageCount);
|
|
30
|
+
pendingNotifyRef.current = {
|
|
31
|
+
current: pageCount,
|
|
32
|
+
pageSize: mergedPageSize
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!pendingNotifyRef.current) return;
|
|
38
|
+
const { current: nextCurrent, pageSize: nextPageSize } = pendingNotifyRef.current;
|
|
39
|
+
pendingNotifyRef.current = null;
|
|
40
|
+
onChangeStable(nextCurrent, nextPageSize);
|
|
41
|
+
});
|
|
42
|
+
const displayCurrent = clampPage(mergedCurrent, pageCount);
|
|
43
|
+
if (hideOnSinglePage && pageCount <= 1) return null;
|
|
44
|
+
const commitCurrent = (nextCurrent, nextPageSize) => {
|
|
45
|
+
setMergedCurrent(nextCurrent);
|
|
46
|
+
onChange?.(nextCurrent, nextPageSize);
|
|
47
|
+
};
|
|
48
|
+
const goTo = (page) => {
|
|
49
|
+
commitCurrent(clampPage(page, pageCount), mergedPageSize);
|
|
50
|
+
};
|
|
51
|
+
const handlePageSizeChange = (value) => {
|
|
52
|
+
const nextSize = Number(value);
|
|
53
|
+
const nextPageCount = getPageCount(total, nextSize);
|
|
54
|
+
const nextCurrent = clampPage(displayCurrent, nextPageCount);
|
|
55
|
+
setMergedPageSize(nextSize);
|
|
56
|
+
commitCurrent(nextCurrent, nextSize);
|
|
57
|
+
onPageSizeChange?.(nextCurrent, nextSize);
|
|
58
|
+
};
|
|
59
|
+
const items = getPaginationItems(displayCurrent, pageCount);
|
|
60
|
+
const rangeStart = total === 0 ? 0 : (displayCurrent - 1) * mergedPageSize + 1;
|
|
61
|
+
const rangeEnd = Math.min(displayCurrent * mergedPageSize, total);
|
|
62
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
63
|
+
"aria-label": "Pagination",
|
|
64
|
+
className: cx(styles.root, className),
|
|
65
|
+
ref,
|
|
66
|
+
role: "navigation",
|
|
67
|
+
style,
|
|
68
|
+
...rest,
|
|
69
|
+
children: [
|
|
70
|
+
showTotal && /* @__PURE__ */ jsx("span", {
|
|
71
|
+
className: styles.total,
|
|
72
|
+
children: showTotal(total, [rangeStart, rangeEnd])
|
|
73
|
+
}),
|
|
74
|
+
/* @__PURE__ */ jsx("button", {
|
|
75
|
+
"aria-label": "Previous page",
|
|
76
|
+
className: buttonVariants({ size }),
|
|
77
|
+
disabled: disabled || displayCurrent <= 1,
|
|
78
|
+
type: "button",
|
|
79
|
+
onClick: () => goTo(displayCurrent - 1),
|
|
80
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { size: size === "small" ? 14 : 16 })
|
|
81
|
+
}),
|
|
82
|
+
items.map((item) => typeof item === "number" ? /* @__PURE__ */ jsx("button", {
|
|
83
|
+
"aria-current": item === displayCurrent ? "page" : void 0,
|
|
84
|
+
className: buttonVariants({ size }),
|
|
85
|
+
disabled,
|
|
86
|
+
type: "button",
|
|
87
|
+
onClick: () => goTo(item),
|
|
88
|
+
children: item
|
|
89
|
+
}, item) : /* @__PURE__ */ jsx("span", {
|
|
90
|
+
className: ellipsisVariants({ size }),
|
|
91
|
+
children: "···"
|
|
92
|
+
}, item)),
|
|
93
|
+
/* @__PURE__ */ jsx("button", {
|
|
94
|
+
"aria-label": "Next page",
|
|
95
|
+
className: buttonVariants({ size }),
|
|
96
|
+
disabled: disabled || displayCurrent >= pageCount,
|
|
97
|
+
type: "button",
|
|
98
|
+
onClick: () => goTo(displayCurrent + 1),
|
|
99
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { size: size === "small" ? 14 : 16 })
|
|
100
|
+
}),
|
|
101
|
+
showSizeChanger && /* @__PURE__ */ jsx(Select, {
|
|
102
|
+
disabled,
|
|
103
|
+
size: size === "small" ? "small" : "middle",
|
|
104
|
+
style: {
|
|
105
|
+
flex: "none",
|
|
106
|
+
marginInlineStart: 8,
|
|
107
|
+
width: "auto"
|
|
108
|
+
},
|
|
109
|
+
value: String(mergedPageSize),
|
|
110
|
+
options: pageSizeOptions.map((option) => ({
|
|
111
|
+
label: `${option} / page`,
|
|
112
|
+
value: String(option)
|
|
113
|
+
})),
|
|
114
|
+
onChange: handlePageSizeChange
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
Pagination.displayName = "Pagination";
|
|
120
|
+
//#endregion
|
|
121
|
+
export { Pagination as default };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=Pagination.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Pagination/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport Select from '@/base-ui/Select';\nimport { useEventCallback } from '@/hooks/useEventCallback';\n\nimport { clampPage, getPageCount, getPaginationItems } from './helpers';\nimport { buttonVariants, ellipsisVariants, styles } from './style';\nimport type { PaginationProps } from './type';\n\nconst Pagination = memo<PaginationProps>(\n ({\n className,\n current,\n defaultCurrent = 1,\n defaultPageSize = 10,\n disabled,\n hideOnSinglePage,\n onChange,\n onPageSizeChange,\n pageSize,\n pageSizeOptions = [10, 20, 50, 100],\n ref,\n showSizeChanger = false,\n showTotal,\n size = 'middle',\n style,\n total,\n ...rest\n }) => {\n const [mergedPageSize, setMergedPageSize] = useControlledState(defaultPageSize, {\n value: pageSize,\n });\n const pageCount = getPageCount(total, mergedPageSize);\n const [mergedCurrent, setMergedCurrent] = useControlledState(defaultCurrent, {\n value: current,\n });\n const onChangeStable = useEventCallback((nextCurrent: number, nextPageSize: number) => {\n onChange?.(nextCurrent, nextPageSize);\n });\n\n const pendingNotifyRef = useRef<{ current: number; pageSize: number } | null>(null);\n const [prevPageCount, setPrevPageCount] = useState(pageCount);\n\n if (pageCount !== prevPageCount) {\n setPrevPageCount(pageCount);\n\n if (mergedCurrent > pageCount && pageCount >= 1) {\n setMergedCurrent(pageCount);\n pendingNotifyRef.current = { current: pageCount, pageSize: mergedPageSize };\n }\n }\n\n useEffect(() => {\n if (!pendingNotifyRef.current) return;\n\n const { current: nextCurrent, pageSize: nextPageSize } = pendingNotifyRef.current;\n pendingNotifyRef.current = null;\n onChangeStable(nextCurrent, nextPageSize);\n });\n\n const displayCurrent = clampPage(mergedCurrent, pageCount);\n\n if (hideOnSinglePage && pageCount <= 1) return null;\n\n const commitCurrent = (nextCurrent: number, nextPageSize: number) => {\n setMergedCurrent(nextCurrent);\n onChange?.(nextCurrent, nextPageSize);\n };\n\n const goTo = (page: number) => {\n commitCurrent(clampPage(page, pageCount), mergedPageSize);\n };\n\n const handlePageSizeChange = (value: string) => {\n const nextSize = Number(value);\n const nextPageCount = getPageCount(total, nextSize);\n const nextCurrent = clampPage(displayCurrent, nextPageCount);\n\n setMergedPageSize(nextSize);\n commitCurrent(nextCurrent, nextSize);\n onPageSizeChange?.(nextCurrent, nextSize);\n };\n\n const items = getPaginationItems(displayCurrent, pageCount);\n const rangeStart = total === 0 ? 0 : (displayCurrent - 1) * mergedPageSize + 1;\n const rangeEnd = Math.min(displayCurrent * mergedPageSize, total);\n\n return (\n <nav\n aria-label=\"Pagination\"\n className={cx(styles.root, className)}\n ref={ref}\n role=\"navigation\"\n style={style}\n {...rest}\n >\n {showTotal && (\n <span className={styles.total}>{showTotal(total, [rangeStart, rangeEnd])}</span>\n )}\n <button\n aria-label=\"Previous page\"\n className={buttonVariants({ size })}\n disabled={disabled || displayCurrent <= 1}\n type=\"button\"\n onClick={() => goTo(displayCurrent - 1)}\n >\n <ChevronLeft size={size === 'small' ? 14 : 16} />\n </button>\n {items.map((item) =>\n typeof item === 'number' ? (\n <button\n aria-current={item === displayCurrent ? 'page' : undefined}\n className={buttonVariants({ size })}\n disabled={disabled}\n key={item}\n type=\"button\"\n onClick={() => goTo(item)}\n >\n {item}\n </button>\n ) : (\n <span className={ellipsisVariants({ size })} key={item}>\n ···\n </span>\n ),\n )}\n <button\n aria-label=\"Next page\"\n className={buttonVariants({ size })}\n disabled={disabled || displayCurrent >= pageCount}\n type=\"button\"\n onClick={() => goTo(displayCurrent + 1)}\n >\n <ChevronRight size={size === 'small' ? 14 : 16} />\n </button>\n {showSizeChanger && (\n <Select\n disabled={disabled}\n size={size === 'small' ? 'small' : 'middle'}\n style={{ flex: 'none', marginInlineStart: 8, width: 'auto' }}\n value={String(mergedPageSize)}\n options={pageSizeOptions.map((option) => ({\n label: `${option} / page`,\n value: String(option),\n }))}\n onChange={handlePageSizeChange}\n />\n )}\n </nav>\n );\n },\n);\n\nPagination.displayName = 'Pagination';\n\nexport default Pagination;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/base-ui/Pagination/helpers.ts
|
|
2
|
+
const getPageCount = (total, pageSize) => Math.max(1, Math.ceil(total / pageSize));
|
|
3
|
+
const clampPage = (page, pageCount) => Math.min(Math.max(page, 1), pageCount);
|
|
4
|
+
const getPaginationItems = (current, pageCount) => {
|
|
5
|
+
if (pageCount <= 1) return [1];
|
|
6
|
+
const items = [1];
|
|
7
|
+
const start = Math.max(2, current - 2);
|
|
8
|
+
const end = Math.min(pageCount - 1, current + 2);
|
|
9
|
+
if (start > 2) items.push("ellipsis-prev");
|
|
10
|
+
for (let page = start; page <= end; page += 1) items.push(page);
|
|
11
|
+
if (end < pageCount - 1) items.push("ellipsis-next");
|
|
12
|
+
items.push(pageCount);
|
|
13
|
+
return items;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { clampPage, getPageCount, getPaginationItems };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=helpers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../../src/base-ui/Pagination/helpers.ts"],"sourcesContent":["export type PaginationItem = number | 'ellipsis-prev' | 'ellipsis-next';\n\nexport const getPageCount = (total: number, pageSize: number) =>\n Math.max(1, Math.ceil(total / pageSize));\n\nexport const clampPage = (page: number, pageCount: number) =>\n Math.min(Math.max(page, 1), pageCount);\n\nexport const getPaginationItems = (current: number, pageCount: number): PaginationItem[] => {\n if (pageCount <= 1) return [1];\n\n const items: PaginationItem[] = [1];\n const start = Math.max(2, current - 2);\n const end = Math.min(pageCount - 1, current + 2);\n\n if (start > 2) items.push('ellipsis-prev');\n for (let page = start; page <= end; page += 1) items.push(page);\n if (end < pageCount - 1) items.push('ellipsis-next');\n\n items.push(pageCount);\n\n return items;\n};\n"],"mappings":";AAEA,MAAa,gBAAgB,OAAe,aAC1C,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,QAAQ,CAAC;AAEzC,MAAa,aAAa,MAAc,cACtC,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC,GAAG,SAAS;AAEvC,MAAa,sBAAsB,SAAiB,cAAwC;CAC1F,IAAI,aAAa,GAAG,OAAO,CAAC,CAAC;CAE7B,MAAM,QAA0B,CAAC,CAAC;CAClC,MAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,CAAC;CACrC,MAAM,MAAM,KAAK,IAAI,YAAY,GAAG,UAAU,CAAC;CAE/C,IAAI,QAAQ,GAAG,MAAM,KAAK,eAAe;CACzC,KAAK,IAAI,OAAO,OAAO,QAAQ,KAAK,QAAQ,GAAG,MAAM,KAAK,IAAI;CAC9D,IAAI,MAAM,YAAY,GAAG,MAAM,KAAK,eAAe;CAEnD,MAAM,KAAK,SAAS;CAEpB,OAAO;AACT"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createStaticStyles } from "antd-style";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
//#region src/base-ui/Pagination/style.ts
|
|
4
|
+
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
5
|
+
button: css`
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
|
|
12
|
+
min-width: 28px;
|
|
13
|
+
height: 28px;
|
|
14
|
+
padding-inline: 6px;
|
|
15
|
+
border: none;
|
|
16
|
+
border-radius: ${cssVar.borderRadius};
|
|
17
|
+
|
|
18
|
+
font-size: 13px;
|
|
19
|
+
font-weight: 500;
|
|
20
|
+
font-variant-numeric: tabular-nums;
|
|
21
|
+
color: ${cssVar.colorTextSecondary};
|
|
22
|
+
|
|
23
|
+
background: transparent;
|
|
24
|
+
|
|
25
|
+
transition: background-color 0.15s;
|
|
26
|
+
|
|
27
|
+
&:hover:not(:disabled) {
|
|
28
|
+
color: ${cssVar.colorText};
|
|
29
|
+
background: ${cssVar.colorFillTertiary};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:disabled {
|
|
33
|
+
cursor: default;
|
|
34
|
+
color: ${cssVar.colorTextQuaternary};
|
|
35
|
+
background: transparent;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&[aria-current='page'] {
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
color: ${cssVar.colorText};
|
|
41
|
+
background: ${cssVar.colorFillSecondary};
|
|
42
|
+
}
|
|
43
|
+
`,
|
|
44
|
+
ellipsis: css`
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
|
|
49
|
+
width: 28px;
|
|
50
|
+
|
|
51
|
+
color: ${cssVar.colorTextQuaternary};
|
|
52
|
+
letter-spacing: 2px;
|
|
53
|
+
`,
|
|
54
|
+
root: css`
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
gap: 4px;
|
|
57
|
+
align-items: center;
|
|
58
|
+
font-variant-numeric: tabular-nums;
|
|
59
|
+
`,
|
|
60
|
+
small: css`
|
|
61
|
+
min-width: 24px;
|
|
62
|
+
height: 24px;
|
|
63
|
+
font-size: 12px;
|
|
64
|
+
`,
|
|
65
|
+
smallEllipsis: css`
|
|
66
|
+
width: 24px;
|
|
67
|
+
`,
|
|
68
|
+
total: css`
|
|
69
|
+
margin-inline-end: 8px;
|
|
70
|
+
font-size: 12px;
|
|
71
|
+
color: ${cssVar.colorTextTertiary};
|
|
72
|
+
white-space: nowrap;
|
|
73
|
+
`
|
|
74
|
+
}));
|
|
75
|
+
const buttonVariants = cva(styles.button, {
|
|
76
|
+
defaultVariants: { size: "middle" },
|
|
77
|
+
variants: { size: {
|
|
78
|
+
middle: null,
|
|
79
|
+
small: styles.small
|
|
80
|
+
} }
|
|
81
|
+
});
|
|
82
|
+
const ellipsisVariants = cva(styles.ellipsis, {
|
|
83
|
+
defaultVariants: { size: "middle" },
|
|
84
|
+
variants: { size: {
|
|
85
|
+
middle: null,
|
|
86
|
+
small: styles.smallEllipsis
|
|
87
|
+
} }
|
|
88
|
+
});
|
|
89
|
+
//#endregion
|
|
90
|
+
export { buttonVariants, ellipsisVariants, styles };
|
|
91
|
+
|
|
92
|
+
//# sourceMappingURL=style.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Pagination/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n button: css`\n cursor: pointer;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n min-width: 28px;\n height: 28px;\n padding-inline: 6px;\n border: none;\n border-radius: ${cssVar.borderRadius};\n\n font-size: 13px;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorTextSecondary};\n\n background: transparent;\n\n transition: background-color 0.15s;\n\n &:hover:not(:disabled) {\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillTertiary};\n }\n\n &:disabled {\n cursor: default;\n color: ${cssVar.colorTextQuaternary};\n background: transparent;\n }\n\n &[aria-current='page'] {\n font-weight: 600;\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillSecondary};\n }\n `,\n ellipsis: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n width: 28px;\n\n color: ${cssVar.colorTextQuaternary};\n letter-spacing: 2px;\n `,\n root: css`\n display: inline-flex;\n gap: 4px;\n align-items: center;\n font-variant-numeric: tabular-nums;\n `,\n small: css`\n min-width: 24px;\n height: 24px;\n font-size: 12px;\n `,\n smallEllipsis: css`\n width: 24px;\n `,\n total: css`\n margin-inline-end: 8px;\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n white-space: nowrap;\n `,\n}));\n\nexport const buttonVariants = cva(styles.button, {\n defaultVariants: {\n size: 'middle',\n },\n variants: {\n size: {\n middle: null,\n small: styles.small,\n },\n },\n});\n\nexport const ellipsisVariants = cva(styles.ellipsis, {\n defaultVariants: {\n size: 'middle',\n },\n variants: {\n size: {\n middle: null,\n small: styles.smallEllipsis,\n },\n },\n});\n"],"mappings":";;;AAGA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;;;;;;;;;;;qBAWQ,OAAO,aAAa;;;;;aAK5B,OAAO,mBAAmB;;;;;;;eAOxB,OAAO,UAAU;oBACZ,OAAO,kBAAkB;;;;;eAK9B,OAAO,oBAAoB;;;;;;eAM3B,OAAO,UAAU;oBACZ,OAAO,mBAAmB;;;CAG5C,UAAU,GAAG;;;;;;;aAOF,OAAO,oBAAoB;;;CAGtC,MAAM,GAAG;;;;;;CAMT,OAAO,GAAG;;;;;CAKV,eAAe,GAAG;;;CAGlB,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;;AAGtC,EAAE;AAEF,MAAa,iBAAiB,IAAI,OAAO,QAAQ;CAC/C,iBAAiB,EACf,MAAM,SACR;CACA,UAAU,EACR,MAAM;EACJ,QAAQ;EACR,OAAO,OAAO;CAChB,EACF;AACF,CAAC;AAED,MAAa,mBAAmB,IAAI,OAAO,UAAU;CACnD,iBAAiB,EACf,MAAM,SACR;CACA,UAAU,EACR,MAAM;EACJ,QAAQ;EACR,OAAO,OAAO;CAChB,EACF;AACF,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode, Ref } from "react";
|
|
2
|
+
//#region src/base-ui/Pagination/type.d.ts
|
|
3
|
+
type PaginationSize = 'small' | 'middle';
|
|
4
|
+
interface PaginationProps extends Omit<ComponentProps<'nav'>, 'onChange'> {
|
|
5
|
+
current?: number;
|
|
6
|
+
defaultCurrent?: number;
|
|
7
|
+
defaultPageSize?: number;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
hideOnSinglePage?: boolean;
|
|
10
|
+
onChange?: (page: number, pageSize: number) => void;
|
|
11
|
+
onPageSizeChange?: (current: number, size: number) => void;
|
|
12
|
+
pageSize?: number;
|
|
13
|
+
pageSizeOptions?: number[];
|
|
14
|
+
ref?: Ref<HTMLElement>;
|
|
15
|
+
showSizeChanger?: boolean;
|
|
16
|
+
showTotal?: (total: number, range: [number, number]) => ReactNode;
|
|
17
|
+
size?: PaginationSize;
|
|
18
|
+
total: number;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { PaginationProps, PaginationSize };
|
|
22
|
+
//# sourceMappingURL=type.d.mts.map
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Icon from "../../Icon/Icon.mjs";
|
|
3
|
+
import { styles, trackHeight } from "./style.mjs";
|
|
4
|
+
import { memo, useMemo } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { cssVar, cx } from "antd-style";
|
|
7
|
+
import { Check, X } from "lucide-react";
|
|
8
|
+
//#region src/base-ui/Progress/Progress.tsx
|
|
9
|
+
const circleDiameterMap = {
|
|
10
|
+
large: 72,
|
|
11
|
+
middle: 40,
|
|
12
|
+
small: 20
|
|
13
|
+
};
|
|
14
|
+
const circleStrokeMap = {
|
|
15
|
+
large: 4,
|
|
16
|
+
middle: 3,
|
|
17
|
+
small: 2
|
|
18
|
+
};
|
|
19
|
+
const statusColor = {
|
|
20
|
+
active: cssVar.colorInfo,
|
|
21
|
+
exception: cssVar.colorError,
|
|
22
|
+
success: cssVar.colorSuccess
|
|
23
|
+
};
|
|
24
|
+
const Progress = memo(({ className, format, label, percent, ref, segments = 20, showInfo = true, size = "middle", status = "normal", strokeColor, style, type = "line", variant = "line", ...rest }) => {
|
|
25
|
+
const clamped = Math.min(100, Math.max(0, percent));
|
|
26
|
+
const barColor = strokeColor ?? (status === "normal" ? cssVar.colorPrimary : statusColor[status]);
|
|
27
|
+
const info = useMemo(() => {
|
|
28
|
+
if (status === "success") return /* @__PURE__ */ jsx(Icon, {
|
|
29
|
+
icon: Check,
|
|
30
|
+
size: 14,
|
|
31
|
+
style: { color: barColor }
|
|
32
|
+
});
|
|
33
|
+
if (status === "exception") return /* @__PURE__ */ jsx(Icon, {
|
|
34
|
+
icon: X,
|
|
35
|
+
size: 14,
|
|
36
|
+
style: { color: barColor }
|
|
37
|
+
});
|
|
38
|
+
return format ? format(clamped) : `${clamped}%`;
|
|
39
|
+
}, [
|
|
40
|
+
status,
|
|
41
|
+
format,
|
|
42
|
+
clamped,
|
|
43
|
+
barColor
|
|
44
|
+
]);
|
|
45
|
+
const progressAria = {
|
|
46
|
+
"aria-valuemax": 100,
|
|
47
|
+
"aria-valuemin": 0,
|
|
48
|
+
"aria-valuenow": clamped,
|
|
49
|
+
"aria-valuetext": useMemo(() => {
|
|
50
|
+
if (!format) return void 0;
|
|
51
|
+
const value = format(clamped);
|
|
52
|
+
return typeof value === "string" || typeof value === "number" ? String(value) : void 0;
|
|
53
|
+
}, [format, clamped]),
|
|
54
|
+
"role": "progressbar"
|
|
55
|
+
};
|
|
56
|
+
if (type === "circle") {
|
|
57
|
+
const isPreset = typeof size === "string";
|
|
58
|
+
const diameter = isPreset ? circleDiameterMap[size] : size;
|
|
59
|
+
const stroke = isPreset ? circleStrokeMap[size] : Math.max(2, Math.round(diameter * 3 / 40));
|
|
60
|
+
const radius = diameter / 2 - stroke;
|
|
61
|
+
const circumference = 2 * Math.PI * radius;
|
|
62
|
+
const offset = circumference * (1 - clamped / 100);
|
|
63
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
64
|
+
className: cx(styles.circleRoot, className),
|
|
65
|
+
ref,
|
|
66
|
+
style,
|
|
67
|
+
...progressAria,
|
|
68
|
+
...rest,
|
|
69
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
70
|
+
className: styles.circleSvg,
|
|
71
|
+
height: diameter,
|
|
72
|
+
viewBox: `0 0 ${diameter} ${diameter}`,
|
|
73
|
+
width: diameter,
|
|
74
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
75
|
+
className: styles.circleTrack,
|
|
76
|
+
cx: diameter / 2,
|
|
77
|
+
cy: diameter / 2,
|
|
78
|
+
r: radius,
|
|
79
|
+
strokeWidth: stroke
|
|
80
|
+
}), /* @__PURE__ */ jsx("circle", {
|
|
81
|
+
cx: diameter / 2,
|
|
82
|
+
cy: diameter / 2,
|
|
83
|
+
fill: "none",
|
|
84
|
+
r: radius,
|
|
85
|
+
stroke: barColor,
|
|
86
|
+
strokeDasharray: circumference,
|
|
87
|
+
strokeDashoffset: offset,
|
|
88
|
+
strokeLinecap: "round",
|
|
89
|
+
strokeWidth: stroke,
|
|
90
|
+
style: { transition: "stroke-dashoffset 0.3s" }
|
|
91
|
+
})]
|
|
92
|
+
}), showInfo && diameter >= 40 && /* @__PURE__ */ jsx("span", {
|
|
93
|
+
className: styles.circleInfo,
|
|
94
|
+
style: { fontSize: diameter <= 40 ? 12 : 16 },
|
|
95
|
+
children: info
|
|
96
|
+
})]
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const heightStyle = typeof size === "number" ? { height: size } : void 0;
|
|
100
|
+
const heightClass = (family) => typeof size === "number" ? void 0 : trackHeight({
|
|
101
|
+
family,
|
|
102
|
+
size
|
|
103
|
+
});
|
|
104
|
+
if (variant === "segments") {
|
|
105
|
+
const filled = Math.round(segments * clamped / 100);
|
|
106
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
107
|
+
className: cx(styles.rowRoot, className),
|
|
108
|
+
ref,
|
|
109
|
+
style,
|
|
110
|
+
...progressAria,
|
|
111
|
+
...rest,
|
|
112
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
113
|
+
className: cx(styles.segments, heightClass("block")),
|
|
114
|
+
style: heightStyle,
|
|
115
|
+
children: Array.from({ length: segments }, (_, index) => /* @__PURE__ */ jsx("span", {
|
|
116
|
+
className: cx(styles.segment, index < filled && styles.segmentOn),
|
|
117
|
+
style: index < filled ? { background: barColor } : void 0
|
|
118
|
+
}, index))
|
|
119
|
+
}), showInfo && /* @__PURE__ */ jsx("span", {
|
|
120
|
+
className: styles.rowInfo,
|
|
121
|
+
children: info
|
|
122
|
+
})]
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (variant === "inset") return /* @__PURE__ */ jsxs("div", {
|
|
126
|
+
className: cx(styles.rowRoot, className),
|
|
127
|
+
ref,
|
|
128
|
+
style,
|
|
129
|
+
...progressAria,
|
|
130
|
+
...rest,
|
|
131
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
132
|
+
className: cx(styles.rowTrack, styles.insetTrack, heightClass("block")),
|
|
133
|
+
style: heightStyle,
|
|
134
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
135
|
+
className: styles.insetBarWrapper,
|
|
136
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
137
|
+
className: styles.bar,
|
|
138
|
+
style: {
|
|
139
|
+
background: barColor,
|
|
140
|
+
width: `${clamped}%`
|
|
141
|
+
},
|
|
142
|
+
children: /* @__PURE__ */ jsx("span", { className: styles.insetCap })
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
}), showInfo && /* @__PURE__ */ jsx("span", {
|
|
146
|
+
className: styles.rowInfo,
|
|
147
|
+
children: info
|
|
148
|
+
})]
|
|
149
|
+
});
|
|
150
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
151
|
+
className: cx(styles.lineRoot, className),
|
|
152
|
+
ref,
|
|
153
|
+
style,
|
|
154
|
+
...progressAria,
|
|
155
|
+
...rest,
|
|
156
|
+
children: [(label || showInfo) && /* @__PURE__ */ jsxs("div", {
|
|
157
|
+
className: styles.lineMeta,
|
|
158
|
+
children: [/* @__PURE__ */ jsx("span", { children: label }), showInfo && /* @__PURE__ */ jsx("span", {
|
|
159
|
+
className: styles.lineValue,
|
|
160
|
+
children: info
|
|
161
|
+
})]
|
|
162
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
163
|
+
className: cx(styles.lineTrack, heightClass("line")),
|
|
164
|
+
style: heightStyle,
|
|
165
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
166
|
+
style: {
|
|
167
|
+
background: barColor,
|
|
168
|
+
width: `${clamped}%`
|
|
169
|
+
},
|
|
170
|
+
className: cx(styles.bar, variant === "line" && status === "active" && styles.barActive)
|
|
171
|
+
})
|
|
172
|
+
})]
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
Progress.displayName = "Progress";
|
|
176
|
+
//#endregion
|
|
177
|
+
export { Progress as default };
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=Progress.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Progress.mjs","names":[],"sources":["../../../src/base-ui/Progress/Progress.tsx"],"sourcesContent":["'use client';\n\nimport { cssVar, cx } from 'antd-style';\nimport { Check, X } from 'lucide-react';\nimport { memo, useMemo } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { styles, trackHeight } from './style';\nimport type { ProgressProps } from './type';\n\nconst circleDiameterMap: Record<'small' | 'middle' | 'large', number> = {\n large: 72,\n middle: 40,\n small: 20,\n};\nconst circleStrokeMap: Record<'small' | 'middle' | 'large', number> = {\n large: 4,\n middle: 3,\n small: 2,\n};\n\nconst statusColor = {\n active: cssVar.colorInfo,\n exception: cssVar.colorError,\n success: cssVar.colorSuccess,\n};\n\nconst Progress = memo<ProgressProps>(\n ({\n className,\n format,\n label,\n percent,\n ref,\n segments = 20,\n showInfo = true,\n size = 'middle',\n status = 'normal',\n strokeColor,\n style,\n type = 'line',\n variant = 'line',\n ...rest\n }) => {\n const clamped = Math.min(100, Math.max(0, percent));\n const barColor =\n strokeColor ?? (status === 'normal' ? cssVar.colorPrimary : statusColor[status]);\n\n const info = useMemo(() => {\n if (status === 'success') return <Icon icon={Check} size={14} style={{ color: barColor }} />;\n if (status === 'exception') return <Icon icon={X} size={14} style={{ color: barColor }} />;\n return format ? format(clamped) : `${clamped}%`;\n }, [status, format, clamped, barColor]);\n\n const ariaValueText = useMemo(() => {\n if (!format) return undefined;\n const value = format(clamped);\n return typeof value === 'string' || typeof value === 'number' ? String(value) : undefined;\n }, [format, clamped]);\n\n const progressAria = {\n 'aria-valuemax': 100,\n 'aria-valuemin': 0,\n 'aria-valuenow': clamped,\n 'aria-valuetext': ariaValueText,\n 'role': 'progressbar' as const,\n };\n\n if (type === 'circle') {\n const isPreset = typeof size === 'string';\n const diameter = isPreset\n ? circleDiameterMap[size as 'small' | 'middle' | 'large']\n : (size as number);\n const stroke = isPreset\n ? circleStrokeMap[size as 'small' | 'middle' | 'large']\n : Math.max(2, Math.round((diameter * 3) / 40));\n const radius = diameter / 2 - stroke;\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - clamped / 100);\n\n return (\n <div\n className={cx(styles.circleRoot, className)}\n ref={ref}\n style={style}\n {...progressAria}\n {...rest}\n >\n <svg\n className={styles.circleSvg}\n height={diameter}\n viewBox={`0 0 ${diameter} ${diameter}`}\n width={diameter}\n >\n <circle\n className={styles.circleTrack}\n cx={diameter / 2}\n cy={diameter / 2}\n r={radius}\n strokeWidth={stroke}\n />\n <circle\n cx={diameter / 2}\n cy={diameter / 2}\n fill=\"none\"\n r={radius}\n stroke={barColor}\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n strokeLinecap=\"round\"\n strokeWidth={stroke}\n style={{ transition: 'stroke-dashoffset 0.3s' }}\n />\n </svg>\n {showInfo && diameter >= 40 && (\n <span className={styles.circleInfo} style={{ fontSize: diameter <= 40 ? 12 : 16 }}>\n {info}\n </span>\n )}\n </div>\n );\n }\n\n const heightStyle = typeof size === 'number' ? { height: size } : undefined;\n const heightClass = (family: 'line' | 'block') =>\n typeof size === 'number' ? undefined : trackHeight({ family, size });\n\n if (variant === 'segments') {\n const filled = Math.round((segments * clamped) / 100);\n\n return (\n <div\n className={cx(styles.rowRoot, className)}\n ref={ref}\n style={style}\n {...progressAria}\n {...rest}\n >\n <div className={cx(styles.segments, heightClass('block'))} style={heightStyle}>\n {Array.from({ length: segments }, (_, index) => (\n <span\n className={cx(styles.segment, index < filled && styles.segmentOn)}\n key={index}\n style={index < filled ? { background: barColor } : undefined}\n />\n ))}\n </div>\n {showInfo && <span className={styles.rowInfo}>{info}</span>}\n </div>\n );\n }\n\n if (variant === 'inset') {\n return (\n <div\n className={cx(styles.rowRoot, className)}\n ref={ref}\n style={style}\n {...progressAria}\n {...rest}\n >\n <div\n className={cx(styles.rowTrack, styles.insetTrack, heightClass('block'))}\n style={heightStyle}\n >\n <div className={styles.insetBarWrapper}>\n <div className={styles.bar} style={{ background: barColor, width: `${clamped}%` }}>\n <span className={styles.insetCap} />\n </div>\n </div>\n </div>\n {showInfo && <span className={styles.rowInfo}>{info}</span>}\n </div>\n );\n }\n\n return (\n <div\n className={cx(styles.lineRoot, className)}\n ref={ref}\n style={style}\n {...progressAria}\n {...rest}\n >\n {(label || showInfo) && (\n <div className={styles.lineMeta}>\n <span>{label}</span>\n {showInfo && <span className={styles.lineValue}>{info}</span>}\n </div>\n )}\n <div className={cx(styles.lineTrack, heightClass('line'))} style={heightStyle}>\n <div\n style={{ background: barColor, width: `${clamped}%` }}\n className={cx(\n styles.bar,\n variant === 'line' && status === 'active' && styles.barActive,\n )}\n />\n </div>\n </div>\n );\n },\n);\n\nProgress.displayName = 'Progress';\n\nexport default Progress;\n"],"mappings":"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"}
|