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.
Files changed (161) hide show
  1. package/package.json +2 -1
  2. package/src/app/components-library/page.tsx +8 -0
  3. package/src/app/favicon.ico +0 -0
  4. package/src/app/globals.css +116 -0
  5. package/src/app/layout.tsx +38 -0
  6. package/src/app/page.tsx +5 -0
  7. package/src/components/avatar/index.tsx +133 -0
  8. package/src/components/banner/index.tsx +62 -0
  9. package/src/components/button/index.tsx +63 -0
  10. package/src/components/carousel/index.tsx +63 -0
  11. package/src/components/checkbox/index.tsx +62 -0
  12. package/src/components/chip/index.tsx +26 -0
  13. package/src/components/ellipsis/index.tsx +38 -0
  14. package/src/components/fileUploader/index.tsx +58 -0
  15. package/src/components/filterDropdown/index.tsx +48 -0
  16. package/src/components/icons/NewTabSVGG/index.tsx +14 -0
  17. package/src/components/icons/alienFaceSVG/index.tsx +14 -0
  18. package/src/components/icons/alienUserSVG/index.tsx +14 -0
  19. package/src/components/icons/arrowLeftSVG/index.tsx +16 -0
  20. package/src/components/icons/arrowRightSVG/index.tsx +16 -0
  21. package/src/components/icons/astronautSVG/index.tsx +14 -0
  22. package/src/components/icons/balanceSVG/index.tsx +14 -0
  23. package/src/components/icons/balloonsSVG/index.tsx +14 -0
  24. package/src/components/icons/basketSVG/index.tsx +14 -0
  25. package/src/components/icons/batSVG/index.tsx +14 -0
  26. package/src/components/icons/batterySVG/index.tsx +14 -0
  27. package/src/components/icons/beeSVG/index.tsx +14 -0
  28. package/src/components/icons/binocularSVG/index.tsx +14 -0
  29. package/src/components/icons/birdSVG/index.tsx +14 -0
  30. package/src/components/icons/boxFilledSVG/index.tsx +14 -0
  31. package/src/components/icons/brainSVG/index.tsx +14 -0
  32. package/src/components/icons/brightHighSVG/index.tsx +14 -0
  33. package/src/components/icons/brightLowSVG/index.tsx +14 -0
  34. package/src/components/icons/bucketSVG/index.tsx +14 -0
  35. package/src/components/icons/cabinSVG/index.tsx +14 -0
  36. package/src/components/icons/cakeSVG/index.tsx +14 -0
  37. package/src/components/icons/chartSVG/index.tsx +14 -0
  38. package/src/components/icons/checkSVG/index.tsx +21 -0
  39. package/src/components/icons/chevDownSVG/index.tsx +16 -0
  40. package/src/components/icons/chevLeftSVG/index.tsx +16 -0
  41. package/src/components/icons/chevRightSVG/index.tsx +16 -0
  42. package/src/components/icons/chevUpSVG/index.tsx +16 -0
  43. package/src/components/icons/circleSVG/index.tsx +16 -0
  44. package/src/components/icons/citySVG/index.tsx +14 -0
  45. package/src/components/icons/clockSVG/index.tsx +14 -0
  46. package/src/components/icons/cocktailSVG/index.tsx +14 -0
  47. package/src/components/icons/codeSVG/index.tsx +14 -0
  48. package/src/components/icons/coinSVG/index.tsx +14 -0
  49. package/src/components/icons/coinsSVG/index.tsx +14 -0
  50. package/src/components/icons/colorsSVG/index.tsx +23 -0
  51. package/src/components/icons/connectionSVG/index.tsx +14 -0
  52. package/src/components/icons/coversSVG/index.tsx +23 -0
  53. package/src/components/icons/cowSVG/index.tsx +14 -0
  54. package/src/components/icons/crabSVG/index.tsx +14 -0
  55. package/src/components/icons/crossSVG/index.tsx +18 -0
  56. package/src/components/icons/csvSVG/index.tsx +14 -0
  57. package/src/components/icons/dashboardSVG/index.tsx +16 -0
  58. package/src/components/icons/diceSVG/index.tsx +14 -0
  59. package/src/components/icons/dolphinSVG/index.tsx +14 -0
  60. package/src/components/icons/doorOpenSVG/index.tsx +14 -0
  61. package/src/components/icons/dotFillSVG/index.tsx +16 -0
  62. package/src/components/icons/downFolderSVG/index.tsx +14 -0
  63. package/src/components/icons/downloadSVG/index.tsx +14 -0
  64. package/src/components/icons/eclipseSVG/index.tsx +23 -0
  65. package/src/components/icons/editSVG/index.tsx +14 -0
  66. package/src/components/icons/elephantSVG/index.tsx +14 -0
  67. package/src/components/icons/fenceSVG/index.tsx +14 -0
  68. package/src/components/icons/filterSVG/index.tsx +23 -0
  69. package/src/components/icons/filtersSVG/index.tsx +14 -0
  70. package/src/components/icons/foxSVG/index.tsx +14 -0
  71. package/src/components/icons/ghostSVG/index.tsx +14 -0
  72. package/src/components/icons/helicopterSVG/index.tsx +14 -0
  73. package/src/components/icons/hospitalSVG/index.tsx +14 -0
  74. package/src/components/icons/imageSVG/index.tsx +14 -0
  75. package/src/components/icons/index.tsx +107 -0
  76. package/src/components/icons/joystickSVG/index.tsx +14 -0
  77. package/src/components/icons/lightSVG/index.tsx +14 -0
  78. package/src/components/icons/lionSVG/index.tsx +14 -0
  79. package/src/components/icons/lobsterSVG/index.tsx +14 -0
  80. package/src/components/icons/lockSVG/index.tsx +14 -0
  81. package/src/components/icons/masksSVG/index.tsx +14 -0
  82. package/src/components/icons/mobileSVG/index.tsx +20 -0
  83. package/src/components/icons/moneyBagSVG/index.tsx +14 -0
  84. package/src/components/icons/moneySVG/index.tsx +14 -0
  85. package/src/components/icons/monkeySVG/index.tsx +14 -0
  86. package/src/components/icons/orderInfoSVG/index.tsx +23 -0
  87. package/src/components/icons/ordersSVG/index.tsx +23 -0
  88. package/src/components/icons/pdfSVG/index.tsx +14 -0
  89. package/src/components/icons/percentageSVG/index.tsx +14 -0
  90. package/src/components/icons/pinSVG/index.tsx +14 -0
  91. package/src/components/icons/planeSVG/index.tsx +14 -0
  92. package/src/components/icons/printerSVG/index.tsx +14 -0
  93. package/src/components/icons/productsSVG/index.tsx +23 -0
  94. package/src/components/icons/radioSVG/index.tsx +14 -0
  95. package/src/components/icons/robotSVG/index.tsx +14 -0
  96. package/src/components/icons/rocketSVG/index.tsx +14 -0
  97. package/src/components/icons/sheepSVG/index.tsx +14 -0
  98. package/src/components/icons/shuttleSVG/index.tsx +14 -0
  99. package/src/components/icons/signInSVG/index.tsx +16 -0
  100. package/src/components/icons/signOutSVG/index.tsx +23 -0
  101. package/src/components/icons/signalSVG/index.tsx +14 -0
  102. package/src/components/icons/sirenSVG/index.tsx +14 -0
  103. package/src/components/icons/snakeSVG/index.tsx +14 -0
  104. package/src/components/icons/sortSVG/index.tsx +14 -0
  105. package/src/components/icons/squareFillSVG/index.tsx +16 -0
  106. package/src/components/icons/starsSVG/index.tsx +26 -0
  107. package/src/components/icons/stepsSVG/index.tsx +14 -0
  108. package/src/components/icons/storeSVG/index.tsx +14 -0
  109. package/src/components/icons/suitcaseSVG/index.tsx +14 -0
  110. package/src/components/icons/tagsSVG/index.tsx +14 -0
  111. package/src/components/icons/templatesSVG/index.tsx +23 -0
  112. package/src/components/icons/terminalSVG/index.tsx +14 -0
  113. package/src/components/icons/toDoSVG/index.tsx +14 -0
  114. package/src/components/icons/turtleSVG/index.tsx +14 -0
  115. package/src/components/icons/ufoSVG/index.tsx +14 -0
  116. package/src/components/icons/unlockSVG/index.tsx +14 -0
  117. package/src/components/icons/upFolderSVG/index.tsx +14 -0
  118. package/src/components/icons/uploadSVG/index.tsx +23 -0
  119. package/src/components/icons/vanSVG/index.tsx +14 -0
  120. package/src/components/icons/videoCamSVG/index.tsx +14 -0
  121. package/src/components/icons/walletSVG/index.tsx +14 -0
  122. package/src/components/icons/whaleSVG/index.tsx +14 -0
  123. package/src/components/icons/wifiSVG/index.tsx +14 -0
  124. package/src/components/input/index.tsx +63 -0
  125. package/src/components/modal/index.tsx +58 -0
  126. package/src/components/navBar/index.tsx +284 -0
  127. package/src/components/pagination/index.tsx +79 -0
  128. package/src/components/radioButton/index.tsx +57 -0
  129. package/src/components/selectDropdown/index.tsx +110 -0
  130. package/src/components/snackBar/index.tsx +50 -0
  131. package/src/components/state/index.tsx +74 -0
  132. package/src/components/table/index.tsx +58 -0
  133. package/src/components/tag/index.tsx +44 -0
  134. package/src/components/textarea/index.tsx +67 -0
  135. package/src/components/timeLine/index.tsx +101 -0
  136. package/src/components/tooltip/index.tsx +74 -0
  137. package/src/index.ts +63 -0
  138. package/src/templates/component-library/avatars/index.tsx +49 -0
  139. package/src/templates/component-library/banners/index.tsx +35 -0
  140. package/src/templates/component-library/buttons/index.tsx +122 -0
  141. package/src/templates/component-library/carousels/index.tsx +38 -0
  142. package/src/templates/component-library/checkboxes/index.tsx +19 -0
  143. package/src/templates/component-library/chips/index.tsx +49 -0
  144. package/src/templates/component-library/ellipsis/index.tsx +20 -0
  145. package/src/templates/component-library/fileUploaders/index.tsx +21 -0
  146. package/src/templates/component-library/filterDropdown/index.tsx +48 -0
  147. package/src/templates/component-library/icons/index.tsx +23 -0
  148. package/src/templates/component-library/index.tsx +184 -0
  149. package/src/templates/component-library/input/index.tsx +42 -0
  150. package/src/templates/component-library/modals/index.tsx +113 -0
  151. package/src/templates/component-library/navBars/index.tsx +110 -0
  152. package/src/templates/component-library/pagination/index.tsx +28 -0
  153. package/src/templates/component-library/radioButtons/index.tsx +33 -0
  154. package/src/templates/component-library/selectDropdown/index.tsx +90 -0
  155. package/src/templates/component-library/snackBars/index.tsx +34 -0
  156. package/src/templates/component-library/states/index.tsx +24 -0
  157. package/src/templates/component-library/tables/index.tsx +149 -0
  158. package/src/templates/component-library/tags/index.tsx +15 -0
  159. package/src/templates/component-library/textarea/index.tsx +42 -0
  160. package/src/templates/component-library/timeLines/index.tsx +109 -0
  161. 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.13",
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": {
@@ -0,0 +1,8 @@
1
+ export const dynamic = "force-dynamic";
2
+ import LibraryTemplate from "@/templates/component-library";
3
+
4
+ const ComponentsLibrary = () => {
5
+ return <LibraryTemplate />;
6
+ };
7
+
8
+ export default ComponentsLibrary;
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
+ }
@@ -0,0 +1,5 @@
1
+ import { redirect } from "next/navigation";
2
+
3
+ export default function Home() {
4
+ redirect("/components-library");
5
+ }
@@ -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;