@payload-onpage/react 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +13 -2
- package/dist/OnPageClient.d.ts +18 -0
- package/dist/OnPageClient.d.ts.map +1 -0
- package/dist/OnPageClient.js +51 -0
- package/dist/OnPageClient.js.map +1 -0
- package/dist/annotations.d.ts +55 -0
- package/dist/annotations.d.ts.map +1 -0
- package/dist/annotations.js +60 -0
- package/dist/annotations.js.map +1 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +19 -0
- package/dist/context.js.map +1 -0
- package/dist/dom.d.ts +42 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +95 -0
- package/dist/dom.js.map +1 -0
- package/dist/editor/FieldHost.d.ts +5 -0
- package/dist/editor/FieldHost.d.ts.map +1 -0
- package/dist/editor/FieldHost.js +36 -0
- package/dist/editor/FieldHost.js.map +1 -0
- package/dist/editor/Ghosts.d.ts +6 -0
- package/dist/editor/Ghosts.d.ts.map +1 -0
- package/dist/editor/Ghosts.js +37 -0
- package/dist/editor/Ghosts.js.map +1 -0
- package/dist/editor/OnPageEditor.d.ts +25 -0
- package/dist/editor/OnPageEditor.d.ts.map +1 -0
- package/dist/editor/OnPageEditor.js +211 -0
- package/dist/editor/OnPageEditor.js.map +1 -0
- package/dist/editor/useGhosts.d.ts +24 -0
- package/dist/editor/useGhosts.d.ts.map +1 -0
- package/dist/editor/useGhosts.js +34 -0
- package/dist/editor/useGhosts.js.map +1 -0
- package/dist/editor/usePageEvents.d.ts +3 -0
- package/dist/editor/usePageEvents.d.ts.map +1 -0
- package/dist/editor/usePageEvents.js +164 -0
- package/dist/editor/usePageEvents.js.map +1 -0
- package/dist/editor-kit.d.ts +19 -0
- package/dist/editor-kit.d.ts.map +1 -0
- package/dist/editor-kit.js +17 -0
- package/dist/editor-kit.js.map +1 -0
- package/dist/editors/CheckboxEditor.d.ts +3 -0
- package/dist/editors/CheckboxEditor.d.ts.map +1 -0
- package/dist/editors/CheckboxEditor.js +10 -0
- package/dist/editors/CheckboxEditor.js.map +1 -0
- package/dist/editors/ColorEditor.d.ts +4 -0
- package/dist/editors/ColorEditor.d.ts.map +1 -0
- package/dist/editors/ColorEditor.js +21 -0
- package/dist/editors/ColorEditor.js.map +1 -0
- package/dist/editors/DateEditor.d.ts +3 -0
- package/dist/editors/DateEditor.d.ts.map +1 -0
- package/dist/editors/DateEditor.js +28 -0
- package/dist/editors/DateEditor.js.map +1 -0
- package/dist/editors/InlineText.d.ts +4 -0
- package/dist/editors/InlineText.d.ts.map +1 -0
- package/dist/editors/InlineText.js +77 -0
- package/dist/editors/InlineText.js.map +1 -0
- package/dist/editors/NumberEditor.d.ts +4 -0
- package/dist/editors/NumberEditor.d.ts.map +1 -0
- package/dist/editors/NumberEditor.js +23 -0
- package/dist/editors/NumberEditor.js.map +1 -0
- package/dist/editors/RelationshipEditor.d.ts +3 -0
- package/dist/editors/RelationshipEditor.d.ts.map +1 -0
- package/dist/editors/RelationshipEditor.js +60 -0
- package/dist/editors/RelationshipEditor.js.map +1 -0
- package/dist/editors/SelectEditor.d.ts +4 -0
- package/dist/editors/SelectEditor.d.ts.map +1 -0
- package/dist/editors/SelectEditor.js +36 -0
- package/dist/editors/SelectEditor.js.map +1 -0
- package/dist/editors/UploadEditor.d.ts +3 -0
- package/dist/editors/UploadEditor.d.ts.map +1 -0
- package/dist/editors/UploadEditor.js +48 -0
- package/dist/editors/UploadEditor.js.map +1 -0
- package/dist/editors/index.d.ts +13 -0
- package/dist/editors/index.d.ts.map +1 -0
- package/dist/editors/index.js +23 -0
- package/dist/editors/index.js.map +1 -0
- package/dist/editors/useDebouncedSearch.d.ts +17 -0
- package/dist/editors/useDebouncedSearch.d.ts.map +1 -0
- package/dist/editors/useDebouncedSearch.js +50 -0
- package/dist/editors/useDebouncedSearch.js.map +1 -0
- package/dist/hub.d.ts +14 -0
- package/dist/hub.d.ts.map +1 -0
- package/dist/hub.js +20 -0
- package/dist/hub.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +12 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +83 -0
- package/dist/layout.js.map +1 -0
- package/dist/locators.d.ts +19 -0
- package/dist/locators.d.ts.map +1 -0
- package/dist/locators.js +215 -0
- package/dist/locators.js.map +1 -0
- package/dist/messages.d.ts +100 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +112 -0
- package/dist/messages.js.map +1 -0
- package/dist/registry.d.ts +15 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +29 -0
- package/dist/registry.js.map +1 -0
- package/dist/renderers.d.ts +7 -0
- package/dist/renderers.d.ts.map +1 -0
- package/dist/renderers.js +12 -0
- package/dist/renderers.js.map +1 -0
- package/dist/sanitize.d.ts +2 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +49 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/styles.d.ts +8 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +122 -0
- package/dist/styles.js.map +1 -0
- package/dist/targets.d.ts +18 -0
- package/dist/targets.d.ts.map +1 -0
- package/dist/targets.js +86 -0
- package/dist/targets.js.map +1 -0
- package/dist/types.d.ts +131 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/BlockPicker.d.ts +3 -0
- package/dist/ui/BlockPicker.d.ts.map +1 -0
- package/dist/ui/BlockPicker.js +27 -0
- package/dist/ui/BlockPicker.js.map +1 -0
- package/dist/ui/Dialog.d.ts +22 -0
- package/dist/ui/Dialog.d.ts.map +1 -0
- package/dist/ui/Dialog.js +83 -0
- package/dist/ui/Dialog.js.map +1 -0
- package/dist/ui/Dock.d.ts +7 -0
- package/dist/ui/Dock.d.ts.map +1 -0
- package/dist/ui/Dock.js +104 -0
- package/dist/ui/Dock.js.map +1 -0
- package/dist/ui/Overlay.d.ts +2 -0
- package/dist/ui/Overlay.d.ts.map +1 -0
- package/dist/ui/Overlay.js +150 -0
- package/dist/ui/Overlay.js.map +1 -0
- package/dist/ui/PostButton.d.ts +10 -0
- package/dist/ui/PostButton.d.ts.map +1 -0
- package/dist/ui/PostButton.js +7 -0
- package/dist/ui/PostButton.js.map +1 -0
- package/dist/ui/PreviewToolbar.d.ts +15 -0
- package/dist/ui/PreviewToolbar.d.ts.map +1 -0
- package/dist/ui/PreviewToolbar.js +45 -0
- package/dist/ui/PreviewToolbar.js.map +1 -0
- package/dist/ui/SettingsPanel.d.ts +11 -0
- package/dist/ui/SettingsPanel.d.ts.map +1 -0
- package/dist/ui/SettingsPanel.js +130 -0
- package/dist/ui/SettingsPanel.js.map +1 -0
- package/dist/useEvent.d.ts +7 -0
- package/dist/useEvent.d.ts.map +1 -0
- package/dist/useEvent.js +15 -0
- package/dist/useEvent.js.map +1 -0
- package/package.json +71 -4
- package/src/OnPageClient.tsx +67 -0
- package/src/annotations.ts +83 -0
- package/src/context.tsx +23 -0
- package/src/dom.ts +118 -0
- package/src/editor/FieldHost.tsx +66 -0
- package/src/editor/Ghosts.tsx +55 -0
- package/src/editor/OnPageEditor.tsx +315 -0
- package/src/editor/useGhosts.ts +64 -0
- package/src/editor/usePageEvents.ts +161 -0
- package/src/editor-kit.ts +27 -0
- package/src/editors/CheckboxEditor.tsx +31 -0
- package/src/editors/ColorEditor.tsx +64 -0
- package/src/editors/DateEditor.tsx +64 -0
- package/src/editors/InlineText.tsx +106 -0
- package/src/editors/NumberEditor.tsx +69 -0
- package/src/editors/RelationshipEditor.tsx +153 -0
- package/src/editors/SelectEditor.tsx +74 -0
- package/src/editors/UploadEditor.tsx +130 -0
- package/src/editors/index.ts +35 -0
- package/src/editors/useDebouncedSearch.ts +54 -0
- package/src/hub.ts +32 -0
- package/src/index.ts +55 -0
- package/src/layout.ts +83 -0
- package/src/locators.ts +210 -0
- package/src/messages.ts +120 -0
- package/src/registry.ts +43 -0
- package/src/renderers.ts +15 -0
- package/src/sanitize.ts +52 -0
- package/src/styles.ts +122 -0
- package/src/targets.ts +101 -0
- package/src/types.ts +132 -0
- package/src/ui/BlockPicker.tsx +49 -0
- package/src/ui/Dialog.tsx +159 -0
- package/src/ui/Dock.tsx +240 -0
- package/src/ui/Overlay.tsx +324 -0
- package/src/ui/PostButton.tsx +26 -0
- package/src/ui/PreviewToolbar.tsx +123 -0
- package/src/ui/SettingsPanel.tsx +279 -0
- package/src/useEvent.ts +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jellologic
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @payload-onpage/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The editor UI: overlay, row toolbars, settings, dock, preview toolbar, field editors, locators, annotations and client mode. Framework-agnostic; [`@payload-onpage/next`](../next) mounts it for Next.js.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { editable } from '@payload-onpage/react/annotations' // server-safe
|
|
7
|
+
import { OnPageClient } from '@payload-onpage/react/client' // client mode, ~1.7 KB
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Entries: `.` (editor, editors, locators, messages), `./annotations`, `./client`, `./editor-kit` (building blocks for [custom field editors](https://github.com/jellologic/payload-onpage/blob/main/docs/guides/custom-field-editor.md)).
|
|
11
|
+
|
|
12
|
+
Part of [**payload-onpage**](https://github.com/jellologic/payload-onpage): on-page editing and draft previews for Payload CMS + Next.js. Start with the [getting started guide](https://github.com/jellologic/payload-onpage/blob/main/docs/getting-started.md).
|
|
13
|
+
|
|
14
|
+
MIT licensed.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type Editable } from './annotations.ts';
|
|
3
|
+
export type OnPageClientProps<T> = {
|
|
4
|
+
doc: T;
|
|
5
|
+
render: (doc: T, e: Editable) => ReactNode;
|
|
6
|
+
/** Mark rendered text so it maps to its fields without annotations. Default true. */
|
|
7
|
+
autoMap?: boolean;
|
|
8
|
+
} & ({
|
|
9
|
+
collection: string;
|
|
10
|
+
global?: never;
|
|
11
|
+
} | {
|
|
12
|
+
global: string;
|
|
13
|
+
collection?: never;
|
|
14
|
+
});
|
|
15
|
+
export declare function OnPageClient<T extends {
|
|
16
|
+
id?: string | number;
|
|
17
|
+
} | null | undefined>(props: OnPageClientProps<T>): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=OnPageClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OnPageClient.d.ts","sourceRoot":"","sources":["../src/OnPageClient.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1D,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGvE,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IACjC,GAAG,EAAE,CAAC,CAAA;IACN,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,KAAK,SAAS,CAAA;IAC1C,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AAErF,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EAChF,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,+BAuC5B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Client mode: render a document from editor state, so edits show instantly
|
|
5
|
+
* (no save → server render round trip). Outside an editor it just renders the
|
|
6
|
+
* document it was given.
|
|
7
|
+
*
|
|
8
|
+
* <OnPageClient doc={page} collection="pages" render={(page, e) => <Page page={page} e={e} />} />
|
|
9
|
+
*
|
|
10
|
+
* `e` is the document's annotation helper (`e.field('title')`, `e.row('layout.0')`).
|
|
11
|
+
* Text is auto-mapped as in refresh mode: the rendered state carries the same
|
|
12
|
+
* invisible markers (turn off with `autoMap={false}`).
|
|
13
|
+
*/
|
|
14
|
+
import { useEvent } from "./useEvent.js";
|
|
15
|
+
import { encodeDocument, refKey } from '@payload-onpage/core';
|
|
16
|
+
import { useEffect, useMemo } from 'react';
|
|
17
|
+
import { editable, editableOff } from "./annotations.js";
|
|
18
|
+
import { useOnPageOptional } from "./context.js";
|
|
19
|
+
export function OnPageClient(props) {
|
|
20
|
+
const { doc, render, global: globalSlug, collection } = props;
|
|
21
|
+
const ctx = useOnPageOptional();
|
|
22
|
+
const id = doc?.id;
|
|
23
|
+
const ref = useMemo(() => globalSlug
|
|
24
|
+
? { kind: 'global', slug: globalSlug }
|
|
25
|
+
: collection && id != null
|
|
26
|
+
? { kind: 'collection', slug: collection, id }
|
|
27
|
+
: null, [globalSlug, collection, id]);
|
|
28
|
+
const key = ref ? refKey(ref) : null;
|
|
29
|
+
const enabled = !!ctx && !!ref;
|
|
30
|
+
// Join the editor once it's there: render from its state (it adopts this page's value).
|
|
31
|
+
const join = useEvent((r) => {
|
|
32
|
+
if (!ctx)
|
|
33
|
+
return undefined;
|
|
34
|
+
const off = ctx.registerClientDoc(refKey(r));
|
|
35
|
+
void ctx.session.open(r, doc ?? undefined);
|
|
36
|
+
return off;
|
|
37
|
+
});
|
|
38
|
+
useEffect(() => (enabled && ref ? join(ref) : undefined), [enabled, ref, join]);
|
|
39
|
+
const state = key ? ctx?.snap.docs[key] : undefined;
|
|
40
|
+
const stateDoc = state?.doc;
|
|
41
|
+
const fields = state?.schema?.fields;
|
|
42
|
+
const autoMap = props.autoMap !== false;
|
|
43
|
+
const current = useMemo(() => {
|
|
44
|
+
if (!stateDoc)
|
|
45
|
+
return doc;
|
|
46
|
+
return autoMap && fields && key ? encodeDocument(stateDoc, fields, key) : stateDoc;
|
|
47
|
+
}, [stateDoc, fields, key, autoMap, doc]);
|
|
48
|
+
const e = useMemo(() => (enabled && ref ? editable(ref, { enabled: true }) : editableOff), [enabled, ref]);
|
|
49
|
+
return _jsx(_Fragment, { children: render(current, e) });
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=OnPageClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OnPageClient.js","sourceRoot":"","sources":["../src/OnPageClient.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Annotations — optional, precise mapping from elements to fields. Pure and
|
|
3
|
+
* dependency-free, so they work in server components. When `enabled` is false
|
|
4
|
+
* every helper returns `{}`: public HTML carries nothing.
|
|
5
|
+
*
|
|
6
|
+
* const e = editable({ collection: 'pages', doc: page }, { enabled })
|
|
7
|
+
* <section {...e.row('layout.2')}>
|
|
8
|
+
* <h2 {...e.field('layout.2.heading')}>…</h2>
|
|
9
|
+
* <img {...e.media('layout.2.image')} />
|
|
10
|
+
* <ul {...e.list('layout.2.items', 'Item')}> <li {...e.row('layout.2.items.0')}>
|
|
11
|
+
*
|
|
12
|
+
* Auto-mapping (stega) already maps most text without any of this; annotate
|
|
13
|
+
* images that have no alt, layout rows you want exact, and lists ("+ Add").
|
|
14
|
+
*/
|
|
15
|
+
import { type DocRef, type TargetKind } from '@payload-onpage/core';
|
|
16
|
+
/** What an annotated element shows (`field` = resolve from the schema). */
|
|
17
|
+
export type FieldKind = Exclude<TargetKind, 'item' | 'list'>;
|
|
18
|
+
export declare const ATTR: {
|
|
19
|
+
readonly ref: "data-onpage-ref";
|
|
20
|
+
readonly field: "data-onpage-field";
|
|
21
|
+
readonly kind: "data-onpage-kind";
|
|
22
|
+
readonly row: "data-onpage-row";
|
|
23
|
+
readonly list: "data-onpage-list";
|
|
24
|
+
readonly label: "data-onpage-label";
|
|
25
|
+
};
|
|
26
|
+
type Attrs = Record<string, string>;
|
|
27
|
+
export interface Editable {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
/** An element showing one field. `kind` defaults to "field" (resolved from the schema). */
|
|
30
|
+
field(path: string, kind?: FieldKind, label?: string): Attrs;
|
|
31
|
+
/** An element showing an upload field (image). */
|
|
32
|
+
media(path: string, label?: string): Attrs;
|
|
33
|
+
/** A row of a blocks or array field (a section, a card, a button). */
|
|
34
|
+
row(path: string, label?: string): Attrs;
|
|
35
|
+
/** The element holding an array's rows (gets "+ Add"). `itemLabel` names one row. */
|
|
36
|
+
list(path: string, itemLabel?: string): Attrs;
|
|
37
|
+
}
|
|
38
|
+
export declare const editableOff: Editable;
|
|
39
|
+
export type EditableTarget = DocRef | {
|
|
40
|
+
collection: string;
|
|
41
|
+
doc: {
|
|
42
|
+
id?: string | number;
|
|
43
|
+
} | null | undefined;
|
|
44
|
+
} | {
|
|
45
|
+
global: string;
|
|
46
|
+
};
|
|
47
|
+
export declare function toRef(t: EditableTarget): DocRef | null;
|
|
48
|
+
/** Annotation helpers bound to one document. */
|
|
49
|
+
export declare function editable(target: EditableTarget, opts: {
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
}): Editable;
|
|
52
|
+
/** Join path parts: p("layout", 2, "heading") → "layout.2.heading". */
|
|
53
|
+
export declare const p: (...parts: Array<string | number>) => string;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=annotations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAU,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAE3E,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAE5D,eAAO,MAAM,IAAI;;;;;;;CAOP,CAAA;AAEV,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,2FAA2F;IAC3F,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC5D,kDAAkD;IAClD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC1C,sEAAsE;IACtE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACxC,qFAAqF;IACrF,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CAC9C;AAGD,eAAO,MAAM,WAAW,EAAE,QAMzB,CAAA;AAED,MAAM,MAAM,cAAc,GACtB,MAAM,GACN;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,GACxE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtB,wBAAgB,KAAK,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAItD;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,QAAQ,CAgBrF;AAED,uEAAuE;AACvE,eAAO,MAAM,CAAC,GAAI,GAAG,OAAO,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAG,MAAyB,CAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Annotations — optional, precise mapping from elements to fields. Pure and
|
|
3
|
+
* dependency-free, so they work in server components. When `enabled` is false
|
|
4
|
+
* every helper returns `{}`: public HTML carries nothing.
|
|
5
|
+
*
|
|
6
|
+
* const e = editable({ collection: 'pages', doc: page }, { enabled })
|
|
7
|
+
* <section {...e.row('layout.2')}>
|
|
8
|
+
* <h2 {...e.field('layout.2.heading')}>…</h2>
|
|
9
|
+
* <img {...e.media('layout.2.image')} />
|
|
10
|
+
* <ul {...e.list('layout.2.items', 'Item')}> <li {...e.row('layout.2.items.0')}>
|
|
11
|
+
*
|
|
12
|
+
* Auto-mapping (stega) already maps most text without any of this; annotate
|
|
13
|
+
* images that have no alt, layout rows you want exact, and lists ("+ Add").
|
|
14
|
+
*/
|
|
15
|
+
import { refKey } from '@payload-onpage/core';
|
|
16
|
+
export const ATTR = {
|
|
17
|
+
ref: 'data-onpage-ref',
|
|
18
|
+
field: 'data-onpage-field',
|
|
19
|
+
kind: 'data-onpage-kind',
|
|
20
|
+
row: 'data-onpage-row',
|
|
21
|
+
list: 'data-onpage-list',
|
|
22
|
+
label: 'data-onpage-label',
|
|
23
|
+
};
|
|
24
|
+
const none = () => ({});
|
|
25
|
+
export const editableOff = {
|
|
26
|
+
enabled: false,
|
|
27
|
+
field: none,
|
|
28
|
+
media: none,
|
|
29
|
+
row: none,
|
|
30
|
+
list: none,
|
|
31
|
+
};
|
|
32
|
+
export function toRef(t) {
|
|
33
|
+
if ('kind' in t)
|
|
34
|
+
return t;
|
|
35
|
+
if ('global' in t)
|
|
36
|
+
return { kind: 'global', slug: t.global };
|
|
37
|
+
return t.doc?.id == null ? null : { kind: 'collection', slug: t.collection, id: t.doc.id };
|
|
38
|
+
}
|
|
39
|
+
/** Annotation helpers bound to one document. */
|
|
40
|
+
export function editable(target, opts) {
|
|
41
|
+
const ref = opts.enabled ? toRef(target) : null;
|
|
42
|
+
if (!ref)
|
|
43
|
+
return editableOff;
|
|
44
|
+
const key = refKey(ref);
|
|
45
|
+
const base = (extra, label) => ({
|
|
46
|
+
[ATTR.ref]: key,
|
|
47
|
+
...extra,
|
|
48
|
+
...(label ? { [ATTR.label]: label } : {}),
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
enabled: true,
|
|
52
|
+
field: (path, kind = 'field', label) => base({ [ATTR.field]: path, [ATTR.kind]: kind }, label),
|
|
53
|
+
media: (path, label) => base({ [ATTR.field]: path, [ATTR.kind]: 'media' }, label),
|
|
54
|
+
row: (path, label) => base({ [ATTR.row]: path }, label),
|
|
55
|
+
list: (path, itemLabel) => base({ [ATTR.list]: path }, itemLabel),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Join path parts: p("layout", 2, "heading") → "layout.2.heading". */
|
|
59
|
+
export const p = (...parts) => parts.join('.');
|
|
60
|
+
//# sourceMappingURL=annotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotations.js","sourceRoot":"","sources":["../src/annotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { OnPageContextValue } from './types.ts';
|
|
2
|
+
export declare const OnPageContext: import("react").Context<OnPageContextValue | null>;
|
|
3
|
+
/** The editor, for code rendered inside it (field editors, panels). */
|
|
4
|
+
export declare function useOnPage(): OnPageContextValue;
|
|
5
|
+
/** The editor, from inside it or anywhere on the page; null when no editor is mounted (public pages). */
|
|
6
|
+
export declare function useOnPageOptional(): OnPageContextValue | null;
|
|
7
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpD,eAAO,MAAM,aAAa,oDAAiD,CAAA;AAE3E,uEAAuE;AACvE,wBAAgB,SAAS,IAAI,kBAAkB,CAI9C;AAID,yGAAyG;AACzG,wBAAgB,iBAAiB,IAAI,kBAAkB,GAAG,IAAI,CAI7D"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext, useSyncExternalStore } from 'react';
|
|
3
|
+
import { hub } from "./hub.js";
|
|
4
|
+
export const OnPageContext = createContext(null);
|
|
5
|
+
/** The editor, for code rendered inside it (field editors, panels). */
|
|
6
|
+
export function useOnPage() {
|
|
7
|
+
const ctx = useContext(OnPageContext);
|
|
8
|
+
if (!ctx)
|
|
9
|
+
throw new Error('useOnPage must be used inside <OnPageEditor>');
|
|
10
|
+
return ctx;
|
|
11
|
+
}
|
|
12
|
+
const getNull = () => null;
|
|
13
|
+
/** The editor, from inside it or anywhere on the page; null when no editor is mounted (public pages). */
|
|
14
|
+
export function useOnPageOptional() {
|
|
15
|
+
const inside = useContext(OnPageContext);
|
|
16
|
+
const outside = useSyncExternalStore(hub.subscribe, hub.get, getNull);
|
|
17
|
+
return inside ?? outside;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AACvE,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG9B,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAA4B,IAAI,CAAC,CAAA;AAE3E,uEAAuE;AACvE,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;IACrC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACzE,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAA;AAE1B,yGAAyG;AACzG,MAAM,UAAU,iBAAiB;IAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAA;IACxC,MAAM,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACrE,OAAO,MAAM,IAAI,OAAO,CAAA;AAC1B,CAAC"}
|
package/dist/dom.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** DOM helpers shared by the editor UI (browser-only, no React). */
|
|
2
|
+
/** Attribute that hides a page element while an editor or ghost stands in for it. */
|
|
3
|
+
export declare const HIDDEN = "data-onpage-hidden";
|
|
4
|
+
/** Marks the editor's own UI, which locators and click handling ignore. */
|
|
5
|
+
export declare const UI = "data-onpage-ui";
|
|
6
|
+
/** Computed styles copied onto an inline editor so it looks like the element it replaces. */
|
|
7
|
+
export declare const TYPOGRAPHY: readonly ["fontFamily", "fontSize", "fontWeight", "fontStyle", "lineHeight", "letterSpacing", "wordSpacing", "textTransform", "textAlign", "textIndent", "color", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft"];
|
|
8
|
+
export declare function copyTypography(from: Element, to: HTMLElement): void;
|
|
9
|
+
/** The typography inline styles of an element (for a ghost that must look like it). */
|
|
10
|
+
export declare function typographyOf(el: HTMLElement): Partial<CSSStyleDeclaration>;
|
|
11
|
+
/** Place an absolutely positioned (document layer) box over `el`. */
|
|
12
|
+
export declare function placeOver(box: HTMLElement, el: Element, opts?: {
|
|
13
|
+
minWidth?: number;
|
|
14
|
+
minHeight?: boolean;
|
|
15
|
+
}): void;
|
|
16
|
+
/** Inside the editor's own UI? */
|
|
17
|
+
export declare const isOurs: (node: EventTarget | null) => boolean;
|
|
18
|
+
/** Focus is in a text input or editable region (keyboard shortcuts stay out of the way). */
|
|
19
|
+
export declare const isTyping: (t: EventTarget | null) => boolean;
|
|
20
|
+
/** The DOM caret position under a viewport point, if it falls inside `within`. */
|
|
21
|
+
export declare function caretAt(point: {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
}, within: Element): {
|
|
25
|
+
node: Node;
|
|
26
|
+
offset: number;
|
|
27
|
+
} | null;
|
|
28
|
+
/** Place the caret at a viewport point inside `el`, else at the end. */
|
|
29
|
+
export declare function placeCaret(el: HTMLElement, point?: {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
}): void;
|
|
33
|
+
/** Position a fixed popover below (or above) an element, kept inside the viewport. */
|
|
34
|
+
export declare function popoverPosition(el: Element | null, size?: {
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
}): {
|
|
38
|
+
top: number;
|
|
39
|
+
left: number;
|
|
40
|
+
};
|
|
41
|
+
export declare const focusableIn: (root: Element) => HTMLElement[];
|
|
42
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,qFAAqF;AACrF,eAAO,MAAM,MAAM,uBAAuB,CAAA;AAC1C,2EAA2E;AAC3E,eAAO,MAAM,EAAE,mBAAmB,CAAA;AAElC,6FAA6F;AAC7F,eAAO,MAAM,UAAU,iOAgBb,CAAA;AAEV,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAGnE;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI1E;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CACvB,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,OAAO,EACX,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACpD,IAAI,CAMN;AAED,kCAAkC;AAClC,eAAO,MAAM,MAAM,GAAI,MAAM,WAAW,GAAG,IAAI,KAAG,OACI,CAAA;AAEtD,4FAA4F;AAC5F,eAAO,MAAM,QAAQ,GAAI,GAAG,WAAW,GAAG,IAAI,KAAG,OAKtB,CAAA;AAE3B,kFAAkF;AAClF,wBAAgB,OAAO,CACrB,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/B,MAAM,EAAE,OAAO,GACd;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAWvC;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAalF;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAC7B,EAAE,EAAE,OAAO,GAAG,IAAI,EAClB,IAAI;;;CAA8B,GACjC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAS/B;AAKD,eAAO,MAAM,WAAW,GAAI,MAAM,OAAO,KAAG,WAAW,EAGpD,CAAA"}
|
package/dist/dom.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** DOM helpers shared by the editor UI (browser-only, no React). */
|
|
2
|
+
/** Attribute that hides a page element while an editor or ghost stands in for it. */
|
|
3
|
+
export const HIDDEN = 'data-onpage-hidden';
|
|
4
|
+
/** Marks the editor's own UI, which locators and click handling ignore. */
|
|
5
|
+
export const UI = 'data-onpage-ui';
|
|
6
|
+
/** Computed styles copied onto an inline editor so it looks like the element it replaces. */
|
|
7
|
+
export const TYPOGRAPHY = [
|
|
8
|
+
'fontFamily',
|
|
9
|
+
'fontSize',
|
|
10
|
+
'fontWeight',
|
|
11
|
+
'fontStyle',
|
|
12
|
+
'lineHeight',
|
|
13
|
+
'letterSpacing',
|
|
14
|
+
'wordSpacing',
|
|
15
|
+
'textTransform',
|
|
16
|
+
'textAlign',
|
|
17
|
+
'textIndent',
|
|
18
|
+
'color',
|
|
19
|
+
'paddingTop',
|
|
20
|
+
'paddingRight',
|
|
21
|
+
'paddingBottom',
|
|
22
|
+
'paddingLeft',
|
|
23
|
+
];
|
|
24
|
+
export function copyTypography(from, to) {
|
|
25
|
+
const cs = getComputedStyle(from);
|
|
26
|
+
for (const k of TYPOGRAPHY)
|
|
27
|
+
to.style[k] = cs[k];
|
|
28
|
+
}
|
|
29
|
+
/** The typography inline styles of an element (for a ghost that must look like it). */
|
|
30
|
+
export function typographyOf(el) {
|
|
31
|
+
const out = {};
|
|
32
|
+
for (const k of TYPOGRAPHY)
|
|
33
|
+
out[k] = el.style[k];
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/** Place an absolutely positioned (document layer) box over `el`. */
|
|
37
|
+
export function placeOver(box, el, opts = {}) {
|
|
38
|
+
const r = el.getBoundingClientRect();
|
|
39
|
+
box.style.top = `${r.top + window.scrollY}px`;
|
|
40
|
+
box.style.left = `${r.left + window.scrollX}px`;
|
|
41
|
+
box.style.width = `${Math.max(r.width, opts.minWidth ?? 0)}px`;
|
|
42
|
+
if (opts.minHeight)
|
|
43
|
+
box.style.minHeight = `${r.height}px`;
|
|
44
|
+
}
|
|
45
|
+
/** Inside the editor's own UI? */
|
|
46
|
+
export const isOurs = (node) => node instanceof Element && !!node.closest(`[${UI}]`);
|
|
47
|
+
/** Focus is in a text input or editable region (keyboard shortcuts stay out of the way). */
|
|
48
|
+
export const isTyping = (t) => t instanceof HTMLElement &&
|
|
49
|
+
(t.isContentEditable ||
|
|
50
|
+
t.tagName === 'INPUT' ||
|
|
51
|
+
t.tagName === 'TEXTAREA' ||
|
|
52
|
+
t.tagName === 'SELECT');
|
|
53
|
+
/** The DOM caret position under a viewport point, if it falls inside `within`. */
|
|
54
|
+
export function caretAt(point, within) {
|
|
55
|
+
const doc = document;
|
|
56
|
+
const pos = doc.caretPositionFromPoint?.(point.x, point.y);
|
|
57
|
+
if (pos && within.contains(pos.offsetNode))
|
|
58
|
+
return { node: pos.offsetNode, offset: pos.offset };
|
|
59
|
+
const r = doc.caretRangeFromPoint?.(point.x, point.y);
|
|
60
|
+
if (r && within.contains(r.startContainer))
|
|
61
|
+
return { node: r.startContainer, offset: r.startOffset };
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/** Place the caret at a viewport point inside `el`, else at the end. */
|
|
65
|
+
export function placeCaret(el, point) {
|
|
66
|
+
const sel = window.getSelection();
|
|
67
|
+
if (!sel)
|
|
68
|
+
return;
|
|
69
|
+
const range = document.createRange();
|
|
70
|
+
const hit = point ? caretAt(point, el) : null;
|
|
71
|
+
if (hit)
|
|
72
|
+
range.setStart(hit.node, hit.offset);
|
|
73
|
+
else {
|
|
74
|
+
range.selectNodeContents(el);
|
|
75
|
+
range.collapse(false);
|
|
76
|
+
}
|
|
77
|
+
range.collapse(true);
|
|
78
|
+
sel.removeAllRanges();
|
|
79
|
+
sel.addRange(range);
|
|
80
|
+
}
|
|
81
|
+
/** Position a fixed popover below (or above) an element, kept inside the viewport. */
|
|
82
|
+
export function popoverPosition(el, size = { width: 300, height: 320 }) {
|
|
83
|
+
const vw = window.innerWidth;
|
|
84
|
+
const vh = window.innerHeight;
|
|
85
|
+
if (!el)
|
|
86
|
+
return { top: 80, left: Math.max(8, vw / 2 - size.width / 2) };
|
|
87
|
+
const r = el.getBoundingClientRect();
|
|
88
|
+
const below = r.bottom + 8;
|
|
89
|
+
const top = below + size.height < vh ? below : Math.max(8, r.top - 8 - size.height);
|
|
90
|
+
const left = Math.min(Math.max(8, r.left), vw - size.width - 8);
|
|
91
|
+
return { top, left };
|
|
92
|
+
}
|
|
93
|
+
const FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
94
|
+
export const focusableIn = (root) => Array.from(root.querySelectorAll(FOCUSABLE)).filter((el) => !el.hasAttribute('disabled'));
|
|
95
|
+
//# sourceMappingURL=dom.js.map
|
package/dist/dom.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/dom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldHost.d.ts","sourceRoot":"","sources":["../../src/editor/FieldHost.tsx"],"names":[],"mappings":"AAOA,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,sCAyDjE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { fieldAtPath, getAt } from '@payload-onpage/core';
|
|
4
|
+
import { Suspense, useCallback } from 'react';
|
|
5
|
+
import { useOnPage } from "../context.js";
|
|
6
|
+
/** Renders the open field editor, if it belongs to this layer. */
|
|
7
|
+
export function FieldHost({ mode }) {
|
|
8
|
+
const { editing, editors, session, snap, targets, setEditing, addGhost, isLive, t } = useOnPage();
|
|
9
|
+
const def = editing ? editors[editing.editor] : undefined;
|
|
10
|
+
const state = editing ? snap.docs[editing.key] : undefined;
|
|
11
|
+
const key = editing?.key ?? '';
|
|
12
|
+
const path = editing?.path ?? '';
|
|
13
|
+
const live = isLive(key);
|
|
14
|
+
const clicked = editing?.el;
|
|
15
|
+
const element = useCallback(() => (clicked?.isConnected ? clicked : (targets.find(key, path)?.el ?? null)), [clicked, targets, key, path]);
|
|
16
|
+
const close = useCallback(() => {
|
|
17
|
+
session.cancelTransient(key);
|
|
18
|
+
setEditing(null);
|
|
19
|
+
}, [session, key, setEditing]);
|
|
20
|
+
const commit = useCallback((value) => {
|
|
21
|
+
session.setValue(key, path, value);
|
|
22
|
+
if (!live)
|
|
23
|
+
void session.flush(); // refresh mode: show it as soon as possible
|
|
24
|
+
}, [session, key, path, live]);
|
|
25
|
+
const preview = useCallback((value) => session.setValue(key, path, value, { transient: true }), [session, key, path]);
|
|
26
|
+
const ghost = useCallback((g) => addGhost({ key, path, ...g }), [addGhost, key, path]);
|
|
27
|
+
if (!editing || !def || def.mode !== mode || !state?.schema || !state.doc)
|
|
28
|
+
return null;
|
|
29
|
+
const field = fieldAtPath(state.schema.fields, state.doc, path)?.field;
|
|
30
|
+
if (!field)
|
|
31
|
+
return null;
|
|
32
|
+
const Editor = def.component;
|
|
33
|
+
// Editors may be lazy (the rich-text editor is): render nothing until they've loaded.
|
|
34
|
+
return (_jsx(Suspense, { fallback: null, children: _jsx(Editor, { docKey: key, path: path, field: field, element: element, value: getAt(state.doc, path), commit: commit, preview: preview, close: close, ghost: ghost, live: live, point: editing.point, t: t }, `${key}|${path}`) }));
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=FieldHost.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldHost.js","sourceRoot":"","sources":["../../src/editor/FieldHost.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Ghost } from './useGhosts.ts';
|
|
2
|
+
/** Refresh mode: committed content stays on screen until the server render shows it. */
|
|
3
|
+
export declare function Ghosts({ ghosts }: {
|
|
4
|
+
ghosts: Ghost[];
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=Ghosts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ghosts.d.ts","sourceRoot":"","sources":["../../src/editor/Ghosts.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,wFAAwF;AACxF,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,+BAQrD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { useOnPage } from "../context.js";
|
|
5
|
+
import { HIDDEN, placeOver } from "../dom.js";
|
|
6
|
+
import { useLayoutTick } from "../layout.js";
|
|
7
|
+
import { sanitizeHtml } from "../sanitize.js";
|
|
8
|
+
/** Refresh mode: committed content stays on screen until the server render shows it. */
|
|
9
|
+
export function Ghosts({ ghosts }) {
|
|
10
|
+
return (_jsx(_Fragment, { children: ghosts.map((g) => (_jsx(GhostView, { ghost: g }, g.id))) }));
|
|
11
|
+
}
|
|
12
|
+
function GhostView({ ghost }) {
|
|
13
|
+
const { targets, editing } = useOnPage();
|
|
14
|
+
const box = useRef(null);
|
|
15
|
+
const hidden = useRef(null);
|
|
16
|
+
const tick = useLayoutTick();
|
|
17
|
+
const reopened = editing?.key === ghost.key && editing.path === ghost.path;
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const el = targets.find(ghost.key, ghost.path)?.el ?? null;
|
|
20
|
+
if (hidden.current && hidden.current !== el)
|
|
21
|
+
hidden.current.removeAttribute(HIDDEN);
|
|
22
|
+
hidden.current = el;
|
|
23
|
+
const b = box.current;
|
|
24
|
+
if (!b)
|
|
25
|
+
return;
|
|
26
|
+
if (!el || reopened) {
|
|
27
|
+
b.style.visibility = 'hidden';
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
el.setAttribute(HIDDEN, 'true');
|
|
31
|
+
placeOver(b, el, { minHeight: true });
|
|
32
|
+
b.style.visibility = 'visible';
|
|
33
|
+
}, [targets, ghost.key, ghost.path, reopened, tick]);
|
|
34
|
+
useEffect(() => () => hidden.current?.removeAttribute(HIDDEN), []);
|
|
35
|
+
return (_jsx("div", { ref: box, className: `po-ghost${ghost.className ? ` ${ghost.className}` : ''}`, style: ghost.style, dangerouslySetInnerHTML: { __html: sanitizeHtml(ghost.html) }, "aria-hidden": true, "data-testid": "onpage-ghost" }));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=Ghosts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ghosts.js","sourceRoot":"","sources":["../../src/editor/Ghosts.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAgB,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAG7C,wFAAwF;AACxF,MAAM,UAAU,MAAM,CAAC,EAAE,MAAM,EAAuB;IACpD,OAAO,CACL,4BACG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACjB,KAAC,SAAS,IAAY,KAAK,EAAE,CAAC,IAAd,CAAC,CAAC,EAAE,CAAc,CACnC,CAAC,GACD,CACJ,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,KAAK,EAAoB;IAC5C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAA;IACxC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACxC,MAAM,MAAM,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,aAAa,EAAE,CAAA;IAC5B,MAAM,QAAQ,GAAG,OAAO,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAA;IAE1E,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,IAAI,CAAA;QAC1D,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE;YAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QACnF,MAAM,CAAC,OAAO,GAAG,EAAE,CAAA;QACnB,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAA;QACrB,IAAI,CAAC,CAAC;YAAE,OAAM;QACd,IAAI,CAAC,EAAE,IAAI,QAAQ,EAAE,CAAC;YACpB,CAAC,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAA;YAC7B,OAAM;QACR,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/B,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrC,CAAC,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAA;IAChC,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;IAEpD,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IAElE,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,WAAW,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EACpE,KAAK,EAAE,KAAK,CAAC,KAA4B,EACzC,uBAAuB,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,sCAEjD,cAAc,GAC1B,CACH,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type DataSource, type Locator, type MediaLibrary, type Renderer } from '@payload-onpage/core';
|
|
2
|
+
import { type Messages } from '../messages.ts';
|
|
3
|
+
import type { FieldEditorDef, Links } from '../types.ts';
|
|
4
|
+
export interface OnPageEditorProps {
|
|
5
|
+
dataSource: DataSource;
|
|
6
|
+
/** Image search/upload (e.g. `payloadUploads()`). Without it, upload fields can't be changed. */
|
|
7
|
+
media?: MediaLibrary;
|
|
8
|
+
/** How elements map to fields. Default: composite(annotations(), stega()). */
|
|
9
|
+
locator?: Locator;
|
|
10
|
+
/** How saved changes reach the page. Default: clientState() (no server refresh). */
|
|
11
|
+
renderer?: Renderer;
|
|
12
|
+
/** Extra or replacement field editors by id; `null` removes a default. */
|
|
13
|
+
editors?: Record<string, FieldEditorDef | null>;
|
|
14
|
+
links: Links;
|
|
15
|
+
/** Content locale to edit. */
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** Autosave debounce, ms. Default: 250 with a refreshing renderer; else the collection's autosave interval, else 800. */
|
|
18
|
+
autosaveDelay?: number;
|
|
19
|
+
/** Where to look for editable content. Default: document.body. */
|
|
20
|
+
root?: () => ParentNode | null;
|
|
21
|
+
/** Override any UI string (see `defaultMessages`). */
|
|
22
|
+
messages?: Messages;
|
|
23
|
+
}
|
|
24
|
+
export declare function OnPageEditor(props: OnPageEditorProps): import("react").JSX.Element | null;
|
|
25
|
+
//# sourceMappingURL=OnPageEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OnPageEditor.d.ts","sourceRoot":"","sources":["../../src/editor/OnPageEditor.tsx"],"names":[],"mappings":"AAUA,OAAO,EAKL,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,QAAQ,EAEd,MAAM,sBAAsB,CAAA;AAS7B,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAK/D,OAAO,KAAK,EAGV,cAAc,EACd,KAAK,EAIN,MAAM,aAAa,CAAA;AAUpB,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAA;IACtB,iGAAiG;IACjG,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC,CAAA;IAC/C,KAAK,EAAE,KAAK,CAAA;IACZ,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yHAAyH;IACzH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,UAAU,GAAG,IAAI,CAAA;IAC9B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,sCA6OpD"}
|