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.
Files changed (112) hide show
  1. package/@types/index.d.ts +2 -0
  2. package/dist/components/button/index.d.ts +15 -0
  3. package/dist/components/calendar/big-calendar/event.d.ts +7 -0
  4. package/dist/components/calendar/big-calendar/index.d.ts +14 -0
  5. package/dist/components/calendar/big-calendar/toolbar.d.ts +8 -0
  6. package/dist/components/calendar/calendar/index.d.ts +11 -0
  7. package/dist/components/chart/index.d.ts +17 -0
  8. package/dist/components/chip/index.d.ts +12 -0
  9. package/dist/components/content-container/accordion/index.d.ts +10 -0
  10. package/dist/components/content-container/accordion/item.d.ts +6 -0
  11. package/dist/components/content-container/card.d.ts +10 -0
  12. package/dist/components/content-container/carousel.d.ts +10 -0
  13. package/dist/components/content-container/drawer.d.ts +8 -0
  14. package/dist/components/content-container/modal/index.d.ts +21 -0
  15. package/dist/components/content-container/sortable/index.d.ts +14 -0
  16. package/dist/components/content-container/sortable/item.d.ts +8 -0
  17. package/dist/components/content-container/sortable/knob.d.ts +5 -0
  18. package/dist/components/content-container/tab/index.d.ts +17 -0
  19. package/dist/components/content-container/tab/window.d.ts +5 -0
  20. package/dist/components/data-tree/index.d.ts +6 -0
  21. package/dist/components/dialog/index.d.ts +16 -0
  22. package/dist/components/dropdown/header.d.ts +5 -0
  23. package/dist/components/dropdown/index.d.ts +15 -0
  24. package/dist/components/dropdown/item.d.ts +7 -0
  25. package/dist/components/form/index.d.ts +44 -0
  26. package/dist/components/form/input/checkbox.d.ts +9 -0
  27. package/dist/components/form/input/color.d.ts +10 -0
  28. package/dist/components/form/input/email.d.ts +9 -0
  29. package/dist/components/form/input/file.d.ts +14 -0
  30. package/dist/components/form/input/number.d.ts +9 -0
  31. package/dist/components/form/input/password.d.ts +9 -0
  32. package/dist/components/form/input/radio.d.ts +9 -0
  33. package/dist/components/form/input/range.d.ts +9 -0
  34. package/dist/components/form/input/search.d.ts +8 -0
  35. package/dist/components/form/input/text.d.ts +9 -0
  36. package/dist/components/form/input/time.d.ts +9 -0
  37. package/dist/components/form/other/autocomplete.d.ts +15 -0
  38. package/dist/components/form/other/multipleSelect.d.ts +23 -0
  39. package/dist/components/form/other/phoneNumber.d.ts +10 -0
  40. package/dist/components/form/other/pin.d.ts +10 -0
  41. package/dist/components/form/other/secret.d.ts +11 -0
  42. package/dist/components/form/other/select.d.ts +15 -0
  43. package/dist/components/form/other/textarea.d.ts +9 -0
  44. package/dist/components/index.d.ts +19 -0
  45. package/dist/components/map/index.d.ts +13 -0
  46. package/dist/components/map/marker.d.ts +8 -0
  47. package/dist/components/syntax-highlighter/index.d.ts +9 -0
  48. package/dist/components/table/action.d.ts +5 -0
  49. package/dist/components/table/index.d.ts +24 -0
  50. package/dist/components/timeline/index.d.ts +10 -0
  51. package/dist/components/timeline/item.d.ts +7 -0
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +2 -0
  54. package/dist/index.js.LICENSE.txt +62 -0
  55. package/package.json +72 -0
  56. package/src/components/button/index.tsx +74 -0
  57. package/src/components/calendar/big-calendar/event.tsx +46 -0
  58. package/src/components/calendar/big-calendar/index.tsx +102 -0
  59. package/src/components/calendar/big-calendar/toolbar.tsx +98 -0
  60. package/src/components/calendar/calendar/index.tsx +26 -0
  61. package/src/components/chart/index.tsx +121 -0
  62. package/src/components/chip/index.tsx +47 -0
  63. package/src/components/content-container/accordion/index.tsx +28 -0
  64. package/src/components/content-container/accordion/item.tsx +40 -0
  65. package/src/components/content-container/card.tsx +21 -0
  66. package/src/components/content-container/carousel.tsx +35 -0
  67. package/src/components/content-container/drawer.tsx +78 -0
  68. package/src/components/content-container/modal/index.tsx +127 -0
  69. package/src/components/content-container/sortable/index.tsx +47 -0
  70. package/src/components/content-container/sortable/item.tsx +20 -0
  71. package/src/components/content-container/sortable/knob.tsx +11 -0
  72. package/src/components/content-container/tab/index.tsx +94 -0
  73. package/src/components/content-container/tab/window.tsx +10 -0
  74. package/src/components/data-tree/index.tsx +60 -0
  75. package/src/components/dialog/index.tsx +88 -0
  76. package/src/components/dropdown/header.tsx +11 -0
  77. package/src/components/dropdown/index.tsx +69 -0
  78. package/src/components/dropdown/item.tsx +22 -0
  79. package/src/components/form/index.tsx +81 -0
  80. package/src/components/form/input/checkbox.tsx +49 -0
  81. package/src/components/form/input/color.tsx +104 -0
  82. package/src/components/form/input/email.tsx +40 -0
  83. package/src/components/form/input/file.tsx +189 -0
  84. package/src/components/form/input/number.tsx +93 -0
  85. package/src/components/form/input/password.tsx +57 -0
  86. package/src/components/form/input/radio.tsx +49 -0
  87. package/src/components/form/input/range.tsx +67 -0
  88. package/src/components/form/input/search.tsx +50 -0
  89. package/src/components/form/input/text.tsx +39 -0
  90. package/src/components/form/input/time.tsx +315 -0
  91. package/src/components/form/other/autocomplete.tsx +199 -0
  92. package/src/components/form/other/multipleSelect.tsx +211 -0
  93. package/src/components/form/other/phoneNumber.tsx +1668 -0
  94. package/src/components/form/other/pin.tsx +56 -0
  95. package/src/components/form/other/secret.tsx +74 -0
  96. package/src/components/form/other/select.tsx +187 -0
  97. package/src/components/form/other/textarea.tsx +44 -0
  98. package/src/components/index.ts +29 -0
  99. package/src/components/map/index.tsx +72 -0
  100. package/src/components/map/marker.tsx +40 -0
  101. package/src/components/syntax-highlighter/index.tsx +45 -0
  102. package/src/components/table/action.tsx +22 -0
  103. package/src/components/table/index.tsx +431 -0
  104. package/src/components/timeline/index.tsx +28 -0
  105. package/src/components/timeline/item.tsx +25 -0
  106. package/src/index.css +1 -0
  107. package/src/index.ts +3 -0
  108. package/src/styles/big-calendar.scss +810 -0
  109. package/src/styles/calendar.scss +195 -0
  110. package/src/styles/index.css +2 -0
  111. package/tsconfig.json +17 -0
  112. 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,10 @@
1
+ "use client";
2
+ import React from "react";
3
+
4
+ export interface WindowProps {
5
+ children: React.ReactNode;
6
+ }
7
+
8
+ export const Window: React.FC<WindowProps> = ({ children }) => {
9
+ return children;
10
+ };
@@ -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
+ };