@mbao01/common 0.9.0 → 0.9.1
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/types/components/IconContainer/IconContainer.d.ts +2 -0
- package/dist/types/components/IconContainer/constants.d.ts +15 -0
- package/dist/types/components/IconContainer/index.d.ts +1 -0
- package/dist/types/components/IconContainer/types.d.ts +3 -0
- package/dist/types/components/KPICard/KPICard.d.ts +1 -1
- package/dist/types/components/KPICard/types.d.ts +2 -6
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/IconContainer/IconContainer.tsx +44 -0
- package/src/components/IconContainer/constants.ts +112 -0
- package/src/components/IconContainer/index.ts +1 -0
- package/src/components/IconContainer/types.ts +5 -0
- package/src/components/KPICard/KPICard.tsx +16 -26
- package/src/components/KPICard/types.ts +2 -6
- package/src/index.ts +1 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const getIconRaisedContainerClasses: (props?: ({
|
|
2
|
+
variant?: "accent" | "default" | "error" | "ghost" | "info" | "neutral" | "primary" | "secondary" | "success" | "warning" | null | undefined;
|
|
3
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | null | undefined;
|
|
4
|
+
shadow?: "sm" | "md" | "lg" | "xl" | "none" | null | undefined;
|
|
5
|
+
raised?: boolean | null | undefined;
|
|
6
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
export declare const getIconContainerClasses: (props?: ({
|
|
8
|
+
variant?: "accent" | "default" | "error" | "ghost" | "info" | "neutral" | "primary" | "secondary" | "success" | "warning" | null | undefined;
|
|
9
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | null | undefined;
|
|
10
|
+
shape?: "rounded" | "circle" | "square" | null | undefined;
|
|
11
|
+
shadow?: "sm" | "md" | "lg" | "xl" | "none" | null | undefined;
|
|
12
|
+
outline?: boolean | null | undefined;
|
|
13
|
+
soft?: boolean | null | undefined;
|
|
14
|
+
raised?: boolean | null | undefined;
|
|
15
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IconContainer } from './IconContainer';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KPICardProps } from './types';
|
|
2
2
|
declare const KPICard: {
|
|
3
|
-
({ title, value, change, description,
|
|
3
|
+
({ title, value, change, description, chart, icon, loading, className, ...props }: KPICardProps): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
displayName: string;
|
|
5
5
|
};
|
|
6
6
|
export { KPICard };
|
|
@@ -8,12 +8,8 @@ export type KPICardProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
8
8
|
change?: number;
|
|
9
9
|
/** Description text below value */
|
|
10
10
|
description?: string;
|
|
11
|
-
/** Sparkline
|
|
12
|
-
|
|
13
|
-
/** Sparkline color */
|
|
14
|
-
sparklineColor?: string;
|
|
15
|
-
/** Whether sparkline is filled */
|
|
16
|
-
sparklineFilled?: boolean;
|
|
11
|
+
/** Inline chart element (e.g. Sparkline, MiniBarChart, MiniAreaChart, MiniDonutChart, MiniStackedBar) */
|
|
12
|
+
chart?: ReactNode;
|
|
17
13
|
/** Icon to show in the card */
|
|
18
14
|
icon?: ReactNode;
|
|
19
15
|
/** Loading state */
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from './components/Heading';
|
|
|
21
21
|
export * from './components/Paragraph';
|
|
22
22
|
/** utility & atoms */
|
|
23
23
|
export * from './components/AspectRatio';
|
|
24
|
+
export * from './components/IconContainer';
|
|
24
25
|
export * from './components/Image';
|
|
25
26
|
export * from './components/Spinner';
|
|
26
27
|
/** data display */
|
package/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { cn } from "../../utilities";
|
|
2
|
+
import { getIconContainerClasses, getIconRaisedContainerClasses } from "./constants";
|
|
3
|
+
import { type IconContainerProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export const IconContainer = ({
|
|
6
|
+
variant,
|
|
7
|
+
size,
|
|
8
|
+
shape,
|
|
9
|
+
shadow,
|
|
10
|
+
outline,
|
|
11
|
+
soft,
|
|
12
|
+
raised,
|
|
13
|
+
className,
|
|
14
|
+
children,
|
|
15
|
+
...props
|
|
16
|
+
}: IconContainerProps) => {
|
|
17
|
+
const content = raised ? (
|
|
18
|
+
<div className={getIconRaisedContainerClasses({ size, variant, shadow, raised })}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
) : (
|
|
22
|
+
children
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
className={cn(
|
|
28
|
+
getIconContainerClasses({
|
|
29
|
+
size,
|
|
30
|
+
soft,
|
|
31
|
+
shape,
|
|
32
|
+
variant,
|
|
33
|
+
outline,
|
|
34
|
+
raised,
|
|
35
|
+
shadow: raised ? "none" : shadow,
|
|
36
|
+
}),
|
|
37
|
+
className
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
{content}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { cva } from "../../libs";
|
|
2
|
+
import { createVariants } from "../../utilities";
|
|
3
|
+
|
|
4
|
+
const variants = createVariants({
|
|
5
|
+
variant: {
|
|
6
|
+
accent: "bg-accent text-accent-content",
|
|
7
|
+
default: "bg-base-200 text-base-content",
|
|
8
|
+
error: "bg-error text-error-content",
|
|
9
|
+
ghost: "bg-ghost text-ghost-content",
|
|
10
|
+
info: "bg-info text-info-content",
|
|
11
|
+
neutral: "bg-neutral text-neutral-content",
|
|
12
|
+
primary: "bg-primary text-primary-content",
|
|
13
|
+
secondary: "bg-secondary text-secondary-content",
|
|
14
|
+
success: "bg-success text-success-content",
|
|
15
|
+
warning: "bg-warning text-warning-content",
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
xs: "size-6 text-xs",
|
|
19
|
+
sm: "size-8 text-sm",
|
|
20
|
+
md: "size-10 text-base",
|
|
21
|
+
lg: "size-12 text-lg",
|
|
22
|
+
xl: "size-16 text-2xl",
|
|
23
|
+
},
|
|
24
|
+
shape: {
|
|
25
|
+
circle: "rounded-full",
|
|
26
|
+
square: "rounded-none",
|
|
27
|
+
rounded: "rounded-lg",
|
|
28
|
+
},
|
|
29
|
+
shadow: {
|
|
30
|
+
none: "",
|
|
31
|
+
sm: "shadow-sm",
|
|
32
|
+
md: "shadow-md",
|
|
33
|
+
lg: "shadow-lg",
|
|
34
|
+
xl: "shadow-xl",
|
|
35
|
+
},
|
|
36
|
+
outline: {
|
|
37
|
+
true: "bg-transparent ring-2 ring-offset-2 ring-offset-base-100",
|
|
38
|
+
},
|
|
39
|
+
soft: {
|
|
40
|
+
true: "",
|
|
41
|
+
},
|
|
42
|
+
raised: {
|
|
43
|
+
true: "ring-3 ring-base-200 bg-base-200 [&>div]:bg-base-100 [&>div]:size-[inherit] [&>div]:rounded-[inherit]",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const getIconRaisedContainerClasses = cva(
|
|
48
|
+
"inline-flex items-center justify-center shrink-0 [&>svg]:size-[1em]",
|
|
49
|
+
{
|
|
50
|
+
variants: createVariants({
|
|
51
|
+
variant: {
|
|
52
|
+
accent: "bg-accent text-accent",
|
|
53
|
+
default: "bg-base-200 text-base",
|
|
54
|
+
error: "bg-error text-error",
|
|
55
|
+
ghost: "bg-ghost text-ghost",
|
|
56
|
+
info: "bg-info text-info",
|
|
57
|
+
neutral: "bg-neutral text-neutral",
|
|
58
|
+
primary: "bg-primary text-primary",
|
|
59
|
+
secondary: "bg-secondary text-secondary",
|
|
60
|
+
success: "bg-success text-success",
|
|
61
|
+
warning: "bg-warning text-warning",
|
|
62
|
+
},
|
|
63
|
+
size: variants.size,
|
|
64
|
+
shadow: variants.shadow,
|
|
65
|
+
raised: {
|
|
66
|
+
true: "",
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
defaultVariants: {
|
|
70
|
+
variant: "default",
|
|
71
|
+
size: "md",
|
|
72
|
+
shadow: "md",
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
export const getIconContainerClasses = cva(
|
|
78
|
+
"inline-flex items-center justify-center shrink-0 [&>svg]:size-[1em]",
|
|
79
|
+
{
|
|
80
|
+
variants,
|
|
81
|
+
compoundVariants: [
|
|
82
|
+
// soft: pastel bg with colored icon
|
|
83
|
+
{ variant: "accent", soft: true, class: "bg-accent/10 text-accent" },
|
|
84
|
+
{ variant: "default", soft: true, class: "bg-base-200/50 text-base-content" },
|
|
85
|
+
{ variant: "error", soft: true, class: "bg-error/10 text-error" },
|
|
86
|
+
{ variant: "ghost", soft: true, class: "bg-base-100 text-base-content" },
|
|
87
|
+
{ variant: "info", soft: true, class: "bg-info/10 text-info" },
|
|
88
|
+
{ variant: "neutral", soft: true, class: "bg-neutral/10 text-neutral" },
|
|
89
|
+
{ variant: "primary", soft: true, class: "bg-primary/10 text-primary" },
|
|
90
|
+
{ variant: "secondary", soft: true, class: "bg-secondary/10 text-secondary" },
|
|
91
|
+
{ variant: "success", soft: true, class: "bg-success/10 text-success" },
|
|
92
|
+
{ variant: "warning", soft: true, class: "bg-warning/10 text-warning" },
|
|
93
|
+
// outline: variant dictates ring color and icon color
|
|
94
|
+
{ variant: "accent", outline: true, class: "ring-accent text-accent" },
|
|
95
|
+
{ variant: "default", outline: true, class: "ring-base-300 text-base-content" },
|
|
96
|
+
{ variant: "error", outline: true, class: "ring-error text-error" },
|
|
97
|
+
{ variant: "ghost", outline: true, class: "ring-base-300 text-base-content" },
|
|
98
|
+
{ variant: "info", outline: true, class: "ring-info text-info" },
|
|
99
|
+
{ variant: "neutral", outline: true, class: "ring-neutral text-neutral" },
|
|
100
|
+
{ variant: "primary", outline: true, class: "ring-primary text-primary" },
|
|
101
|
+
{ variant: "secondary", outline: true, class: "ring-secondary text-secondary" },
|
|
102
|
+
{ variant: "success", outline: true, class: "ring-success text-success" },
|
|
103
|
+
{ variant: "warning", outline: true, class: "ring-warning text-warning" },
|
|
104
|
+
],
|
|
105
|
+
defaultVariants: {
|
|
106
|
+
variant: "default",
|
|
107
|
+
size: "md",
|
|
108
|
+
shape: "circle",
|
|
109
|
+
shadow: "md",
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IconContainer } from "./IconContainer";
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
import type { KPICardProps } from "./types";
|
|
1
2
|
import { cn } from "../../utilities";
|
|
2
|
-
import {
|
|
3
|
+
import { Skeleton } from "../Skeleton";
|
|
3
4
|
import { TrendBadge } from "../TrendBadge";
|
|
4
|
-
import type { KPICardProps } from "./types";
|
|
5
5
|
|
|
6
6
|
const KPICard = ({
|
|
7
7
|
title,
|
|
8
8
|
value,
|
|
9
9
|
change,
|
|
10
10
|
description,
|
|
11
|
-
|
|
12
|
-
sparklineColor,
|
|
13
|
-
sparklineFilled = true,
|
|
11
|
+
chart,
|
|
14
12
|
icon,
|
|
15
13
|
loading = false,
|
|
16
14
|
className,
|
|
@@ -26,15 +24,15 @@ const KPICard = ({
|
|
|
26
24
|
{...props}
|
|
27
25
|
>
|
|
28
26
|
<div className="flex items-center justify-between">
|
|
29
|
-
<
|
|
30
|
-
{icon && <
|
|
27
|
+
<Skeleton className="h-4 w-24 rounded" />
|
|
28
|
+
{icon && <Skeleton className="size-8 rounded-md" />}
|
|
31
29
|
</div>
|
|
32
|
-
<div className="mt-
|
|
30
|
+
<div className="mt-4 flex items-end justify-between gap-4">
|
|
33
31
|
<div className="flex flex-col gap-1.5">
|
|
34
|
-
<
|
|
35
|
-
<
|
|
32
|
+
<Skeleton className="h-7 w-28 rounded" />
|
|
33
|
+
<Skeleton className="h-3.5 w-20 rounded" />
|
|
36
34
|
</div>
|
|
37
|
-
<
|
|
35
|
+
<Skeleton className="h-8 w-20 rounded" />
|
|
38
36
|
</div>
|
|
39
37
|
</div>
|
|
40
38
|
);
|
|
@@ -43,38 +41,30 @@ const KPICard = ({
|
|
|
43
41
|
return (
|
|
44
42
|
<div
|
|
45
43
|
className={cn(
|
|
46
|
-
"rounded-lg border bg-base-100 p-4 shadow-sm transition-shadow duration-300 hover:shadow-md",
|
|
44
|
+
"w-full @container/kpicard overflow-hidden rounded-lg border bg-base-100 p-4 shadow-sm transition-shadow duration-300 hover:shadow-md",
|
|
47
45
|
className
|
|
48
46
|
)}
|
|
49
47
|
{...props}
|
|
50
48
|
>
|
|
51
49
|
<div className="flex items-center justify-between">
|
|
52
|
-
<span className="text-sm font-medium text-base-content/60">{title}</span>
|
|
50
|
+
<span className="min-w-0 truncate text-sm font-medium text-base-content/60">{title}</span>
|
|
53
51
|
{icon && (
|
|
54
|
-
<div className="flex size-8 items-center justify-center rounded-md bg-base-200/50 text-base-content/60">
|
|
52
|
+
<div className="flex size-8 shrink-0 items-center justify-center rounded-md bg-base-200/50 text-base-content/60">
|
|
55
53
|
{icon}
|
|
56
54
|
</div>
|
|
57
55
|
)}
|
|
58
56
|
</div>
|
|
59
57
|
<div className="mt-3 flex items-end justify-between gap-4">
|
|
60
|
-
<div className="flex flex-col gap-1">
|
|
61
|
-
<span className="text-2xl font-bold tracking-tight">{value}</span>
|
|
58
|
+
<div className="min-w-0 flex flex-col gap-1">
|
|
59
|
+
<span className="truncate text-2xl font-bold tracking-tight">{value}</span>
|
|
62
60
|
<div className="flex items-center gap-2">
|
|
63
61
|
{change !== undefined && <TrendBadge value={change} size="xs" />}
|
|
64
62
|
{description && (
|
|
65
|
-
<span className="text-xs text-base-content/50">{description}</span>
|
|
63
|
+
<span className="truncate text-xs text-base-content/50">{description}</span>
|
|
66
64
|
)}
|
|
67
65
|
</div>
|
|
68
66
|
</div>
|
|
69
|
-
{
|
|
70
|
-
<Sparkline
|
|
71
|
-
data={sparklineData}
|
|
72
|
-
color={sparklineColor ?? (change !== undefined && change >= 0 ? "oklch(0.7 0.2 150)" : "oklch(0.65 0.25 25)")}
|
|
73
|
-
filled={sparklineFilled}
|
|
74
|
-
width={80}
|
|
75
|
-
height={32}
|
|
76
|
-
/>
|
|
77
|
-
)}
|
|
67
|
+
{chart && <div className="shrink-0 @max-[160px]/kpicard:hidden">{chart}</div>}
|
|
78
68
|
</div>
|
|
79
69
|
</div>
|
|
80
70
|
);
|
|
@@ -9,12 +9,8 @@ export type KPICardProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
9
9
|
change?: number;
|
|
10
10
|
/** Description text below value */
|
|
11
11
|
description?: string;
|
|
12
|
-
/** Sparkline
|
|
13
|
-
|
|
14
|
-
/** Sparkline color */
|
|
15
|
-
sparklineColor?: string;
|
|
16
|
-
/** Whether sparkline is filled */
|
|
17
|
-
sparklineFilled?: boolean;
|
|
12
|
+
/** Inline chart element (e.g. Sparkline, MiniBarChart, MiniAreaChart, MiniDonutChart, MiniStackedBar) */
|
|
13
|
+
chart?: ReactNode;
|
|
18
14
|
/** Icon to show in the card */
|
|
19
15
|
icon?: ReactNode;
|
|
20
16
|
/** Loading state */
|
package/src/index.ts
CHANGED