@wikex/admin-kit 0.2.1 → 0.3.0
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/CHANGELOG.md +5 -0
- package/dist/admin/before-login.js +2 -1
- package/dist/admin/brand.js +3 -2
- package/dist/admin/header.js +30 -21
- package/dist/admin/logout-button.js +2 -1
- package/dist/admin/nav-client.d.ts +16 -0
- package/dist/admin/nav-client.js +258 -0
- package/dist/admin/nav.d.ts +2 -5
- package/dist/admin/nav.js +5 -259
- package/dist/admin/theme-toggle.js +2 -1
- package/dist/admin/view-site.js +8 -3
- package/dist/{chunk-IL2CUCDG.js → chunk-GMPR6LHH.js} +2 -1
- package/dist/{chunk-W4ZKDOWJ.js → chunk-GZ2B5BTH.js} +2 -0
- package/dist/{chunk-GGSOO4FQ.js → chunk-SAI5SWZA.js} +2 -0
- package/dist/{chunk-LP22Y3NO.js → chunk-SM6CCKQQ.js} +2 -1
- package/dist/chunk-VK4EFLWH.js +119 -0
- package/dist/{chunk-XGKGKCQ6.js → chunk-X7VETFVD.js} +2 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +66 -6
- package/dist/live-preview.d.ts +69 -1
- package/dist/live-preview.js +3 -2
- package/dist/project-ClCmpyeX.d.ts +54 -0
- package/dist/project.d.ts +1 -34
- package/dist/rich-text-client.js +2 -1
- package/dist/scanner.d.ts +23 -0
- package/dist/scanner.js +72 -0
- package/dist/starter-client.d.ts +45 -4
- package/dist/starter-client.js +7 -6
- package/dist/starter.d.ts +1 -2
- package/dist/text-style-runtime.js +69 -3
- package/package.json +3 -1
- package/dist/chunk-MDMKKWPU.js +0 -12
- package/dist/chunk-YMBJCWN3.js +0 -73
package/dist/admin/nav.js
CHANGED
|
@@ -1,262 +1,8 @@
|
|
|
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
1
|
// src/admin/Nav.tsx
|
|
13
2
|
import { getNavGroups } from "@payloadcms/ui/shared";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import {
|
|
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";
|
|
3
|
+
import { AdminNavClient } from "@wikex/admin-kit/admin/nav-client";
|
|
4
|
+
import { AdminNavClient as AdminNavClient2 } from "@wikex/admin-kit/admin/nav-client";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
260
6
|
var localizeLabel = (label, language) => {
|
|
261
7
|
if (typeof label === "string") return label;
|
|
262
8
|
return label[language] || Object.values(label)[0] || "";
|
|
@@ -276,10 +22,10 @@ var AdminNav = ({ i18n, payload, permissions, visibleEntities }) => {
|
|
|
276
22
|
})),
|
|
277
23
|
label: group.label
|
|
278
24
|
}));
|
|
279
|
-
return /* @__PURE__ */
|
|
25
|
+
return /* @__PURE__ */ jsx(AdminNavClient, { groups });
|
|
280
26
|
};
|
|
281
27
|
var Nav_default = AdminNav;
|
|
282
28
|
export {
|
|
283
|
-
AdminNavClient,
|
|
29
|
+
AdminNavClient2 as AdminNavClient,
|
|
284
30
|
Nav_default as default
|
|
285
31
|
};
|
package/dist/admin/view-site.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
} from "
|
|
1
|
+
// src/admin/ViewSite.tsx
|
|
2
|
+
import { ArrowUpRight } from "lucide-react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var AdminViewSite = () => /* @__PURE__ */ jsxs("a", { className: "admin-view-site", "data-slot": "button", href: "/", rel: "noreferrer", target: "_blank", children: [
|
|
5
|
+
"Xem website",
|
|
6
|
+
/* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": "true" })
|
|
7
|
+
] });
|
|
8
|
+
var ViewSite_default = AdminViewSite;
|
|
4
9
|
export {
|
|
5
10
|
ViewSite_default as default
|
|
6
11
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import {
|
|
2
3
|
EDITABLE_INTERACTIVE_SELECTOR,
|
|
3
4
|
EDITABLE_PREVIEW_SELECTOR,
|
|
@@ -8,7 +9,7 @@ import {
|
|
|
8
9
|
isSyntheticElementStyleKey,
|
|
9
10
|
normalizeTextStyleMap,
|
|
10
11
|
normalizeTextStyleValue
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-VK4EFLWH.js";
|
|
12
13
|
|
|
13
14
|
// src/live-preview/LivePreviewEditor.tsx
|
|
14
15
|
import { createPortal } from "react-dom";
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/textStyles.ts
|
|
4
|
+
var TEXT_FONT_OPTIONS = [
|
|
5
|
+
{ css: "", label: "M\u1EB7c \u0111\u1ECBnh", value: "default" },
|
|
6
|
+
{ css: "var(--font-manrope), sans-serif", label: "Manrope", value: "manrope" },
|
|
7
|
+
{ css: "var(--font-inter), sans-serif", label: "Inter", value: "inter" },
|
|
8
|
+
{ css: "var(--font-roboto), sans-serif", label: "Roboto", value: "roboto" },
|
|
9
|
+
{ css: "var(--font-montserrat), sans-serif", label: "Montserrat", value: "montserrat" },
|
|
10
|
+
{ css: "var(--font-lora), serif", label: "Lora", value: "lora" },
|
|
11
|
+
{
|
|
12
|
+
css: "var(--font-playfair-display), serif",
|
|
13
|
+
label: "Playfair Display",
|
|
14
|
+
value: "playfair-display"
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
var TEXT_LINE_HEIGHT_OPTIONS = [
|
|
18
|
+
{ css: "", label: "M\u1EB7c \u0111\u1ECBnh", value: "default" },
|
|
19
|
+
{ css: "0.9", label: "R\u1EA5t ch\u1EB7t \xB7 0.9", value: "0.9" },
|
|
20
|
+
{ css: "1", label: "Ch\u1EB7t \xB7 1.0", value: "1" },
|
|
21
|
+
{ css: "1.15", label: "G\u1ECDn \xB7 1.15", value: "1.15" },
|
|
22
|
+
{ css: "1.35", label: "Ti\xEAu chu\u1EA9n \xB7 1.35", value: "1.35" },
|
|
23
|
+
{ css: "1.5", label: "Tho\xE1ng \xB7 1.5", value: "1.5" },
|
|
24
|
+
{ css: "1.7", label: "R\u1ED9ng \xB7 1.7", value: "1.7" }
|
|
25
|
+
];
|
|
26
|
+
var EDITABLE_INTERACTIVE_SELECTOR = [
|
|
27
|
+
"a",
|
|
28
|
+
"button",
|
|
29
|
+
'input:not([type="hidden"])',
|
|
30
|
+
"select",
|
|
31
|
+
"textarea",
|
|
32
|
+
'[role="button"]',
|
|
33
|
+
'[role="link"]',
|
|
34
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
35
|
+
].join(",");
|
|
36
|
+
var EDITABLE_PREVIEW_SELECTOR = [
|
|
37
|
+
"h1",
|
|
38
|
+
"h2",
|
|
39
|
+
"h3",
|
|
40
|
+
"h4",
|
|
41
|
+
"h5",
|
|
42
|
+
"h6",
|
|
43
|
+
"p",
|
|
44
|
+
"li",
|
|
45
|
+
"span",
|
|
46
|
+
"strong",
|
|
47
|
+
EDITABLE_INTERACTIVE_SELECTOR
|
|
48
|
+
].join(",");
|
|
49
|
+
var isSyntheticElementStyleKey = (value) => value.startsWith("@element:");
|
|
50
|
+
var getEditableElementStyleKey = (element) => {
|
|
51
|
+
const scopedRoot = element.closest("[data-wikex-scope]");
|
|
52
|
+
const root = scopedRoot ?? element.ownerDocument.body;
|
|
53
|
+
const scope = scopedRoot?.dataset.wikexScope || "body";
|
|
54
|
+
const segments = [];
|
|
55
|
+
let current = element;
|
|
56
|
+
while (current && current !== root) {
|
|
57
|
+
const parentElement = current.parentElement;
|
|
58
|
+
if (!parentElement) break;
|
|
59
|
+
const tagName = current.tagName.toLowerCase();
|
|
60
|
+
const sameTagSiblings = Array.from(parentElement.children).filter(
|
|
61
|
+
(sibling) => sibling.tagName === current?.tagName
|
|
62
|
+
);
|
|
63
|
+
const index = sameTagSiblings.indexOf(current) + 1;
|
|
64
|
+
segments.push(`${tagName}:nth-of-type(${Math.max(index, 1)})`);
|
|
65
|
+
current = parentElement;
|
|
66
|
+
}
|
|
67
|
+
return `@element:${scope}:${segments.reverse().join(">")}`;
|
|
68
|
+
};
|
|
69
|
+
var fontValues = new Set(TEXT_FONT_OPTIONS.map((option) => option.value));
|
|
70
|
+
var lineHeightValues = new Set(TEXT_LINE_HEIGHT_OPTIONS.map((option) => option.value));
|
|
71
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
72
|
+
var normalizeTextStyleValue = (value) => {
|
|
73
|
+
if (!isRecord(value)) return {};
|
|
74
|
+
const fontFamily = typeof value.fontFamily === "string" && fontValues.has(value.fontFamily) ? value.fontFamily : void 0;
|
|
75
|
+
const lineHeight = typeof value.lineHeight === "string" && lineHeightValues.has(value.lineHeight) ? value.lineHeight : void 0;
|
|
76
|
+
const legacyWidth = typeof value.width === "string" && /^\d+(?:\.\d+)?%$/.test(value.width) ? Number.parseFloat(value.width) : void 0;
|
|
77
|
+
const widthValue = typeof value.width === "number" ? value.width : legacyWidth;
|
|
78
|
+
const width = typeof widthValue === "number" && Number.isFinite(widthValue) ? Math.min(100, Math.max(5, widthValue)) : void 0;
|
|
79
|
+
const widthOffset = typeof value.widthOffset === "number" && Number.isFinite(value.widthOffset) ? Math.min(width ? 100 - width : 95, Math.max(0, value.widthOffset)) : void 0;
|
|
80
|
+
return { fontFamily, lineHeight, width, widthOffset };
|
|
81
|
+
};
|
|
82
|
+
var normalizeTextStyleMap = (value) => {
|
|
83
|
+
if (!isRecord(value)) return {};
|
|
84
|
+
return Object.fromEntries(
|
|
85
|
+
Object.entries(value).map(([fieldPath, fieldStyle]) => [
|
|
86
|
+
fieldPath,
|
|
87
|
+
normalizeTextStyleValue(fieldStyle)
|
|
88
|
+
])
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
var getTextStyleCSS = (value) => {
|
|
92
|
+
const fontFamily = TEXT_FONT_OPTIONS.find((option) => option.value === value.fontFamily)?.css;
|
|
93
|
+
const lineHeight = TEXT_LINE_HEIGHT_OPTIONS.find(
|
|
94
|
+
(option) => option.value === value.lineHeight
|
|
95
|
+
)?.css;
|
|
96
|
+
const width = typeof value.width === "number" ? `${value.width}%` : void 0;
|
|
97
|
+
const widthOffset = typeof value.widthOffset === "number" ? `${value.widthOffset}%` : void 0;
|
|
98
|
+
return {
|
|
99
|
+
boxSizing: width ? "border-box" : void 0,
|
|
100
|
+
fontFamily: fontFamily || void 0,
|
|
101
|
+
lineHeight: lineHeight || void 0,
|
|
102
|
+
marginLeft: width ? widthOffset || "0%" : void 0,
|
|
103
|
+
marginRight: width ? "auto" : void 0,
|
|
104
|
+
maxWidth: width ? "none" : void 0,
|
|
105
|
+
width
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
TEXT_FONT_OPTIONS,
|
|
111
|
+
TEXT_LINE_HEIGHT_OPTIONS,
|
|
112
|
+
EDITABLE_INTERACTIVE_SELECTOR,
|
|
113
|
+
EDITABLE_PREVIEW_SELECTOR,
|
|
114
|
+
isSyntheticElementStyleKey,
|
|
115
|
+
getEditableElementStyleKey,
|
|
116
|
+
normalizeTextStyleValue,
|
|
117
|
+
normalizeTextStyleMap,
|
|
118
|
+
getTextStyleCSS
|
|
119
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Plugin } from 'payload';
|
|
2
|
-
export { VisualEditorRouteRegistry, WikexProjectDefinition, createVisualEditorRouteResolver, defineWikexProject } from './project.js';
|
|
2
|
+
export { V as VisualEditorRouteRegistry, W as WikexProjectDefinition, c as createVisualEditorRouteResolver, d as defineWikexProject } from './project-ClCmpyeX.js';
|
|
3
3
|
export { RichTextTypographyFeature } from './rich-text.js';
|
|
4
|
-
export { TextStyleRuntime } from './text-style-runtime.js';
|
|
5
4
|
export { EDITABLE_INTERACTIVE_SELECTOR, EDITABLE_PREVIEW_SELECTOR, TEXT_FONT_OPTIONS, TEXT_LINE_HEIGHT_OPTIONS, TextFontFamily, TextLineHeight, TextStyleMap, TextStyleValue, getEditableElementStyleKey, getTextStyleCSS, isSyntheticElementStyleKey, normalizeTextStyleMap, normalizeTextStyleValue } from './text-styles.js';
|
|
6
|
-
import './runtimeConfig-BwjQepcW.js';
|
|
7
5
|
import '@payloadcms/richtext-lexical';
|
|
8
6
|
|
|
9
7
|
declare const IMAGE_UPLOAD_GUIDANCE = "Y\u00EAu c\u1EA7u \u0111\u1EC3 \u1EA3nh hi\u1EC3n th\u1ECB r\u00F5: hero/banner n\u00EAn t\u1EEB 1920 \u00D7 1080 px; \u1EA3nh n\u1ED9i dung n\u00EAn r\u1ED9ng t\u1ED1i thi\u1EC3u 1200 px. \u01AFu ti\u00EAn WebP ho\u1EB7c JPEG, dung l\u01B0\u1EE3ng d\u01B0\u1EDBi 500 KB.";
|
|
@@ -23,4 +21,8 @@ type WikexAdminPluginOptions = {
|
|
|
23
21
|
*/
|
|
24
22
|
declare const wikexAdminPlugin: (options?: WikexAdminPluginOptions) => Plugin;
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
declare const TextStyleRuntime: ({ styles }: {
|
|
25
|
+
styles?: unknown;
|
|
26
|
+
}) => null;
|
|
27
|
+
|
|
28
|
+
export { IMAGE_UPLOAD_GUIDANCE, TextStyleRuntime, type WikexAdminPluginOptions, adminExperiencePlugin, wikexAdminPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RichTextTypographyFeature
|
|
3
|
-
} from "./chunk-LC2CP5SR.js";
|
|
4
|
-
import {
|
|
5
|
-
TextStyleRuntime
|
|
6
|
-
} from "./chunk-YMBJCWN3.js";
|
|
7
1
|
import {
|
|
8
2
|
IMAGE_UPLOAD_GUIDANCE,
|
|
9
3
|
adminExperiencePlugin,
|
|
@@ -13,6 +7,9 @@ import {
|
|
|
13
7
|
createVisualEditorRouteResolver,
|
|
14
8
|
defineWikexProject
|
|
15
9
|
} from "./chunk-JJLHSZ3T.js";
|
|
10
|
+
import {
|
|
11
|
+
RichTextTypographyFeature
|
|
12
|
+
} from "./chunk-LC2CP5SR.js";
|
|
16
13
|
import {
|
|
17
14
|
EDITABLE_INTERACTIVE_SELECTOR,
|
|
18
15
|
EDITABLE_PREVIEW_SELECTOR,
|
|
@@ -24,6 +21,69 @@ import {
|
|
|
24
21
|
normalizeTextStyleMap,
|
|
25
22
|
normalizeTextStyleValue
|
|
26
23
|
} from "./chunk-BUD6BMFV.js";
|
|
24
|
+
|
|
25
|
+
// src/TextStyleRuntime.tsx
|
|
26
|
+
import { useEffect } from "react";
|
|
27
|
+
var TextStyleRuntime = ({ styles }) => {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const normalizedStyles = normalizeTextStyleMap(styles);
|
|
30
|
+
const originals = /* @__PURE__ */ new Map();
|
|
31
|
+
let applyFrame = 0;
|
|
32
|
+
const applyStyles = () => {
|
|
33
|
+
const fields = new Set(
|
|
34
|
+
document.querySelectorAll(`[data-wikex-field],${EDITABLE_PREVIEW_SELECTOR}`)
|
|
35
|
+
);
|
|
36
|
+
for (const element of fields) {
|
|
37
|
+
const fieldPath = element.dataset.wikexField || getEditableElementStyleKey(element);
|
|
38
|
+
if (!fieldPath || !normalizedStyles[fieldPath]) continue;
|
|
39
|
+
if (!originals.has(element)) {
|
|
40
|
+
originals.set(element, {
|
|
41
|
+
boxSizing: element.style.boxSizing,
|
|
42
|
+
fontFamily: element.style.fontFamily,
|
|
43
|
+
lineHeight: element.style.lineHeight,
|
|
44
|
+
marginLeft: element.style.marginLeft,
|
|
45
|
+
marginRight: element.style.marginRight,
|
|
46
|
+
maxWidth: element.style.maxWidth,
|
|
47
|
+
width: element.style.width
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const style = getTextStyleCSS(normalizedStyles[fieldPath]);
|
|
51
|
+
element.style.boxSizing = style.boxSizing || "";
|
|
52
|
+
element.style.fontFamily = style.fontFamily || "";
|
|
53
|
+
element.style.lineHeight = style.lineHeight || "";
|
|
54
|
+
element.style.marginLeft = style.marginLeft || "";
|
|
55
|
+
element.style.marginRight = style.marginRight || "";
|
|
56
|
+
element.style.maxWidth = style.maxWidth || "";
|
|
57
|
+
element.style.width = style.width || "";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const scheduleApplyStyles = () => {
|
|
61
|
+
if (applyFrame) return;
|
|
62
|
+
applyFrame = window.requestAnimationFrame(() => {
|
|
63
|
+
applyFrame = 0;
|
|
64
|
+
applyStyles();
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
applyStyles();
|
|
68
|
+
const observer = new MutationObserver(scheduleApplyStyles);
|
|
69
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
70
|
+
return () => {
|
|
71
|
+
observer.disconnect();
|
|
72
|
+
window.cancelAnimationFrame(applyFrame);
|
|
73
|
+
for (const [element, original] of originals) {
|
|
74
|
+
if (!element.isConnected) continue;
|
|
75
|
+
element.style.boxSizing = original.boxSizing;
|
|
76
|
+
element.style.fontFamily = original.fontFamily;
|
|
77
|
+
element.style.lineHeight = original.lineHeight;
|
|
78
|
+
element.style.marginLeft = original.marginLeft;
|
|
79
|
+
element.style.marginRight = original.marginRight;
|
|
80
|
+
element.style.maxWidth = original.maxWidth;
|
|
81
|
+
element.style.width = original.width;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}, [styles]);
|
|
85
|
+
return null;
|
|
86
|
+
};
|
|
27
87
|
export {
|
|
28
88
|
EDITABLE_INTERACTIVE_SELECTOR,
|
|
29
89
|
EDITABLE_PREVIEW_SELECTOR,
|
package/dist/live-preview.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { TextStyleValue } from './text-styles.js';
|
|
4
3
|
import { V as VisualEditorDocumentTarget } from './runtimeConfig-BwjQepcW.js';
|
|
5
4
|
export { B as BlockPickerOption, a as BlockPickerScope, L as LivePreviewRuntimeConfig, b as VisualEditorRoute, c as VisualEditorScope, d as configureLivePreview } from './runtimeConfig-BwjQepcW.js';
|
|
6
5
|
|
|
@@ -33,6 +32,75 @@ declare const GlobalInlineInspector: ({ onApply, selection, }: {
|
|
|
33
32
|
selection: GlobalInspectorSelection;
|
|
34
33
|
}) => react_jsx_runtime.JSX.Element;
|
|
35
34
|
|
|
35
|
+
declare const TEXT_FONT_OPTIONS: readonly [{
|
|
36
|
+
readonly css: "";
|
|
37
|
+
readonly label: "Mặc định";
|
|
38
|
+
readonly value: "default";
|
|
39
|
+
}, {
|
|
40
|
+
readonly css: "var(--font-manrope), sans-serif";
|
|
41
|
+
readonly label: "Manrope";
|
|
42
|
+
readonly value: "manrope";
|
|
43
|
+
}, {
|
|
44
|
+
readonly css: "var(--font-inter), sans-serif";
|
|
45
|
+
readonly label: "Inter";
|
|
46
|
+
readonly value: "inter";
|
|
47
|
+
}, {
|
|
48
|
+
readonly css: "var(--font-roboto), sans-serif";
|
|
49
|
+
readonly label: "Roboto";
|
|
50
|
+
readonly value: "roboto";
|
|
51
|
+
}, {
|
|
52
|
+
readonly css: "var(--font-montserrat), sans-serif";
|
|
53
|
+
readonly label: "Montserrat";
|
|
54
|
+
readonly value: "montserrat";
|
|
55
|
+
}, {
|
|
56
|
+
readonly css: "var(--font-lora), serif";
|
|
57
|
+
readonly label: "Lora";
|
|
58
|
+
readonly value: "lora";
|
|
59
|
+
}, {
|
|
60
|
+
readonly css: "var(--font-playfair-display), serif";
|
|
61
|
+
readonly label: "Playfair Display";
|
|
62
|
+
readonly value: "playfair-display";
|
|
63
|
+
}];
|
|
64
|
+
declare const TEXT_LINE_HEIGHT_OPTIONS: readonly [{
|
|
65
|
+
readonly css: "";
|
|
66
|
+
readonly label: "Mặc định";
|
|
67
|
+
readonly value: "default";
|
|
68
|
+
}, {
|
|
69
|
+
readonly css: "0.9";
|
|
70
|
+
readonly label: "Rất chặt · 0.9";
|
|
71
|
+
readonly value: "0.9";
|
|
72
|
+
}, {
|
|
73
|
+
readonly css: "1";
|
|
74
|
+
readonly label: "Chặt · 1.0";
|
|
75
|
+
readonly value: "1";
|
|
76
|
+
}, {
|
|
77
|
+
readonly css: "1.15";
|
|
78
|
+
readonly label: "Gọn · 1.15";
|
|
79
|
+
readonly value: "1.15";
|
|
80
|
+
}, {
|
|
81
|
+
readonly css: "1.35";
|
|
82
|
+
readonly label: "Tiêu chuẩn · 1.35";
|
|
83
|
+
readonly value: "1.35";
|
|
84
|
+
}, {
|
|
85
|
+
readonly css: "1.5";
|
|
86
|
+
readonly label: "Thoáng · 1.5";
|
|
87
|
+
readonly value: "1.5";
|
|
88
|
+
}, {
|
|
89
|
+
readonly css: "1.7";
|
|
90
|
+
readonly label: "Rộng · 1.7";
|
|
91
|
+
readonly value: "1.7";
|
|
92
|
+
}];
|
|
93
|
+
type TextFontFamily = (typeof TEXT_FONT_OPTIONS)[number]['value'];
|
|
94
|
+
type TextLineHeight = (typeof TEXT_LINE_HEIGHT_OPTIONS)[number]['value'];
|
|
95
|
+
type TextStyleValue = {
|
|
96
|
+
fontFamily?: TextFontFamily;
|
|
97
|
+
lineHeight?: TextLineHeight;
|
|
98
|
+
/** Percentage of the containing block, written by the canvas resize handles. */
|
|
99
|
+
width?: number;
|
|
100
|
+
/** Percentage offset from the containing block's left content edge. */
|
|
101
|
+
widthOffset?: number;
|
|
102
|
+
};
|
|
103
|
+
|
|
36
104
|
type TextInspectorSelection = VisualEditorDocumentTarget & {
|
|
37
105
|
canEditText: boolean;
|
|
38
106
|
fieldPath: string;
|
package/dist/live-preview.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import {
|
|
2
3
|
GlobalInlineInspector,
|
|
3
4
|
LivePreviewEditor_default,
|
|
@@ -6,8 +7,8 @@ import {
|
|
|
6
7
|
readGlobal,
|
|
7
8
|
saveTextStylePatch,
|
|
8
9
|
updateGlobalFields
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-GMPR6LHH.js";
|
|
11
|
+
import "./chunk-VK4EFLWH.js";
|
|
11
12
|
export {
|
|
12
13
|
GlobalInlineInspector,
|
|
13
14
|
TextStyleInspector,
|