@skalfa/skalfa-component 1.0.7 → 1.0.8

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 (58) hide show
  1. package/package.json +2 -2
  2. package/src/accordion/Accordion.component.tsx +87 -0
  3. package/src/breadcrumb/Breadcrumb.component.tsx +79 -0
  4. package/src/button/Button.component.tsx +89 -0
  5. package/src/card/AlertCard.component.tsx +69 -0
  6. package/src/card/Card.component.tsx +25 -0
  7. package/src/card/DashboardCard.component.tsx +44 -0
  8. package/src/card/GalleryCard.component.tsx +50 -0
  9. package/src/card/ProductCard.component.tsx +65 -0
  10. package/src/card/ProfileCard.component.tsx +71 -0
  11. package/src/carousel/Carousel.component.tsx +111 -0
  12. package/src/chip/Chip.component.tsx +39 -0
  13. package/src/index.ts +70 -0
  14. package/src/input/Checkbox.component.tsx +102 -0
  15. package/src/input/Input.component.tsx +334 -0
  16. package/src/input/InputCheckbox.component.tsx +174 -0
  17. package/src/input/InputCurrency.component.tsx +165 -0
  18. package/src/input/InputDate.component.tsx +356 -0
  19. package/src/input/InputDatetime.component.tsx +267 -0
  20. package/src/input/InputDocument.component.tsx +360 -0
  21. package/src/input/InputImage.component.tsx +535 -0
  22. package/src/input/InputNumber.component.tsx +194 -0
  23. package/src/input/InputOtp.component.tsx +169 -0
  24. package/src/input/InputPassword.component.tsx +245 -0
  25. package/src/input/InputRadio.component.tsx +174 -0
  26. package/src/input/InputTime.component.tsx +280 -0
  27. package/src/input/InputValues.component.tsx +71 -0
  28. package/src/input/Radio.component.tsx +98 -0
  29. package/src/input/Select.component.tsx +557 -0
  30. package/src/modal/BottomSheet.component.tsx +246 -0
  31. package/src/modal/FloatingPage.component.tsx +103 -0
  32. package/src/modal/Modal.component.tsx +95 -0
  33. package/src/modal/ModalConfirm.component.tsx +219 -0
  34. package/src/modal/Toast.component.tsx +125 -0
  35. package/src/nav/Bottombar.component.tsx +72 -0
  36. package/src/nav/Footer.component.tsx +177 -0
  37. package/src/nav/Headbar.component.tsx +33 -0
  38. package/src/nav/Navbar.component.tsx +138 -0
  39. package/src/nav/Sidebar.component.tsx +298 -0
  40. package/src/nav/Tabbar.component.tsx +61 -0
  41. package/src/nav/Wizard.component.tsx +80 -0
  42. package/src/supervision/FormSupervision.component.tsx +425 -0
  43. package/src/supervision/TableSupervision.component.tsx +688 -0
  44. package/src/table/ControlBar.component.tsx +501 -0
  45. package/src/table/FilterComponent.tsx +519 -0
  46. package/src/table/Pagination.component.tsx +152 -0
  47. package/src/table/Table.component.tsx +436 -0
  48. package/src/types.d.ts +7 -0
  49. package/src/typography/TypographyArticle.component.tsx +26 -0
  50. package/src/typography/TypographyColumn.component.tsx +20 -0
  51. package/src/typography/TypographyContent.component.tsx +20 -0
  52. package/src/typography/TypographyTips.component.tsx +20 -0
  53. package/src/wrap/Draggable.component.tsx +303 -0
  54. package/src/wrap/Image.component.tsx +10 -0
  55. package/src/wrap/OutsideClick.component.tsx +48 -0
  56. package/src/wrap/ScrollContainer.component.tsx +107 -0
  57. package/src/wrap/ShortcutProvider.tsx +57 -0
  58. package/src/wrap/Swipe.component.tsx +121 -0
@@ -0,0 +1,298 @@
1
+ "use client"
2
+
3
+ import { Fragment, ReactNode, useEffect, useState } from "react";
4
+ import { usePathname } from "next/navigation";
5
+ import Link from "next/link";
6
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7
+ import { faChevronDown, faChevronUp } from "@fortawesome/free-solid-svg-icons";
8
+ import { cn, pcn } from "@utils";
9
+
10
+
11
+
12
+ type CT = "backdrop" | "base" | "head-item" | "item" | "child-item";
13
+
14
+ export interface SidebarItemProps {
15
+ label : string;
16
+ key ?: number;
17
+ leftContent ?: any;
18
+ rightContent ?: any;
19
+ path ?: string;
20
+ items ?: SidebarItemProps[];
21
+ className ?: string;
22
+ };
23
+
24
+ export interface SidebarHeadItemProps {
25
+ label : string;
26
+ collapse ?: boolean;
27
+ items ?: SidebarItemProps[];
28
+ className ?: string;
29
+ };
30
+
31
+ export interface sidebarProps {
32
+ head ?: any;
33
+ items ?: SidebarHeadItemProps[];
34
+ basePath ?: string;
35
+ show ?: boolean;
36
+ toggle ?: boolean;
37
+ onToggleChange ?: () => void;
38
+ children ?: any;
39
+ hasAccess ?: number[];
40
+ onChange ?: () => void;
41
+
42
+ /** Use custom class with: "backdrop::", "head-item::", "item::", "child-item::". */
43
+ className?: string;
44
+ };
45
+
46
+ interface sidebarWrapperProps {
47
+ path ?: string;
48
+ onClick ?: () => void;
49
+ children ?: any;
50
+ }
51
+
52
+
53
+
54
+
55
+ function SidebarWrapper({
56
+ path,
57
+ children,
58
+ onClick,
59
+ } : sidebarWrapperProps) {
60
+ if (path) {
61
+ return <Link href={path}>{children}</Link>;
62
+ } else {
63
+ return <div onClick={() => onClick?.()}>{children}</div>;
64
+ }
65
+ }
66
+
67
+
68
+
69
+ export function SidebarComponent({
70
+ head,
71
+ items,
72
+ basePath,
73
+ toggle,
74
+ onToggleChange,
75
+ // onChange,
76
+ // hasAccess,
77
+ className = "",
78
+ } : sidebarProps) {
79
+ const pathName = usePathname();
80
+
81
+ const [shows, setShows] = useState<string[]>([]);
82
+
83
+ const setShow = (key: string) => {
84
+ setShows((prevShows) =>
85
+ prevShows?.find((pk) => pk === key)
86
+ ? prevShows.filter((pk) => pk !== key)
87
+ : [...prevShows, key],
88
+ );
89
+ };
90
+
91
+ const checkShow = (key: string): boolean => {
92
+ if (shows?.includes(key)) {
93
+ return true;
94
+ }
95
+
96
+ return false;
97
+ };
98
+
99
+ const cekActive = (path: string) => {
100
+ const activePath =
101
+ pathName?.split("?")[0]?.replace(`${basePath || ""}`, "") || "/";
102
+
103
+ const currentPath = `${path ? `${path}` : ""}`;
104
+
105
+ const isPrefix = (longer: string, shorter: string): boolean => {
106
+ return (
107
+ longer.startsWith(shorter) &&
108
+ (longer === shorter || longer[shorter.length] === "/")
109
+ );
110
+ };
111
+
112
+ return (
113
+ isPrefix(activePath, currentPath) || isPrefix(currentPath, activePath)
114
+ );
115
+ };
116
+
117
+ useEffect(() => {
118
+ items?.map((head, head_key) => {
119
+ head?.items?.map((menu, key) => {
120
+ if (menu?.path && cekActive(menu?.path || "")) {
121
+ setShow(`${head_key}`);
122
+ }
123
+ menu?.items?.map((child) => {
124
+ if (child?.path && cekActive(child?.path || "")) {
125
+ setShow(`${head_key}`);
126
+ setShow(`${head_key}.${key}`);
127
+ }
128
+ });
129
+ });
130
+ });
131
+ }, []);
132
+
133
+ return (
134
+ <>
135
+ <div
136
+ className={cn(
137
+ "sidebar-backdrop",
138
+ toggle ? "scale-100 md:scale-0" : "scale-0",
139
+ pcn<CT>(className, "backdrop"),
140
+ )}
141
+ onClick={() => onToggleChange?.()}
142
+ ></div>
143
+ <aside
144
+ className={cn(
145
+ "sidebar-base scroll-sm",
146
+ toggle ? "scale-x-100 md:scale-x-0" : "scale-x-0 md:scale-x-100",
147
+ pcn<CT>(className, "base"),
148
+ )}
149
+ >
150
+ {head}
151
+ <nav className="flex flex-col flex-1 mt-3">
152
+ {items?.map((menu_head, menu_head_key) => {
153
+ return (
154
+ <Fragment key={menu_head_key}>
155
+ <div className="px-2 pt-2">
156
+ <div
157
+ className={cn(
158
+ "sidebar-head-item",
159
+ menu_head?.collapse && "cursor-pointer",
160
+ pcn<CT>(className, "head-item"),
161
+ menu_head?.className,
162
+ )}
163
+ onClick={() => setShow(String(menu_head_key))}
164
+ >
165
+ {menu_head?.label}
166
+ {menu_head.collapse && (
167
+ <FontAwesomeIcon
168
+ icon={faChevronDown}
169
+ className={cn(
170
+ "text-xs",
171
+ checkShow(String(menu_head_key)) && "rotate-180",
172
+ )}
173
+ />
174
+ )}
175
+ </div>
176
+
177
+ {(!menu_head?.collapse || checkShow(String(menu_head_key))) &&
178
+ menu_head?.items?.map((menu, menu_key) => {
179
+ return (
180
+ <Fragment key={`${menu_head_key}.${menu_key}`}>
181
+ <SidebarWrapper
182
+ path={
183
+ menu?.path ? `${basePath || ""}${menu?.path}` : ""
184
+ }
185
+ onClick={() =>
186
+ setShow(`${menu_head_key}.${menu_key}`)
187
+ }
188
+ >
189
+ <div
190
+ className={cn(
191
+ "sidebar-item",
192
+ menu?.path &&
193
+ cekActive(menu?.path || "") &&
194
+ "sidebar-item-active",
195
+ pcn<CT>(className, "item"),
196
+ menu?.className,
197
+ )}
198
+ >
199
+ <div className="flex gap-2 items-center">
200
+ {menu?.leftContent}
201
+ <span className="text-sm font-medium">
202
+ {menu?.label}
203
+ </span>
204
+ </div>
205
+ <div className="flex gap-2 items-center">
206
+ {menu?.rightContent}
207
+
208
+ {menu?.items?.length && (
209
+ <FontAwesomeIcon
210
+ icon={faChevronUp}
211
+ className={`text-sm ${
212
+ checkShow(
213
+ `${menu_head_key}.${menu_key}`,
214
+ ) || "rotate-180"
215
+ }`}
216
+ />
217
+ )}
218
+ </div>
219
+ </div>
220
+ </SidebarWrapper>
221
+ <div className="px-4">
222
+ <div className="flex flex-col">
223
+ {menu?.items?.length &&
224
+ checkShow(`${menu_head_key}.${menu_key}`) &&
225
+ menu?.items?.map((child, menu_child_key) => {
226
+ return (
227
+ <Fragment
228
+ key={`${menu_head_key}.${menu_key}.${menu_child_key}`}
229
+ >
230
+ <SidebarWrapper
231
+ path={
232
+ child?.path
233
+ ? `${basePath || ""}${child?.path}`
234
+ : ""
235
+ }
236
+ onClick={() =>
237
+ setShow(
238
+ `${menu_head_key}.${menu_key}.${menu_child_key}`,
239
+ )
240
+ }
241
+ >
242
+ <div
243
+ className={cn(
244
+ "sidebar-child-item",
245
+ child?.path &&
246
+ cekActive(child?.path || "") &&
247
+ "sidebar-child-item-active",
248
+ pcn<CT>(className, "child-item"),
249
+ child?.className,
250
+ )}
251
+ >
252
+ <div className="flex gap-2 items-center">
253
+ {child?.leftContent}
254
+ <span className="text-sm font-medium">
255
+ {child?.label}
256
+ </span>
257
+ </div>
258
+ <div className="flex gap-2 items-center">
259
+ {child?.rightContent}
260
+
261
+ {child?.items?.length && (
262
+ <FontAwesomeIcon
263
+ icon={faChevronUp}
264
+ className={`block text-sm ${
265
+ checkShow(
266
+ `${menu_head_key}.${menu_key}`,
267
+ ) || "rotate-180"
268
+ }`}
269
+ />
270
+ )}
271
+ </div>
272
+ </div>
273
+ </SidebarWrapper>
274
+ </Fragment>
275
+ );
276
+ })}
277
+ </div>
278
+ </div>
279
+ </Fragment>
280
+ );
281
+ })}
282
+ </div>
283
+ </Fragment>
284
+ );
285
+ })}
286
+ </nav>
287
+ </aside>
288
+ </>
289
+ );
290
+ }
291
+
292
+ export function SidebarContentComponent({ children }: { children: ReactNode }) {
293
+ return (
294
+ <main className="sidebar-main-content">
295
+ {children}
296
+ </main>
297
+ );
298
+ }
@@ -0,0 +1,61 @@
1
+ import { cn, pcn } from "@utils";
2
+
3
+
4
+
5
+ type CT = "item" | "active" | "base";
6
+
7
+ export interface TabbarItemProps {
8
+ label : string;
9
+ value : string | number;
10
+ };
11
+
12
+ export interface TabbarProps {
13
+ items : string[] | TabbarItemProps[];
14
+ onChange ?: (item: string | number) => void;
15
+ active ?: string | number;
16
+ className ?: string;
17
+ };
18
+
19
+
20
+
21
+ export function TabbarComponent({
22
+ items,
23
+ onChange,
24
+ active,
25
+
26
+ /** Use custom class with: "item::", "active::". */
27
+ className = "",
28
+ }: TabbarProps) {
29
+ return (
30
+ <>
31
+ <div
32
+ className={cn(
33
+ "tabbar-base",
34
+ pcn<CT>(className, "base"),
35
+ )}
36
+ >
37
+ {items?.map((item, i) => {
38
+ const isItemActive = active == (typeof item != "string" ? item?.value : item);
39
+ return (
40
+ <div
41
+ key={i}
42
+ className={cn(
43
+ "tabbar-item",
44
+ isItemActive
45
+ ? "tabbar-item-active"
46
+ : "tabbar-item-inactive",
47
+ pcn<CT>(className, "item"),
48
+ pcn<CT>(className, "active"),
49
+ )}
50
+ onClick={() =>
51
+ onChange?.(typeof item != "string" ? item?.value : item)
52
+ }
53
+ >
54
+ {typeof item != "string" ? item?.label : item}
55
+ </div>
56
+ );
57
+ })}
58
+ </div>
59
+ </>
60
+ );
61
+ }
@@ -0,0 +1,80 @@
1
+ import { ReactNode } from "react";
2
+ import { cn } from "@utils";
3
+
4
+
5
+
6
+ export interface WizardProps {
7
+ items : {label: string, circle_content: ReactNode}[];
8
+ active : number;
9
+ };
10
+
11
+
12
+
13
+ export function WizardComponent({
14
+ items,
15
+ active
16
+ }: WizardProps) {
17
+ return (
18
+ <div>
19
+ <div className="w-full py-4">
20
+ <div className="flex">
21
+ {items.map((item, key) => {
22
+ const isStepActive = key <= active;
23
+ const isLineActive = key <= active + 1;
24
+ const isLineGradient = key == active + 1;
25
+
26
+ return (
27
+ <div
28
+ key={key}
29
+ style={{ width: `calc(100% * 1 / ${items.length})` }}
30
+ >
31
+ <div className="wizard-step-header">
32
+ {key > 0 && (
33
+ <div
34
+ className="wizard-progress-bar-wrapper"
35
+ style={{
36
+ width: "calc(100% - 2.5rem - 1rem)",
37
+ top: "50%",
38
+ transform: "translate(-50%, -50%)",
39
+ }}
40
+ >
41
+ <div className="wizard-progress-bar-bg">
42
+ <div
43
+ className={cn(
44
+ "wizard-progress-bar-fill",
45
+ isLineGradient
46
+ ? "wizard-progress-bar-fill-gradient"
47
+ : isLineActive
48
+ ? "wizard-progress-bar-fill-active"
49
+ : ""
50
+ )}
51
+ ></div>
52
+ </div>
53
+ </div>
54
+ )}
55
+
56
+ <div
57
+ className={cn(
58
+ "wizard-circle",
59
+ isStepActive
60
+ ? "wizard-circle-active"
61
+ : "wizard-circle-inactive"
62
+ )}
63
+ >
64
+ <span className="text-center w-full">
65
+ {item.circle_content}
66
+ </span>
67
+ </div>
68
+ </div>
69
+
70
+ <div className="wizard-label">
71
+ {item.label}
72
+ </div>
73
+ </div>
74
+ );
75
+ })}
76
+ </div>
77
+ </div>
78
+ </div>
79
+ );
80
+ }