@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.
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
- // 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";
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__ */ jsx2(AdminNavClient, { groups });
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
  };
@@ -1,7 +1,8 @@
1
+ 'use client';
1
2
  "use client";
2
3
  import {
3
4
  ThemeToggle_default
4
- } from "../chunk-GGSOO4FQ.js";
5
+ } from "../chunk-SAI5SWZA.js";
5
6
  export {
6
7
  ThemeToggle_default as default
7
8
  };
@@ -1,6 +1,11 @@
1
- import {
2
- ViewSite_default
3
- } from "../chunk-MDMKKWPU.js";
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-BUD6BMFV.js";
12
+ } from "./chunk-VK4EFLWH.js";
12
13
 
13
14
  // src/live-preview/LivePreviewEditor.tsx
14
15
  import { createPortal } from "react-dom";
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/admin/LogoutButton.tsx
2
4
  import { Link, useConfig, useTranslation } from "@payloadcms/ui";
3
5
  import { LogOut } from "lucide-react";
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/admin/ThemeToggle.tsx
2
4
  import { useTheme } from "@payloadcms/ui";
3
5
  import { Moon, Sun } from "lucide-react";
@@ -1,6 +1,7 @@
1
+ 'use client';
1
2
  import {
2
3
  useAdminBrand
3
- } from "./chunk-XGKGKCQ6.js";
4
+ } from "./chunk-X7VETFVD.js";
4
5
 
5
6
  // src/admin/Brand.tsx
6
7
  import Image from "next/image";
@@ -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
+ };
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/admin/useAdminBrand.ts
2
4
  import { useEffect, useState } from "react";
3
5
  var defaultBrand = {
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
- export { IMAGE_UPLOAD_GUIDANCE, type WikexAdminPluginOptions, adminExperiencePlugin, wikexAdminPlugin };
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,
@@ -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;
@@ -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-IL2CUCDG.js";
10
- import "./chunk-BUD6BMFV.js";
10
+ } from "./chunk-GMPR6LHH.js";
11
+ import "./chunk-VK4EFLWH.js";
11
12
  export {
12
13
  GlobalInlineInspector,
13
14
  TextStyleInspector,