@wikex/admin-kit 0.2.1 → 0.2.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.
@@ -1,7 +1,8 @@
1
+ 'use client';
1
2
  "use client";
2
3
  import {
3
4
  useAdminBrand
4
- } from "../chunk-XGKGKCQ6.js";
5
+ } from "../chunk-X7VETFVD.js";
5
6
 
6
7
  // src/admin/BeforeLogin.tsx
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,12 +1,13 @@
1
+ 'use client';
1
2
  "use client";
2
3
  import {
3
4
  AdminIcon,
4
5
  AdminLogo
5
- } from "../chunk-LP22Y3NO.js";
6
+ } from "../chunk-SM6CCKQQ.js";
6
7
  import {
7
8
  configureAdminBrand,
8
9
  useAdminBrand
9
- } from "../chunk-XGKGKCQ6.js";
10
+ } from "../chunk-X7VETFVD.js";
10
11
  export {
11
12
  AdminIcon,
12
13
  AdminLogo,
@@ -1,20 +1,29 @@
1
+ 'use client';
1
2
  "use client";
2
- import {
3
- ThemeToggle_default
4
- } from "../chunk-GGSOO4FQ.js";
5
- import {
6
- ViewSite_default
7
- } from "../chunk-MDMKKWPU.js";
8
3
  import {
9
4
  AdminIcon
10
- } from "../chunk-LP22Y3NO.js";
11
- import "../chunk-XGKGKCQ6.js";
5
+ } from "../chunk-SM6CCKQQ.js";
6
+ import "../chunk-X7VETFVD.js";
7
+ import {
8
+ ThemeToggle_default
9
+ } from "../chunk-SAI5SWZA.js";
12
10
 
13
11
  // src/admin/Header.tsx
14
12
  import { Link, useAuth, useConfig, useNav } from "@payloadcms/ui";
15
13
  import { Menu, Settings2 } from "lucide-react";
16
14
  import { formatAdminURL } from "payload/shared";
15
+
16
+ // src/admin/ViewSite.tsx
17
+ import { ArrowUpRight } from "lucide-react";
17
18
  import { jsx, jsxs } from "react/jsx-runtime";
19
+ var AdminViewSite = () => /* @__PURE__ */ jsxs("a", { className: "admin-view-site", "data-slot": "button", href: "/", rel: "noreferrer", target: "_blank", children: [
20
+ "Xem website",
21
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": "true" })
22
+ ] });
23
+ var ViewSite_default = AdminViewSite;
24
+
25
+ // src/admin/Header.tsx
26
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
18
27
  var getInitials = (name, email) => {
19
28
  const source = name?.trim() || email?.split("@")[0] || "AD";
20
29
  return source.split(/\s+/).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
@@ -30,33 +39,33 @@ var AdminHeader = () => {
30
39
  } = useConfig();
31
40
  const userLabel = user?.name?.trim() || user?.email?.split("@")[0] || "Qu\u1EA3n tr\u1ECB vi\xEAn";
32
41
  const initials = getInitials(user?.name, user?.email);
33
- return /* @__PURE__ */ jsxs("header", { className: "minimal-admin-header", children: [
34
- /* @__PURE__ */ jsxs("div", { className: "minimal-admin-header__left", children: [
35
- /* @__PURE__ */ jsx(
42
+ return /* @__PURE__ */ jsxs2("header", { className: "minimal-admin-header", children: [
43
+ /* @__PURE__ */ jsxs2("div", { className: "minimal-admin-header__left", children: [
44
+ /* @__PURE__ */ jsx2(
36
45
  "button",
37
46
  {
38
47
  "aria-label": "M\u1EDF menu qu\u1EA3n tr\u1ECB",
39
48
  className: "minimal-admin-header__menu",
40
49
  onClick: () => setNavOpen(true),
41
50
  type: "button",
42
- children: /* @__PURE__ */ jsx(Menu, { "aria-hidden": "true" })
51
+ children: /* @__PURE__ */ jsx2(Menu, { "aria-hidden": "true" })
43
52
  }
44
53
  ),
45
- /* @__PURE__ */ jsx(
54
+ /* @__PURE__ */ jsx2(
46
55
  Link,
47
56
  {
48
57
  "aria-label": "V\u1EC1 dashboard",
49
58
  className: "minimal-admin-header__mobile-brand",
50
59
  href: adminRoute,
51
60
  prefetch: false,
52
- children: /* @__PURE__ */ jsx(AdminIcon, {})
61
+ children: /* @__PURE__ */ jsx2(AdminIcon, {})
53
62
  }
54
63
  )
55
64
  ] }),
56
- /* @__PURE__ */ jsxs("div", { className: "minimal-admin-header__actions", children: [
57
- /* @__PURE__ */ jsx(ViewSite_default, {}),
58
- /* @__PURE__ */ jsx(ThemeToggle_default, {}),
59
- /* @__PURE__ */ jsx(
65
+ /* @__PURE__ */ jsxs2("div", { className: "minimal-admin-header__actions", children: [
66
+ /* @__PURE__ */ jsx2(ViewSite_default, {}),
67
+ /* @__PURE__ */ jsx2(ThemeToggle_default, {}),
68
+ /* @__PURE__ */ jsx2(
60
69
  Link,
61
70
  {
62
71
  "aria-label": `M\u1EDF t\xE0i kho\u1EA3n ${userLabel}`,
@@ -64,10 +73,10 @@ var AdminHeader = () => {
64
73
  href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
65
74
  prefetch: false,
66
75
  title: "C\xE0i \u0111\u1EB7t t\xE0i kho\u1EA3n",
67
- children: /* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true" })
76
+ children: /* @__PURE__ */ jsx2(Settings2, { "aria-hidden": "true" })
68
77
  }
69
78
  ),
70
- /* @__PURE__ */ jsx(
79
+ /* @__PURE__ */ jsx2(
71
80
  Link,
72
81
  {
73
82
  "aria-label": `M\u1EDF t\xE0i kho\u1EA3n ${userLabel}`,
@@ -75,7 +84,7 @@ var AdminHeader = () => {
75
84
  href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
76
85
  prefetch: false,
77
86
  title: userLabel,
78
- children: /* @__PURE__ */ jsx("span", { children: initials })
87
+ children: /* @__PURE__ */ jsx2("span", { children: initials })
79
88
  }
80
89
  )
81
90
  ] })
@@ -1,7 +1,8 @@
1
+ 'use client';
1
2
  "use client";
2
3
  import {
3
4
  LogoutButton_default
4
- } from "../chunk-W4ZKDOWJ.js";
5
+ } from "../chunk-GZ2B5BTH.js";
5
6
  export {
6
7
  LogoutButton_default as default
7
8
  };
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type AdminNavGroup = {
4
+ items: Array<{
5
+ label: string;
6
+ slug: string;
7
+ type: 'collections' | 'globals';
8
+ }>;
9
+ label: string;
10
+ };
11
+ type AdminNavClientProps = {
12
+ groups: AdminNavGroup[];
13
+ };
14
+ declare const AdminNavClient: ({ groups }: AdminNavClientProps) => react_jsx_runtime.JSX.Element;
15
+
16
+ export { AdminNavClient, type AdminNavGroup };
@@ -0,0 +1,258 @@
1
+ 'use client';
2
+ "use client";
3
+ import {
4
+ AdminIcon,
5
+ AdminLogo
6
+ } from "../chunk-SM6CCKQQ.js";
7
+ import {
8
+ useAdminBrand
9
+ } from "../chunk-X7VETFVD.js";
10
+ import {
11
+ LogoutButton_default
12
+ } from "../chunk-GZ2B5BTH.js";
13
+
14
+ // src/admin/NavClient.tsx
15
+ import { Link, useAuth, useConfig, useNav } from "@payloadcms/ui";
16
+ import {
17
+ BookOpenText,
18
+ BriefcaseBusiness,
19
+ ChevronLeft,
20
+ ChevronRight,
21
+ FileText,
22
+ FolderKanban,
23
+ GalleryVerticalEnd,
24
+ Home,
25
+ Image,
26
+ LayoutDashboard,
27
+ Library,
28
+ Menu,
29
+ PanelBottom,
30
+ PanelTop,
31
+ Settings2,
32
+ Tags,
33
+ Users,
34
+ X
35
+ } from "lucide-react";
36
+ import { usePathname } from "next/navigation";
37
+ import { formatAdminURL } from "payload/shared";
38
+ import { useEffect, useMemo, useState } from "react";
39
+ import { jsx, jsxs } from "react/jsx-runtime";
40
+ var iconBySlug = {
41
+ categories: Tags,
42
+ footer: PanelBottom,
43
+ header: PanelTop,
44
+ homepage: Home,
45
+ media: Image,
46
+ pages: FileText,
47
+ posts: BookOpenText,
48
+ projects: FolderKanban,
49
+ services: BriefcaseBusiness,
50
+ settings: Settings2,
51
+ users: Users
52
+ };
53
+ var translateGroupLabel = (label) => label === "Collections" ? "B\u1ED9 s\u01B0u t\u1EADp" : label === "Globals" ? "Thi\u1EBFt l\u1EADp chung" : label;
54
+ var getInitials = (name, email) => {
55
+ const source = name?.trim() || email?.split("@")[0] || "AD";
56
+ return source.split(/\s+/).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
57
+ };
58
+ var AdminNavClient = ({ groups }) => {
59
+ const pathname = usePathname();
60
+ const brand = useAdminBrand();
61
+ const { user } = useAuth();
62
+ const { hydrated, navOpen, navRef, setNavOpen, shouldAnimate } = useNav();
63
+ const {
64
+ config: {
65
+ admin: { routes: adminRoutes },
66
+ folders,
67
+ routes: { admin: adminRoute }
68
+ }
69
+ } = useConfig();
70
+ const [isMini, setIsMini] = useState(false);
71
+ const [isMobile, setIsMobile] = useState(false);
72
+ useEffect(() => {
73
+ const storedValue = window.localStorage.getItem("minimal-admin-nav-mini");
74
+ setIsMini(storedValue === "true");
75
+ }, []);
76
+ useEffect(() => {
77
+ const mediaQuery = window.matchMedia("(max-width: 768px)");
78
+ const syncViewport = () => setIsMobile(mediaQuery.matches);
79
+ syncViewport();
80
+ mediaQuery.addEventListener("change", syncViewport);
81
+ return () => mediaQuery.removeEventListener("change", syncViewport);
82
+ }, []);
83
+ useEffect(() => {
84
+ document.documentElement.style.setProperty("--nav-width", isMini ? "88px" : "280px");
85
+ window.localStorage.setItem("minimal-admin-nav-mini", String(isMini));
86
+ return () => {
87
+ document.documentElement.style.removeProperty("--nav-width");
88
+ };
89
+ }, [isMini]);
90
+ const userLabel = user?.name?.trim() || user?.email?.split("@")[0] || "Qu\u1EA3n tr\u1ECB vi\xEAn";
91
+ const initials = useMemo(() => getInitials(user?.name, user?.email), [user?.email, user?.name]);
92
+ const closeMobileNav = () => {
93
+ if (window.matchMedia("(max-width: 768px)").matches) setNavOpen(false);
94
+ };
95
+ const classes = [
96
+ "minimal-nav",
97
+ navOpen && "minimal-nav--open",
98
+ isMini && "minimal-nav--mini",
99
+ shouldAnimate && "minimal-nav--animate",
100
+ hydrated && "minimal-nav--hydrated"
101
+ ].filter(Boolean).join(" ");
102
+ const isActive = (href) => pathname === href || href !== adminRoute && pathname.startsWith(`${href}/`);
103
+ return /* @__PURE__ */ jsxs(
104
+ "aside",
105
+ {
106
+ "aria-label": "\u0110i\u1EC1u h\u01B0\u1EDBng qu\u1EA3n tr\u1ECB",
107
+ className: classes,
108
+ inert: isMobile && !navOpen || void 0,
109
+ children: [
110
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__scroll", ref: navRef, children: [
111
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__brand-row", children: [
112
+ /* @__PURE__ */ jsxs(
113
+ Link,
114
+ {
115
+ "aria-label": `V\u1EC1 dashboard ${brand.siteName}`,
116
+ className: "minimal-nav__brand",
117
+ href: adminRoute,
118
+ onClick: closeMobileNav,
119
+ prefetch: false,
120
+ children: [
121
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__brand-full", children: /* @__PURE__ */ jsx(AdminLogo, {}) }),
122
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__brand-icon", children: /* @__PURE__ */ jsx(AdminIcon, {}) })
123
+ ]
124
+ }
125
+ ),
126
+ /* @__PURE__ */ jsx(
127
+ "button",
128
+ {
129
+ "aria-label": "\u0110\xF3ng menu",
130
+ className: "minimal-nav__mobile-close",
131
+ onClick: () => setNavOpen(false),
132
+ type: "button",
133
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
134
+ }
135
+ )
136
+ ] }),
137
+ /* @__PURE__ */ jsxs(
138
+ Link,
139
+ {
140
+ className: "minimal-nav__workspace",
141
+ href: adminRoute,
142
+ onClick: closeMobileNav,
143
+ prefetch: false,
144
+ title: brand.siteName,
145
+ children: [
146
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__workspace-icon", children: /* @__PURE__ */ jsx(GalleryVerticalEnd, { "aria-hidden": "true" }) }),
147
+ /* @__PURE__ */ jsxs("span", { className: "minimal-nav__workspace-copy", children: [
148
+ /* @__PURE__ */ jsx("small", { children: "Kh\xF4ng gian l\xE0m vi\u1EC7c" }),
149
+ /* @__PURE__ */ jsx("strong", { children: brand.siteName })
150
+ ] }),
151
+ /* @__PURE__ */ jsx(Menu, { "aria-hidden": "true", className: "minimal-nav__workspace-menu" })
152
+ ]
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsxs("nav", { className: "minimal-nav__menu", children: [
156
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
157
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: "T\u1ED5ng quan" }),
158
+ /* @__PURE__ */ jsxs(
159
+ Link,
160
+ {
161
+ "aria-current": pathname === adminRoute ? "page" : void 0,
162
+ className: `minimal-nav__item ${pathname === adminRoute ? "minimal-nav__item--active" : ""}`,
163
+ href: adminRoute,
164
+ onClick: closeMobileNav,
165
+ prefetch: false,
166
+ title: "Dashboard",
167
+ children: [
168
+ /* @__PURE__ */ jsx(LayoutDashboard, { "aria-hidden": "true" }),
169
+ /* @__PURE__ */ jsx("span", { children: "T\u1ED5ng quan" })
170
+ ]
171
+ }
172
+ )
173
+ ] }),
174
+ groups.map((group) => /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
175
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: translateGroupLabel(group.label) }),
176
+ group.items.map((item) => {
177
+ const href = formatAdminURL({
178
+ adminRoute,
179
+ path: `/${item.type}/${item.slug}`
180
+ });
181
+ const Icon = iconBySlug[item.slug] || FileText;
182
+ const active = isActive(href);
183
+ return /* @__PURE__ */ jsxs(
184
+ Link,
185
+ {
186
+ "aria-current": active ? "page" : void 0,
187
+ className: `minimal-nav__item ${active ? "minimal-nav__item--active" : ""}`,
188
+ href,
189
+ onClick: closeMobileNav,
190
+ prefetch: false,
191
+ title: item.label,
192
+ children: [
193
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
194
+ /* @__PURE__ */ jsx("span", { children: item.label })
195
+ ]
196
+ },
197
+ `${item.type}-${item.slug}`
198
+ );
199
+ })
200
+ ] }, group.label)),
201
+ folders && folders.browseByFolder && /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
202
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: "Th\u01B0 vi\u1EC7n" }),
203
+ /* @__PURE__ */ jsxs(
204
+ Link,
205
+ {
206
+ "aria-current": isActive(formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder })) ? "page" : void 0,
207
+ className: `minimal-nav__item ${isActive(formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder })) ? "minimal-nav__item--active" : ""}`,
208
+ href: formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder }),
209
+ onClick: closeMobileNav,
210
+ prefetch: false,
211
+ title: "Duy\u1EC7t theo th\u01B0 m\u1EE5c",
212
+ children: [
213
+ /* @__PURE__ */ jsx(Library, { "aria-hidden": "true" }),
214
+ /* @__PURE__ */ jsx("span", { children: "Duy\u1EC7t theo th\u01B0 m\u1EE5c" })
215
+ ]
216
+ }
217
+ )
218
+ ] })
219
+ ] }),
220
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__footer", children: [
221
+ /* @__PURE__ */ jsxs(
222
+ Link,
223
+ {
224
+ className: "minimal-nav__account",
225
+ href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
226
+ onClick: closeMobileNav,
227
+ prefetch: false,
228
+ title: userLabel,
229
+ children: [
230
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__avatar", children: initials }),
231
+ /* @__PURE__ */ jsxs("span", { className: "minimal-nav__account-copy", children: [
232
+ /* @__PURE__ */ jsx("strong", { children: userLabel }),
233
+ /* @__PURE__ */ jsx("small", { children: user?.email || "T\xE0i kho\u1EA3n qu\u1EA3n tr\u1ECB" })
234
+ ] })
235
+ ]
236
+ }
237
+ ),
238
+ /* @__PURE__ */ jsx("div", { className: "minimal-nav__logout", children: /* @__PURE__ */ jsx(LogoutButton_default, {}) })
239
+ ] })
240
+ ] }),
241
+ /* @__PURE__ */ jsx(
242
+ "button",
243
+ {
244
+ "aria-label": isMini ? "M\u1EDF r\u1ED9ng menu" : "Thu g\u1ECDn menu",
245
+ className: "minimal-nav__collapse",
246
+ onClick: () => setIsMini((current) => !current),
247
+ title: isMini ? "M\u1EDF r\u1ED9ng menu" : "Thu g\u1ECDn menu",
248
+ type: "button",
249
+ children: isMini ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true" })
250
+ }
251
+ )
252
+ ]
253
+ }
254
+ );
255
+ };
256
+ export {
257
+ AdminNavClient
258
+ };
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ServerProps } from 'payload';
3
+ export { AdminNavClient } from '@wikex/admin-kit/admin/nav-client';
3
4
 
4
5
  type AdminNavGroup = {
5
6
  items: Array<{
@@ -9,11 +10,7 @@ type AdminNavGroup = {
9
10
  }>;
10
11
  label: string;
11
12
  };
12
- type AdminNavClientProps = {
13
- groups: AdminNavGroup[];
14
- };
15
- declare const AdminNavClient: ({ groups }: AdminNavClientProps) => react_jsx_runtime.JSX.Element;
16
13
 
17
14
  declare const AdminNav: ({ i18n, payload, permissions, visibleEntities }: ServerProps) => react_jsx_runtime.JSX.Element | null;
18
15
 
19
- export { AdminNavClient, type AdminNavGroup, AdminNav as default };
16
+ export { type AdminNavGroup, AdminNav as default };