gwan-design-system 0.1.13 → 0.1.14
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/package.json +2 -1
- package/src/app/components-library/page.tsx +8 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +116 -0
- package/src/app/layout.tsx +38 -0
- package/src/app/page.tsx +5 -0
- package/src/components/avatar/index.tsx +133 -0
- package/src/components/banner/index.tsx +62 -0
- package/src/components/button/index.tsx +63 -0
- package/src/components/carousel/index.tsx +63 -0
- package/src/components/checkbox/index.tsx +62 -0
- package/src/components/chip/index.tsx +26 -0
- package/src/components/ellipsis/index.tsx +38 -0
- package/src/components/fileUploader/index.tsx +58 -0
- package/src/components/filterDropdown/index.tsx +48 -0
- package/src/components/icons/NewTabSVGG/index.tsx +14 -0
- package/src/components/icons/alienFaceSVG/index.tsx +14 -0
- package/src/components/icons/alienUserSVG/index.tsx +14 -0
- package/src/components/icons/arrowLeftSVG/index.tsx +16 -0
- package/src/components/icons/arrowRightSVG/index.tsx +16 -0
- package/src/components/icons/astronautSVG/index.tsx +14 -0
- package/src/components/icons/balanceSVG/index.tsx +14 -0
- package/src/components/icons/balloonsSVG/index.tsx +14 -0
- package/src/components/icons/basketSVG/index.tsx +14 -0
- package/src/components/icons/batSVG/index.tsx +14 -0
- package/src/components/icons/batterySVG/index.tsx +14 -0
- package/src/components/icons/beeSVG/index.tsx +14 -0
- package/src/components/icons/binocularSVG/index.tsx +14 -0
- package/src/components/icons/birdSVG/index.tsx +14 -0
- package/src/components/icons/boxFilledSVG/index.tsx +14 -0
- package/src/components/icons/brainSVG/index.tsx +14 -0
- package/src/components/icons/brightHighSVG/index.tsx +14 -0
- package/src/components/icons/brightLowSVG/index.tsx +14 -0
- package/src/components/icons/bucketSVG/index.tsx +14 -0
- package/src/components/icons/cabinSVG/index.tsx +14 -0
- package/src/components/icons/cakeSVG/index.tsx +14 -0
- package/src/components/icons/chartSVG/index.tsx +14 -0
- package/src/components/icons/checkSVG/index.tsx +21 -0
- package/src/components/icons/chevDownSVG/index.tsx +16 -0
- package/src/components/icons/chevLeftSVG/index.tsx +16 -0
- package/src/components/icons/chevRightSVG/index.tsx +16 -0
- package/src/components/icons/chevUpSVG/index.tsx +16 -0
- package/src/components/icons/circleSVG/index.tsx +16 -0
- package/src/components/icons/citySVG/index.tsx +14 -0
- package/src/components/icons/clockSVG/index.tsx +14 -0
- package/src/components/icons/cocktailSVG/index.tsx +14 -0
- package/src/components/icons/codeSVG/index.tsx +14 -0
- package/src/components/icons/coinSVG/index.tsx +14 -0
- package/src/components/icons/coinsSVG/index.tsx +14 -0
- package/src/components/icons/colorsSVG/index.tsx +23 -0
- package/src/components/icons/connectionSVG/index.tsx +14 -0
- package/src/components/icons/coversSVG/index.tsx +23 -0
- package/src/components/icons/cowSVG/index.tsx +14 -0
- package/src/components/icons/crabSVG/index.tsx +14 -0
- package/src/components/icons/crossSVG/index.tsx +18 -0
- package/src/components/icons/csvSVG/index.tsx +14 -0
- package/src/components/icons/dashboardSVG/index.tsx +16 -0
- package/src/components/icons/diceSVG/index.tsx +14 -0
- package/src/components/icons/dolphinSVG/index.tsx +14 -0
- package/src/components/icons/doorOpenSVG/index.tsx +14 -0
- package/src/components/icons/dotFillSVG/index.tsx +16 -0
- package/src/components/icons/downFolderSVG/index.tsx +14 -0
- package/src/components/icons/downloadSVG/index.tsx +14 -0
- package/src/components/icons/eclipseSVG/index.tsx +23 -0
- package/src/components/icons/editSVG/index.tsx +14 -0
- package/src/components/icons/elephantSVG/index.tsx +14 -0
- package/src/components/icons/fenceSVG/index.tsx +14 -0
- package/src/components/icons/filterSVG/index.tsx +23 -0
- package/src/components/icons/filtersSVG/index.tsx +14 -0
- package/src/components/icons/foxSVG/index.tsx +14 -0
- package/src/components/icons/ghostSVG/index.tsx +14 -0
- package/src/components/icons/helicopterSVG/index.tsx +14 -0
- package/src/components/icons/hospitalSVG/index.tsx +14 -0
- package/src/components/icons/imageSVG/index.tsx +14 -0
- package/src/components/icons/index.tsx +107 -0
- package/src/components/icons/joystickSVG/index.tsx +14 -0
- package/src/components/icons/lightSVG/index.tsx +14 -0
- package/src/components/icons/lionSVG/index.tsx +14 -0
- package/src/components/icons/lobsterSVG/index.tsx +14 -0
- package/src/components/icons/lockSVG/index.tsx +14 -0
- package/src/components/icons/masksSVG/index.tsx +14 -0
- package/src/components/icons/mobileSVG/index.tsx +20 -0
- package/src/components/icons/moneyBagSVG/index.tsx +14 -0
- package/src/components/icons/moneySVG/index.tsx +14 -0
- package/src/components/icons/monkeySVG/index.tsx +14 -0
- package/src/components/icons/orderInfoSVG/index.tsx +23 -0
- package/src/components/icons/ordersSVG/index.tsx +23 -0
- package/src/components/icons/pdfSVG/index.tsx +14 -0
- package/src/components/icons/percentageSVG/index.tsx +14 -0
- package/src/components/icons/pinSVG/index.tsx +14 -0
- package/src/components/icons/planeSVG/index.tsx +14 -0
- package/src/components/icons/printerSVG/index.tsx +14 -0
- package/src/components/icons/productsSVG/index.tsx +23 -0
- package/src/components/icons/radioSVG/index.tsx +14 -0
- package/src/components/icons/robotSVG/index.tsx +14 -0
- package/src/components/icons/rocketSVG/index.tsx +14 -0
- package/src/components/icons/sheepSVG/index.tsx +14 -0
- package/src/components/icons/shuttleSVG/index.tsx +14 -0
- package/src/components/icons/signInSVG/index.tsx +16 -0
- package/src/components/icons/signOutSVG/index.tsx +23 -0
- package/src/components/icons/signalSVG/index.tsx +14 -0
- package/src/components/icons/sirenSVG/index.tsx +14 -0
- package/src/components/icons/snakeSVG/index.tsx +14 -0
- package/src/components/icons/sortSVG/index.tsx +14 -0
- package/src/components/icons/squareFillSVG/index.tsx +16 -0
- package/src/components/icons/starsSVG/index.tsx +26 -0
- package/src/components/icons/stepsSVG/index.tsx +14 -0
- package/src/components/icons/storeSVG/index.tsx +14 -0
- package/src/components/icons/suitcaseSVG/index.tsx +14 -0
- package/src/components/icons/tagsSVG/index.tsx +14 -0
- package/src/components/icons/templatesSVG/index.tsx +23 -0
- package/src/components/icons/terminalSVG/index.tsx +14 -0
- package/src/components/icons/toDoSVG/index.tsx +14 -0
- package/src/components/icons/turtleSVG/index.tsx +14 -0
- package/src/components/icons/ufoSVG/index.tsx +14 -0
- package/src/components/icons/unlockSVG/index.tsx +14 -0
- package/src/components/icons/upFolderSVG/index.tsx +14 -0
- package/src/components/icons/uploadSVG/index.tsx +23 -0
- package/src/components/icons/vanSVG/index.tsx +14 -0
- package/src/components/icons/videoCamSVG/index.tsx +14 -0
- package/src/components/icons/walletSVG/index.tsx +14 -0
- package/src/components/icons/whaleSVG/index.tsx +14 -0
- package/src/components/icons/wifiSVG/index.tsx +14 -0
- package/src/components/input/index.tsx +63 -0
- package/src/components/modal/index.tsx +58 -0
- package/src/components/navBar/index.tsx +284 -0
- package/src/components/pagination/index.tsx +79 -0
- package/src/components/radioButton/index.tsx +57 -0
- package/src/components/selectDropdown/index.tsx +110 -0
- package/src/components/snackBar/index.tsx +50 -0
- package/src/components/state/index.tsx +74 -0
- package/src/components/table/index.tsx +58 -0
- package/src/components/tag/index.tsx +44 -0
- package/src/components/textarea/index.tsx +67 -0
- package/src/components/timeLine/index.tsx +101 -0
- package/src/components/tooltip/index.tsx +74 -0
- package/src/index.ts +63 -0
- package/src/templates/component-library/avatars/index.tsx +49 -0
- package/src/templates/component-library/banners/index.tsx +35 -0
- package/src/templates/component-library/buttons/index.tsx +122 -0
- package/src/templates/component-library/carousels/index.tsx +38 -0
- package/src/templates/component-library/checkboxes/index.tsx +19 -0
- package/src/templates/component-library/chips/index.tsx +49 -0
- package/src/templates/component-library/ellipsis/index.tsx +20 -0
- package/src/templates/component-library/fileUploaders/index.tsx +21 -0
- package/src/templates/component-library/filterDropdown/index.tsx +48 -0
- package/src/templates/component-library/icons/index.tsx +23 -0
- package/src/templates/component-library/index.tsx +184 -0
- package/src/templates/component-library/input/index.tsx +42 -0
- package/src/templates/component-library/modals/index.tsx +113 -0
- package/src/templates/component-library/navBars/index.tsx +110 -0
- package/src/templates/component-library/pagination/index.tsx +28 -0
- package/src/templates/component-library/radioButtons/index.tsx +33 -0
- package/src/templates/component-library/selectDropdown/index.tsx +90 -0
- package/src/templates/component-library/snackBars/index.tsx +34 -0
- package/src/templates/component-library/states/index.tsx +24 -0
- package/src/templates/component-library/tables/index.tsx +149 -0
- package/src/templates/component-library/tags/index.tsx +15 -0
- package/src/templates/component-library/textarea/index.tsx +42 -0
- package/src/templates/component-library/timeLines/index.tsx +109 -0
- package/src/templates/component-library/tooltips/index.tsx +61 -0
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gwan-design-system",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "✨ A reusable component library for Next.js projects.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
|
+
"src",
|
|
10
11
|
"README.md"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
Binary file
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght@8..144,100..1000&display=swap");
|
|
2
|
+
@import "tailwindcss";
|
|
3
|
+
|
|
4
|
+
:root {
|
|
5
|
+
--background: #ffffff;
|
|
6
|
+
--foreground: #171717;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@theme {
|
|
10
|
+
/* Existing CSS variables */
|
|
11
|
+
--color-background: var(--background);
|
|
12
|
+
--color-foreground: var(--foreground);
|
|
13
|
+
|
|
14
|
+
/* Primary */
|
|
15
|
+
--color-primary-50: #f2f3ee;
|
|
16
|
+
--color-primary-100: #e1e3da;
|
|
17
|
+
--color-primary-200: #d0d3c6;
|
|
18
|
+
--color-primary-300: #bec3b2;
|
|
19
|
+
--color-primary-400: #adb39e;
|
|
20
|
+
--color-primary-500: #9ea593;
|
|
21
|
+
--color-primary-600: #8c9382;
|
|
22
|
+
--color-primary-700: #787d6e;
|
|
23
|
+
--color-primary-800: #64675a;
|
|
24
|
+
--color-primary-900: #505146;
|
|
25
|
+
|
|
26
|
+
/* Green */
|
|
27
|
+
--color-green-50: #e6f7e6;
|
|
28
|
+
--color-green-100: #c0eac0;
|
|
29
|
+
--color-green-200: #99dc99;
|
|
30
|
+
--color-green-300: #73cf73;
|
|
31
|
+
--color-green-400: #4cc14c;
|
|
32
|
+
--color-green-500: #0ba803;
|
|
33
|
+
--color-green-600: #0a9602;
|
|
34
|
+
--color-green-700: #087f02;
|
|
35
|
+
--color-green-800: #066602;
|
|
36
|
+
--color-green-900: #044c01;
|
|
37
|
+
|
|
38
|
+
/* Red */
|
|
39
|
+
--color-red-50: #fde7e7;
|
|
40
|
+
--color-red-100: #fbc0c0;
|
|
41
|
+
--color-red-200: #f89999;
|
|
42
|
+
--color-red-300: #f47373;
|
|
43
|
+
--color-red-400: #f04c4c;
|
|
44
|
+
--color-red-500: #df0303;
|
|
45
|
+
--color-red-600: #c90202;
|
|
46
|
+
--color-red-700: #a50202;
|
|
47
|
+
--color-red-800: #800202;
|
|
48
|
+
--color-red-900: #5c0101;
|
|
49
|
+
|
|
50
|
+
/* Blue */
|
|
51
|
+
--color-blue-50: #e6f3fa;
|
|
52
|
+
--color-blue-100: #bfe1f3;
|
|
53
|
+
--color-blue-200: #99ceeb;
|
|
54
|
+
--color-blue-300: #73bce4;
|
|
55
|
+
--color-blue-400: #4caadc;
|
|
56
|
+
--color-blue-500: #0369a8;
|
|
57
|
+
--color-blue-600: #025e97;
|
|
58
|
+
--color-blue-700: #024d7c;
|
|
59
|
+
--color-blue-800: #013c61;
|
|
60
|
+
--color-blue-900: #012b46;
|
|
61
|
+
|
|
62
|
+
/* Yellow */
|
|
63
|
+
--color-yellow-50: #f9f7e6;
|
|
64
|
+
--color-yellow-100: #f0efc0;
|
|
65
|
+
--color-yellow-200: #e6e699;
|
|
66
|
+
--color-yellow-300: #dcdc73;
|
|
67
|
+
--color-yellow-400: #d1d14c;
|
|
68
|
+
--color-yellow-500: #a8a203;
|
|
69
|
+
--color-yellow-600: #969002;
|
|
70
|
+
--color-yellow-700: #7c7602;
|
|
71
|
+
--color-yellow-800: #615c01;
|
|
72
|
+
--color-yellow-900: #464301;
|
|
73
|
+
|
|
74
|
+
/* Neutral */
|
|
75
|
+
--color-neutral-50: #f8f8f8;
|
|
76
|
+
--color-neutral-100: #f0f0f0;
|
|
77
|
+
--color-neutral-200: #e7e7e7;
|
|
78
|
+
--color-neutral-300: #dedede;
|
|
79
|
+
--color-neutral-400: #d9d9d9;
|
|
80
|
+
--color-neutral-500: #bfbfbf;
|
|
81
|
+
--color-neutral-600: #a6a6a6;
|
|
82
|
+
--color-neutral-700: #8c8c8c;
|
|
83
|
+
--color-neutral-800: #737373;
|
|
84
|
+
--color-neutral-900: #595959;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@layer utilities {
|
|
88
|
+
.custom-bg {
|
|
89
|
+
background-image: linear-gradient(
|
|
90
|
+
135deg,
|
|
91
|
+
#9ea593,
|
|
92
|
+
#93a594,
|
|
93
|
+
#93a59c,
|
|
94
|
+
#939fa5,
|
|
95
|
+
#9394a5,
|
|
96
|
+
#9c93a5,
|
|
97
|
+
#a593a4,
|
|
98
|
+
#a59393
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (prefers-color-scheme: light) {
|
|
104
|
+
:root {
|
|
105
|
+
--background: #0a0a0a;
|
|
106
|
+
--foreground: #ededed;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
body {
|
|
111
|
+
color: var(--foreground);
|
|
112
|
+
background: var(--background);
|
|
113
|
+
font-family: "Roboto Flex", sans-serif;
|
|
114
|
+
font-optical-sizing: auto;
|
|
115
|
+
font-style: normal;
|
|
116
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import "./globals.css";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
4
|
+
import { SpeedInsights } from "@vercel/speed-insights/next";
|
|
5
|
+
import { Analytics } from "@vercel/analytics/next";
|
|
6
|
+
|
|
7
|
+
const geistSans = Geist({
|
|
8
|
+
variable: "--font-geist-sans",
|
|
9
|
+
subsets: ["latin"],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const geistMono = Geist_Mono({
|
|
13
|
+
variable: "--font-geist-mono",
|
|
14
|
+
subsets: ["latin"],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const metadata: Metadata = {
|
|
18
|
+
title: "GWAN Design System",
|
|
19
|
+
description: "A design system for Next.js",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function RootLayout({
|
|
23
|
+
children,
|
|
24
|
+
}: Readonly<{
|
|
25
|
+
children: React.ReactNode;
|
|
26
|
+
}>) {
|
|
27
|
+
return (
|
|
28
|
+
<html lang="en">
|
|
29
|
+
<body
|
|
30
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
31
|
+
>
|
|
32
|
+
<SpeedInsights />
|
|
33
|
+
<Analytics />
|
|
34
|
+
{children}
|
|
35
|
+
</body>
|
|
36
|
+
</html>
|
|
37
|
+
);
|
|
38
|
+
}
|
package/src/app/page.tsx
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
import { FC, useEffect, useState } from "react";
|
|
3
|
+
import Tooltip, { TOOLTIP_POSITION } from "../tooltip";
|
|
4
|
+
|
|
5
|
+
export enum AVATAR_VARIANT {
|
|
6
|
+
IMAGE_WITH_FULL = "image_with_full",
|
|
7
|
+
INITIALS_WITH_FULL = "initials_with_full",
|
|
8
|
+
IMAGE_ONLY = "image-only",
|
|
9
|
+
INITIALS_ONLY = "initials-only",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface IAvatar {
|
|
13
|
+
name: string;
|
|
14
|
+
email: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
variant: string;
|
|
17
|
+
className?: string;
|
|
18
|
+
isLoading?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const generatePastelColor = () => {
|
|
22
|
+
const hue = Math.floor(Math.random() * 360);
|
|
23
|
+
const saturation = 60 + Math.random() * 20;
|
|
24
|
+
const lightness = 75 + Math.random() * 10;
|
|
25
|
+
|
|
26
|
+
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const Avatar: FC<IAvatar> = ({
|
|
30
|
+
name,
|
|
31
|
+
email,
|
|
32
|
+
image,
|
|
33
|
+
variant,
|
|
34
|
+
className = "",
|
|
35
|
+
isLoading = false,
|
|
36
|
+
}: IAvatar) => {
|
|
37
|
+
const [bgColor, setBgColor] = useState<string>("transparent");
|
|
38
|
+
const [isTooltipInitialVisible, setIsTooltipInitialVisible] = useState(false);
|
|
39
|
+
const [isTooltipImageVisible, setIsTooltipImageVisible] = useState(false);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
setBgColor(generatePastelColor());
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const generateInitials = (name: string) => {
|
|
46
|
+
const nameArray = name.split(" ");
|
|
47
|
+
return nameArray.length > 1
|
|
48
|
+
? `${nameArray[0].charAt(0)}${nameArray[1].charAt(0)}`
|
|
49
|
+
: nameArray[0].charAt(0);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const renderTooltip = (name: string, email: string, isVisible: boolean) => {
|
|
53
|
+
return (
|
|
54
|
+
<Tooltip
|
|
55
|
+
position={TOOLTIP_POSITION.RIGHT}
|
|
56
|
+
label={
|
|
57
|
+
<div className="flex flex-col">
|
|
58
|
+
{name}
|
|
59
|
+
<p className="text-neutral-300 text-xs">{email}</p>
|
|
60
|
+
</div>
|
|
61
|
+
}
|
|
62
|
+
isVisible={isVisible}
|
|
63
|
+
toolTipWidth="w-36"
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const renderAvatarImage = () => {
|
|
69
|
+
if (image) {
|
|
70
|
+
return (
|
|
71
|
+
<div
|
|
72
|
+
className="relative"
|
|
73
|
+
onMouseEnter={() => setIsTooltipImageVisible(true)}
|
|
74
|
+
onMouseLeave={() => setIsTooltipImageVisible(false)}
|
|
75
|
+
>
|
|
76
|
+
<Image
|
|
77
|
+
className="rounded-full border border-neutral-400"
|
|
78
|
+
src={image}
|
|
79
|
+
alt="profile"
|
|
80
|
+
width={55}
|
|
81
|
+
height={55}
|
|
82
|
+
/>
|
|
83
|
+
{variant === AVATAR_VARIANT.IMAGE_ONLY &&
|
|
84
|
+
renderTooltip(name, email, isTooltipImageVisible)}
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
className="size-[55px] flex items-center justify-center rounded-full font-semibold cursor-default relative"
|
|
92
|
+
style={{ backgroundColor: bgColor }}
|
|
93
|
+
onMouseEnter={() => setIsTooltipInitialVisible(true)}
|
|
94
|
+
onMouseLeave={() => setIsTooltipInitialVisible(false)}
|
|
95
|
+
>
|
|
96
|
+
{generateInitials(name)}
|
|
97
|
+
{variant === AVATAR_VARIANT.INITIALS_ONLY &&
|
|
98
|
+
renderTooltip(name, email, isTooltipInitialVisible)}
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if (isLoading) {
|
|
104
|
+
return (
|
|
105
|
+
<div className="flex flex-row items-center gap-2 pl-[5px] animate-pulse">
|
|
106
|
+
<div className="w-[55px] h-[55px] rounded-full bg-neutral-400"></div>
|
|
107
|
+
{(variant === AVATAR_VARIANT.IMAGE_WITH_FULL ||
|
|
108
|
+
variant === AVATAR_VARIANT.INITIALS_WITH_FULL) && (
|
|
109
|
+
<div className="flex flex-col gap-2 flex-1">
|
|
110
|
+
<div className="w-full h-6 bg-neutral-400 rounded-lg"></div>
|
|
111
|
+
<div className="w-[70%] h-4 bg-neutral-400 rounded-lg"></div>
|
|
112
|
+
</div>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div className={`flex flex-row items-center gap-2 pl-[5px] ${className}`}>
|
|
120
|
+
{renderAvatarImage()}
|
|
121
|
+
|
|
122
|
+
{(variant === AVATAR_VARIANT.IMAGE_WITH_FULL ||
|
|
123
|
+
variant === AVATAR_VARIANT.INITIALS_WITH_FULL) && (
|
|
124
|
+
<div className="flex flex-col">
|
|
125
|
+
<p className="text-base font-semibold">{name}</p>
|
|
126
|
+
<p className="text-sm text-neutral-700">{email}</p>
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default Avatar;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
|
|
3
|
+
export interface IBanner {
|
|
4
|
+
title?: string;
|
|
5
|
+
titleClassName?: string;
|
|
6
|
+
subTitle?: string;
|
|
7
|
+
subTitleClassName?: string;
|
|
8
|
+
contentPlacement?: "left" | "right";
|
|
9
|
+
backgroundImage?: string;
|
|
10
|
+
backgroundColor?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Banner: FC<IBanner> = ({
|
|
15
|
+
title = "",
|
|
16
|
+
subTitle = "",
|
|
17
|
+
contentPlacement = "left",
|
|
18
|
+
backgroundImage = "",
|
|
19
|
+
backgroundColor = "",
|
|
20
|
+
titleClassName = "",
|
|
21
|
+
subTitleClassName = "",
|
|
22
|
+
className = "",
|
|
23
|
+
}: IBanner) => {
|
|
24
|
+
const handleContentPlacement = () => {
|
|
25
|
+
if (contentPlacement === "left") {
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<div className="flex flex-col gap-2">
|
|
29
|
+
<p className={titleClassName}>{title}</p>
|
|
30
|
+
<p className={subTitleClassName}>{subTitle}</p>
|
|
31
|
+
</div>
|
|
32
|
+
<div></div>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<div></div>
|
|
40
|
+
<div className="flex flex-col gap-2">
|
|
41
|
+
<p className={titleClassName}>{title}</p>
|
|
42
|
+
<p className={subTitleClassName}>{subTitle}</p>
|
|
43
|
+
</div>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
className={`w-full h-[484px] grid grid-cols-2 items-center px-16 ${backgroundColor} bg-no-repeat bg-cover bg-center ${className}`}
|
|
51
|
+
style={
|
|
52
|
+
backgroundImage !== ""
|
|
53
|
+
? { backgroundImage: `url(${backgroundImage})` }
|
|
54
|
+
: {}
|
|
55
|
+
}
|
|
56
|
+
>
|
|
57
|
+
{handleContentPlacement()}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default Banner;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FC, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export enum BUTTON_VARIANTS {
|
|
4
|
+
PRIMARY = "primary",
|
|
5
|
+
SECONDARY = "secondary",
|
|
6
|
+
TERTIARY = "tertiary",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface IButton {
|
|
10
|
+
variant?: BUTTON_VARIANTS;
|
|
11
|
+
label?: string;
|
|
12
|
+
onClick: () => void;
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
type?: "button" | "submit";
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Button: FC<IButton> = ({
|
|
20
|
+
variant = BUTTON_VARIANTS.PRIMARY,
|
|
21
|
+
label,
|
|
22
|
+
onClick,
|
|
23
|
+
icon,
|
|
24
|
+
type = "button",
|
|
25
|
+
disabled = false,
|
|
26
|
+
className = "",
|
|
27
|
+
}: IButton) => {
|
|
28
|
+
const getButtonVariant = (variant: BUTTON_VARIANTS) => {
|
|
29
|
+
switch (variant) {
|
|
30
|
+
case BUTTON_VARIANTS.PRIMARY:
|
|
31
|
+
return disabled
|
|
32
|
+
? "bg-neutral-300 text-neutral-800 cursor-not-allowed"
|
|
33
|
+
: "bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700";
|
|
34
|
+
|
|
35
|
+
case BUTTON_VARIANTS.SECONDARY:
|
|
36
|
+
return disabled
|
|
37
|
+
? "bg-neutral-100 text-neutral-800 cursor-not-allowed"
|
|
38
|
+
: "bg-neutral-50 text-primary-700 hover:bg-primary-50 active:bg-primary-100";
|
|
39
|
+
case BUTTON_VARIANTS.TERTIARY:
|
|
40
|
+
return disabled
|
|
41
|
+
? "text-neutral-300 border border-neutral-300 cursor-not-allowed"
|
|
42
|
+
: "bg-transparent text-primary-500 border border-primary-500 hover:bg-neutral-50 active:bg-neutral-100";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<button
|
|
48
|
+
className={`${getButtonVariant(variant)} px-4 ${
|
|
49
|
+
label ? "py-2" : "py-4"
|
|
50
|
+
} rounded-lg ${className}`}
|
|
51
|
+
type={type}
|
|
52
|
+
onClick={onClick}
|
|
53
|
+
disabled={disabled}
|
|
54
|
+
>
|
|
55
|
+
<div className="flex flex-row gap-2 items-center">
|
|
56
|
+
{icon && <div className="size-5">{icon}</div>}
|
|
57
|
+
{label && <p>{label}</p>}
|
|
58
|
+
</div>
|
|
59
|
+
</button>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default Button;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FC, useEffect, useState } from "react";
|
|
2
|
+
import Banner, { IBanner } from "../banner";
|
|
3
|
+
|
|
4
|
+
export interface ICarousel {
|
|
5
|
+
slides: IBanner[];
|
|
6
|
+
interval?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Carousel: FC<ICarousel> = ({
|
|
11
|
+
slides,
|
|
12
|
+
interval = 3000,
|
|
13
|
+
className = "",
|
|
14
|
+
}: ICarousel) => {
|
|
15
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const timer = setInterval(() => {
|
|
19
|
+
setCurrentIndex((prev) => (prev + 1) % slides.length);
|
|
20
|
+
}, interval);
|
|
21
|
+
return () => clearInterval(timer);
|
|
22
|
+
}, [slides.length, interval]);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={`relative w-full h-[484px] overflow-hidden ${className}`}>
|
|
26
|
+
{slides.map(
|
|
27
|
+
(
|
|
28
|
+
{
|
|
29
|
+
title,
|
|
30
|
+
titleClassName,
|
|
31
|
+
subTitle,
|
|
32
|
+
subTitleClassName,
|
|
33
|
+
backgroundImage,
|
|
34
|
+
backgroundColor,
|
|
35
|
+
contentPlacement,
|
|
36
|
+
},
|
|
37
|
+
index
|
|
38
|
+
) => {
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
key={index}
|
|
42
|
+
className={`absolute inset-0 transition-opacity duration-1000 ease-in-out ${
|
|
43
|
+
index === currentIndex ? "opacity-100 z-10" : "opacity-0 z-0"
|
|
44
|
+
}`}
|
|
45
|
+
>
|
|
46
|
+
<Banner
|
|
47
|
+
title={title}
|
|
48
|
+
titleClassName={titleClassName}
|
|
49
|
+
subTitle={subTitle}
|
|
50
|
+
subTitleClassName={subTitleClassName}
|
|
51
|
+
contentPlacement={contentPlacement}
|
|
52
|
+
backgroundImage={backgroundImage}
|
|
53
|
+
backgroundColor={backgroundColor}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default Carousel;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { FC, useState } from "react";
|
|
2
|
+
import { CheckSVG } from "../icons";
|
|
3
|
+
|
|
4
|
+
export interface ICheckbox {
|
|
5
|
+
label: string;
|
|
6
|
+
checked: boolean;
|
|
7
|
+
onChange: (checked: boolean) => void;
|
|
8
|
+
className?: string;
|
|
9
|
+
disabled?:boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Checkbox: FC<ICheckbox> = ({
|
|
13
|
+
label,
|
|
14
|
+
checked = false,
|
|
15
|
+
onChange,
|
|
16
|
+
className = "",
|
|
17
|
+
disabled = false,
|
|
18
|
+
}: ICheckbox) => {
|
|
19
|
+
const [isChecked, setIsChecked] = useState(checked);
|
|
20
|
+
|
|
21
|
+
const handleToggle = () => {
|
|
22
|
+
if (disabled) return;
|
|
23
|
+
|
|
24
|
+
setIsChecked(!isChecked);
|
|
25
|
+
if (onChange) {
|
|
26
|
+
onChange(!isChecked);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<label className={`flex items-center gap-2 cursor-pointer ${className} ${
|
|
32
|
+
disabled ? "cursor-not-allowed opacity-50" : ""
|
|
33
|
+
}`}>
|
|
34
|
+
<input
|
|
35
|
+
type="checkbox"
|
|
36
|
+
checked={isChecked}
|
|
37
|
+
onChange={handleToggle}
|
|
38
|
+
disabled={disabled}
|
|
39
|
+
className="hidden"
|
|
40
|
+
/>
|
|
41
|
+
<div
|
|
42
|
+
className={`w-5 h-5 flex items-center justify-center border-2 rounded-md transition-all
|
|
43
|
+
${
|
|
44
|
+
isChecked
|
|
45
|
+
? "bg-primary-300 border-primary-400"
|
|
46
|
+
: "bg-white border-neutral-500"
|
|
47
|
+
}
|
|
48
|
+
${disabled ? "bg-neutral-200 border-neutral-400" : ""}
|
|
49
|
+
`}
|
|
50
|
+
>
|
|
51
|
+
{isChecked && (
|
|
52
|
+
<div className="size-4 text-black">
|
|
53
|
+
<CheckSVG />
|
|
54
|
+
</div>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
{label && <span className="text-black">{label}</span>}
|
|
58
|
+
</label>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default Checkbox;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { CrossSVG } from "../icons";
|
|
3
|
+
|
|
4
|
+
export interface IChip {
|
|
5
|
+
label: string;
|
|
6
|
+
onClear: () => void;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Chip: FC<IChip> = ({ label, onClear, className = "" }: IChip) => {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
className={`flex flex-row gap-2 items-center bg-neutral-700 w-fit px-4 py-2 rounded-full ${className}`}
|
|
14
|
+
>
|
|
15
|
+
<div
|
|
16
|
+
className="size-3 cursor-pointer text-neutral-200 hover:text-white"
|
|
17
|
+
onClick={onClear}
|
|
18
|
+
>
|
|
19
|
+
<CrossSVG />
|
|
20
|
+
</div>
|
|
21
|
+
<p className="text-neutral-200 text-base font-semibold">{label}</p>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default Chip;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FC, useState } from "react";
|
|
2
|
+
import Tooltip, { TOOLTIP_POSITION } from "../tooltip";
|
|
3
|
+
|
|
4
|
+
export interface IEllipsis {
|
|
5
|
+
label: string;
|
|
6
|
+
tooltipPosition?: TOOLTIP_POSITION;
|
|
7
|
+
tooltipWidth?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Ellipsis: FC<IEllipsis> = ({
|
|
12
|
+
label,
|
|
13
|
+
tooltipPosition = TOOLTIP_POSITION.RIGHT,
|
|
14
|
+
tooltipWidth = "w-40",
|
|
15
|
+
className = "",
|
|
16
|
+
}: IEllipsis) => {
|
|
17
|
+
const [isTooltipVisible, setIsTooltipVisible] = useState(false);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className={`relative ${className}`}
|
|
22
|
+
onMouseEnter={() => setIsTooltipVisible(true)}
|
|
23
|
+
onMouseLeave={() => setIsTooltipVisible(false)}
|
|
24
|
+
>
|
|
25
|
+
<p className="text-ellipsis w-32 overflow-hidden whitespace-nowrap">
|
|
26
|
+
{label}
|
|
27
|
+
</p>
|
|
28
|
+
<Tooltip
|
|
29
|
+
label={label}
|
|
30
|
+
position={tooltipPosition}
|
|
31
|
+
isVisible={isTooltipVisible}
|
|
32
|
+
toolTipWidth={tooltipWidth}
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default Ellipsis;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { FC, useRef } from "react";
|
|
2
|
+
import { UploadSVG } from "../icons";
|
|
3
|
+
|
|
4
|
+
export interface IFileUploader {
|
|
5
|
+
title: string;
|
|
6
|
+
subTitle1?: string;
|
|
7
|
+
subTitle2?: string;
|
|
8
|
+
handleAttachment: (file: File) => void;
|
|
9
|
+
accept?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const FileUploader: FC<IFileUploader> = ({
|
|
14
|
+
title,
|
|
15
|
+
subTitle1 = "",
|
|
16
|
+
subTitle2 = "",
|
|
17
|
+
handleAttachment,
|
|
18
|
+
accept = ".jpg,.jpeg,.png",
|
|
19
|
+
className = "",
|
|
20
|
+
}: IFileUploader) => {
|
|
21
|
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
22
|
+
|
|
23
|
+
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
24
|
+
const files = event.target.files;
|
|
25
|
+
if (files && files.length > 0) {
|
|
26
|
+
handleAttachment(files[0]);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
className={`flex flex-row gap-4 items-start border border-dashed border-neutral-200 p-4 rounded-lg ${className}`}
|
|
33
|
+
>
|
|
34
|
+
<div
|
|
35
|
+
className="bg-primary-500 hover:bg-primary-600 text-white px-6 py-8 rounded-lg cursor-pointer"
|
|
36
|
+
onClick={() => fileInputRef.current?.click()}
|
|
37
|
+
>
|
|
38
|
+
<div className="size-10">
|
|
39
|
+
<UploadSVG />
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
<input
|
|
43
|
+
type="file"
|
|
44
|
+
ref={fileInputRef}
|
|
45
|
+
accept={accept}
|
|
46
|
+
className="hidden"
|
|
47
|
+
onChange={handleFileUpload}
|
|
48
|
+
/>
|
|
49
|
+
<div className="flex-1 flex flex-col">
|
|
50
|
+
<p className="text-lg">{title}</p>
|
|
51
|
+
<p className="text-sm text-neutral-400">{subTitle1}</p>
|
|
52
|
+
<p className="text-sm text-neutral-400">{subTitle2}</p>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default FileUploader;
|