@wikex/admin-kit 0.2.0 → 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.
Files changed (72) 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 +27 -0
  4. package/dist/admin/brand.d.ts +19 -0
  5. package/dist/admin/brand.js +16 -0
  6. package/dist/admin/header.d.ts +5 -0
  7. package/dist/admin/header.js +96 -0
  8. package/dist/admin/logout-button.d.ts +8 -0
  9. package/dist/admin/logout-button.js +8 -0
  10. package/dist/admin/nav-client.d.ts +16 -0
  11. package/dist/admin/nav-client.js +258 -0
  12. package/dist/admin/nav.d.ts +16 -0
  13. package/dist/admin/nav.js +31 -0
  14. package/dist/admin/theme-toggle.d.ts +5 -0
  15. package/dist/admin/theme-toggle.js +8 -0
  16. package/dist/admin/view-site.d.ts +5 -0
  17. package/dist/admin/view-site.js +11 -0
  18. package/dist/chunk-7FEACJUN.js +151 -0
  19. package/dist/chunk-BUD6BMFV.js +117 -0
  20. package/dist/chunk-GMPR6LHH.js +2063 -0
  21. package/dist/chunk-GZ2B5BTH.js +39 -0
  22. package/dist/chunk-JJLHSZ3T.js +40 -0
  23. package/dist/chunk-LC2CP5SR.js +13 -0
  24. package/dist/chunk-SAI5SWZA.js +29 -0
  25. package/dist/chunk-SM6CCKQQ.js +62 -0
  26. package/dist/chunk-VK4EFLWH.js +119 -0
  27. package/dist/chunk-X7VETFVD.js +52 -0
  28. package/dist/index.d.ts +28 -0
  29. package/dist/index.js +104 -0
  30. package/dist/live-preview.d.ts +118 -0
  31. package/dist/live-preview.js +20 -0
  32. package/dist/project-ClCmpyeX.d.ts +54 -0
  33. package/dist/project.d.ts +1 -0
  34. package/dist/project.js +8 -0
  35. package/dist/rich-text-client.d.ts +5 -0
  36. package/dist/rich-text-client.js +166 -0
  37. package/dist/rich-text.d.ts +5 -0
  38. package/dist/rich-text.js +6 -0
  39. package/dist/runtimeConfig-BwjQepcW.d.ts +30 -0
  40. package/dist/starter-client.d.ts +56 -0
  41. package/dist/starter-client.js +26 -0
  42. package/dist/starter.d.ts +39 -0
  43. package/dist/starter.js +62 -0
  44. package/dist/text-style-runtime.d.ts +5 -0
  45. package/dist/text-style-runtime.js +74 -0
  46. package/dist/text-styles.d.ts +86 -0
  47. package/dist/text-styles.js +22 -0
  48. package/package.json +24 -19
  49. package/src/TextStyleRuntime.tsx +0 -90
  50. package/src/admin/BeforeLogin.tsx +0 -19
  51. package/src/admin/Brand.tsx +0 -74
  52. package/src/admin/Header.tsx +0 -87
  53. package/src/admin/LogoutButton.tsx +0 -41
  54. package/src/admin/Nav.tsx +0 -35
  55. package/src/admin/NavClient.tsx +0 -288
  56. package/src/admin/ThemeToggle.tsx +0 -31
  57. package/src/admin/ViewSite.tsx +0 -11
  58. package/src/admin/useAdminBrand.ts +0 -81
  59. package/src/adminExperience.ts +0 -117
  60. package/src/index.ts +0 -11
  61. package/src/live-preview/GlobalInlineInspector.tsx +0 -334
  62. package/src/live-preview/LivePreviewEditor.tsx +0 -2088
  63. package/src/live-preview/TextStyleInspector.tsx +0 -289
  64. package/src/live-preview/index.ts +0 -23
  65. package/src/live-preview/runtimeConfig.ts +0 -52
  66. package/src/plugin.ts +0 -70
  67. package/src/project.ts +0 -82
  68. package/src/rich-text/client.tsx +0 -202
  69. package/src/rich-text/index.ts +0 -10
  70. package/src/starter/client.tsx +0 -22
  71. package/src/starter.ts +0 -95
  72. package/src/textStyles.ts +0 -161
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+
3
+ // src/admin/LogoutButton.tsx
4
+ import { Link, useConfig, useTranslation } from "@payloadcms/ui";
5
+ import { LogOut } from "lucide-react";
6
+ import { formatAdminURL } from "payload/shared";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var AdminLogoutButton = ({ tabIndex = 0 }) => {
9
+ const {
10
+ config: {
11
+ admin: {
12
+ routes: { logout: logoutRoute }
13
+ },
14
+ routes: { admin: adminRoute }
15
+ }
16
+ } = useConfig();
17
+ const { t } = useTranslation();
18
+ const label = t("authentication:logOut");
19
+ return /* @__PURE__ */ jsxs(
20
+ Link,
21
+ {
22
+ "aria-label": label,
23
+ className: "admin-sign-out",
24
+ href: formatAdminURL({ adminRoute, path: logoutRoute }),
25
+ prefetch: false,
26
+ tabIndex,
27
+ title: label,
28
+ children: [
29
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "admin-sign-out__icon", children: /* @__PURE__ */ jsx(LogOut, { strokeWidth: 2 }) }),
30
+ /* @__PURE__ */ jsx("span", { className: "admin-sign-out__label", children: label })
31
+ ]
32
+ }
33
+ );
34
+ };
35
+ var LogoutButton_default = AdminLogoutButton;
36
+
37
+ export {
38
+ LogoutButton_default
39
+ };
@@ -0,0 +1,40 @@
1
+ // src/project.ts
2
+ var defineWikexProject = (project) => project;
3
+ var normalizeGlobalScopes = (globals) => {
4
+ if (!globals) return /* @__PURE__ */ new Map();
5
+ if (Array.isArray(globals)) {
6
+ return new Map(globals.map((slug) => [slug, "content"]));
7
+ }
8
+ return new Map(Object.entries(globals));
9
+ };
10
+ var createVisualEditorRouteResolver = (registry) => {
11
+ const collections = new Set(registry.collections ?? []);
12
+ const globals = normalizeGlobalScopes(registry.globals);
13
+ return (pathname) => {
14
+ const collectionMatch = pathname.match(/\/collections\/([^/?#]+)\/([^/?#]+)/);
15
+ if (collectionMatch && collections.has(collectionMatch[1])) {
16
+ const collection = collectionMatch[1];
17
+ const rawDocumentID = decodeURIComponent(collectionMatch[2]);
18
+ return {
19
+ documentTarget: rawDocumentID === "create" ? null : { collection, documentID: rawDocumentID, kind: "collection" },
20
+ scope: "content",
21
+ type: "collection"
22
+ };
23
+ }
24
+ const globalMatch = pathname.match(/\/globals\/([^/?#]+)/);
25
+ const global = globalMatch?.[1];
26
+ if (global && globals.has(global)) {
27
+ return {
28
+ documentTarget: { global, kind: "global" },
29
+ scope: globals.get(global) ?? "content",
30
+ type: "global"
31
+ };
32
+ }
33
+ return null;
34
+ };
35
+ };
36
+
37
+ export {
38
+ defineWikexProject,
39
+ createVisualEditorRouteResolver
40
+ };
@@ -0,0 +1,13 @@
1
+ // src/rich-text/index.ts
2
+ import { createServerFeature } from "@payloadcms/richtext-lexical";
3
+ var TypographyFeature = createServerFeature({
4
+ feature: {
5
+ ClientFeature: "@wikex/admin-kit/rich-text/client#RichTextTypographyFeatureClient"
6
+ },
7
+ key: "wikexTypography"
8
+ });
9
+ var RichTextTypographyFeature = () => TypographyFeature();
10
+
11
+ export {
12
+ RichTextTypographyFeature
13
+ };
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+
3
+ // src/admin/ThemeToggle.tsx
4
+ import { useTheme } from "@payloadcms/ui";
5
+ import { Moon, Sun } from "lucide-react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var AdminThemeToggle = () => {
8
+ const { setTheme, theme } = useTheme();
9
+ const isDark = theme === "dark";
10
+ const label = isDark ? "Chuy\u1EC3n sang giao di\u1EC7n s\xE1ng" : "Chuy\u1EC3n sang giao di\u1EC7n t\u1ED1i";
11
+ return /* @__PURE__ */ jsx(
12
+ "button",
13
+ {
14
+ "aria-checked": isDark,
15
+ "aria-label": label,
16
+ className: "admin-theme-toggle",
17
+ onClick: () => setTheme(isDark ? "light" : "dark"),
18
+ role: "switch",
19
+ title: label,
20
+ type: "button",
21
+ children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "admin-theme-toggle__track", children: /* @__PURE__ */ jsx("span", { className: "admin-theme-toggle__thumb", children: isDark ? /* @__PURE__ */ jsx(Moon, { strokeWidth: 2.2 }) : /* @__PURE__ */ jsx(Sun, { strokeWidth: 2.2 }) }) })
22
+ }
23
+ );
24
+ };
25
+ var ThemeToggle_default = AdminThemeToggle;
26
+
27
+ export {
28
+ ThemeToggle_default
29
+ };
@@ -0,0 +1,62 @@
1
+ 'use client';
2
+ import {
3
+ useAdminBrand
4
+ } from "./chunk-X7VETFVD.js";
5
+
6
+ // src/admin/Brand.tsx
7
+ import Image from "next/image";
8
+ import { jsx } from "react/jsx-runtime";
9
+ var BrandLogo = ({
10
+ asset,
11
+ className,
12
+ height,
13
+ maxWidth
14
+ }) => /* @__PURE__ */ jsx(
15
+ "span",
16
+ {
17
+ className: ["brand-logo", className].filter(Boolean).join(" "),
18
+ style: { alignItems: "center", display: "inline-flex", height, maxWidth },
19
+ children: /* @__PURE__ */ jsx(
20
+ Image,
21
+ {
22
+ alt: "",
23
+ height: asset.height,
24
+ src: asset.url,
25
+ style: { height: "100%", maxWidth: "100%", objectFit: "contain", width: "auto" },
26
+ unoptimized: true,
27
+ width: asset.width
28
+ }
29
+ )
30
+ }
31
+ );
32
+ var AdminIcon = () => {
33
+ const brand = useAdminBrand();
34
+ return /* @__PURE__ */ jsx("span", { className: "aurea-brand aurea-brand--icon", children: /* @__PURE__ */ jsx(
35
+ BrandLogo,
36
+ {
37
+ asset: brand.logo,
38
+ className: "aurea-brand__image",
39
+ height: 32,
40
+ maxWidth: 32,
41
+ siteName: brand.siteName
42
+ }
43
+ ) });
44
+ };
45
+ var AdminLogo = () => {
46
+ const brand = useAdminBrand();
47
+ return /* @__PURE__ */ jsx("span", { "aria-label": brand.siteName, className: "aurea-brand aurea-brand--logo", role: "img", children: /* @__PURE__ */ jsx(
48
+ BrandLogo,
49
+ {
50
+ asset: brand.logo,
51
+ className: "aurea-brand__image",
52
+ height: 42,
53
+ maxWidth: 190,
54
+ siteName: brand.siteName
55
+ }
56
+ ) });
57
+ };
58
+
59
+ export {
60
+ AdminIcon,
61
+ AdminLogo
62
+ };
@@ -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
+ };
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+
3
+ // src/admin/useAdminBrand.ts
4
+ import { useEffect, useState } from "react";
5
+ var defaultBrand = {
6
+ logo: { alt: "Wikex", height: 64, url: "/favicon.svg", width: 64 },
7
+ siteName: "Wikex"
8
+ };
9
+ var configureAdminBrand = (brand) => {
10
+ defaultBrand = brand;
11
+ };
12
+ var normalizeBrand = (settings) => {
13
+ const logo = settings?.logo;
14
+ const resolvedLogo = logo && typeof logo !== "number" && logo.url ? {
15
+ alt: logo.alt || settings?.siteName || defaultBrand.siteName,
16
+ height: logo.height || 64,
17
+ url: logo.updatedAt ? `${logo.url}?${encodeURIComponent(logo.updatedAt)}` : logo.url,
18
+ width: logo.width || 240
19
+ } : defaultBrand.logo;
20
+ return {
21
+ logo: resolvedLogo,
22
+ siteName: settings?.siteName?.trim() || defaultBrand.siteName
23
+ };
24
+ };
25
+ var useAdminBrand = () => {
26
+ const [brand, setBrand] = useState(() => normalizeBrand());
27
+ useEffect(() => {
28
+ const controller = new AbortController();
29
+ const loadBrand = async () => {
30
+ try {
31
+ const response = await fetch("/api/globals/settings?depth=1", {
32
+ cache: "no-store",
33
+ signal: controller.signal
34
+ });
35
+ if (!response.ok) return;
36
+ setBrand(normalizeBrand(await response.json()));
37
+ } catch (error) {
38
+ if (!(error instanceof DOMException && error.name === "AbortError")) {
39
+ console.error("Unable to load admin branding", error);
40
+ }
41
+ }
42
+ };
43
+ void loadBrand();
44
+ return () => controller.abort();
45
+ }, []);
46
+ return brand;
47
+ };
48
+
49
+ export {
50
+ configureAdminBrand,
51
+ useAdminBrand
52
+ };
@@ -0,0 +1,28 @@
1
+ import { Plugin } from 'payload';
2
+ export { V as VisualEditorRouteRegistry, W as WikexProjectDefinition, c as createVisualEditorRouteResolver, d as defineWikexProject } from './project-ClCmpyeX.js';
3
+ export { RichTextTypographyFeature } from './rich-text.js';
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';
5
+ import '@payloadcms/richtext-lexical';
6
+
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.";
8
+ declare const adminExperiencePlugin: Plugin;
9
+
10
+ type WikexAdminPluginOptions = {
11
+ components?: {
12
+ beforeDashboard?: false | string;
13
+ provider?: false | string;
14
+ };
15
+ enabled?: boolean;
16
+ };
17
+ /**
18
+ * Reusable Payload admin shell. This plugin deliberately owns only generic admin
19
+ * behavior; project collections, globals and blocks are assembled separately by
20
+ * the project module registry.
21
+ */
22
+ declare const wikexAdminPlugin: (options?: WikexAdminPluginOptions) => Plugin;
23
+
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 ADDED
@@ -0,0 +1,104 @@
1
+ import {
2
+ IMAGE_UPLOAD_GUIDANCE,
3
+ adminExperiencePlugin,
4
+ wikexAdminPlugin
5
+ } from "./chunk-7FEACJUN.js";
6
+ import {
7
+ createVisualEditorRouteResolver,
8
+ defineWikexProject
9
+ } from "./chunk-JJLHSZ3T.js";
10
+ import {
11
+ RichTextTypographyFeature
12
+ } from "./chunk-LC2CP5SR.js";
13
+ import {
14
+ EDITABLE_INTERACTIVE_SELECTOR,
15
+ EDITABLE_PREVIEW_SELECTOR,
16
+ TEXT_FONT_OPTIONS,
17
+ TEXT_LINE_HEIGHT_OPTIONS,
18
+ getEditableElementStyleKey,
19
+ getTextStyleCSS,
20
+ isSyntheticElementStyleKey,
21
+ normalizeTextStyleMap,
22
+ normalizeTextStyleValue
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
+ };
87
+ export {
88
+ EDITABLE_INTERACTIVE_SELECTOR,
89
+ EDITABLE_PREVIEW_SELECTOR,
90
+ IMAGE_UPLOAD_GUIDANCE,
91
+ RichTextTypographyFeature,
92
+ TEXT_FONT_OPTIONS,
93
+ TEXT_LINE_HEIGHT_OPTIONS,
94
+ TextStyleRuntime,
95
+ adminExperiencePlugin,
96
+ createVisualEditorRouteResolver,
97
+ defineWikexProject,
98
+ getEditableElementStyleKey,
99
+ getTextStyleCSS,
100
+ isSyntheticElementStyleKey,
101
+ normalizeTextStyleMap,
102
+ normalizeTextStyleValue,
103
+ wikexAdminPlugin
104
+ };
@@ -0,0 +1,118 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { V as VisualEditorDocumentTarget } from './runtimeConfig-BwjQepcW.js';
4
+ export { B as BlockPickerOption, a as BlockPickerScope, L as LivePreviewRuntimeConfig, b as VisualEditorRoute, c as VisualEditorScope, d as configureLivePreview } from './runtimeConfig-BwjQepcW.js';
5
+
6
+ declare const LivePreviewResizer: ({ children }: {
7
+ children?: React.ReactNode;
8
+ }) => react_jsx_runtime.JSX.Element;
9
+
10
+ type EditableGlobalScope = 'footer' | 'header' | 'settings';
11
+ type GlobalInspectorSelection = {
12
+ fieldPath: string;
13
+ href?: string;
14
+ scope: EditableGlobalScope;
15
+ supportsLink: boolean;
16
+ text: string;
17
+ };
18
+ type GlobalFieldUpdate = {
19
+ path: string;
20
+ value: unknown;
21
+ };
22
+ type InspectorValues = {
23
+ backgroundColor: string;
24
+ text: string;
25
+ textColor: string;
26
+ url: string;
27
+ };
28
+ declare const readGlobal: (scope: EditableGlobalScope, signal?: AbortSignal) => Promise<Record<string, unknown>>;
29
+ declare const updateGlobalFields: (scope: EditableGlobalScope, updates: GlobalFieldUpdate[]) => Promise<void>;
30
+ declare const GlobalInlineInspector: ({ onApply, selection, }: {
31
+ onApply: (values: InspectorValues) => void;
32
+ selection: GlobalInspectorSelection;
33
+ }) => react_jsx_runtime.JSX.Element;
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
+
104
+ type TextInspectorSelection = VisualEditorDocumentTarget & {
105
+ canEditText: boolean;
106
+ fieldPath: string;
107
+ multiline: boolean;
108
+ tagName: string;
109
+ text: string;
110
+ };
111
+ declare const saveTextStylePatch: (selection: TextInspectorSelection, patch: TextStyleValue, signal?: AbortSignal) => Promise<TextStyleValue>;
112
+ declare const TextStyleInspector: ({ onApply, onTextApply, selection, }: {
113
+ onApply: (values: TextStyleValue) => void;
114
+ onTextApply: (value: string) => void;
115
+ selection: TextInspectorSelection;
116
+ }) => react_jsx_runtime.JSX.Element;
117
+
118
+ export { type EditableGlobalScope, GlobalInlineInspector, type GlobalInspectorSelection, type InspectorValues, type TextInspectorSelection, TextStyleInspector, VisualEditorDocumentTarget, LivePreviewResizer as default, readGlobal, saveTextStylePatch, updateGlobalFields };
@@ -0,0 +1,20 @@
1
+ 'use client';
2
+ import {
3
+ GlobalInlineInspector,
4
+ LivePreviewEditor_default,
5
+ TextStyleInspector,
6
+ configureLivePreview,
7
+ readGlobal,
8
+ saveTextStylePatch,
9
+ updateGlobalFields
10
+ } from "./chunk-GMPR6LHH.js";
11
+ import "./chunk-VK4EFLWH.js";
12
+ export {
13
+ GlobalInlineInspector,
14
+ TextStyleInspector,
15
+ configureLivePreview,
16
+ LivePreviewEditor_default as default,
17
+ readGlobal,
18
+ saveTextStylePatch,
19
+ updateGlobalFields
20
+ };
@@ -0,0 +1,54 @@
1
+ type BlockPickerOption = {
2
+ description: string;
3
+ image?: string;
4
+ label: string;
5
+ payloadLabel?: string;
6
+ slug: string;
7
+ };
8
+ type VisualEditorDocumentTarget = {
9
+ collection: string;
10
+ documentID: string;
11
+ kind: 'collection';
12
+ } | {
13
+ global: string;
14
+ kind: 'global';
15
+ };
16
+ type VisualEditorScope = 'content' | 'footer' | 'header';
17
+ type VisualEditorRoute = {
18
+ documentTarget: VisualEditorDocumentTarget | null;
19
+ scope: VisualEditorScope;
20
+ type: 'collection' | 'global';
21
+ };
22
+
23
+ type WikexProjectDefinition<TModuleID extends string = string> = {
24
+ admin?: {
25
+ collectionOrder?: readonly string[];
26
+ globalOrder?: readonly string[];
27
+ };
28
+ brand: {
29
+ description: string;
30
+ logo: {
31
+ height: number;
32
+ url: string;
33
+ width: number;
34
+ };
35
+ name: string;
36
+ };
37
+ homepage?: {
38
+ defaultMode: 'builder' | 'preset';
39
+ };
40
+ id: string;
41
+ modules: readonly TModuleID[];
42
+ };
43
+ declare const defineWikexProject: <const TModuleID extends string, const TProject extends WikexProjectDefinition<TModuleID>>(project: TProject) => TProject;
44
+ type VisualEditorRouteRegistry = {
45
+ collections?: readonly string[];
46
+ globals?: Readonly<Record<string, VisualEditorScope>> | readonly string[];
47
+ };
48
+ /**
49
+ * Creates the route adapter consumed by Live Preview without coupling the admin
50
+ * kit to collection names from a specific website.
51
+ */
52
+ declare const createVisualEditorRouteResolver: (registry: VisualEditorRouteRegistry) => (pathname: string) => VisualEditorRoute | null;
53
+
54
+ export { type BlockPickerOption as B, type VisualEditorRouteRegistry as V, type WikexProjectDefinition as W, type VisualEditorRoute as a, createVisualEditorRouteResolver as c, defineWikexProject as d };