@wikex/admin-kit 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/admin/before-login.d.ts +5 -0
  3. package/dist/admin/before-login.js +26 -0
  4. package/dist/admin/brand.d.ts +19 -0
  5. package/dist/admin/brand.js +15 -0
  6. package/dist/admin/header.d.ts +5 -0
  7. package/dist/admin/header.js +87 -0
  8. package/dist/admin/logout-button.d.ts +8 -0
  9. package/dist/admin/logout-button.js +7 -0
  10. package/dist/admin/nav.d.ts +19 -0
  11. package/dist/admin/nav.js +285 -0
  12. package/dist/admin/theme-toggle.d.ts +5 -0
  13. package/dist/admin/theme-toggle.js +7 -0
  14. package/dist/admin/view-site.d.ts +5 -0
  15. package/dist/admin/view-site.js +6 -0
  16. package/dist/chunk-7FEACJUN.js +151 -0
  17. package/dist/chunk-BUD6BMFV.js +117 -0
  18. package/dist/chunk-GGSOO4FQ.js +27 -0
  19. package/dist/chunk-IL2CUCDG.js +2062 -0
  20. package/dist/chunk-JJLHSZ3T.js +40 -0
  21. package/dist/chunk-LC2CP5SR.js +13 -0
  22. package/dist/chunk-LP22Y3NO.js +61 -0
  23. package/dist/chunk-MDMKKWPU.js +12 -0
  24. package/dist/chunk-W4ZKDOWJ.js +37 -0
  25. package/dist/chunk-XGKGKCQ6.js +50 -0
  26. package/dist/chunk-YMBJCWN3.js +73 -0
  27. package/dist/index.d.ts +26 -0
  28. package/dist/index.js +44 -0
  29. package/dist/live-preview.d.ts +50 -0
  30. package/dist/live-preview.js +19 -0
  31. package/dist/project.d.ts +34 -0
  32. package/dist/project.js +8 -0
  33. package/dist/rich-text-client.d.ts +5 -0
  34. package/dist/rich-text-client.js +165 -0
  35. package/dist/rich-text.d.ts +5 -0
  36. package/dist/rich-text.js +6 -0
  37. package/dist/runtimeConfig-BwjQepcW.d.ts +30 -0
  38. package/dist/starter-client.d.ts +15 -0
  39. package/dist/starter-client.js +25 -0
  40. package/dist/starter.d.ts +40 -0
  41. package/dist/starter.js +62 -0
  42. package/dist/text-style-runtime.d.ts +5 -0
  43. package/dist/text-style-runtime.js +8 -0
  44. package/dist/text-styles.d.ts +86 -0
  45. package/dist/text-styles.js +22 -0
  46. package/package.json +23 -19
  47. package/src/TextStyleRuntime.tsx +0 -90
  48. package/src/admin/BeforeLogin.tsx +0 -19
  49. package/src/admin/Brand.tsx +0 -74
  50. package/src/admin/Header.tsx +0 -87
  51. package/src/admin/LogoutButton.tsx +0 -41
  52. package/src/admin/Nav.tsx +0 -35
  53. package/src/admin/NavClient.tsx +0 -288
  54. package/src/admin/ThemeToggle.tsx +0 -31
  55. package/src/admin/ViewSite.tsx +0 -11
  56. package/src/admin/useAdminBrand.ts +0 -81
  57. package/src/adminExperience.ts +0 -117
  58. package/src/index.ts +0 -11
  59. package/src/live-preview/GlobalInlineInspector.tsx +0 -334
  60. package/src/live-preview/LivePreviewEditor.tsx +0 -2088
  61. package/src/live-preview/TextStyleInspector.tsx +0 -289
  62. package/src/live-preview/index.ts +0 -23
  63. package/src/live-preview/runtimeConfig.ts +0 -52
  64. package/src/plugin.ts +0 -70
  65. package/src/project.ts +0 -82
  66. package/src/rich-text/client.tsx +0 -202
  67. package/src/rich-text/index.ts +0 -10
  68. package/src/starter/client.tsx +0 -22
  69. package/src/starter.ts +0 -95
  70. package/src/textStyles.ts +0 -161
@@ -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
+ };
@@ -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 };
@@ -0,0 +1,8 @@
1
+ import {
2
+ createVisualEditorRouteResolver,
3
+ defineWikexProject
4
+ } from "./chunk-JJLHSZ3T.js";
5
+ export {
6
+ createVisualEditorRouteResolver,
7
+ defineWikexProject
8
+ };
@@ -0,0 +1,5 @@
1
+ import * as _payloadcms_richtext_lexical from '@payloadcms/richtext-lexical';
2
+
3
+ declare const RichTextTypographyFeatureClient: _payloadcms_richtext_lexical.FeatureProviderProviderClient<undefined, undefined>;
4
+
5
+ export { RichTextTypographyFeatureClient };
@@ -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
+ };
@@ -0,0 +1,5 @@
1
+ import * as _payloadcms_richtext_lexical from '@payloadcms/richtext-lexical';
2
+
3
+ declare const RichTextTypographyFeature: () => _payloadcms_richtext_lexical.FeatureProviderServer<undefined, undefined, undefined>;
4
+
5
+ export { RichTextTypographyFeature };
@@ -0,0 +1,6 @@
1
+ import {
2
+ RichTextTypographyFeature
3
+ } from "./chunk-LC2CP5SR.js";
4
+ export {
5
+ RichTextTypographyFeature
6
+ };