gbs-add-block 1.0.0 → 1.0.2
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/README.md +3 -2
- package/package.json +1 -1
- package/source/components/sidebar/components/MenuItem.tsx +12 -0
- package/source/components/sidebar/components/SidebarFooter.tsx +5 -21
- package/source/components/sidebar/components/SidebarMenu.tsx +1 -0
- package/source/components/sidebar/hooks/useSidebarState.ts +8 -5
- package/source/components/sidebar/index.tsx +64 -14
- package/source/components/sidebar/type.ts +7 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# GBS Building Blocks 2.0 (v1.0.
|
|
1
|
+
# GBS Building Blocks 2.0 (v1.0.2)
|
|
2
2
|
|
|
3
3
|
Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
|
|
4
4
|
|
|
@@ -6,12 +6,13 @@ Latest and upgraded version of GBS building blocks with headless UI and removed
|
|
|
6
6
|
|
|
7
7
|
For detailed documentation on usage and props, Please visit: [Building Block Documentation v2.0](https://blackmax-designs.gitbook.io/building-block-v2.0)
|
|
8
8
|
|
|
9
|
-
## What's New 🎉 (Ver 1.0.
|
|
9
|
+
## What's New 🎉 (Ver 1.0.2)
|
|
10
10
|
|
|
11
11
|
- Major Update with more stable features and Data Grid.
|
|
12
12
|
- Deprecated Grid Component, Use New Data Grid instead.
|
|
13
13
|
- More UI/UX Optimization.
|
|
14
14
|
- Animation improvements.
|
|
15
|
+
- Custom Components in SideBar and Mobile Screen Support
|
|
15
16
|
|
|
16
17
|
## Authors
|
|
17
18
|
|
package/package.json
CHANGED
|
@@ -21,6 +21,18 @@ export const MenuItemComponent = ({
|
|
|
21
21
|
}
|
|
22
22
|
}, []);
|
|
23
23
|
|
|
24
|
+
if (item.type === "custom" && item.component) {
|
|
25
|
+
const CustomComponent = item.component;
|
|
26
|
+
return (
|
|
27
|
+
<li className="py-2 px-3 flex items-center text-sm text-gray-700">
|
|
28
|
+
<span className="mr-3">
|
|
29
|
+
<IconComponent />
|
|
30
|
+
</span>
|
|
31
|
+
<CustomComponent />
|
|
32
|
+
</li>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
return (
|
|
25
37
|
<li>
|
|
26
38
|
<a
|
|
@@ -3,14 +3,9 @@ import { MenuItem, IconComponent } from "../type";
|
|
|
3
3
|
type SidebarFooterProps = {
|
|
4
4
|
footerItems?: MenuItem[];
|
|
5
5
|
iconMap: Record<string, IconComponent>;
|
|
6
|
-
toggleProMode: () => void;
|
|
7
6
|
};
|
|
8
7
|
|
|
9
|
-
export const SidebarFooter = ({
|
|
10
|
-
footerItems,
|
|
11
|
-
iconMap,
|
|
12
|
-
toggleProMode,
|
|
13
|
-
}: SidebarFooterProps) => {
|
|
8
|
+
export const SidebarFooter = ({ footerItems, iconMap }: SidebarFooterProps) => {
|
|
14
9
|
if (!footerItems) return null;
|
|
15
10
|
if (!iconMap) return null;
|
|
16
11
|
|
|
@@ -20,28 +15,17 @@ export const SidebarFooter = ({
|
|
|
20
15
|
{footerItems?.map((item) => {
|
|
21
16
|
const IconComponent = iconMap[item.icon] || (() => null);
|
|
22
17
|
|
|
23
|
-
if (item.
|
|
18
|
+
if (item.type === "custom" && item.component) {
|
|
19
|
+
const CustomComponent = item.component;
|
|
24
20
|
return (
|
|
25
21
|
<li
|
|
26
22
|
key={item.id}
|
|
27
|
-
className="
|
|
23
|
+
className="py-2 px-3 flex items-center text-sm text-gray-700"
|
|
28
24
|
>
|
|
29
25
|
<span className="mr-3">
|
|
30
26
|
<IconComponent />
|
|
31
27
|
</span>
|
|
32
|
-
<
|
|
33
|
-
<button
|
|
34
|
-
onClick={toggleProMode}
|
|
35
|
-
className={`w-10 h-5 flex items-center rounded-full p-1 ${
|
|
36
|
-
item.active ? "bg-black" : "bg-gray-300"
|
|
37
|
-
}`}
|
|
38
|
-
>
|
|
39
|
-
<span
|
|
40
|
-
className={`bg-white w-4 h-4 rounded-full shadow-md transform transition-transform ${
|
|
41
|
-
item.active ? "translate-x-5" : ""
|
|
42
|
-
}`}
|
|
43
|
-
/>
|
|
44
|
-
</button>
|
|
28
|
+
<CustomComponent />
|
|
45
29
|
</li>
|
|
46
30
|
);
|
|
47
31
|
}
|
|
@@ -19,20 +19,23 @@ export const useSidebarState = (menuData: MenuData) => {
|
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const
|
|
22
|
+
const toggleMode = (): void => {
|
|
23
23
|
const newData = { ...sidebarData };
|
|
24
24
|
if (!newData.footer) return;
|
|
25
25
|
|
|
26
|
-
const
|
|
27
|
-
|
|
26
|
+
const toggleModeIndex = newData.footer.findIndex(
|
|
27
|
+
(item) => item.type === "toggle"
|
|
28
|
+
);
|
|
29
|
+
if (toggleModeIndex === -1) return;
|
|
28
30
|
|
|
29
|
-
newData.footer[
|
|
31
|
+
newData.footer[toggleModeIndex].active =
|
|
32
|
+
!newData.footer[toggleModeIndex].active;
|
|
30
33
|
setSidebarData({ ...newData });
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
return {
|
|
34
37
|
sidebarData,
|
|
35
38
|
toggleItem,
|
|
36
|
-
|
|
39
|
+
toggleMode,
|
|
37
40
|
};
|
|
38
41
|
};
|
|
@@ -4,24 +4,74 @@ import { SidebarLogo } from "./components/SidebarLogo";
|
|
|
4
4
|
import { SidebarMenu } from "./components/SidebarMenu";
|
|
5
5
|
import { SidebarFooter } from "./components/SidebarFooter";
|
|
6
6
|
import { UserProfile } from "./components/UserProfile";
|
|
7
|
+
import Icon from "../icon/Icon";
|
|
8
|
+
import { menuIcon, x } from "../icon/iconPaths";
|
|
9
|
+
import { useState } from "react";
|
|
7
10
|
|
|
8
11
|
export function Sidebar({ menuData, iconMap }: SidebarProps) {
|
|
9
|
-
const { sidebarData, toggleItem
|
|
12
|
+
const { sidebarData, toggleItem } = useSidebarState(menuData);
|
|
13
|
+
const [showSideBarMobile, setShowSideBarMobile] = useState(false);
|
|
10
14
|
|
|
11
15
|
return (
|
|
12
|
-
<div
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
<div>
|
|
17
|
+
{/* Mobile menu button - only show when sidebar is closed */}
|
|
18
|
+
{!showSideBarMobile && (
|
|
19
|
+
<button
|
|
20
|
+
className="md:hidden flex items-center justify-between absolute p-4 border z-50 bg-white rounded-xl top-3 left-3"
|
|
21
|
+
onClick={() => setShowSideBarMobile(true)}
|
|
22
|
+
>
|
|
23
|
+
<Icon
|
|
24
|
+
elements={menuIcon}
|
|
25
|
+
svgClass={"stroke-black fill-none"}
|
|
26
|
+
dimensions={{ width: "18", height: "18" }}
|
|
27
|
+
/>
|
|
28
|
+
</button>
|
|
29
|
+
)}
|
|
30
|
+
|
|
31
|
+
{/* Mobile sidebar overlay */}
|
|
32
|
+
{showSideBarMobile && (
|
|
33
|
+
<div
|
|
34
|
+
className="md:hidden fixed inset-0 z-40"
|
|
35
|
+
onClick={() => setShowSideBarMobile(false)}
|
|
36
|
+
/>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
{/* Mobile sidebar */}
|
|
40
|
+
<div
|
|
41
|
+
className={`md:hidden fixed left-0 top-0 h-screen bg-white w-64 border-r border-gray-200 z-40 transform transition-transform duration-300 ease-in-out ${
|
|
42
|
+
showSideBarMobile ? "translate-x-0" : "-translate-x-full"
|
|
43
|
+
}`}
|
|
44
|
+
>
|
|
45
|
+
<div className="flex items-center justify-between pr-4">
|
|
46
|
+
<SidebarLogo logo={sidebarData.logo} />
|
|
47
|
+
<button onClick={() => setShowSideBarMobile(false)}>
|
|
48
|
+
<Icon
|
|
49
|
+
elements={x}
|
|
50
|
+
svgClass={"stroke-black fill-none"}
|
|
51
|
+
dimensions={{ width: "18", height: "18" }}
|
|
52
|
+
/>
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
<SidebarMenu
|
|
56
|
+
sections={sidebarData.sections}
|
|
57
|
+
iconMap={iconMap}
|
|
58
|
+
toggleItem={toggleItem}
|
|
59
|
+
/>
|
|
60
|
+
<SidebarFooter footerItems={sidebarData.footer} iconMap={iconMap} />
|
|
61
|
+
<UserProfile profile={sidebarData.profile} />
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
{/* Desktop sidebar */}
|
|
65
|
+
<div className="hidden md:flex flex-col h-screen bg-white w-64 border-r border-gray-200 sticky left-0 top-0">
|
|
66
|
+
<SidebarLogo logo={sidebarData.logo} />
|
|
67
|
+
<SidebarMenu
|
|
68
|
+
sections={sidebarData.sections}
|
|
69
|
+
iconMap={iconMap}
|
|
70
|
+
toggleItem={toggleItem}
|
|
71
|
+
/>
|
|
72
|
+
<SidebarFooter footerItems={sidebarData.footer} iconMap={iconMap} />
|
|
73
|
+
<UserProfile profile={sidebarData.profile} />
|
|
74
|
+
</div>
|
|
25
75
|
</div>
|
|
26
76
|
);
|
|
27
77
|
}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
export type IconComponent = React.FC;
|
|
2
2
|
|
|
3
3
|
export type MenuItem = {
|
|
4
|
-
id: number;
|
|
4
|
+
id: number | string;
|
|
5
5
|
name: string;
|
|
6
6
|
icon: string;
|
|
7
|
-
path
|
|
7
|
+
path?: string;
|
|
8
8
|
active?: boolean;
|
|
9
9
|
expandable?: boolean;
|
|
10
10
|
expanded?: boolean;
|
|
11
11
|
badge?: string;
|
|
12
12
|
toggle?: boolean;
|
|
13
|
+
type?: string;
|
|
14
|
+
component?: React.FC;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export type MenuSection = {
|
|
18
|
+
id?: number | string;
|
|
16
19
|
title: string;
|
|
17
20
|
items: MenuItem[];
|
|
21
|
+
component?: React.FC;
|
|
22
|
+
type?: string;
|
|
18
23
|
};
|
|
19
24
|
|
|
20
25
|
export type MenuData = {
|