analytica-frontend-lib 1.0.22 → 1.0.24
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/chunk-CETSS3RA.mjs +52 -0
- package/dist/chunk-GSEO6POW.mjs +93 -0
- package/dist/chunk-IB4IJ3GF.mjs +60 -0
- package/dist/chunk-IH5TEC64.mjs +35 -0
- package/dist/chunk-JNPCNN67.mjs +86 -0
- package/dist/chunk-KT6HNGRV.mjs +241 -0
- package/dist/chunk-LYOJCBOM.mjs +195 -0
- package/dist/chunk-MI5FIRHM.mjs +75 -0
- package/dist/chunk-NWGRQN6R.mjs +108 -0
- package/dist/chunk-QODEDLAX.mjs +142 -0
- package/dist/chunk-QOFMTSHE.mjs +44 -0
- package/dist/chunk-RPYPJ5O5.mjs +55 -0
- package/dist/chunk-SESX5OEP.mjs +57 -0
- package/dist/chunk-TT3VCQGR.mjs +53 -0
- package/dist/chunk-WIOCQOM7.mjs +20 -0
- package/dist/client-components.d.mts +9 -0
- package/dist/client-components.d.ts +9 -0
- package/dist/client-components.js +755 -0
- package/dist/client-components.mjs +39 -0
- package/dist/components/Alert/Alert.d.mts +13 -0
- package/dist/components/Alert/Alert.d.ts +13 -0
- package/dist/components/Alert/Alert.js +158 -0
- package/dist/components/Alert/Alert.mjs +7 -0
- package/dist/components/Badge/Badge.d.mts +47 -0
- package/dist/components/Badge/Badge.d.ts +47 -0
- package/dist/components/Badge/Badge.js +117 -0
- package/dist/components/Badge/Badge.mjs +6 -0
- package/dist/components/Button/Button.d.mts +46 -0
- package/dist/components/Button/Button.d.ts +46 -0
- package/dist/components/Button/Button.js +84 -0
- package/dist/components/Button/Button.mjs +6 -0
- package/dist/components/CheckBox/CheckBox.d.mts +74 -0
- package/dist/components/CheckBox/CheckBox.d.ts +74 -0
- package/dist/components/CheckBox/CheckBox.js +264 -0
- package/dist/components/CheckBox/CheckBox.mjs +8 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.mts +29 -0
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +29 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +262 -0
- package/dist/components/DropdownMenu/DropdownMenu.mjs +17 -0
- package/dist/components/IconButton/IconButton.d.mts +77 -0
- package/dist/components/IconButton/IconButton.d.ts +77 -0
- package/dist/components/IconButton/IconButton.js +79 -0
- package/dist/components/IconButton/IconButton.mjs +6 -0
- package/dist/components/IconRoundedButton/IconRoundedButton.d.mts +35 -0
- package/dist/components/IconRoundedButton/IconRoundedButton.d.ts +35 -0
- package/dist/components/IconRoundedButton/IconRoundedButton.js +68 -0
- package/dist/components/IconRoundedButton/IconRoundedButton.mjs +6 -0
- package/dist/components/NavButton/NavButton.d.mts +58 -0
- package/dist/components/NavButton/NavButton.d.ts +58 -0
- package/dist/components/NavButton/NavButton.js +76 -0
- package/dist/components/NavButton/NavButton.mjs +6 -0
- package/dist/components/SelectionButton/SelectionButton.d.mts +58 -0
- package/dist/components/SelectionButton/SelectionButton.d.ts +58 -0
- package/dist/components/SelectionButton/SelectionButton.js +81 -0
- package/dist/components/SelectionButton/SelectionButton.mjs +6 -0
- package/dist/components/Table/Table.d.mts +17 -0
- package/dist/components/Table/Table.d.ts +17 -0
- package/dist/components/Table/Table.js +139 -0
- package/dist/components/Table/Table.mjs +20 -0
- package/dist/components/Text/Text.d.mts +59 -0
- package/dist/components/Text/Text.d.ts +59 -0
- package/dist/components/Text/Text.js +77 -0
- package/dist/components/Text/Text.mjs +6 -0
- package/dist/components/TextArea/TextArea.d.mts +69 -0
- package/dist/components/TextArea/TextArea.d.ts +69 -0
- package/dist/components/TextArea/TextArea.js +211 -0
- package/dist/components/TextArea/TextArea.mjs +8 -0
- package/dist/components/Toast/Toast.d.mts +17 -0
- package/dist/components/Toast/Toast.d.ts +17 -0
- package/dist/components/Toast/Toast.js +100 -0
- package/dist/components/Toast/Toast.mjs +7 -0
- package/dist/components/Toast/utils/ToastStore.d.mts +19 -0
- package/dist/components/Toast/utils/ToastStore.d.ts +19 -0
- package/dist/components/Toast/utils/ToastStore.js +44 -0
- package/dist/components/Toast/utils/ToastStore.mjs +6 -0
- package/dist/components/Toast/utils/Toaster.d.mts +11 -0
- package/dist/components/Toast/utils/Toaster.d.ts +11 -0
- package/dist/components/Toast/utils/Toaster.js +145 -0
- package/dist/components/Toast/utils/Toaster.mjs +11 -0
- package/dist/index.d.mts +168 -355
- package/dist/index.d.ts +168 -355
- package/dist/index.js +341 -936
- package/dist/index.mjs +340 -941
- package/dist/server-components.d.mts +11 -0
- package/dist/server-components.d.ts +11 -0
- package/dist/server-components.js +629 -0
- package/dist/server-components.mjs +52 -0
- package/package.json +76 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/components/NavButton/NavButton.tsx
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var NavButton = forwardRef(
|
|
5
|
+
({ icon, label, selected = false, className = "", disabled, ...props }, ref) => {
|
|
6
|
+
const baseClasses = [
|
|
7
|
+
"flex",
|
|
8
|
+
"flex-col",
|
|
9
|
+
"items-center",
|
|
10
|
+
"justify-center",
|
|
11
|
+
"gap-0.5",
|
|
12
|
+
"px-12",
|
|
13
|
+
"py-1",
|
|
14
|
+
"rounded-sm",
|
|
15
|
+
"cursor-pointer",
|
|
16
|
+
"text-text-950",
|
|
17
|
+
"text-xs",
|
|
18
|
+
"font-medium",
|
|
19
|
+
"hover:text-text",
|
|
20
|
+
"hover:bg-primary-600",
|
|
21
|
+
"focus-visible:outline-none",
|
|
22
|
+
"focus-visible:ring-2",
|
|
23
|
+
"focus-visible:ring-offset-0",
|
|
24
|
+
"focus-visible:ring-indicator-info",
|
|
25
|
+
"disabled:opacity-50",
|
|
26
|
+
"disabled:cursor-not-allowed",
|
|
27
|
+
"disabled:pointer-events-none"
|
|
28
|
+
];
|
|
29
|
+
const stateClasses = selected ? ["bg-primary-50", "text-primary-950"] : [];
|
|
30
|
+
const allClasses = [...baseClasses, ...stateClasses].join(" ");
|
|
31
|
+
return /* @__PURE__ */ jsxs(
|
|
32
|
+
"button",
|
|
33
|
+
{
|
|
34
|
+
ref,
|
|
35
|
+
type: "button",
|
|
36
|
+
className: `${allClasses} ${className}`,
|
|
37
|
+
disabled,
|
|
38
|
+
"aria-pressed": selected,
|
|
39
|
+
...props,
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-5 h-5", children: icon }),
|
|
42
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: label })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
NavButton.displayName = "NavButton";
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
NavButton
|
|
52
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/components/Badge/Badge.tsx
|
|
2
|
+
import { Bell } from "phosphor-react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var VARIANT_ACTION_CLASSES = {
|
|
5
|
+
solid: {
|
|
6
|
+
error: "bg-error text-error-700 focus-visible:outline-none",
|
|
7
|
+
warning: "bg-warning text-warning-800 focus-visible:outline-none",
|
|
8
|
+
success: "bg-success text-success-800 focus-visible:outline-none",
|
|
9
|
+
info: "bg-info text-info-800 focus-visible:outline-none",
|
|
10
|
+
muted: "bg-background-muted text-background-800 focus-visible:outline-none"
|
|
11
|
+
},
|
|
12
|
+
outlined: {
|
|
13
|
+
error: "bg-error text-error-700 border border-error-300 focus-visible:outline-none",
|
|
14
|
+
warning: "bg-warning text-warning-800 border border-warning-300 focus-visible:outline-none",
|
|
15
|
+
success: "bg-success text-success-800 border border-success-300 focus-visible:outline-none",
|
|
16
|
+
info: "bg-info text-info-800 border border-info-300 focus-visible:outline-none",
|
|
17
|
+
muted: "bg-background-muted text-background-800 border border-border-300 focus-visible:outline-none"
|
|
18
|
+
},
|
|
19
|
+
exams: {
|
|
20
|
+
exam1: "bg-exam-1 text-info-200 focus-visible:outline-none",
|
|
21
|
+
exam2: "bg-exam-2 text-typography-1 focus-visible:outline-none",
|
|
22
|
+
exam3: "bg-exam-3 text-typography-2 focus-visible:outline-none",
|
|
23
|
+
exam4: "bg-exam-4 text-success-700 focus-visible:outline-none"
|
|
24
|
+
},
|
|
25
|
+
resultStatus: {
|
|
26
|
+
negative: "bg-error text-error-800 focus-visible:outline-none",
|
|
27
|
+
positive: "bg-success text-success-800 focus-visible:outline-none"
|
|
28
|
+
},
|
|
29
|
+
notification: "text-primary"
|
|
30
|
+
};
|
|
31
|
+
var SIZE_CLASSES = {
|
|
32
|
+
small: "text-2xs px-2 py-1",
|
|
33
|
+
medium: "text-xs px-2 py-1",
|
|
34
|
+
large: "text-sm px-2 py-1"
|
|
35
|
+
};
|
|
36
|
+
var SIZE_CLASSES_ICON = {
|
|
37
|
+
small: "size-3",
|
|
38
|
+
medium: "size-3.5",
|
|
39
|
+
large: "size-4"
|
|
40
|
+
};
|
|
41
|
+
var Badge = ({
|
|
42
|
+
children,
|
|
43
|
+
iconLeft,
|
|
44
|
+
iconRight,
|
|
45
|
+
size = "medium",
|
|
46
|
+
variant = "solid",
|
|
47
|
+
action = "error",
|
|
48
|
+
className = "",
|
|
49
|
+
notificationActive = false,
|
|
50
|
+
...props
|
|
51
|
+
}) => {
|
|
52
|
+
const sizeClasses = SIZE_CLASSES[size];
|
|
53
|
+
const sizeClassesIcon = SIZE_CLASSES_ICON[size];
|
|
54
|
+
const variantActionMap = VARIANT_ACTION_CLASSES[variant] || {};
|
|
55
|
+
const variantClasses = typeof variantActionMap === "string" ? variantActionMap : variantActionMap[action] ?? variantActionMap.muted ?? "";
|
|
56
|
+
const baseClasses = "inline-flex items-center justify-center rounded-xs font-medium gap-1 relative";
|
|
57
|
+
const baseClassesIcon = "flex items-center";
|
|
58
|
+
if (variant === "notification") {
|
|
59
|
+
return /* @__PURE__ */ jsxs(
|
|
60
|
+
"div",
|
|
61
|
+
{
|
|
62
|
+
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
|
|
63
|
+
...props,
|
|
64
|
+
children: [
|
|
65
|
+
/* @__PURE__ */ jsx(Bell, { size: 24, className: "text-primary-950" }),
|
|
66
|
+
notificationActive && /* @__PURE__ */ jsx(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
"data-testid": "notification-dot",
|
|
70
|
+
className: "absolute top-[5px] right-[10px] block h-2 w-2 rounded-full bg-indicator-error ring-2 ring-white"
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return /* @__PURE__ */ jsxs(
|
|
78
|
+
"div",
|
|
79
|
+
{
|
|
80
|
+
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
|
|
81
|
+
...props,
|
|
82
|
+
children: [
|
|
83
|
+
iconLeft && /* @__PURE__ */ jsx("span", { className: `${baseClassesIcon} ${sizeClassesIcon}`, children: iconLeft }),
|
|
84
|
+
children,
|
|
85
|
+
iconRight && /* @__PURE__ */ jsx("span", { className: `${baseClassesIcon} ${sizeClassesIcon}`, children: iconRight })
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
Badge
|
|
93
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/components/Button/Button.tsx
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
var VARIANT_ACTION_CLASSES = {
|
|
4
|
+
solid: {
|
|
5
|
+
primary: "bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
6
|
+
positive: "bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
7
|
+
negative: "bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed"
|
|
8
|
+
},
|
|
9
|
+
outline: {
|
|
10
|
+
primary: "bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
11
|
+
positive: "bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
12
|
+
negative: "bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
|
|
13
|
+
},
|
|
14
|
+
link: {
|
|
15
|
+
primary: "bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
16
|
+
positive: "bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
17
|
+
negative: "bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var SIZE_CLASSES = {
|
|
21
|
+
"extra-small": "text-xs px-3.5 py-2",
|
|
22
|
+
small: "text-sm px-4 py-2.5",
|
|
23
|
+
medium: "text-md px-5 py-2.5",
|
|
24
|
+
large: "text-lg px-6 py-3",
|
|
25
|
+
"extra-large": "text-lg px-7 py-3.5"
|
|
26
|
+
};
|
|
27
|
+
var Button = ({
|
|
28
|
+
children,
|
|
29
|
+
iconLeft,
|
|
30
|
+
iconRight,
|
|
31
|
+
size = "medium",
|
|
32
|
+
variant = "solid",
|
|
33
|
+
action = "primary",
|
|
34
|
+
className = "",
|
|
35
|
+
disabled,
|
|
36
|
+
type = "button",
|
|
37
|
+
...props
|
|
38
|
+
}) => {
|
|
39
|
+
const sizeClasses = SIZE_CLASSES[size];
|
|
40
|
+
const variantClasses = VARIANT_ACTION_CLASSES[variant][action];
|
|
41
|
+
const baseClasses = "inline-flex items-center justify-center rounded-full cursor-pointer font-medium";
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"button",
|
|
44
|
+
{
|
|
45
|
+
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
|
|
46
|
+
disabled,
|
|
47
|
+
type,
|
|
48
|
+
...props,
|
|
49
|
+
children: [
|
|
50
|
+
iconLeft && /* @__PURE__ */ jsx("span", { className: "mr-2 flex items-center", children: iconLeft }),
|
|
51
|
+
children,
|
|
52
|
+
iconRight && /* @__PURE__ */ jsx("span", { className: "ml-2 flex items-center", children: iconRight })
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
Button
|
|
60
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Toast
|
|
3
|
+
} from "./chunk-MI5FIRHM.mjs";
|
|
4
|
+
import {
|
|
5
|
+
useToastStore
|
|
6
|
+
} from "./chunk-WIOCQOM7.mjs";
|
|
7
|
+
|
|
8
|
+
// src/components/Toast/utils/Toaster.tsx
|
|
9
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
10
|
+
var Toaster = () => {
|
|
11
|
+
const toasts = useToastStore((state) => state.toasts);
|
|
12
|
+
const removeToast = useToastStore((state) => state.removeToast);
|
|
13
|
+
return /* @__PURE__ */ jsx(Fragment, { children: toasts.map((toast) => /* @__PURE__ */ jsx(
|
|
14
|
+
Toast,
|
|
15
|
+
{
|
|
16
|
+
title: toast.title,
|
|
17
|
+
description: toast.description,
|
|
18
|
+
variant: toast.variant,
|
|
19
|
+
action: toast.action,
|
|
20
|
+
position: toast.position,
|
|
21
|
+
onClose: () => removeToast(toast.id)
|
|
22
|
+
},
|
|
23
|
+
toast.id
|
|
24
|
+
)) });
|
|
25
|
+
};
|
|
26
|
+
var useToast = () => {
|
|
27
|
+
const addToast = useToastStore((state) => state.addToast);
|
|
28
|
+
const removeToast = useToastStore((state) => state.removeToast);
|
|
29
|
+
return { addToast, removeToast };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
Toaster,
|
|
34
|
+
useToast
|
|
35
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Text
|
|
3
|
+
} from "./chunk-TT3VCQGR.mjs";
|
|
4
|
+
|
|
5
|
+
// src/components/Alert/Alert.tsx
|
|
6
|
+
import { CheckCircle, Info, WarningCircle, XCircle } from "phosphor-react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var VARIANT_ACTION_CLASSES = {
|
|
9
|
+
solid: {
|
|
10
|
+
default: "bg-background-50 border-transparent",
|
|
11
|
+
info: "bg-info border-transparent",
|
|
12
|
+
success: "bg-success border-transparent",
|
|
13
|
+
warning: "bg-warning border-transparent",
|
|
14
|
+
error: "bg-error border-transparent"
|
|
15
|
+
},
|
|
16
|
+
outline: {
|
|
17
|
+
default: "bg-background border border-border-100",
|
|
18
|
+
info: "bg-background border border-border-100",
|
|
19
|
+
success: "bg-background border border-border-100",
|
|
20
|
+
warning: "bg-background border border-border-100",
|
|
21
|
+
error: "bg-background border border-border-100"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var COLOR_CLASSES = {
|
|
25
|
+
default: "text-text-950",
|
|
26
|
+
info: "text-info-800",
|
|
27
|
+
success: "text-success-800",
|
|
28
|
+
warning: "text-warning-800",
|
|
29
|
+
error: "text-error-800"
|
|
30
|
+
};
|
|
31
|
+
var ICONS = {
|
|
32
|
+
default: /* @__PURE__ */ jsx(CheckCircle, { size: 18 }),
|
|
33
|
+
info: /* @__PURE__ */ jsx(Info, { size: 18 }),
|
|
34
|
+
success: /* @__PURE__ */ jsx(CheckCircle, { size: 18 }),
|
|
35
|
+
warning: /* @__PURE__ */ jsx(WarningCircle, { size: 18 }),
|
|
36
|
+
error: /* @__PURE__ */ jsx(XCircle, { size: 18 })
|
|
37
|
+
};
|
|
38
|
+
var Alert = ({
|
|
39
|
+
variant = "solid",
|
|
40
|
+
title,
|
|
41
|
+
description,
|
|
42
|
+
action = "default",
|
|
43
|
+
className,
|
|
44
|
+
...props
|
|
45
|
+
}) => {
|
|
46
|
+
const baseClasses = "alert-wrapper flex items-start gap-2 w-[384px] py-3 px-4 font-inherit rounded-md";
|
|
47
|
+
const variantClasses = VARIANT_ACTION_CLASSES[variant][action];
|
|
48
|
+
const variantColor = COLOR_CLASSES[action];
|
|
49
|
+
const variantIcon = ICONS[action];
|
|
50
|
+
const hasHeading = Boolean(title);
|
|
51
|
+
return /* @__PURE__ */ jsxs(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
className: `${baseClasses} ${variantClasses} ${className ?? ""}`,
|
|
55
|
+
...props,
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ jsx("span", { className: `mt-0.5 ${variantColor}`, children: variantIcon }),
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
59
|
+
hasHeading && /* @__PURE__ */ jsx(
|
|
60
|
+
Text,
|
|
61
|
+
{
|
|
62
|
+
size: "md",
|
|
63
|
+
weight: "medium",
|
|
64
|
+
color: variantColor,
|
|
65
|
+
className: "mb-0.5",
|
|
66
|
+
children: title
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
Text,
|
|
71
|
+
{
|
|
72
|
+
size: hasHeading ? "sm" : "md",
|
|
73
|
+
weight: "normal",
|
|
74
|
+
color: !hasHeading ? variantColor : "text-text-700",
|
|
75
|
+
children: description
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
] })
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
Alert
|
|
86
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// src/components/DropdownMenu/DropdownMenu.tsx
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
useState,
|
|
5
|
+
useCallback,
|
|
6
|
+
useContext,
|
|
7
|
+
forwardRef,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
useMemo
|
|
11
|
+
} from "react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var DropdownMenuContext = createContext(
|
|
14
|
+
void 0
|
|
15
|
+
);
|
|
16
|
+
var DropdownMenu = ({ children, open, onOpenChange }) => {
|
|
17
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
18
|
+
const isControlled = open !== void 0;
|
|
19
|
+
const currentOpen = isControlled ? open : internalOpen;
|
|
20
|
+
const setOpen = useCallback(
|
|
21
|
+
(newOpen) => {
|
|
22
|
+
if (onOpenChange) onOpenChange(newOpen);
|
|
23
|
+
if (!isControlled) setInternalOpen(newOpen);
|
|
24
|
+
},
|
|
25
|
+
[isControlled, onOpenChange]
|
|
26
|
+
);
|
|
27
|
+
const menuRef = useRef(null);
|
|
28
|
+
const handleArrowDownOrArrowUp = (event) => {
|
|
29
|
+
const menuContent = menuRef.current?.querySelector('[role="menu"]');
|
|
30
|
+
if (menuContent) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
const items = Array.from(
|
|
33
|
+
menuContent.querySelectorAll(
|
|
34
|
+
'[role="menuitem"]:not([aria-disabled="true"])'
|
|
35
|
+
)
|
|
36
|
+
).filter((el) => el instanceof HTMLElement);
|
|
37
|
+
if (items.length === 0) return;
|
|
38
|
+
const focusedItem = document.activeElement;
|
|
39
|
+
const currentIndex = items.findIndex((item) => item === focusedItem);
|
|
40
|
+
let nextIndex;
|
|
41
|
+
if (event.key === "ArrowDown") {
|
|
42
|
+
nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;
|
|
43
|
+
} else {
|
|
44
|
+
nextIndex = currentIndex === -1 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length;
|
|
45
|
+
}
|
|
46
|
+
items[nextIndex]?.focus();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const handleDownkey = (event) => {
|
|
50
|
+
if (event.key === "Escape") {
|
|
51
|
+
setOpen(false);
|
|
52
|
+
} else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
53
|
+
handleArrowDownOrArrowUp(event);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const handleClickOutside = (event) => {
|
|
57
|
+
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
58
|
+
setOpen(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (currentOpen) {
|
|
63
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
64
|
+
document.addEventListener("keydown", handleDownkey);
|
|
65
|
+
}
|
|
66
|
+
return () => {
|
|
67
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
68
|
+
document.removeEventListener("keydown", handleDownkey);
|
|
69
|
+
};
|
|
70
|
+
}, [currentOpen]);
|
|
71
|
+
const value = useMemo(
|
|
72
|
+
() => ({ open: currentOpen, setOpen }),
|
|
73
|
+
[currentOpen, setOpen]
|
|
74
|
+
);
|
|
75
|
+
return /* @__PURE__ */ jsx(DropdownMenuContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: "relative", ref: menuRef, children }) });
|
|
76
|
+
};
|
|
77
|
+
var DropdownMenuTrigger = forwardRef(({ className, children, onClick, ...props }, ref) => {
|
|
78
|
+
const context = useContext(DropdownMenuContext);
|
|
79
|
+
if (!context)
|
|
80
|
+
throw new Error("DropdownMenuTrigger must be used within a DropdownMenu");
|
|
81
|
+
const { open, setOpen } = context;
|
|
82
|
+
return /* @__PURE__ */ jsx(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
ref,
|
|
86
|
+
className: `border border-border-200 cursor-pointer bg-background-muted hover:bg-background-200 transition-colors px-4 py-2 rounded-sm ${className}`,
|
|
87
|
+
onClick: (e) => {
|
|
88
|
+
e.stopPropagation();
|
|
89
|
+
setOpen(!open);
|
|
90
|
+
if (onClick) onClick(e);
|
|
91
|
+
},
|
|
92
|
+
"aria-expanded": open,
|
|
93
|
+
...props,
|
|
94
|
+
children
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
99
|
+
var ITEM_SIZE_CLASSES = {
|
|
100
|
+
small: "text-sm",
|
|
101
|
+
medium: "text-md"
|
|
102
|
+
};
|
|
103
|
+
var SIDE_CLASSES = {
|
|
104
|
+
top: "bottom-full",
|
|
105
|
+
right: "top-full",
|
|
106
|
+
bottom: "top-full",
|
|
107
|
+
left: "top-full"
|
|
108
|
+
};
|
|
109
|
+
var ALIGN_CLASSES = {
|
|
110
|
+
start: "left-0",
|
|
111
|
+
center: "left-1/2 -translate-x-1/2",
|
|
112
|
+
end: "right-0"
|
|
113
|
+
};
|
|
114
|
+
var MenuLabel = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
115
|
+
"fieldset",
|
|
116
|
+
{
|
|
117
|
+
ref,
|
|
118
|
+
role: "group",
|
|
119
|
+
className: `text-sm w-full ${inset ? "pl-8" : ""} ${className ?? ""}`,
|
|
120
|
+
...props
|
|
121
|
+
}
|
|
122
|
+
));
|
|
123
|
+
MenuLabel.displayName = "MenuLabel";
|
|
124
|
+
var MenuContent = forwardRef(
|
|
125
|
+
({
|
|
126
|
+
className,
|
|
127
|
+
align = "start",
|
|
128
|
+
side = "bottom",
|
|
129
|
+
sideOffset = 4,
|
|
130
|
+
children,
|
|
131
|
+
...props
|
|
132
|
+
}, ref) => {
|
|
133
|
+
const { open } = useContext(DropdownMenuContext);
|
|
134
|
+
const [isVisible, setIsVisible] = useState(open);
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
if (open) {
|
|
137
|
+
setIsVisible(true);
|
|
138
|
+
} else {
|
|
139
|
+
const timer = setTimeout(() => setIsVisible(false), 200);
|
|
140
|
+
return () => clearTimeout(timer);
|
|
141
|
+
}
|
|
142
|
+
}, [open]);
|
|
143
|
+
if (!isVisible) return null;
|
|
144
|
+
const getPositionClasses = () => {
|
|
145
|
+
const vertical = SIDE_CLASSES[side];
|
|
146
|
+
const horizontal = ALIGN_CLASSES[align];
|
|
147
|
+
return `absolute ${vertical} ${horizontal}`;
|
|
148
|
+
};
|
|
149
|
+
return /* @__PURE__ */ jsx(
|
|
150
|
+
"div",
|
|
151
|
+
{
|
|
152
|
+
ref,
|
|
153
|
+
role: "menu",
|
|
154
|
+
className: `
|
|
155
|
+
bg-background z-50 min-w-[210px] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md border-border-100
|
|
156
|
+
${open ? "animate-in fade-in-0 zoom-in-95" : "animate-out fade-out-0 zoom-out-95"}
|
|
157
|
+
${getPositionClasses()}
|
|
158
|
+
${className}
|
|
159
|
+
`,
|
|
160
|
+
style: {
|
|
161
|
+
marginTop: side === "bottom" ? sideOffset : void 0,
|
|
162
|
+
marginBottom: side === "top" ? sideOffset : void 0,
|
|
163
|
+
marginLeft: side === "right" ? sideOffset : void 0,
|
|
164
|
+
marginRight: side === "left" ? sideOffset : void 0
|
|
165
|
+
},
|
|
166
|
+
...props,
|
|
167
|
+
children
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
MenuContent.displayName = "MenuContent";
|
|
173
|
+
var MenuItem = forwardRef(
|
|
174
|
+
({
|
|
175
|
+
className,
|
|
176
|
+
inset,
|
|
177
|
+
size = "small",
|
|
178
|
+
children,
|
|
179
|
+
iconRight,
|
|
180
|
+
iconLeft,
|
|
181
|
+
disabled = false,
|
|
182
|
+
onClick,
|
|
183
|
+
...props
|
|
184
|
+
}, ref) => {
|
|
185
|
+
const sizeClasses = ITEM_SIZE_CLASSES[size];
|
|
186
|
+
const handleClick = (e) => {
|
|
187
|
+
if (disabled) {
|
|
188
|
+
e.preventDefault();
|
|
189
|
+
e.stopPropagation();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
onClick?.(e);
|
|
193
|
+
};
|
|
194
|
+
return /* @__PURE__ */ jsxs(
|
|
195
|
+
"div",
|
|
196
|
+
{
|
|
197
|
+
ref,
|
|
198
|
+
role: "menuitem",
|
|
199
|
+
"aria-disabled": disabled,
|
|
200
|
+
className: `
|
|
201
|
+
focus-visible:bg-background-50
|
|
202
|
+
relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0
|
|
203
|
+
${inset && "pl-8"}
|
|
204
|
+
${sizeClasses}
|
|
205
|
+
${className}
|
|
206
|
+
${disabled ? "cursor-not-allowed text-text-400" : "cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground"}
|
|
207
|
+
`,
|
|
208
|
+
onClick: handleClick,
|
|
209
|
+
onKeyDown: (e) => {
|
|
210
|
+
if (e.key === "Enter" || e.key === " ") handleClick(e);
|
|
211
|
+
},
|
|
212
|
+
tabIndex: disabled ? -1 : 0,
|
|
213
|
+
...props,
|
|
214
|
+
children: [
|
|
215
|
+
iconLeft,
|
|
216
|
+
children,
|
|
217
|
+
iconRight
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
MenuItem.displayName = "MenuItem";
|
|
224
|
+
var MenuSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
225
|
+
"div",
|
|
226
|
+
{
|
|
227
|
+
ref,
|
|
228
|
+
className: `my-1 h-px bg-border-200 ${className}`,
|
|
229
|
+
...props
|
|
230
|
+
}
|
|
231
|
+
));
|
|
232
|
+
MenuSeparator.displayName = "MenuSeparator";
|
|
233
|
+
|
|
234
|
+
export {
|
|
235
|
+
DropdownMenu,
|
|
236
|
+
DropdownMenuTrigger,
|
|
237
|
+
MenuLabel,
|
|
238
|
+
MenuContent,
|
|
239
|
+
MenuItem,
|
|
240
|
+
MenuSeparator
|
|
241
|
+
};
|