@wikex/admin-kit 0.2.0 → 0.2.1

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 (70) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/admin/before-login.d.ts +5 -0
  3. package/dist/admin/before-login.js +26 -0
  4. package/dist/admin/brand.d.ts +19 -0
  5. package/dist/admin/brand.js +15 -0
  6. package/dist/admin/header.d.ts +5 -0
  7. package/dist/admin/header.js +87 -0
  8. package/dist/admin/logout-button.d.ts +8 -0
  9. package/dist/admin/logout-button.js +7 -0
  10. package/dist/admin/nav.d.ts +19 -0
  11. package/dist/admin/nav.js +285 -0
  12. package/dist/admin/theme-toggle.d.ts +5 -0
  13. package/dist/admin/theme-toggle.js +7 -0
  14. package/dist/admin/view-site.d.ts +5 -0
  15. package/dist/admin/view-site.js +6 -0
  16. package/dist/chunk-7FEACJUN.js +151 -0
  17. package/dist/chunk-BUD6BMFV.js +117 -0
  18. package/dist/chunk-GGSOO4FQ.js +27 -0
  19. package/dist/chunk-IL2CUCDG.js +2062 -0
  20. package/dist/chunk-JJLHSZ3T.js +40 -0
  21. package/dist/chunk-LC2CP5SR.js +13 -0
  22. package/dist/chunk-LP22Y3NO.js +61 -0
  23. package/dist/chunk-MDMKKWPU.js +12 -0
  24. package/dist/chunk-W4ZKDOWJ.js +37 -0
  25. package/dist/chunk-XGKGKCQ6.js +50 -0
  26. package/dist/chunk-YMBJCWN3.js +73 -0
  27. package/dist/index.d.ts +26 -0
  28. package/dist/index.js +44 -0
  29. package/dist/live-preview.d.ts +50 -0
  30. package/dist/live-preview.js +19 -0
  31. package/dist/project.d.ts +34 -0
  32. package/dist/project.js +8 -0
  33. package/dist/rich-text-client.d.ts +5 -0
  34. package/dist/rich-text-client.js +165 -0
  35. package/dist/rich-text.d.ts +5 -0
  36. package/dist/rich-text.js +6 -0
  37. package/dist/runtimeConfig-BwjQepcW.d.ts +30 -0
  38. package/dist/starter-client.d.ts +15 -0
  39. package/dist/starter-client.js +25 -0
  40. package/dist/starter.d.ts +40 -0
  41. package/dist/starter.js +62 -0
  42. package/dist/text-style-runtime.d.ts +5 -0
  43. package/dist/text-style-runtime.js +8 -0
  44. package/dist/text-styles.d.ts +86 -0
  45. package/dist/text-styles.js +22 -0
  46. package/package.json +23 -19
  47. package/src/TextStyleRuntime.tsx +0 -90
  48. package/src/admin/BeforeLogin.tsx +0 -19
  49. package/src/admin/Brand.tsx +0 -74
  50. package/src/admin/Header.tsx +0 -87
  51. package/src/admin/LogoutButton.tsx +0 -41
  52. package/src/admin/Nav.tsx +0 -35
  53. package/src/admin/NavClient.tsx +0 -288
  54. package/src/admin/ThemeToggle.tsx +0 -31
  55. package/src/admin/ViewSite.tsx +0 -11
  56. package/src/admin/useAdminBrand.ts +0 -81
  57. package/src/adminExperience.ts +0 -117
  58. package/src/index.ts +0 -11
  59. package/src/live-preview/GlobalInlineInspector.tsx +0 -334
  60. package/src/live-preview/LivePreviewEditor.tsx +0 -2088
  61. package/src/live-preview/TextStyleInspector.tsx +0 -289
  62. package/src/live-preview/index.ts +0 -23
  63. package/src/live-preview/runtimeConfig.ts +0 -52
  64. package/src/plugin.ts +0 -70
  65. package/src/project.ts +0 -82
  66. package/src/rich-text/client.tsx +0 -202
  67. package/src/rich-text/index.ts +0 -10
  68. package/src/starter/client.tsx +0 -22
  69. package/src/starter.ts +0 -95
  70. package/src/textStyles.ts +0 -161
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Các thay đổi đáng chú ý của `@wikex/admin-kit` được ghi tại đây theo Semantic Versioning.
4
4
 
5
+ ## 0.2.1 - 2026-09-12
6
+
7
+ - Publish JavaScript build và type declarations để Payload CLI chạy được trong project độc lập.
8
+
5
9
  ## 0.2.0 - 2026-09-12
6
10
 
7
11
  - Thêm `createWikexStarter`: một factory cấu hình content schema, SEO, redirect, admin UI,
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+
3
+ declare const BeforeLogin: React.FC;
4
+
5
+ export { BeforeLogin as default };
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import {
3
+ useAdminBrand
4
+ } from "../chunk-XGKGKCQ6.js";
5
+
6
+ // src/admin/BeforeLogin.tsx
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var BeforeLogin = () => {
9
+ const { siteName } = useAdminBrand();
10
+ return /* @__PURE__ */ jsxs("div", { className: "admin-login-intro", children: [
11
+ /* @__PURE__ */ jsxs("span", { className: "admin-login-intro__eyebrow", children: [
12
+ siteName,
13
+ " \xB7 Trung t\xE2m n\u1ED9i dung"
14
+ ] }),
15
+ /* @__PURE__ */ jsx("h1", { children: "Ch\xE0o m\u1EEBng tr\u1EDF l\u1EA1i." }),
16
+ /* @__PURE__ */ jsxs("p", { children: [
17
+ "\u0110\u0103ng nh\u1EADp \u0111\u1EC3 qu\u1EA3n l\xFD n\u1ED9i dung, h\xECnh \u1EA3nh v\xE0 xu\u1EA5t b\u1EA3n c\u1EE7a ",
18
+ siteName,
19
+ "."
20
+ ] })
21
+ ] });
22
+ };
23
+ var BeforeLogin_default = BeforeLogin;
24
+ export {
25
+ BeforeLogin_default as default
26
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+
3
+ type AdminBrandSettings = {
4
+ logo: AdminBrandAsset;
5
+ siteName: string;
6
+ };
7
+ declare const configureAdminBrand: (brand: AdminBrandSettings) => void;
8
+ declare const useAdminBrand: () => AdminBrandSettings;
9
+
10
+ type AdminBrandAsset = {
11
+ alt: string;
12
+ height: number;
13
+ url: string;
14
+ width: number;
15
+ };
16
+ declare const AdminIcon: React.FC;
17
+ declare const AdminLogo: React.FC;
18
+
19
+ export { type AdminBrandAsset, type AdminBrandSettings, AdminIcon, AdminLogo, configureAdminBrand, useAdminBrand };
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import {
3
+ AdminIcon,
4
+ AdminLogo
5
+ } from "../chunk-LP22Y3NO.js";
6
+ import {
7
+ configureAdminBrand,
8
+ useAdminBrand
9
+ } from "../chunk-XGKGKCQ6.js";
10
+ export {
11
+ AdminIcon,
12
+ AdminLogo,
13
+ configureAdminBrand,
14
+ useAdminBrand
15
+ };
@@ -0,0 +1,5 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare const AdminHeader: () => react_jsx_runtime.JSX.Element;
4
+
5
+ export { AdminHeader as default };
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ import {
3
+ ThemeToggle_default
4
+ } from "../chunk-GGSOO4FQ.js";
5
+ import {
6
+ ViewSite_default
7
+ } from "../chunk-MDMKKWPU.js";
8
+ import {
9
+ AdminIcon
10
+ } from "../chunk-LP22Y3NO.js";
11
+ import "../chunk-XGKGKCQ6.js";
12
+
13
+ // src/admin/Header.tsx
14
+ import { Link, useAuth, useConfig, useNav } from "@payloadcms/ui";
15
+ import { Menu, Settings2 } from "lucide-react";
16
+ import { formatAdminURL } from "payload/shared";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ var getInitials = (name, email) => {
19
+ const source = name?.trim() || email?.split("@")[0] || "AD";
20
+ return source.split(/\s+/).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
21
+ };
22
+ var AdminHeader = () => {
23
+ const { user } = useAuth();
24
+ const { setNavOpen } = useNav();
25
+ const {
26
+ config: {
27
+ admin: { routes: adminRoutes },
28
+ routes: { admin: adminRoute }
29
+ }
30
+ } = useConfig();
31
+ const userLabel = user?.name?.trim() || user?.email?.split("@")[0] || "Qu\u1EA3n tr\u1ECB vi\xEAn";
32
+ 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(
36
+ "button",
37
+ {
38
+ "aria-label": "M\u1EDF menu qu\u1EA3n tr\u1ECB",
39
+ className: "minimal-admin-header__menu",
40
+ onClick: () => setNavOpen(true),
41
+ type: "button",
42
+ children: /* @__PURE__ */ jsx(Menu, { "aria-hidden": "true" })
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx(
46
+ Link,
47
+ {
48
+ "aria-label": "V\u1EC1 dashboard",
49
+ className: "minimal-admin-header__mobile-brand",
50
+ href: adminRoute,
51
+ prefetch: false,
52
+ children: /* @__PURE__ */ jsx(AdminIcon, {})
53
+ }
54
+ )
55
+ ] }),
56
+ /* @__PURE__ */ jsxs("div", { className: "minimal-admin-header__actions", children: [
57
+ /* @__PURE__ */ jsx(ViewSite_default, {}),
58
+ /* @__PURE__ */ jsx(ThemeToggle_default, {}),
59
+ /* @__PURE__ */ jsx(
60
+ Link,
61
+ {
62
+ "aria-label": `M\u1EDF t\xE0i kho\u1EA3n ${userLabel}`,
63
+ className: "minimal-admin-header__settings",
64
+ href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
65
+ prefetch: false,
66
+ title: "C\xE0i \u0111\u1EB7t t\xE0i kho\u1EA3n",
67
+ children: /* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true" })
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx(
71
+ Link,
72
+ {
73
+ "aria-label": `M\u1EDF t\xE0i kho\u1EA3n ${userLabel}`,
74
+ className: "minimal-admin-header__account",
75
+ href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
76
+ prefetch: false,
77
+ title: userLabel,
78
+ children: /* @__PURE__ */ jsx("span", { children: initials })
79
+ }
80
+ )
81
+ ] })
82
+ ] });
83
+ };
84
+ var Header_default = AdminHeader;
85
+ export {
86
+ Header_default as default
87
+ };
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+
3
+ type AdminLogoutButtonProps = {
4
+ tabIndex?: number;
5
+ };
6
+ declare const AdminLogoutButton: React.FC<AdminLogoutButtonProps>;
7
+
8
+ export { AdminLogoutButton as default };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ import {
3
+ LogoutButton_default
4
+ } from "../chunk-W4ZKDOWJ.js";
5
+ export {
6
+ LogoutButton_default as default
7
+ };
@@ -0,0 +1,19 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ServerProps } from 'payload';
3
+
4
+ type AdminNavGroup = {
5
+ items: Array<{
6
+ label: string;
7
+ slug: string;
8
+ type: 'collections' | 'globals';
9
+ }>;
10
+ label: string;
11
+ };
12
+ type AdminNavClientProps = {
13
+ groups: AdminNavGroup[];
14
+ };
15
+ declare const AdminNavClient: ({ groups }: AdminNavClientProps) => react_jsx_runtime.JSX.Element;
16
+
17
+ declare const AdminNav: ({ i18n, payload, permissions, visibleEntities }: ServerProps) => react_jsx_runtime.JSX.Element | null;
18
+
19
+ export { AdminNavClient, type AdminNavGroup, AdminNav as default };
@@ -0,0 +1,285 @@
1
+ import {
2
+ AdminIcon,
3
+ AdminLogo
4
+ } from "../chunk-LP22Y3NO.js";
5
+ import {
6
+ useAdminBrand
7
+ } from "../chunk-XGKGKCQ6.js";
8
+ import {
9
+ LogoutButton_default
10
+ } from "../chunk-W4ZKDOWJ.js";
11
+
12
+ // src/admin/Nav.tsx
13
+ import { getNavGroups } from "@payloadcms/ui/shared";
14
+
15
+ // src/admin/NavClient.tsx
16
+ import { Link, useAuth, useConfig, useNav } from "@payloadcms/ui";
17
+ import {
18
+ BookOpenText,
19
+ BriefcaseBusiness,
20
+ ChevronLeft,
21
+ ChevronRight,
22
+ FileText,
23
+ FolderKanban,
24
+ GalleryVerticalEnd,
25
+ Home,
26
+ Image,
27
+ LayoutDashboard,
28
+ Library,
29
+ Menu,
30
+ PanelBottom,
31
+ PanelTop,
32
+ Settings2,
33
+ Tags,
34
+ Users,
35
+ X
36
+ } from "lucide-react";
37
+ import { usePathname } from "next/navigation";
38
+ import { formatAdminURL } from "payload/shared";
39
+ import { useEffect, useMemo, useState } from "react";
40
+ import { jsx, jsxs } from "react/jsx-runtime";
41
+ var iconBySlug = {
42
+ categories: Tags,
43
+ footer: PanelBottom,
44
+ header: PanelTop,
45
+ homepage: Home,
46
+ media: Image,
47
+ pages: FileText,
48
+ posts: BookOpenText,
49
+ projects: FolderKanban,
50
+ services: BriefcaseBusiness,
51
+ settings: Settings2,
52
+ users: Users
53
+ };
54
+ var translateGroupLabel = (label) => label === "Collections" ? "B\u1ED9 s\u01B0u t\u1EADp" : label === "Globals" ? "Thi\u1EBFt l\u1EADp chung" : label;
55
+ var getInitials = (name, email) => {
56
+ const source = name?.trim() || email?.split("@")[0] || "AD";
57
+ return source.split(/\s+/).slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("");
58
+ };
59
+ var AdminNavClient = ({ groups }) => {
60
+ const pathname = usePathname();
61
+ const brand = useAdminBrand();
62
+ const { user } = useAuth();
63
+ const { hydrated, navOpen, navRef, setNavOpen, shouldAnimate } = useNav();
64
+ const {
65
+ config: {
66
+ admin: { routes: adminRoutes },
67
+ folders,
68
+ routes: { admin: adminRoute }
69
+ }
70
+ } = useConfig();
71
+ const [isMini, setIsMini] = useState(false);
72
+ const [isMobile, setIsMobile] = useState(false);
73
+ useEffect(() => {
74
+ const storedValue = window.localStorage.getItem("minimal-admin-nav-mini");
75
+ setIsMini(storedValue === "true");
76
+ }, []);
77
+ useEffect(() => {
78
+ const mediaQuery = window.matchMedia("(max-width: 768px)");
79
+ const syncViewport = () => setIsMobile(mediaQuery.matches);
80
+ syncViewport();
81
+ mediaQuery.addEventListener("change", syncViewport);
82
+ return () => mediaQuery.removeEventListener("change", syncViewport);
83
+ }, []);
84
+ useEffect(() => {
85
+ document.documentElement.style.setProperty("--nav-width", isMini ? "88px" : "280px");
86
+ window.localStorage.setItem("minimal-admin-nav-mini", String(isMini));
87
+ return () => {
88
+ document.documentElement.style.removeProperty("--nav-width");
89
+ };
90
+ }, [isMini]);
91
+ const userLabel = user?.name?.trim() || user?.email?.split("@")[0] || "Qu\u1EA3n tr\u1ECB vi\xEAn";
92
+ const initials = useMemo(() => getInitials(user?.name, user?.email), [user?.email, user?.name]);
93
+ const closeMobileNav = () => {
94
+ if (window.matchMedia("(max-width: 768px)").matches) setNavOpen(false);
95
+ };
96
+ const classes = [
97
+ "minimal-nav",
98
+ navOpen && "minimal-nav--open",
99
+ isMini && "minimal-nav--mini",
100
+ shouldAnimate && "minimal-nav--animate",
101
+ hydrated && "minimal-nav--hydrated"
102
+ ].filter(Boolean).join(" ");
103
+ const isActive = (href) => pathname === href || href !== adminRoute && pathname.startsWith(`${href}/`);
104
+ return /* @__PURE__ */ jsxs(
105
+ "aside",
106
+ {
107
+ "aria-label": "\u0110i\u1EC1u h\u01B0\u1EDBng qu\u1EA3n tr\u1ECB",
108
+ className: classes,
109
+ inert: isMobile && !navOpen || void 0,
110
+ children: [
111
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__scroll", ref: navRef, children: [
112
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__brand-row", children: [
113
+ /* @__PURE__ */ jsxs(
114
+ Link,
115
+ {
116
+ "aria-label": `V\u1EC1 dashboard ${brand.siteName}`,
117
+ className: "minimal-nav__brand",
118
+ href: adminRoute,
119
+ onClick: closeMobileNav,
120
+ prefetch: false,
121
+ children: [
122
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__brand-full", children: /* @__PURE__ */ jsx(AdminLogo, {}) }),
123
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__brand-icon", children: /* @__PURE__ */ jsx(AdminIcon, {}) })
124
+ ]
125
+ }
126
+ ),
127
+ /* @__PURE__ */ jsx(
128
+ "button",
129
+ {
130
+ "aria-label": "\u0110\xF3ng menu",
131
+ className: "minimal-nav__mobile-close",
132
+ onClick: () => setNavOpen(false),
133
+ type: "button",
134
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
135
+ }
136
+ )
137
+ ] }),
138
+ /* @__PURE__ */ jsxs(
139
+ Link,
140
+ {
141
+ className: "minimal-nav__workspace",
142
+ href: adminRoute,
143
+ onClick: closeMobileNav,
144
+ prefetch: false,
145
+ title: brand.siteName,
146
+ children: [
147
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__workspace-icon", children: /* @__PURE__ */ jsx(GalleryVerticalEnd, { "aria-hidden": "true" }) }),
148
+ /* @__PURE__ */ jsxs("span", { className: "minimal-nav__workspace-copy", children: [
149
+ /* @__PURE__ */ jsx("small", { children: "Kh\xF4ng gian l\xE0m vi\u1EC7c" }),
150
+ /* @__PURE__ */ jsx("strong", { children: brand.siteName })
151
+ ] }),
152
+ /* @__PURE__ */ jsx(Menu, { "aria-hidden": "true", className: "minimal-nav__workspace-menu" })
153
+ ]
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsxs("nav", { className: "minimal-nav__menu", children: [
157
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
158
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: "T\u1ED5ng quan" }),
159
+ /* @__PURE__ */ jsxs(
160
+ Link,
161
+ {
162
+ "aria-current": pathname === adminRoute ? "page" : void 0,
163
+ className: `minimal-nav__item ${pathname === adminRoute ? "minimal-nav__item--active" : ""}`,
164
+ href: adminRoute,
165
+ onClick: closeMobileNav,
166
+ prefetch: false,
167
+ title: "Dashboard",
168
+ children: [
169
+ /* @__PURE__ */ jsx(LayoutDashboard, { "aria-hidden": "true" }),
170
+ /* @__PURE__ */ jsx("span", { children: "T\u1ED5ng quan" })
171
+ ]
172
+ }
173
+ )
174
+ ] }),
175
+ groups.map((group) => /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
176
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: translateGroupLabel(group.label) }),
177
+ group.items.map((item) => {
178
+ const href = formatAdminURL({
179
+ adminRoute,
180
+ path: `/${item.type}/${item.slug}`
181
+ });
182
+ const Icon = iconBySlug[item.slug] || FileText;
183
+ const active = isActive(href);
184
+ return /* @__PURE__ */ jsxs(
185
+ Link,
186
+ {
187
+ "aria-current": active ? "page" : void 0,
188
+ className: `minimal-nav__item ${active ? "minimal-nav__item--active" : ""}`,
189
+ href,
190
+ onClick: closeMobileNav,
191
+ prefetch: false,
192
+ title: item.label,
193
+ children: [
194
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
195
+ /* @__PURE__ */ jsx("span", { children: item.label })
196
+ ]
197
+ },
198
+ `${item.type}-${item.slug}`
199
+ );
200
+ })
201
+ ] }, group.label)),
202
+ folders && folders.browseByFolder && /* @__PURE__ */ jsxs("div", { className: "minimal-nav__group", children: [
203
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__group-label", children: "Th\u01B0 vi\u1EC7n" }),
204
+ /* @__PURE__ */ jsxs(
205
+ Link,
206
+ {
207
+ "aria-current": isActive(formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder })) ? "page" : void 0,
208
+ className: `minimal-nav__item ${isActive(formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder })) ? "minimal-nav__item--active" : ""}`,
209
+ href: formatAdminURL({ adminRoute, path: adminRoutes.browseByFolder }),
210
+ onClick: closeMobileNav,
211
+ prefetch: false,
212
+ title: "Duy\u1EC7t theo th\u01B0 m\u1EE5c",
213
+ children: [
214
+ /* @__PURE__ */ jsx(Library, { "aria-hidden": "true" }),
215
+ /* @__PURE__ */ jsx("span", { children: "Duy\u1EC7t theo th\u01B0 m\u1EE5c" })
216
+ ]
217
+ }
218
+ )
219
+ ] })
220
+ ] }),
221
+ /* @__PURE__ */ jsxs("div", { className: "minimal-nav__footer", children: [
222
+ /* @__PURE__ */ jsxs(
223
+ Link,
224
+ {
225
+ className: "minimal-nav__account",
226
+ href: formatAdminURL({ adminRoute, path: adminRoutes.account }),
227
+ onClick: closeMobileNav,
228
+ prefetch: false,
229
+ title: userLabel,
230
+ children: [
231
+ /* @__PURE__ */ jsx("span", { className: "minimal-nav__avatar", children: initials }),
232
+ /* @__PURE__ */ jsxs("span", { className: "minimal-nav__account-copy", children: [
233
+ /* @__PURE__ */ jsx("strong", { children: userLabel }),
234
+ /* @__PURE__ */ jsx("small", { children: user?.email || "T\xE0i kho\u1EA3n qu\u1EA3n tr\u1ECB" })
235
+ ] })
236
+ ]
237
+ }
238
+ ),
239
+ /* @__PURE__ */ jsx("div", { className: "minimal-nav__logout", children: /* @__PURE__ */ jsx(LogoutButton_default, {}) })
240
+ ] })
241
+ ] }),
242
+ /* @__PURE__ */ jsx(
243
+ "button",
244
+ {
245
+ "aria-label": isMini ? "M\u1EDF r\u1ED9ng menu" : "Thu g\u1ECDn menu",
246
+ className: "minimal-nav__collapse",
247
+ onClick: () => setIsMini((current) => !current),
248
+ title: isMini ? "M\u1EDF r\u1ED9ng menu" : "Thu g\u1ECDn menu",
249
+ type: "button",
250
+ children: isMini ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true" })
251
+ }
252
+ )
253
+ ]
254
+ }
255
+ );
256
+ };
257
+
258
+ // src/admin/Nav.tsx
259
+ import { jsx as jsx2 } from "react/jsx-runtime";
260
+ var localizeLabel = (label, language) => {
261
+ if (typeof label === "string") return label;
262
+ return label[language] || Object.values(label)[0] || "";
263
+ };
264
+ var AdminNav = ({ i18n, payload, permissions, visibleEntities }) => {
265
+ if (!permissions || !visibleEntities) return null;
266
+ const groups = getNavGroups(
267
+ permissions,
268
+ visibleEntities,
269
+ payload.config,
270
+ i18n
271
+ ).map((group) => ({
272
+ items: group.entities.map((entity) => ({
273
+ label: localizeLabel(entity.label, i18n.language),
274
+ slug: entity.slug,
275
+ type: entity.type
276
+ })),
277
+ label: group.label
278
+ }));
279
+ return /* @__PURE__ */ jsx2(AdminNavClient, { groups });
280
+ };
281
+ var Nav_default = AdminNav;
282
+ export {
283
+ AdminNavClient,
284
+ Nav_default as default
285
+ };
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+
3
+ declare const AdminThemeToggle: React.FC;
4
+
5
+ export { AdminThemeToggle as default };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ import {
3
+ ThemeToggle_default
4
+ } from "../chunk-GGSOO4FQ.js";
5
+ export {
6
+ ThemeToggle_default as default
7
+ };
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+
3
+ declare const AdminViewSite: React.FC;
4
+
5
+ export { AdminViewSite as default };
@@ -0,0 +1,6 @@
1
+ import {
2
+ ViewSite_default
3
+ } from "../chunk-MDMKKWPU.js";
4
+ export {
5
+ ViewSite_default as default
6
+ };
@@ -0,0 +1,151 @@
1
+ // src/adminExperience.ts
2
+ var IMAGE_UPLOAD_GUIDANCE = "Y\xEAu c\u1EA7u \u0111\u1EC3 \u1EA3nh hi\u1EC3n th\u1ECB r\xF5: hero/banner n\xEAn t\u1EEB 1920 \xD7 1080 px; \u1EA3nh n\u1ED9i dung n\xEAn r\u1ED9ng t\u1ED1i thi\u1EC3u 1200 px. \u01AFu ti\xEAn WebP ho\u1EB7c JPEG, dung l\u01B0\u1EE3ng d\u01B0\u1EDBi 500 KB.";
3
+ var labelTranslations = {
4
+ "Archive Block": "Kh\u1ED1i l\u01B0u tr\u1EEF",
5
+ Content: "N\u1ED9i dung",
6
+ Description: "M\xF4 t\u1EA3",
7
+ Hero: "M\u1EDF \u0111\u1EA7u",
8
+ "Hero Image": "\u1EA2nh \u0111\u1EA1i di\u1EC7n",
9
+ Image: "H\xECnh \u1EA3nh",
10
+ Layout: "B\u1ED1 c\u1EE5c",
11
+ Link: "Li\xEAn k\u1EBFt",
12
+ Media: "H\xECnh \u1EA3nh",
13
+ Meta: "Th\xF4ng tin b\u1ED5 sung",
14
+ Title: "Ti\xEAu \u0111\u1EC1"
15
+ };
16
+ var fieldNameLabels = {
17
+ alt: "V\u0103n b\u1EA3n thay th\u1EBF",
18
+ authors: "T\xE1c gi\u1EA3",
19
+ caption: "Ch\xFA th\xEDch",
20
+ categories: "Chuy\xEAn m\u1EE5c",
21
+ content: "N\u1ED9i dung",
22
+ coverImage: "\u1EA2nh b\xECa",
23
+ defaultOgImage: "\u1EA2nh chia s\u1EBB m\u1EB7c \u0111\u1ECBnh",
24
+ description: "M\xF4 t\u1EA3",
25
+ excerpt: "T\xF3m t\u1EAFt",
26
+ featuredImage: "\u1EA2nh n\u1ED5i b\u1EADt",
27
+ heroImage: "\u1EA2nh \u0111\u1EA1i di\u1EC7n",
28
+ image: "H\xECnh \u1EA3nh",
29
+ logo: "Logo",
30
+ media: "H\xECnh \u1EA3nh",
31
+ appearance: "Ki\u1EC3u hi\u1EC3n th\u1ECB",
32
+ links: "Li\xEAn k\u1EBFt",
33
+ newTab: "M\u1EDF trong tab m\u1EDBi",
34
+ publishedAt: "Ng\xE0y xu\u1EA5t b\u1EA3n",
35
+ relatedPosts: "B\xE0i vi\u1EBFt li\xEAn quan",
36
+ slug: "\u0110\u01B0\u1EDDng d\u1EABn",
37
+ summary: "M\xF4 t\u1EA3 ng\u1EAFn",
38
+ title: "Ti\xEAu \u0111\u1EC1",
39
+ type: "Lo\u1EA1i"
40
+ };
41
+ var entityLabels = {
42
+ "form-submissions": { plural: "D\u1EEF li\u1EC7u bi\u1EC3u m\u1EABu", singular: "D\u1EEF li\u1EC7u bi\u1EC3u m\u1EABu" },
43
+ forms: { plural: "Bi\u1EC3u m\u1EABu", singular: "Bi\u1EC3u m\u1EABu" },
44
+ redirects: { plural: "Chuy\u1EC3n h\u01B0\u1EDBng", singular: "Chuy\u1EC3n h\u01B0\u1EDBng" },
45
+ search: { plural: "K\u1EBFt qu\u1EA3 t\xECm ki\u1EBFm", singular: "K\u1EBFt qu\u1EA3 t\xECm ki\u1EBFm" }
46
+ };
47
+ var translateLabel = (label) => typeof label === "string" ? labelTranslations[label] || label : label;
48
+ var enhanceFields = (fields) => {
49
+ for (const field of fields) {
50
+ if ("name" in field) {
51
+ field.label = field.label === void 0 ? fieldNameLabels[field.name] : translateLabel(field.label);
52
+ } else if ("label" in field) {
53
+ field.label = translateLabel(field.label);
54
+ }
55
+ if (field.type === "upload" && field.relationTo === "media") {
56
+ const currentDescription = field.admin?.description;
57
+ field.admin = {
58
+ ...field.admin,
59
+ description: typeof currentDescription === "string" && !currentDescription.includes(IMAGE_UPLOAD_GUIDANCE) ? `${currentDescription} ${IMAGE_UPLOAD_GUIDANCE}` : IMAGE_UPLOAD_GUIDANCE
60
+ };
61
+ }
62
+ if (field.type === "tabs") {
63
+ for (const tab of field.tabs) {
64
+ tab.label = translateLabel(tab.label);
65
+ enhanceFields(tab.fields);
66
+ }
67
+ } else if ("fields" in field && Array.isArray(field.fields)) {
68
+ enhanceFields(field.fields);
69
+ }
70
+ if (field.type === "blocks") {
71
+ for (const block of field.blocks ?? []) {
72
+ if (block.labels) {
73
+ block.labels = {
74
+ plural: translateLabel(block.labels.plural),
75
+ singular: translateLabel(block.labels.singular)
76
+ };
77
+ }
78
+ enhanceFields(block.fields);
79
+ }
80
+ }
81
+ }
82
+ };
83
+ var adminExperiencePlugin = (config) => {
84
+ for (const collection of config.collections ?? []) {
85
+ const translatedLabels = entityLabels[collection.slug];
86
+ if (translatedLabels) collection.labels = translatedLabels;
87
+ enhanceFields(collection.fields);
88
+ if (collection.slug === "media") {
89
+ collection.admin = {
90
+ ...collection.admin,
91
+ description: IMAGE_UPLOAD_GUIDANCE
92
+ };
93
+ }
94
+ }
95
+ for (const global of config.globals ?? []) enhanceFields(global.fields);
96
+ return config;
97
+ };
98
+
99
+ // src/plugin.ts
100
+ var appendUnique = (current, additions) => [
101
+ .../* @__PURE__ */ new Set([...current ?? [], ...additions])
102
+ ];
103
+ var wikexAdminPlugin = (options = {}) => {
104
+ return (config) => {
105
+ if (options.enabled === false) return config;
106
+ const admin = config.admin ?? {};
107
+ const components = admin.components ?? {};
108
+ const beforeDashboard = options.components?.beforeDashboard;
109
+ const provider = options.components?.provider;
110
+ return {
111
+ ...config,
112
+ admin: {
113
+ ...admin,
114
+ components: {
115
+ ...components,
116
+ Nav: components.Nav ?? "@wikex/admin-kit/admin/nav",
117
+ actions: appendUnique(components.actions, [
118
+ "@wikex/admin-kit/admin/theme-toggle",
119
+ "@wikex/admin-kit/admin/view-site"
120
+ ]),
121
+ beforeDashboard: typeof beforeDashboard !== "string" ? components.beforeDashboard : appendUnique(components.beforeDashboard, [beforeDashboard]),
122
+ beforeLogin: appendUnique(components.beforeLogin, [
123
+ "@wikex/admin-kit/admin/before-login"
124
+ ]),
125
+ graphics: {
126
+ Icon: components.graphics?.Icon ?? "@wikex/admin-kit/admin/brand#AdminIcon",
127
+ Logo: components.graphics?.Logo ?? "@wikex/admin-kit/admin/brand#AdminLogo"
128
+ },
129
+ header: appendUnique(components.header, ["@wikex/admin-kit/admin/header"]),
130
+ logout: {
131
+ Button: components.logout?.Button ?? "@wikex/admin-kit/admin/logout-button"
132
+ },
133
+ providers: typeof provider !== "string" ? components.providers : appendUnique(components.providers, [provider])
134
+ },
135
+ livePreview: admin.livePreview ?? {
136
+ breakpoints: [
137
+ { height: 667, label: "\u0110i\u1EC7n tho\u1EA1i", name: "mobile", width: 375 },
138
+ { height: 1024, label: "M\xE1y t\xEDnh b\u1EA3ng", name: "tablet", width: 768 },
139
+ { height: 900, label: "M\xE1y t\xEDnh", name: "desktop", width: 1440 }
140
+ ]
141
+ }
142
+ }
143
+ };
144
+ };
145
+ };
146
+
147
+ export {
148
+ IMAGE_UPLOAD_GUIDANCE,
149
+ adminExperiencePlugin,
150
+ wikexAdminPlugin
151
+ };