@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.
- package/CHANGELOG.md +4 -0
- package/dist/admin/before-login.d.ts +5 -0
- package/dist/admin/before-login.js +26 -0
- package/dist/admin/brand.d.ts +19 -0
- package/dist/admin/brand.js +15 -0
- package/dist/admin/header.d.ts +5 -0
- package/dist/admin/header.js +87 -0
- package/dist/admin/logout-button.d.ts +8 -0
- package/dist/admin/logout-button.js +7 -0
- package/dist/admin/nav.d.ts +19 -0
- package/dist/admin/nav.js +285 -0
- package/dist/admin/theme-toggle.d.ts +5 -0
- package/dist/admin/theme-toggle.js +7 -0
- package/dist/admin/view-site.d.ts +5 -0
- package/dist/admin/view-site.js +6 -0
- package/dist/chunk-7FEACJUN.js +151 -0
- package/dist/chunk-BUD6BMFV.js +117 -0
- package/dist/chunk-GGSOO4FQ.js +27 -0
- package/dist/chunk-IL2CUCDG.js +2062 -0
- package/dist/chunk-JJLHSZ3T.js +40 -0
- package/dist/chunk-LC2CP5SR.js +13 -0
- package/dist/chunk-LP22Y3NO.js +61 -0
- package/dist/chunk-MDMKKWPU.js +12 -0
- package/dist/chunk-W4ZKDOWJ.js +37 -0
- package/dist/chunk-XGKGKCQ6.js +50 -0
- package/dist/chunk-YMBJCWN3.js +73 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +44 -0
- package/dist/live-preview.d.ts +50 -0
- package/dist/live-preview.js +19 -0
- package/dist/project.d.ts +34 -0
- package/dist/project.js +8 -0
- package/dist/rich-text-client.d.ts +5 -0
- package/dist/rich-text-client.js +165 -0
- package/dist/rich-text.d.ts +5 -0
- package/dist/rich-text.js +6 -0
- package/dist/runtimeConfig-BwjQepcW.d.ts +30 -0
- package/dist/starter-client.d.ts +15 -0
- package/dist/starter-client.js +25 -0
- package/dist/starter.d.ts +40 -0
- package/dist/starter.js +62 -0
- package/dist/text-style-runtime.d.ts +5 -0
- package/dist/text-style-runtime.js +8 -0
- package/dist/text-styles.d.ts +86 -0
- package/dist/text-styles.js +22 -0
- package/package.json +23 -19
- package/src/TextStyleRuntime.tsx +0 -90
- package/src/admin/BeforeLogin.tsx +0 -19
- package/src/admin/Brand.tsx +0 -74
- package/src/admin/Header.tsx +0 -87
- package/src/admin/LogoutButton.tsx +0 -41
- package/src/admin/Nav.tsx +0 -35
- package/src/admin/NavClient.tsx +0 -288
- package/src/admin/ThemeToggle.tsx +0 -31
- package/src/admin/ViewSite.tsx +0 -11
- package/src/admin/useAdminBrand.ts +0 -81
- package/src/adminExperience.ts +0 -117
- package/src/index.ts +0 -11
- package/src/live-preview/GlobalInlineInspector.tsx +0 -334
- package/src/live-preview/LivePreviewEditor.tsx +0 -2088
- package/src/live-preview/TextStyleInspector.tsx +0 -289
- package/src/live-preview/index.ts +0 -23
- package/src/live-preview/runtimeConfig.ts +0 -52
- package/src/plugin.ts +0 -70
- package/src/project.ts +0 -82
- package/src/rich-text/client.tsx +0 -202
- package/src/rich-text/index.ts +0 -10
- package/src/starter/client.tsx +0 -22
- package/src/starter.ts +0 -95
- package/src/textStyles.ts +0 -161
|
@@ -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,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useAdminBrand
|
|
3
|
+
} from "./chunk-XGKGKCQ6.js";
|
|
4
|
+
|
|
5
|
+
// src/admin/Brand.tsx
|
|
6
|
+
import Image from "next/image";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var BrandLogo = ({
|
|
9
|
+
asset,
|
|
10
|
+
className,
|
|
11
|
+
height,
|
|
12
|
+
maxWidth
|
|
13
|
+
}) => /* @__PURE__ */ jsx(
|
|
14
|
+
"span",
|
|
15
|
+
{
|
|
16
|
+
className: ["brand-logo", className].filter(Boolean).join(" "),
|
|
17
|
+
style: { alignItems: "center", display: "inline-flex", height, maxWidth },
|
|
18
|
+
children: /* @__PURE__ */ jsx(
|
|
19
|
+
Image,
|
|
20
|
+
{
|
|
21
|
+
alt: "",
|
|
22
|
+
height: asset.height,
|
|
23
|
+
src: asset.url,
|
|
24
|
+
style: { height: "100%", maxWidth: "100%", objectFit: "contain", width: "auto" },
|
|
25
|
+
unoptimized: true,
|
|
26
|
+
width: asset.width
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
var AdminIcon = () => {
|
|
32
|
+
const brand = useAdminBrand();
|
|
33
|
+
return /* @__PURE__ */ jsx("span", { className: "aurea-brand aurea-brand--icon", children: /* @__PURE__ */ jsx(
|
|
34
|
+
BrandLogo,
|
|
35
|
+
{
|
|
36
|
+
asset: brand.logo,
|
|
37
|
+
className: "aurea-brand__image",
|
|
38
|
+
height: 32,
|
|
39
|
+
maxWidth: 32,
|
|
40
|
+
siteName: brand.siteName
|
|
41
|
+
}
|
|
42
|
+
) });
|
|
43
|
+
};
|
|
44
|
+
var AdminLogo = () => {
|
|
45
|
+
const brand = useAdminBrand();
|
|
46
|
+
return /* @__PURE__ */ jsx("span", { "aria-label": brand.siteName, className: "aurea-brand aurea-brand--logo", role: "img", children: /* @__PURE__ */ jsx(
|
|
47
|
+
BrandLogo,
|
|
48
|
+
{
|
|
49
|
+
asset: brand.logo,
|
|
50
|
+
className: "aurea-brand__image",
|
|
51
|
+
height: 42,
|
|
52
|
+
maxWidth: 190,
|
|
53
|
+
siteName: brand.siteName
|
|
54
|
+
}
|
|
55
|
+
) });
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
AdminIcon,
|
|
60
|
+
AdminLogo
|
|
61
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
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;
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
ViewSite_default
|
|
12
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// src/admin/LogoutButton.tsx
|
|
2
|
+
import { Link, useConfig, useTranslation } from "@payloadcms/ui";
|
|
3
|
+
import { LogOut } from "lucide-react";
|
|
4
|
+
import { formatAdminURL } from "payload/shared";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
var AdminLogoutButton = ({ tabIndex = 0 }) => {
|
|
7
|
+
const {
|
|
8
|
+
config: {
|
|
9
|
+
admin: {
|
|
10
|
+
routes: { logout: logoutRoute }
|
|
11
|
+
},
|
|
12
|
+
routes: { admin: adminRoute }
|
|
13
|
+
}
|
|
14
|
+
} = useConfig();
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const label = t("authentication:logOut");
|
|
17
|
+
return /* @__PURE__ */ jsxs(
|
|
18
|
+
Link,
|
|
19
|
+
{
|
|
20
|
+
"aria-label": label,
|
|
21
|
+
className: "admin-sign-out",
|
|
22
|
+
href: formatAdminURL({ adminRoute, path: logoutRoute }),
|
|
23
|
+
prefetch: false,
|
|
24
|
+
tabIndex,
|
|
25
|
+
title: label,
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "admin-sign-out__icon", children: /* @__PURE__ */ jsx(LogOut, { strokeWidth: 2 }) }),
|
|
28
|
+
/* @__PURE__ */ jsx("span", { className: "admin-sign-out__label", children: label })
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
var LogoutButton_default = AdminLogoutButton;
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
LogoutButton_default
|
|
37
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/admin/useAdminBrand.ts
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
var defaultBrand = {
|
|
4
|
+
logo: { alt: "Wikex", height: 64, url: "/favicon.svg", width: 64 },
|
|
5
|
+
siteName: "Wikex"
|
|
6
|
+
};
|
|
7
|
+
var configureAdminBrand = (brand) => {
|
|
8
|
+
defaultBrand = brand;
|
|
9
|
+
};
|
|
10
|
+
var normalizeBrand = (settings) => {
|
|
11
|
+
const logo = settings?.logo;
|
|
12
|
+
const resolvedLogo = logo && typeof logo !== "number" && logo.url ? {
|
|
13
|
+
alt: logo.alt || settings?.siteName || defaultBrand.siteName,
|
|
14
|
+
height: logo.height || 64,
|
|
15
|
+
url: logo.updatedAt ? `${logo.url}?${encodeURIComponent(logo.updatedAt)}` : logo.url,
|
|
16
|
+
width: logo.width || 240
|
|
17
|
+
} : defaultBrand.logo;
|
|
18
|
+
return {
|
|
19
|
+
logo: resolvedLogo,
|
|
20
|
+
siteName: settings?.siteName?.trim() || defaultBrand.siteName
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
var useAdminBrand = () => {
|
|
24
|
+
const [brand, setBrand] = useState(() => normalizeBrand());
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const controller = new AbortController();
|
|
27
|
+
const loadBrand = async () => {
|
|
28
|
+
try {
|
|
29
|
+
const response = await fetch("/api/globals/settings?depth=1", {
|
|
30
|
+
cache: "no-store",
|
|
31
|
+
signal: controller.signal
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) return;
|
|
34
|
+
setBrand(normalizeBrand(await response.json()));
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (!(error instanceof DOMException && error.name === "AbortError")) {
|
|
37
|
+
console.error("Unable to load admin branding", error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
void loadBrand();
|
|
42
|
+
return () => controller.abort();
|
|
43
|
+
}, []);
|
|
44
|
+
return brand;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
configureAdminBrand,
|
|
49
|
+
useAdminBrand
|
|
50
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EDITABLE_PREVIEW_SELECTOR,
|
|
3
|
+
getEditableElementStyleKey,
|
|
4
|
+
getTextStyleCSS,
|
|
5
|
+
normalizeTextStyleMap
|
|
6
|
+
} from "./chunk-BUD6BMFV.js";
|
|
7
|
+
|
|
8
|
+
// src/TextStyleRuntime.tsx
|
|
9
|
+
import { useEffect } from "react";
|
|
10
|
+
var TextStyleRuntime = ({ styles }) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const normalizedStyles = normalizeTextStyleMap(styles);
|
|
13
|
+
const originals = /* @__PURE__ */ new Map();
|
|
14
|
+
let applyFrame = 0;
|
|
15
|
+
const applyStyles = () => {
|
|
16
|
+
const fields = new Set(
|
|
17
|
+
document.querySelectorAll(`[data-wikex-field],${EDITABLE_PREVIEW_SELECTOR}`)
|
|
18
|
+
);
|
|
19
|
+
for (const element of fields) {
|
|
20
|
+
const fieldPath = element.dataset.wikexField || getEditableElementStyleKey(element);
|
|
21
|
+
if (!fieldPath || !normalizedStyles[fieldPath]) continue;
|
|
22
|
+
if (!originals.has(element)) {
|
|
23
|
+
originals.set(element, {
|
|
24
|
+
boxSizing: element.style.boxSizing,
|
|
25
|
+
fontFamily: element.style.fontFamily,
|
|
26
|
+
lineHeight: element.style.lineHeight,
|
|
27
|
+
marginLeft: element.style.marginLeft,
|
|
28
|
+
marginRight: element.style.marginRight,
|
|
29
|
+
maxWidth: element.style.maxWidth,
|
|
30
|
+
width: element.style.width
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const style = getTextStyleCSS(normalizedStyles[fieldPath]);
|
|
34
|
+
element.style.boxSizing = style.boxSizing || "";
|
|
35
|
+
element.style.fontFamily = style.fontFamily || "";
|
|
36
|
+
element.style.lineHeight = style.lineHeight || "";
|
|
37
|
+
element.style.marginLeft = style.marginLeft || "";
|
|
38
|
+
element.style.marginRight = style.marginRight || "";
|
|
39
|
+
element.style.maxWidth = style.maxWidth || "";
|
|
40
|
+
element.style.width = style.width || "";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const scheduleApplyStyles = () => {
|
|
44
|
+
if (applyFrame) return;
|
|
45
|
+
applyFrame = window.requestAnimationFrame(() => {
|
|
46
|
+
applyFrame = 0;
|
|
47
|
+
applyStyles();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
applyStyles();
|
|
51
|
+
const observer = new MutationObserver(scheduleApplyStyles);
|
|
52
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
53
|
+
return () => {
|
|
54
|
+
observer.disconnect();
|
|
55
|
+
window.cancelAnimationFrame(applyFrame);
|
|
56
|
+
for (const [element, original] of originals) {
|
|
57
|
+
if (!element.isConnected) continue;
|
|
58
|
+
element.style.boxSizing = original.boxSizing;
|
|
59
|
+
element.style.fontFamily = original.fontFamily;
|
|
60
|
+
element.style.lineHeight = original.lineHeight;
|
|
61
|
+
element.style.marginLeft = original.marginLeft;
|
|
62
|
+
element.style.marginRight = original.marginRight;
|
|
63
|
+
element.style.maxWidth = original.maxWidth;
|
|
64
|
+
element.style.width = original.width;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}, [styles]);
|
|
68
|
+
return null;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export {
|
|
72
|
+
TextStyleRuntime
|
|
73
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Plugin } from 'payload';
|
|
2
|
+
export { VisualEditorRouteRegistry, WikexProjectDefinition, createVisualEditorRouteResolver, defineWikexProject } from './project.js';
|
|
3
|
+
export { RichTextTypographyFeature } from './rich-text.js';
|
|
4
|
+
export { TextStyleRuntime } from './text-style-runtime.js';
|
|
5
|
+
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
|
+
import '@payloadcms/richtext-lexical';
|
|
8
|
+
|
|
9
|
+
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.";
|
|
10
|
+
declare const adminExperiencePlugin: Plugin;
|
|
11
|
+
|
|
12
|
+
type WikexAdminPluginOptions = {
|
|
13
|
+
components?: {
|
|
14
|
+
beforeDashboard?: false | string;
|
|
15
|
+
provider?: false | string;
|
|
16
|
+
};
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Reusable Payload admin shell. This plugin deliberately owns only generic admin
|
|
21
|
+
* behavior; project collections, globals and blocks are assembled separately by
|
|
22
|
+
* the project module registry.
|
|
23
|
+
*/
|
|
24
|
+
declare const wikexAdminPlugin: (options?: WikexAdminPluginOptions) => Plugin;
|
|
25
|
+
|
|
26
|
+
export { IMAGE_UPLOAD_GUIDANCE, type WikexAdminPluginOptions, adminExperiencePlugin, wikexAdminPlugin };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RichTextTypographyFeature
|
|
3
|
+
} from "./chunk-LC2CP5SR.js";
|
|
4
|
+
import {
|
|
5
|
+
TextStyleRuntime
|
|
6
|
+
} from "./chunk-YMBJCWN3.js";
|
|
7
|
+
import {
|
|
8
|
+
IMAGE_UPLOAD_GUIDANCE,
|
|
9
|
+
adminExperiencePlugin,
|
|
10
|
+
wikexAdminPlugin
|
|
11
|
+
} from "./chunk-7FEACJUN.js";
|
|
12
|
+
import {
|
|
13
|
+
createVisualEditorRouteResolver,
|
|
14
|
+
defineWikexProject
|
|
15
|
+
} from "./chunk-JJLHSZ3T.js";
|
|
16
|
+
import {
|
|
17
|
+
EDITABLE_INTERACTIVE_SELECTOR,
|
|
18
|
+
EDITABLE_PREVIEW_SELECTOR,
|
|
19
|
+
TEXT_FONT_OPTIONS,
|
|
20
|
+
TEXT_LINE_HEIGHT_OPTIONS,
|
|
21
|
+
getEditableElementStyleKey,
|
|
22
|
+
getTextStyleCSS,
|
|
23
|
+
isSyntheticElementStyleKey,
|
|
24
|
+
normalizeTextStyleMap,
|
|
25
|
+
normalizeTextStyleValue
|
|
26
|
+
} from "./chunk-BUD6BMFV.js";
|
|
27
|
+
export {
|
|
28
|
+
EDITABLE_INTERACTIVE_SELECTOR,
|
|
29
|
+
EDITABLE_PREVIEW_SELECTOR,
|
|
30
|
+
IMAGE_UPLOAD_GUIDANCE,
|
|
31
|
+
RichTextTypographyFeature,
|
|
32
|
+
TEXT_FONT_OPTIONS,
|
|
33
|
+
TEXT_LINE_HEIGHT_OPTIONS,
|
|
34
|
+
TextStyleRuntime,
|
|
35
|
+
adminExperiencePlugin,
|
|
36
|
+
createVisualEditorRouteResolver,
|
|
37
|
+
defineWikexProject,
|
|
38
|
+
getEditableElementStyleKey,
|
|
39
|
+
getTextStyleCSS,
|
|
40
|
+
isSyntheticElementStyleKey,
|
|
41
|
+
normalizeTextStyleMap,
|
|
42
|
+
normalizeTextStyleValue,
|
|
43
|
+
wikexAdminPlugin
|
|
44
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TextStyleValue } from './text-styles.js';
|
|
4
|
+
import { V as VisualEditorDocumentTarget } from './runtimeConfig-BwjQepcW.js';
|
|
5
|
+
export { B as BlockPickerOption, a as BlockPickerScope, L as LivePreviewRuntimeConfig, b as VisualEditorRoute, c as VisualEditorScope, d as configureLivePreview } from './runtimeConfig-BwjQepcW.js';
|
|
6
|
+
|
|
7
|
+
declare const LivePreviewResizer: ({ children }: {
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
type EditableGlobalScope = 'footer' | 'header' | 'settings';
|
|
12
|
+
type GlobalInspectorSelection = {
|
|
13
|
+
fieldPath: string;
|
|
14
|
+
href?: string;
|
|
15
|
+
scope: EditableGlobalScope;
|
|
16
|
+
supportsLink: boolean;
|
|
17
|
+
text: string;
|
|
18
|
+
};
|
|
19
|
+
type GlobalFieldUpdate = {
|
|
20
|
+
path: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
};
|
|
23
|
+
type InspectorValues = {
|
|
24
|
+
backgroundColor: string;
|
|
25
|
+
text: string;
|
|
26
|
+
textColor: string;
|
|
27
|
+
url: string;
|
|
28
|
+
};
|
|
29
|
+
declare const readGlobal: (scope: EditableGlobalScope, signal?: AbortSignal) => Promise<Record<string, unknown>>;
|
|
30
|
+
declare const updateGlobalFields: (scope: EditableGlobalScope, updates: GlobalFieldUpdate[]) => Promise<void>;
|
|
31
|
+
declare const GlobalInlineInspector: ({ onApply, selection, }: {
|
|
32
|
+
onApply: (values: InspectorValues) => void;
|
|
33
|
+
selection: GlobalInspectorSelection;
|
|
34
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
35
|
+
|
|
36
|
+
type TextInspectorSelection = VisualEditorDocumentTarget & {
|
|
37
|
+
canEditText: boolean;
|
|
38
|
+
fieldPath: string;
|
|
39
|
+
multiline: boolean;
|
|
40
|
+
tagName: string;
|
|
41
|
+
text: string;
|
|
42
|
+
};
|
|
43
|
+
declare const saveTextStylePatch: (selection: TextInspectorSelection, patch: TextStyleValue, signal?: AbortSignal) => Promise<TextStyleValue>;
|
|
44
|
+
declare const TextStyleInspector: ({ onApply, onTextApply, selection, }: {
|
|
45
|
+
onApply: (values: TextStyleValue) => void;
|
|
46
|
+
onTextApply: (value: string) => void;
|
|
47
|
+
selection: TextInspectorSelection;
|
|
48
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
export { type EditableGlobalScope, GlobalInlineInspector, type GlobalInspectorSelection, type InspectorValues, type TextInspectorSelection, TextStyleInspector, VisualEditorDocumentTarget, LivePreviewResizer as default, readGlobal, saveTextStylePatch, updateGlobalFields };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GlobalInlineInspector,
|
|
3
|
+
LivePreviewEditor_default,
|
|
4
|
+
TextStyleInspector,
|
|
5
|
+
configureLivePreview,
|
|
6
|
+
readGlobal,
|
|
7
|
+
saveTextStylePatch,
|
|
8
|
+
updateGlobalFields
|
|
9
|
+
} from "./chunk-IL2CUCDG.js";
|
|
10
|
+
import "./chunk-BUD6BMFV.js";
|
|
11
|
+
export {
|
|
12
|
+
GlobalInlineInspector,
|
|
13
|
+
TextStyleInspector,
|
|
14
|
+
configureLivePreview,
|
|
15
|
+
LivePreviewEditor_default as default,
|
|
16
|
+
readGlobal,
|
|
17
|
+
saveTextStylePatch,
|
|
18
|
+
updateGlobalFields
|
|
19
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { c as VisualEditorScope, b as VisualEditorRoute } from './runtimeConfig-BwjQepcW.js';
|
|
2
|
+
|
|
3
|
+
type WikexProjectDefinition<TModuleID extends string = string> = {
|
|
4
|
+
admin?: {
|
|
5
|
+
collectionOrder?: readonly string[];
|
|
6
|
+
globalOrder?: readonly string[];
|
|
7
|
+
};
|
|
8
|
+
brand: {
|
|
9
|
+
description: string;
|
|
10
|
+
logo: {
|
|
11
|
+
height: number;
|
|
12
|
+
url: string;
|
|
13
|
+
width: number;
|
|
14
|
+
};
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
homepage?: {
|
|
18
|
+
defaultMode: 'builder' | 'preset';
|
|
19
|
+
};
|
|
20
|
+
id: string;
|
|
21
|
+
modules: readonly TModuleID[];
|
|
22
|
+
};
|
|
23
|
+
declare const defineWikexProject: <const TModuleID extends string, const TProject extends WikexProjectDefinition<TModuleID>>(project: TProject) => TProject;
|
|
24
|
+
type VisualEditorRouteRegistry = {
|
|
25
|
+
collections?: readonly string[];
|
|
26
|
+
globals?: Readonly<Record<string, VisualEditorScope>> | readonly string[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Creates the route adapter consumed by Live Preview without coupling the admin
|
|
30
|
+
* kit to collection names from a specific website.
|
|
31
|
+
*/
|
|
32
|
+
declare const createVisualEditorRouteResolver: (registry: VisualEditorRouteRegistry) => (pathname: string) => VisualEditorRoute | null;
|
|
33
|
+
|
|
34
|
+
export { type VisualEditorRouteRegistry, type WikexProjectDefinition, createVisualEditorRouteResolver, defineWikexProject };
|
package/dist/project.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
TEXT_FONT_OPTIONS,
|
|
4
|
+
TEXT_LINE_HEIGHT_OPTIONS,
|
|
5
|
+
getTextStyleCSS,
|
|
6
|
+
normalizeTextStyleValue
|
|
7
|
+
} from "./chunk-BUD6BMFV.js";
|
|
8
|
+
|
|
9
|
+
// src/rich-text/client.tsx
|
|
10
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
11
|
+
import { $forEachSelectedTextNode } from "@lexical/selection";
|
|
12
|
+
import { createClientFeature } from "@payloadcms/richtext-lexical/client";
|
|
13
|
+
import {
|
|
14
|
+
$getNodeByKey,
|
|
15
|
+
$getSelection,
|
|
16
|
+
$getState,
|
|
17
|
+
$isRangeSelection,
|
|
18
|
+
$isTextNode,
|
|
19
|
+
$setSelection,
|
|
20
|
+
$setState,
|
|
21
|
+
createState,
|
|
22
|
+
TextNode
|
|
23
|
+
} from "lexical";
|
|
24
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
25
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
26
|
+
var fontFamilyState = createState("fontFamily", {
|
|
27
|
+
parse: (value) => normalizeTextStyleValue({ fontFamily: value }).fontFamily
|
|
28
|
+
});
|
|
29
|
+
var lineHeightState = createState("lineHeight", {
|
|
30
|
+
parse: (value) => normalizeTextStyleValue({ lineHeight: value }).lineHeight
|
|
31
|
+
});
|
|
32
|
+
var DEFAULT_TYPOGRAPHY = {
|
|
33
|
+
fontFamily: "default",
|
|
34
|
+
lineHeight: "default"
|
|
35
|
+
};
|
|
36
|
+
var readSelectedTypography = (editor) => editor.getEditorState().read(() => {
|
|
37
|
+
const selection = $getSelection();
|
|
38
|
+
if (!$isRangeSelection(selection)) return DEFAULT_TYPOGRAPHY;
|
|
39
|
+
const textNode = selection.getNodes().find($isTextNode);
|
|
40
|
+
if (!textNode) return DEFAULT_TYPOGRAPHY;
|
|
41
|
+
return {
|
|
42
|
+
fontFamily: $getState(textNode, fontFamilyState) ?? "default",
|
|
43
|
+
lineHeight: $getState(textNode, lineHeightState) ?? "default"
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
var updateSelectedTypography = (editor, property, value, savedSelection) => {
|
|
47
|
+
editor.update(() => {
|
|
48
|
+
if (!$isRangeSelection($getSelection()) && savedSelection) {
|
|
49
|
+
$setSelection(savedSelection.clone());
|
|
50
|
+
}
|
|
51
|
+
$forEachSelectedTextNode((textNode) => {
|
|
52
|
+
if (property === "fontFamily") {
|
|
53
|
+
const fontFamily = value;
|
|
54
|
+
$setState(textNode, fontFamilyState, fontFamily === "default" ? void 0 : fontFamily);
|
|
55
|
+
} else {
|
|
56
|
+
const lineHeight = value;
|
|
57
|
+
$setState(textNode, lineHeightState, lineHeight === "default" ? void 0 : lineHeight);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
var TypographyToolbarItem = ({ editor }) => {
|
|
63
|
+
const [value, setValue] = useState(DEFAULT_TYPOGRAPHY);
|
|
64
|
+
const savedSelection = useRef(null);
|
|
65
|
+
const captureSelection = useCallback(() => {
|
|
66
|
+
editor.getEditorState().read(() => {
|
|
67
|
+
const selection = $getSelection();
|
|
68
|
+
if ($isRangeSelection(selection)) savedSelection.current = selection.clone();
|
|
69
|
+
});
|
|
70
|
+
}, [editor]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const syncValue = () => {
|
|
73
|
+
captureSelection();
|
|
74
|
+
setValue(readSelectedTypography(editor));
|
|
75
|
+
};
|
|
76
|
+
syncValue();
|
|
77
|
+
return editor.registerUpdateListener(syncValue);
|
|
78
|
+
}, [captureSelection, editor]);
|
|
79
|
+
return /* @__PURE__ */ jsxs(
|
|
80
|
+
"div",
|
|
81
|
+
{
|
|
82
|
+
"aria-label": "Ki\u1EC3u ch\u1EEF",
|
|
83
|
+
className: "wikex-typography-selects",
|
|
84
|
+
onMouseDown: (event) => {
|
|
85
|
+
event.stopPropagation();
|
|
86
|
+
captureSelection();
|
|
87
|
+
},
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsx(
|
|
90
|
+
"select",
|
|
91
|
+
{
|
|
92
|
+
"aria-label": "Ph\xF4ng ch\u1EEF",
|
|
93
|
+
className: "wikex-minimal-select wikex-minimal-select--font",
|
|
94
|
+
onChange: (event) => {
|
|
95
|
+
const fontFamily = event.target.value;
|
|
96
|
+
setValue((current) => ({ ...current, fontFamily }));
|
|
97
|
+
updateSelectedTypography(editor, "fontFamily", fontFamily, savedSelection.current);
|
|
98
|
+
},
|
|
99
|
+
title: "Ph\xF4ng ch\u1EEF",
|
|
100
|
+
value: value.fontFamily,
|
|
101
|
+
children: TEXT_FONT_OPTIONS.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
/* @__PURE__ */ jsx(
|
|
105
|
+
"select",
|
|
106
|
+
{
|
|
107
|
+
"aria-label": "Chi\u1EC1u cao d\xF2ng",
|
|
108
|
+
className: "wikex-minimal-select wikex-minimal-select--line-height",
|
|
109
|
+
onChange: (event) => {
|
|
110
|
+
const lineHeight = event.target.value;
|
|
111
|
+
setValue((current) => ({ ...current, lineHeight }));
|
|
112
|
+
updateSelectedTypography(editor, "lineHeight", lineHeight, savedSelection.current);
|
|
113
|
+
},
|
|
114
|
+
title: "Chi\u1EC1u cao d\xF2ng",
|
|
115
|
+
value: value.lineHeight,
|
|
116
|
+
children: TEXT_LINE_HEIGHT_OPTIONS.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
var TypographyStatePlugin = () => {
|
|
124
|
+
const [editor] = useLexicalComposerContext();
|
|
125
|
+
useEffect(
|
|
126
|
+
() => editor.registerMutationListener(TextNode, (mutatedNodes) => {
|
|
127
|
+
editor.getEditorState().read(() => {
|
|
128
|
+
for (const [nodeKey, mutation] of mutatedNodes) {
|
|
129
|
+
if (mutation === "destroyed") continue;
|
|
130
|
+
const node = $getNodeByKey(nodeKey);
|
|
131
|
+
const element = editor.getElementByKey(nodeKey);
|
|
132
|
+
if (!$isTextNode(node) || !element) continue;
|
|
133
|
+
const style = getTextStyleCSS({
|
|
134
|
+
fontFamily: $getState(node, fontFamilyState),
|
|
135
|
+
lineHeight: $getState(node, lineHeightState)
|
|
136
|
+
});
|
|
137
|
+
if (style.fontFamily) element.style.fontFamily = style.fontFamily;
|
|
138
|
+
else element.style.removeProperty("font-family");
|
|
139
|
+
if (style.lineHeight) element.style.lineHeight = style.lineHeight;
|
|
140
|
+
else element.style.removeProperty("line-height");
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}),
|
|
144
|
+
[editor]
|
|
145
|
+
);
|
|
146
|
+
return null;
|
|
147
|
+
};
|
|
148
|
+
var toolbarItem = {
|
|
149
|
+
Component: TypographyToolbarItem,
|
|
150
|
+
key: "wikex-typography-controls"
|
|
151
|
+
};
|
|
152
|
+
var typographyToolbarGroup = {
|
|
153
|
+
items: [toolbarItem],
|
|
154
|
+
key: "wikexTypography",
|
|
155
|
+
order: 34,
|
|
156
|
+
type: "buttons"
|
|
157
|
+
};
|
|
158
|
+
var RichTextTypographyFeatureClient = createClientFeature({
|
|
159
|
+
plugins: [{ Component: TypographyStatePlugin, position: "normal" }],
|
|
160
|
+
toolbarFixed: { groups: [typographyToolbarGroup] },
|
|
161
|
+
toolbarInline: { groups: [typographyToolbarGroup] }
|
|
162
|
+
});
|
|
163
|
+
export {
|
|
164
|
+
RichTextTypographyFeatureClient
|
|
165
|
+
};
|