next-helios-fe 1.0.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/@types/index.d.ts +2 -0
- package/dist/components/button/index.d.ts +15 -0
- package/dist/components/calendar/big-calendar/event.d.ts +7 -0
- package/dist/components/calendar/big-calendar/index.d.ts +14 -0
- package/dist/components/calendar/big-calendar/toolbar.d.ts +8 -0
- package/dist/components/calendar/calendar/index.d.ts +11 -0
- package/dist/components/chart/index.d.ts +17 -0
- package/dist/components/chip/index.d.ts +12 -0
- package/dist/components/content-container/accordion/index.d.ts +10 -0
- package/dist/components/content-container/accordion/item.d.ts +6 -0
- package/dist/components/content-container/card.d.ts +10 -0
- package/dist/components/content-container/carousel.d.ts +10 -0
- package/dist/components/content-container/drawer.d.ts +8 -0
- package/dist/components/content-container/modal/index.d.ts +21 -0
- package/dist/components/content-container/sortable/index.d.ts +14 -0
- package/dist/components/content-container/sortable/item.d.ts +8 -0
- package/dist/components/content-container/sortable/knob.d.ts +5 -0
- package/dist/components/content-container/tab/index.d.ts +17 -0
- package/dist/components/content-container/tab/window.d.ts +5 -0
- package/dist/components/data-tree/index.d.ts +6 -0
- package/dist/components/dialog/index.d.ts +16 -0
- package/dist/components/dropdown/header.d.ts +5 -0
- package/dist/components/dropdown/index.d.ts +15 -0
- package/dist/components/dropdown/item.d.ts +7 -0
- package/dist/components/form/index.d.ts +44 -0
- package/dist/components/form/input/checkbox.d.ts +9 -0
- package/dist/components/form/input/color.d.ts +10 -0
- package/dist/components/form/input/email.d.ts +9 -0
- package/dist/components/form/input/file.d.ts +14 -0
- package/dist/components/form/input/number.d.ts +9 -0
- package/dist/components/form/input/password.d.ts +9 -0
- package/dist/components/form/input/radio.d.ts +9 -0
- package/dist/components/form/input/range.d.ts +9 -0
- package/dist/components/form/input/search.d.ts +8 -0
- package/dist/components/form/input/text.d.ts +9 -0
- package/dist/components/form/input/time.d.ts +9 -0
- package/dist/components/form/other/autocomplete.d.ts +15 -0
- package/dist/components/form/other/multipleSelect.d.ts +23 -0
- package/dist/components/form/other/phoneNumber.d.ts +10 -0
- package/dist/components/form/other/pin.d.ts +10 -0
- package/dist/components/form/other/secret.d.ts +11 -0
- package/dist/components/form/other/select.d.ts +15 -0
- package/dist/components/form/other/textarea.d.ts +9 -0
- package/dist/components/index.d.ts +19 -0
- package/dist/components/map/index.d.ts +13 -0
- package/dist/components/map/marker.d.ts +8 -0
- package/dist/components/syntax-highlighter/index.d.ts +9 -0
- package/dist/components/table/action.d.ts +5 -0
- package/dist/components/table/index.d.ts +24 -0
- package/dist/components/timeline/index.d.ts +10 -0
- package/dist/components/timeline/item.d.ts +7 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.LICENSE.txt +62 -0
- package/package.json +72 -0
- package/src/components/button/index.tsx +74 -0
- package/src/components/calendar/big-calendar/event.tsx +46 -0
- package/src/components/calendar/big-calendar/index.tsx +102 -0
- package/src/components/calendar/big-calendar/toolbar.tsx +98 -0
- package/src/components/calendar/calendar/index.tsx +26 -0
- package/src/components/chart/index.tsx +121 -0
- package/src/components/chip/index.tsx +47 -0
- package/src/components/content-container/accordion/index.tsx +28 -0
- package/src/components/content-container/accordion/item.tsx +40 -0
- package/src/components/content-container/card.tsx +21 -0
- package/src/components/content-container/carousel.tsx +35 -0
- package/src/components/content-container/drawer.tsx +78 -0
- package/src/components/content-container/modal/index.tsx +127 -0
- package/src/components/content-container/sortable/index.tsx +47 -0
- package/src/components/content-container/sortable/item.tsx +20 -0
- package/src/components/content-container/sortable/knob.tsx +11 -0
- package/src/components/content-container/tab/index.tsx +94 -0
- package/src/components/content-container/tab/window.tsx +10 -0
- package/src/components/data-tree/index.tsx +60 -0
- package/src/components/dialog/index.tsx +88 -0
- package/src/components/dropdown/header.tsx +11 -0
- package/src/components/dropdown/index.tsx +69 -0
- package/src/components/dropdown/item.tsx +22 -0
- package/src/components/form/index.tsx +81 -0
- package/src/components/form/input/checkbox.tsx +49 -0
- package/src/components/form/input/color.tsx +104 -0
- package/src/components/form/input/email.tsx +40 -0
- package/src/components/form/input/file.tsx +189 -0
- package/src/components/form/input/number.tsx +93 -0
- package/src/components/form/input/password.tsx +57 -0
- package/src/components/form/input/radio.tsx +49 -0
- package/src/components/form/input/range.tsx +67 -0
- package/src/components/form/input/search.tsx +50 -0
- package/src/components/form/input/text.tsx +39 -0
- package/src/components/form/input/time.tsx +315 -0
- package/src/components/form/other/autocomplete.tsx +199 -0
- package/src/components/form/other/multipleSelect.tsx +211 -0
- package/src/components/form/other/phoneNumber.tsx +1668 -0
- package/src/components/form/other/pin.tsx +56 -0
- package/src/components/form/other/secret.tsx +74 -0
- package/src/components/form/other/select.tsx +187 -0
- package/src/components/form/other/textarea.tsx +44 -0
- package/src/components/index.ts +29 -0
- package/src/components/map/index.tsx +72 -0
- package/src/components/map/marker.tsx +40 -0
- package/src/components/syntax-highlighter/index.tsx +45 -0
- package/src/components/table/action.tsx +22 -0
- package/src/components/table/index.tsx +431 -0
- package/src/components/timeline/index.tsx +28 -0
- package/src/components/timeline/item.tsx +25 -0
- package/src/index.css +1 -0
- package/src/index.ts +3 -0
- package/src/styles/big-calendar.scss +810 -0
- package/src/styles/calendar.scss +195 -0
- package/src/styles/index.css +2 -0
- package/tsconfig.json +17 -0
- package/webpack.config.js +35 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { Icon } from "@iconify/react";
|
|
4
|
+
|
|
5
|
+
export interface ItemProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
title: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Item: React.FC<ItemProps> = ({ children, title }) => {
|
|
11
|
+
const [active, setActive] = useState(false);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
className={`grid w-full rounded-md overflow-hidden duration-300 ${
|
|
16
|
+
active ? "border-l-4 border-primary" : "border-l-0"
|
|
17
|
+
}`}
|
|
18
|
+
>
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
className={`flex justify-between items-center w-full px-4 py-2 hover:bg-secondary-light ${
|
|
22
|
+
active && "text-primary font-medium"
|
|
23
|
+
}`}
|
|
24
|
+
onClick={() => {
|
|
25
|
+
setActive(!active);
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<span>{title}</span>
|
|
29
|
+
<Icon icon={`gravity-ui:chevron-${active ? "up" : "down"}`} />
|
|
30
|
+
</button>
|
|
31
|
+
<div
|
|
32
|
+
className={`overflow-auto duration-300 transition-all ${
|
|
33
|
+
active ? "max-h-96 border-t" : "max-h-0"
|
|
34
|
+
}`}
|
|
35
|
+
>
|
|
36
|
+
<div className="px-6 py-4">{children}</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
interface CardProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
id?: string;
|
|
7
|
+
options?: { enablePadding?: boolean };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Card: React.FC<CardProps> = ({ children, id, options }) => {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
id={id}
|
|
14
|
+
className={`w-full min-h-64 h-full rounded-md shadow-md bg-secondary-bg ${
|
|
15
|
+
options?.enablePadding && "px-6 py-8"
|
|
16
|
+
}`}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Carousel as Cr } from "flowbite-react";
|
|
4
|
+
|
|
5
|
+
interface CarouselProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
options?: {
|
|
8
|
+
interval?: number;
|
|
9
|
+
pauseOnHover?: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Carousel: React.FC<CarouselProps> = ({ children, options }) => {
|
|
14
|
+
const childrenList = React.Children.toArray(children);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="h-full">
|
|
18
|
+
<Cr
|
|
19
|
+
slideInterval={options?.interval || 5000}
|
|
20
|
+
pauseOnHover={options?.pauseOnHover || false}
|
|
21
|
+
>
|
|
22
|
+
{childrenList?.map((item, index) => {
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
key={index}
|
|
26
|
+
className="relative grid w-full h-full px-8 py-10 rounded-md shadow-md bg-gradient-to-r from-primary to-primary-dark text-white"
|
|
27
|
+
>
|
|
28
|
+
{item}
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
})}
|
|
32
|
+
</Cr>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState, useEffect } from "react";
|
|
3
|
+
import { Icon } from "@iconify/react";
|
|
4
|
+
|
|
5
|
+
interface DrawerProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
title: string;
|
|
8
|
+
subtitle: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Drawer: React.FC<DrawerProps> = ({
|
|
12
|
+
children,
|
|
13
|
+
title,
|
|
14
|
+
subtitle,
|
|
15
|
+
}) => {
|
|
16
|
+
const [open, setOpen] = useState(false);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
document.addEventListener("mousedown", (e) => {
|
|
20
|
+
if (
|
|
21
|
+
e.target instanceof HTMLElement &&
|
|
22
|
+
!e.target.closest("#info-screen")
|
|
23
|
+
) {
|
|
24
|
+
setOpen(false);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
className={`absolute top-0 right-0 h-full z-40 ${
|
|
32
|
+
!open && "pointer-events-none"
|
|
33
|
+
}`}
|
|
34
|
+
>
|
|
35
|
+
<div
|
|
36
|
+
className={`flex h-full duration-300 ${
|
|
37
|
+
open ? "translate-x-0" : "translate-x-96"
|
|
38
|
+
}`}
|
|
39
|
+
>
|
|
40
|
+
<button
|
|
41
|
+
type="button"
|
|
42
|
+
className="group sticky top-36 h-min rounded-l-md text-white bg-primary p-2 hover:bg-primary-dark pointer-events-auto active:opacity-70 active:duration-300 active:ease-out"
|
|
43
|
+
onClick={() => {
|
|
44
|
+
setOpen((prev) => !prev);
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<Icon
|
|
48
|
+
icon="ant-design:setting-outlined"
|
|
49
|
+
className="text-xl group-hover:animate-spin"
|
|
50
|
+
/>
|
|
51
|
+
</button>
|
|
52
|
+
<div
|
|
53
|
+
id="info-screen"
|
|
54
|
+
className="w-96 h-full py-4 pb-4 shadow-md bg-secondary-bg"
|
|
55
|
+
>
|
|
56
|
+
<div className="flex flex-col">
|
|
57
|
+
<div className="flex justify-between items-center px-6 pb-2 border-b">
|
|
58
|
+
<div className="grid">
|
|
59
|
+
<span className="text-lg">{title}</span>
|
|
60
|
+
<span className="text-sm font-light">{subtitle}</span>
|
|
61
|
+
</div>
|
|
62
|
+
<button
|
|
63
|
+
type="button"
|
|
64
|
+
className="flex justify-center items-center rounded-full p-1 text-slate-400 hover:bg-secondary-light"
|
|
65
|
+
onClick={() => {
|
|
66
|
+
setOpen(false);
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Icon icon="pajamas:close" className="text-2xl" />
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="px-6 py-4">{children}</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
import ReactDom from "react-dom";
|
|
4
|
+
import { Icon } from "@iconify/react";
|
|
5
|
+
import { Button } from "../../../components";
|
|
6
|
+
|
|
7
|
+
interface ModalProps {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
id?: string;
|
|
10
|
+
title: string;
|
|
11
|
+
options?: {
|
|
12
|
+
size?: "fit" | "regular" | "large" | "full";
|
|
13
|
+
disablePadding?: boolean;
|
|
14
|
+
disableClose?: boolean;
|
|
15
|
+
hideFooter?: boolean;
|
|
16
|
+
};
|
|
17
|
+
action?: {
|
|
18
|
+
variant?: "primary" | "secondary" | "success" | "warning" | "danger";
|
|
19
|
+
label?: string;
|
|
20
|
+
onClick: () => void;
|
|
21
|
+
};
|
|
22
|
+
open: boolean;
|
|
23
|
+
setOpen: (open: boolean) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Modal: React.FC<ModalProps> = ({
|
|
27
|
+
children,
|
|
28
|
+
id,
|
|
29
|
+
title,
|
|
30
|
+
options,
|
|
31
|
+
action,
|
|
32
|
+
open,
|
|
33
|
+
setOpen,
|
|
34
|
+
}) => {
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!options?.disableClose) {
|
|
37
|
+
document.addEventListener("keydown", (e) => {
|
|
38
|
+
if (e.key === "Escape") {
|
|
39
|
+
setOpen(false);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const size =
|
|
46
|
+
options?.size === "fit"
|
|
47
|
+
? "w-fit h-fit"
|
|
48
|
+
: options?.size === "large"
|
|
49
|
+
? "w-11/12 sm:w-9/12 md:w-7/12 h-5/6 md:h-4/6"
|
|
50
|
+
: options?.size === "full"
|
|
51
|
+
? "w-full h-full"
|
|
52
|
+
: "w-11/12 sm:w-9/12 md:w-7/12 lg:w-5/12 h-5/6 sm:h-4/6 md:h-2/3 lg:h-2/4";
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
typeof document !== "undefined" &&
|
|
56
|
+
ReactDom.createPortal(
|
|
57
|
+
<div
|
|
58
|
+
id={id}
|
|
59
|
+
className={`absolute top-0 left-0 w-dvw h-dvh z-40 bg-black/30 backdrop-blur-sm ${
|
|
60
|
+
!open && "hidden"
|
|
61
|
+
}`}
|
|
62
|
+
>
|
|
63
|
+
<div className="flex justify-center items-center w-full h-full">
|
|
64
|
+
<div
|
|
65
|
+
className={`flex flex-col rounded-md shadow-md divide-y bg-secondary-bg ${size}`}
|
|
66
|
+
>
|
|
67
|
+
<div className="flex justify-between items-center gap-2 px-6 py-2">
|
|
68
|
+
<span className="text-lg">{title}</span>
|
|
69
|
+
{!options?.disableClose && (
|
|
70
|
+
<div className="flex items-center gap-2">
|
|
71
|
+
<span className="text-sm text-slate-400">[esc]</span>
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
className="flex justify-center items-center rounded-full px-1 py-1 text-slate-400 hover:bg-secondary-light"
|
|
75
|
+
onClick={() => {
|
|
76
|
+
setOpen(false);
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<Icon icon="pajamas:close" className="text-2xl" />
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
<div
|
|
85
|
+
className={`flex-1 h-full overflow-auto ${
|
|
86
|
+
!options?.disablePadding && "px-6 py-4"
|
|
87
|
+
}`}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</div>
|
|
91
|
+
{(!options?.disableClose || action) && !options?.hideFooter && (
|
|
92
|
+
<div className="flex justify-end items-center gap-4 px-6 py-2">
|
|
93
|
+
{!options?.disableClose && (
|
|
94
|
+
<Button
|
|
95
|
+
options={{
|
|
96
|
+
width: "fit",
|
|
97
|
+
height: "short",
|
|
98
|
+
border: true,
|
|
99
|
+
}}
|
|
100
|
+
onClick={() => {
|
|
101
|
+
setOpen(false);
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
Close
|
|
105
|
+
</Button>
|
|
106
|
+
)}
|
|
107
|
+
{action?.label && (
|
|
108
|
+
<Button
|
|
109
|
+
options={{
|
|
110
|
+
variant: action?.variant ?? "primary",
|
|
111
|
+
width: "fit",
|
|
112
|
+
height: "short",
|
|
113
|
+
}}
|
|
114
|
+
onClick={action?.onClick}
|
|
115
|
+
>
|
|
116
|
+
{action?.label}
|
|
117
|
+
</Button>
|
|
118
|
+
)}
|
|
119
|
+
</div>
|
|
120
|
+
)}
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>,
|
|
124
|
+
document.body
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import SortableList from "react-easy-sort";
|
|
4
|
+
import { arrayMoveImmutable } from "array-move";
|
|
5
|
+
import { Item, type ItemProps } from "./item";
|
|
6
|
+
import { Knob, type KnobProps } from "./knob";
|
|
7
|
+
|
|
8
|
+
interface SortableProps {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
setItems: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface SortableComponent extends React.FC<SortableProps> {
|
|
15
|
+
Item: React.FC<ItemProps>;
|
|
16
|
+
Knob: React.FC<KnobProps>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const Sortable: SortableComponent = ({
|
|
20
|
+
children,
|
|
21
|
+
className,
|
|
22
|
+
setItems,
|
|
23
|
+
}) => {
|
|
24
|
+
const childrenList = React.Children.toArray(children);
|
|
25
|
+
const itemList = childrenList.filter((child) => {
|
|
26
|
+
return (child as React.ReactElement).type === Sortable.Item;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const onSortEnd = (oldIndex: number, newIndex: number) => {
|
|
30
|
+
setItems((array: any) => arrayMoveImmutable(array, oldIndex, newIndex));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SortableList
|
|
35
|
+
className={className}
|
|
36
|
+
onSortEnd={onSortEnd}
|
|
37
|
+
draggedItemClassName="dragged"
|
|
38
|
+
>
|
|
39
|
+
{itemList.map((item) => {
|
|
40
|
+
return item;
|
|
41
|
+
})}
|
|
42
|
+
</SortableList>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
Sortable.Item = Item;
|
|
47
|
+
Sortable.Knob = Knob;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { SortableItem } from "react-easy-sort";
|
|
4
|
+
|
|
5
|
+
export interface ItemProps {
|
|
6
|
+
children: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
7
|
+
options?: {
|
|
8
|
+
columnSpan?: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Item: React.FC<ItemProps> = ({ children, options }) => {
|
|
13
|
+
const columnSpanNumber = `col-span-${options?.columnSpan || 1}`;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className={`${columnSpanNumber} h-full`}>
|
|
17
|
+
<SortableItem>{children}</SortableItem>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { SortableKnob } from "react-easy-sort";
|
|
4
|
+
|
|
5
|
+
export interface KnobProps {
|
|
6
|
+
children: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Knob: React.FC<KnobProps> = ({ children }) => {
|
|
10
|
+
return <SortableKnob>{children}</SortableKnob>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { Icon } from "@iconify/react";
|
|
4
|
+
import { Window, type WindowProps } from "./window";
|
|
5
|
+
|
|
6
|
+
interface TabProps {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
tabs: {
|
|
9
|
+
title: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
}[];
|
|
12
|
+
options?: {
|
|
13
|
+
variant?: "vertical" | "horizontal";
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface TabComponent extends React.FC<TabProps> {
|
|
18
|
+
Window: React.FC<WindowProps>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const Tab: TabComponent = ({ children, tabs, options }) => {
|
|
22
|
+
const childrenList = React.Children.toArray(children);
|
|
23
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
24
|
+
const windowList = childrenList.filter((child) => {
|
|
25
|
+
return (child as React.ReactElement).type === Tab.Window;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
className={`flex w-full h-full ${
|
|
31
|
+
options?.variant !== "horizontal"
|
|
32
|
+
? "flex-col divide-y-1"
|
|
33
|
+
: "flex-col lg:flex-row divide-y-1 lg:divide-y-0 divide-x-0 lg:divide-x-1"
|
|
34
|
+
}`}
|
|
35
|
+
>
|
|
36
|
+
{options?.variant !== "horizontal" ? (
|
|
37
|
+
<div className="flex overflow-auto [&::-webkit-scrollbar]:hidden">
|
|
38
|
+
{tabs.slice(0, childrenList.length).map((tab, index) => {
|
|
39
|
+
return (
|
|
40
|
+
<button
|
|
41
|
+
key={index}
|
|
42
|
+
type="button"
|
|
43
|
+
className={`flex items-center gap-2 px-6 pt-2 pb-1.5 border-b-2 whitespace-nowrap duration-300 ${
|
|
44
|
+
activeTab === index
|
|
45
|
+
? "text-primary border-primary"
|
|
46
|
+
: "border-transparent hover:text-primary hover:border-primary-transparent"
|
|
47
|
+
}`}
|
|
48
|
+
onClick={() => {
|
|
49
|
+
setActiveTab(index);
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{tab?.icon && <Icon icon={tab?.icon} className="text-lg" />}
|
|
53
|
+
{tab.title}
|
|
54
|
+
</button>
|
|
55
|
+
);
|
|
56
|
+
})}
|
|
57
|
+
</div>
|
|
58
|
+
) : (
|
|
59
|
+
<div className="flex flex-row lg:flex-col lg:min-w-36 lg:max-w-48 overflow-auto [&::-webkit-scrollbar]:hidden">
|
|
60
|
+
{tabs.slice(0, childrenList.length).map((tab, index) => {
|
|
61
|
+
return (
|
|
62
|
+
<button
|
|
63
|
+
key={index}
|
|
64
|
+
type="button"
|
|
65
|
+
className={`flex items-center gap-2 px-6 pt-2 pb-1.5 border-b-2 lg:border-b-0 border-r-0 lg:border-r-2 text-left whitespace-nowrap duration-300 ${
|
|
66
|
+
activeTab === index
|
|
67
|
+
? "text-primary border-primary"
|
|
68
|
+
: "border-transparent hover:text-primary hover:border-primary-transparent"
|
|
69
|
+
}`}
|
|
70
|
+
onClick={() => {
|
|
71
|
+
setActiveTab(index);
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{tab?.icon && <Icon icon={tab?.icon} className="text-lg" />}
|
|
75
|
+
{tab.title}
|
|
76
|
+
</button>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</div>
|
|
80
|
+
)}
|
|
81
|
+
<div
|
|
82
|
+
className={`flex-1 overflow-auto ${
|
|
83
|
+
options?.variant !== "horizontal"
|
|
84
|
+
? "px-6 py-8"
|
|
85
|
+
: "px-6 lg:px-8 py-8 lg:py-6"
|
|
86
|
+
}`}
|
|
87
|
+
>
|
|
88
|
+
{windowList[activeTab]}
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
Tab.Window = Window;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { Icon } from "@iconify/react";
|
|
4
|
+
|
|
5
|
+
export interface DataTreeProps {
|
|
6
|
+
data: any[];
|
|
7
|
+
defaultExpanded?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const RecursiveComponent = ({ data, defaultExpanded }: any) => {
|
|
11
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded || false);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="ps-3">
|
|
15
|
+
<div className="flex justify-between items-center gap-6">
|
|
16
|
+
<div className="flex items-center gap-4">
|
|
17
|
+
<div className="flex items-center gap-2">
|
|
18
|
+
<button
|
|
19
|
+
type="button"
|
|
20
|
+
className={`${data?.children.length ? "" : "invisible"}`}
|
|
21
|
+
onClick={() => {
|
|
22
|
+
setIsExpanded(!isExpanded);
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<Icon
|
|
26
|
+
icon={`gravity-ui:chevron-${isExpanded ? "down" : "right"}`}
|
|
27
|
+
/>
|
|
28
|
+
</button>
|
|
29
|
+
<span>{data.name}</span>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
{isExpanded &&
|
|
34
|
+
data?.children.map((item: any) => (
|
|
35
|
+
<RecursiveComponent
|
|
36
|
+
key={item.id}
|
|
37
|
+
data={item}
|
|
38
|
+
defaultExpanded={defaultExpanded}
|
|
39
|
+
/>
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const DataTree: React.FC<DataTreeProps> = ({
|
|
46
|
+
data,
|
|
47
|
+
defaultExpanded,
|
|
48
|
+
}) => {
|
|
49
|
+
return (
|
|
50
|
+
<div className="flex flex-col gap-6">
|
|
51
|
+
{data.map((item) => (
|
|
52
|
+
<RecursiveComponent
|
|
53
|
+
key={item.id}
|
|
54
|
+
data={item}
|
|
55
|
+
defaultExpanded={defaultExpanded}
|
|
56
|
+
/>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
|
|
4
|
+
interface DialogProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
action: {
|
|
7
|
+
variant: "primary" | "secondary" | "success" | "warning" | "danger";
|
|
8
|
+
label: string;
|
|
9
|
+
onClick: () => void;
|
|
10
|
+
};
|
|
11
|
+
options?: {
|
|
12
|
+
timeout?: 3000 | 5000 | 7000 | 10000;
|
|
13
|
+
};
|
|
14
|
+
open: boolean;
|
|
15
|
+
setOpen: (open: boolean) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Dialog: React.FC<DialogProps> = ({
|
|
19
|
+
children,
|
|
20
|
+
action,
|
|
21
|
+
options,
|
|
22
|
+
open,
|
|
23
|
+
setOpen,
|
|
24
|
+
}) => {
|
|
25
|
+
const actionVariant =
|
|
26
|
+
action.variant === "secondary"
|
|
27
|
+
? "text-secondary hover:text-secondary-dark hover:underline"
|
|
28
|
+
: action.variant === "success"
|
|
29
|
+
? "text-success hover:text-success-dark hover:underline"
|
|
30
|
+
: action.variant === "warning"
|
|
31
|
+
? "text-warning hover:text-warning-dark hover:underline"
|
|
32
|
+
: action.variant === "danger"
|
|
33
|
+
? "text-danger hover:text-danger-dark hover:underline"
|
|
34
|
+
: "text-primary hover:text-primary-dark hover:underline";
|
|
35
|
+
const shrinkAnimation =
|
|
36
|
+
options?.timeout === 3000
|
|
37
|
+
? `animate-shrink-3000`
|
|
38
|
+
: options?.timeout === 5000
|
|
39
|
+
? `animate-shrink-5000`
|
|
40
|
+
: options?.timeout === 7000
|
|
41
|
+
? `animate-shrink-7000`
|
|
42
|
+
: options?.timeout === 10000
|
|
43
|
+
? `animate-shrink-10000`
|
|
44
|
+
: "";
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (options?.timeout) {
|
|
48
|
+
const timeout = setTimeout(() => {
|
|
49
|
+
setOpen(false);
|
|
50
|
+
}, options.timeout);
|
|
51
|
+
return () => clearTimeout(timeout);
|
|
52
|
+
}
|
|
53
|
+
}, [open]);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
className={`absolute top-0 left-0 w-dvw h-dvh z-40 ${
|
|
58
|
+
!open && "hidden"
|
|
59
|
+
} ${options?.timeout ? "pointer-events-none" : "bg-black/30"}`}
|
|
60
|
+
>
|
|
61
|
+
<div className="flex justify-center mt-4">
|
|
62
|
+
<div
|
|
63
|
+
className={`flex flex-col gap-4 w-full sm:w-4/5 md:w-3/5 lg:w-2/5 xl:w-4/12 min-h-24 border rounded-md bg-secondary-bg text-sm overflow-hidden pointer-events-auto ${
|
|
64
|
+
options?.timeout ? "pt-4" : "py-4"
|
|
65
|
+
}`}
|
|
66
|
+
>
|
|
67
|
+
<div className="flex-1 h-full px-4">{children}</div>
|
|
68
|
+
<div className="flex justify-end gap-4 px-4">
|
|
69
|
+
<button className={actionVariant}>{action.label}</button>
|
|
70
|
+
<button
|
|
71
|
+
className="text-danger hover:text-danger-dark hover:underline"
|
|
72
|
+
onClick={() => {
|
|
73
|
+
setOpen(false);
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
Close
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
{options?.timeout && (
|
|
80
|
+
<div className="w-full h-1.5 bg-primary-transparent">
|
|
81
|
+
<div className={`h-full bg-primary ${shrinkAnimation}`}></div>
|
|
82
|
+
</div>
|
|
83
|
+
)}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Dropdown as Dd } from "flowbite-react";
|
|
4
|
+
|
|
5
|
+
export interface HeaderProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Header: React.FC<HeaderProps> = ({ children }) => {
|
|
10
|
+
return <Dd.Header>{children}</Dd.Header>;
|
|
11
|
+
};
|