@payload-onpage/react 0.0.0-stage → 0.2.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.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -2
  3. package/dist/OnPageClient.d.ts +18 -0
  4. package/dist/OnPageClient.d.ts.map +1 -0
  5. package/dist/OnPageClient.js +51 -0
  6. package/dist/OnPageClient.js.map +1 -0
  7. package/dist/annotations.d.ts +55 -0
  8. package/dist/annotations.d.ts.map +1 -0
  9. package/dist/annotations.js +60 -0
  10. package/dist/annotations.js.map +1 -0
  11. package/dist/context.d.ts +7 -0
  12. package/dist/context.d.ts.map +1 -0
  13. package/dist/context.js +19 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/dom.d.ts +42 -0
  16. package/dist/dom.d.ts.map +1 -0
  17. package/dist/dom.js +95 -0
  18. package/dist/dom.js.map +1 -0
  19. package/dist/editor/FieldHost.d.ts +5 -0
  20. package/dist/editor/FieldHost.d.ts.map +1 -0
  21. package/dist/editor/FieldHost.js +36 -0
  22. package/dist/editor/FieldHost.js.map +1 -0
  23. package/dist/editor/Ghosts.d.ts +6 -0
  24. package/dist/editor/Ghosts.d.ts.map +1 -0
  25. package/dist/editor/Ghosts.js +37 -0
  26. package/dist/editor/Ghosts.js.map +1 -0
  27. package/dist/editor/OnPageEditor.d.ts +25 -0
  28. package/dist/editor/OnPageEditor.d.ts.map +1 -0
  29. package/dist/editor/OnPageEditor.js +211 -0
  30. package/dist/editor/OnPageEditor.js.map +1 -0
  31. package/dist/editor/useGhosts.d.ts +24 -0
  32. package/dist/editor/useGhosts.d.ts.map +1 -0
  33. package/dist/editor/useGhosts.js +34 -0
  34. package/dist/editor/useGhosts.js.map +1 -0
  35. package/dist/editor/usePageEvents.d.ts +3 -0
  36. package/dist/editor/usePageEvents.d.ts.map +1 -0
  37. package/dist/editor/usePageEvents.js +164 -0
  38. package/dist/editor/usePageEvents.js.map +1 -0
  39. package/dist/editor-kit.d.ts +19 -0
  40. package/dist/editor-kit.d.ts.map +1 -0
  41. package/dist/editor-kit.js +17 -0
  42. package/dist/editor-kit.js.map +1 -0
  43. package/dist/editors/CheckboxEditor.d.ts +3 -0
  44. package/dist/editors/CheckboxEditor.d.ts.map +1 -0
  45. package/dist/editors/CheckboxEditor.js +10 -0
  46. package/dist/editors/CheckboxEditor.js.map +1 -0
  47. package/dist/editors/ColorEditor.d.ts +4 -0
  48. package/dist/editors/ColorEditor.d.ts.map +1 -0
  49. package/dist/editors/ColorEditor.js +21 -0
  50. package/dist/editors/ColorEditor.js.map +1 -0
  51. package/dist/editors/DateEditor.d.ts +3 -0
  52. package/dist/editors/DateEditor.d.ts.map +1 -0
  53. package/dist/editors/DateEditor.js +28 -0
  54. package/dist/editors/DateEditor.js.map +1 -0
  55. package/dist/editors/InlineText.d.ts +4 -0
  56. package/dist/editors/InlineText.d.ts.map +1 -0
  57. package/dist/editors/InlineText.js +77 -0
  58. package/dist/editors/InlineText.js.map +1 -0
  59. package/dist/editors/NumberEditor.d.ts +4 -0
  60. package/dist/editors/NumberEditor.d.ts.map +1 -0
  61. package/dist/editors/NumberEditor.js +23 -0
  62. package/dist/editors/NumberEditor.js.map +1 -0
  63. package/dist/editors/RelationshipEditor.d.ts +3 -0
  64. package/dist/editors/RelationshipEditor.d.ts.map +1 -0
  65. package/dist/editors/RelationshipEditor.js +60 -0
  66. package/dist/editors/RelationshipEditor.js.map +1 -0
  67. package/dist/editors/SelectEditor.d.ts +4 -0
  68. package/dist/editors/SelectEditor.d.ts.map +1 -0
  69. package/dist/editors/SelectEditor.js +36 -0
  70. package/dist/editors/SelectEditor.js.map +1 -0
  71. package/dist/editors/UploadEditor.d.ts +3 -0
  72. package/dist/editors/UploadEditor.d.ts.map +1 -0
  73. package/dist/editors/UploadEditor.js +48 -0
  74. package/dist/editors/UploadEditor.js.map +1 -0
  75. package/dist/editors/index.d.ts +13 -0
  76. package/dist/editors/index.d.ts.map +1 -0
  77. package/dist/editors/index.js +23 -0
  78. package/dist/editors/index.js.map +1 -0
  79. package/dist/editors/useDebouncedSearch.d.ts +17 -0
  80. package/dist/editors/useDebouncedSearch.d.ts.map +1 -0
  81. package/dist/editors/useDebouncedSearch.js +50 -0
  82. package/dist/editors/useDebouncedSearch.js.map +1 -0
  83. package/dist/hub.d.ts +14 -0
  84. package/dist/hub.d.ts.map +1 -0
  85. package/dist/hub.js +20 -0
  86. package/dist/hub.js.map +1 -0
  87. package/dist/index.d.ts +20 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +19 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/layout.d.ts +12 -0
  92. package/dist/layout.d.ts.map +1 -0
  93. package/dist/layout.js +83 -0
  94. package/dist/layout.js.map +1 -0
  95. package/dist/locators.d.ts +19 -0
  96. package/dist/locators.d.ts.map +1 -0
  97. package/dist/locators.js +215 -0
  98. package/dist/locators.js.map +1 -0
  99. package/dist/messages.d.ts +100 -0
  100. package/dist/messages.d.ts.map +1 -0
  101. package/dist/messages.js +112 -0
  102. package/dist/messages.js.map +1 -0
  103. package/dist/registry.d.ts +15 -0
  104. package/dist/registry.d.ts.map +1 -0
  105. package/dist/registry.js +29 -0
  106. package/dist/registry.js.map +1 -0
  107. package/dist/renderers.d.ts +7 -0
  108. package/dist/renderers.d.ts.map +1 -0
  109. package/dist/renderers.js +12 -0
  110. package/dist/renderers.js.map +1 -0
  111. package/dist/sanitize.d.ts +2 -0
  112. package/dist/sanitize.d.ts.map +1 -0
  113. package/dist/sanitize.js +49 -0
  114. package/dist/sanitize.js.map +1 -0
  115. package/dist/styles.d.ts +8 -0
  116. package/dist/styles.d.ts.map +1 -0
  117. package/dist/styles.js +122 -0
  118. package/dist/styles.js.map +1 -0
  119. package/dist/targets.d.ts +18 -0
  120. package/dist/targets.d.ts.map +1 -0
  121. package/dist/targets.js +86 -0
  122. package/dist/targets.js.map +1 -0
  123. package/dist/types.d.ts +131 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +2 -0
  126. package/dist/types.js.map +1 -0
  127. package/dist/ui/BlockPicker.d.ts +3 -0
  128. package/dist/ui/BlockPicker.d.ts.map +1 -0
  129. package/dist/ui/BlockPicker.js +27 -0
  130. package/dist/ui/BlockPicker.js.map +1 -0
  131. package/dist/ui/Dialog.d.ts +22 -0
  132. package/dist/ui/Dialog.d.ts.map +1 -0
  133. package/dist/ui/Dialog.js +83 -0
  134. package/dist/ui/Dialog.js.map +1 -0
  135. package/dist/ui/Dock.d.ts +7 -0
  136. package/dist/ui/Dock.d.ts.map +1 -0
  137. package/dist/ui/Dock.js +104 -0
  138. package/dist/ui/Dock.js.map +1 -0
  139. package/dist/ui/Overlay.d.ts +2 -0
  140. package/dist/ui/Overlay.d.ts.map +1 -0
  141. package/dist/ui/Overlay.js +150 -0
  142. package/dist/ui/Overlay.js.map +1 -0
  143. package/dist/ui/PostButton.d.ts +10 -0
  144. package/dist/ui/PostButton.d.ts.map +1 -0
  145. package/dist/ui/PostButton.js +7 -0
  146. package/dist/ui/PostButton.js.map +1 -0
  147. package/dist/ui/PreviewToolbar.d.ts +15 -0
  148. package/dist/ui/PreviewToolbar.d.ts.map +1 -0
  149. package/dist/ui/PreviewToolbar.js +45 -0
  150. package/dist/ui/PreviewToolbar.js.map +1 -0
  151. package/dist/ui/SettingsPanel.d.ts +11 -0
  152. package/dist/ui/SettingsPanel.d.ts.map +1 -0
  153. package/dist/ui/SettingsPanel.js +130 -0
  154. package/dist/ui/SettingsPanel.js.map +1 -0
  155. package/dist/useEvent.d.ts +7 -0
  156. package/dist/useEvent.d.ts.map +1 -0
  157. package/dist/useEvent.js +15 -0
  158. package/dist/useEvent.js.map +1 -0
  159. package/package.json +71 -4
  160. package/src/OnPageClient.tsx +67 -0
  161. package/src/annotations.ts +83 -0
  162. package/src/context.tsx +23 -0
  163. package/src/dom.ts +118 -0
  164. package/src/editor/FieldHost.tsx +66 -0
  165. package/src/editor/Ghosts.tsx +55 -0
  166. package/src/editor/OnPageEditor.tsx +315 -0
  167. package/src/editor/useGhosts.ts +64 -0
  168. package/src/editor/usePageEvents.ts +161 -0
  169. package/src/editor-kit.ts +27 -0
  170. package/src/editors/CheckboxEditor.tsx +31 -0
  171. package/src/editors/ColorEditor.tsx +64 -0
  172. package/src/editors/DateEditor.tsx +64 -0
  173. package/src/editors/InlineText.tsx +106 -0
  174. package/src/editors/NumberEditor.tsx +69 -0
  175. package/src/editors/RelationshipEditor.tsx +153 -0
  176. package/src/editors/SelectEditor.tsx +74 -0
  177. package/src/editors/UploadEditor.tsx +130 -0
  178. package/src/editors/index.ts +35 -0
  179. package/src/editors/useDebouncedSearch.ts +54 -0
  180. package/src/hub.ts +32 -0
  181. package/src/index.ts +55 -0
  182. package/src/layout.ts +83 -0
  183. package/src/locators.ts +210 -0
  184. package/src/messages.ts +120 -0
  185. package/src/registry.ts +43 -0
  186. package/src/renderers.ts +15 -0
  187. package/src/sanitize.ts +52 -0
  188. package/src/styles.ts +122 -0
  189. package/src/targets.ts +101 -0
  190. package/src/types.ts +132 -0
  191. package/src/ui/BlockPicker.tsx +49 -0
  192. package/src/ui/Dialog.tsx +159 -0
  193. package/src/ui/Dock.tsx +240 -0
  194. package/src/ui/Overlay.tsx +324 -0
  195. package/src/ui/PostButton.tsx +26 -0
  196. package/src/ui/PreviewToolbar.tsx +123 -0
  197. package/src/ui/SettingsPanel.tsx +279 -0
  198. package/src/useEvent.ts +16 -0
@@ -0,0 +1,211 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * The on-page editor. Mount it once (the Next adapter's <OnPage /> does) and
5
+ * it finds editable content through the Locator, opens each document it finds
6
+ * in an EditorSession, and edits through the field-editor registry. Saves go
7
+ * through the DataSource; the Renderer shows them (server refresh by default,
8
+ * instant for documents rendered with <OnPageClient>).
9
+ */
10
+ import { useEvent } from "../useEvent.js";
11
+ import { EditorSession, fieldAtPath, isEditablePath, refKey, } from '@payload-onpage/core';
12
+ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
13
+ import { createPortal } from 'react-dom';
14
+ import { OnPageContext } from "../context.js";
15
+ import { UI } from "../dom.js";
16
+ import { defaultEditors } from "../editors/index.js";
17
+ import { hub } from "../hub.js";
18
+ import { notifyLayout } from "../layout.js";
19
+ import { annotations, composite, stega } from "../locators.js";
20
+ import { createTranslate } from "../messages.js";
21
+ import { mergeEditors, resolveEditor } from "../registry.js";
22
+ import { clientState } from "../renderers.js";
23
+ import { injectStyles } from "../styles.js";
24
+ import { useTargets } from "../targets.js";
25
+ import { BlockPicker } from "../ui/BlockPicker.js";
26
+ import { Dock } from "../ui/Dock.js";
27
+ import { Overlay } from "../ui/Overlay.js";
28
+ import { SettingsPanel } from "../ui/SettingsPanel.js";
29
+ import { FieldHost } from "./FieldHost.js";
30
+ import { Ghosts } from "./Ghosts.js";
31
+ import { usePageEvents } from "./usePageEvents.js";
32
+ import { useGhosts } from "./useGhosts.js";
33
+ const EMPTY_SNAP = { docs: {}, canUndo: false, canRedo: false, busy: false };
34
+ const noopSubscribe = () => () => { };
35
+ export function OnPageEditor(props) {
36
+ const { dataSource, locale, autosaveDelay, links, media } = props;
37
+ const renderer = useMemo(() => props.renderer ?? clientState(), [props.renderer]);
38
+ const locator = useMemo(() => props.locator ?? composite(annotations(), stega()), [props.locator]);
39
+ const editors = useMemo(() => mergeEditors(defaultEditors, props.editors), [props.editors]);
40
+ const t = useMemo(() => createTranslate(props.messages), [props.messages]);
41
+ const rootProp = props.root;
42
+ const root = useCallback(() => (rootProp ? rootProp() : typeof document === 'undefined' ? null : document.body), [rootProp]);
43
+ const [panel, setPanel] = useState(null);
44
+ const [editing, setEditing] = useState(null);
45
+ const [selected, setSelected] = useState(null);
46
+ const [renders, setRenders] = useState(0);
47
+ const [flash, setFlash] = useState(null);
48
+ const [clientDocs, setClientDocs] = useState(() => new Set());
49
+ const [session, setSession] = useState(null);
50
+ const snap = useSyncExternalStore(session?.subscribe ?? noopSubscribe, session?.getSnapshot ?? (() => EMPTY_SNAP), () => EMPTY_SNAP);
51
+ const targets = useTargets(locator, root);
52
+ const { ghosts, add: addGhostEntry, rendered: ghostsRendered } = useGhosts(session ? snap : null);
53
+ const isLive = useCallback((key) => renderer.live || clientDocs.has(key), [renderer, clientDocs]);
54
+ /** Re-render documents that aren't client-rendered, then retire their ghosts. */
55
+ const rerender = useCallback(async (refs, seq) => {
56
+ const stale = refs.filter((r) => !isLive(refKey(r)));
57
+ if (!stale.length)
58
+ return;
59
+ setRenders((n) => n + 1);
60
+ try {
61
+ await renderer.afterSave({ refs: stale });
62
+ }
63
+ catch (e) {
64
+ console.error('[payload-onpage] render after save failed', e);
65
+ }
66
+ finally {
67
+ setRenders((n) => n - 1);
68
+ // Give the new DOM a moment to land (and the locator to rescan) before uncovering it.
69
+ setTimeout(() => {
70
+ for (const r of stale)
71
+ ghostsRendered(refKey(r), seq ?? Number.MAX_SAFE_INTEGER);
72
+ }, 250);
73
+ }
74
+ }, [isLive, renderer, ghostsRendered]);
75
+ const handleSaved = useEvent((ref, seq) => void rerender([ref], seq));
76
+ // One session per data source and locale; disposed (after flushing) when they change or on unmount.
77
+ useEffect(() => {
78
+ // Refresh mode saves quickly (the page only updates after a save); client mode uses the collection's interval.
79
+ const delay = autosaveDelay ?? (renderer.live ? undefined : 250);
80
+ const s = new EditorSession({
81
+ dataSource,
82
+ locale,
83
+ autosaveDelay: delay,
84
+ onSaved: (ref, seq) => handleSaved(ref, seq),
85
+ });
86
+ // The session is an external resource with a lifecycle; it lives in state so StrictMode's
87
+ // mount/unmount/mount gets a fresh one each time.
88
+ // eslint-disable-next-line react-hooks/set-state-in-effect
89
+ setSession(s);
90
+ return () => {
91
+ void s.flush().finally(() => s.dispose());
92
+ };
93
+ }, [dataSource, locale, autosaveDelay, renderer.live, handleSaved]);
94
+ useEffect(() => {
95
+ if (!flash)
96
+ return;
97
+ const id = setTimeout(() => setFlash(null), 4000);
98
+ return () => clearTimeout(id);
99
+ }, [flash]);
100
+ // Documents on this page: everything the locator found, plus client-mode documents.
101
+ const docKeys = useMemo(() => {
102
+ const keys = new Set(clientDocs);
103
+ for (const target of targets.all)
104
+ keys.add(refKey(target.ref));
105
+ return [...keys];
106
+ }, [targets, clientDocs]);
107
+ useEffect(() => {
108
+ if (!session)
109
+ return;
110
+ const seen = new Set();
111
+ for (const target of targets.all) {
112
+ const k = refKey(target.ref);
113
+ if (seen.has(k))
114
+ continue;
115
+ seen.add(k);
116
+ void session.open(target.ref);
117
+ }
118
+ }, [targets, session]);
119
+ useEffect(() => notifyLayout(), [snap, targets]);
120
+ const notify = useCallback((key, vars, bad) => setFlash({ text: t(key, vars), bad }), [t]);
121
+ const registerClientDoc = useCallback((key) => {
122
+ setClientDocs((s) => new Set(s).add(key));
123
+ return () => setClientDocs((s) => {
124
+ const next = new Set(s);
125
+ next.delete(key);
126
+ return next;
127
+ });
128
+ }, []);
129
+ const addGhost = useCallback((g) => addGhostEntry(g, session?.get(g.key)?.save.seq ?? 0), [addGhostEntry, session]);
130
+ const edit = useCallback((key, path, opts = {}) => {
131
+ const state = session?.get(key);
132
+ if (!state?.schema || !state.doc) {
133
+ if (state?.status === 'error')
134
+ notify('notify.cantEdit', { message: state.error ?? '' }, true);
135
+ else
136
+ notify('notify.loading');
137
+ return true;
138
+ }
139
+ if (!isEditablePath(state.schema, path))
140
+ return false;
141
+ const hit = fieldAtPath(state.schema.fields, state.doc, path);
142
+ if (!hit)
143
+ return false;
144
+ const editor = resolveEditor(editors, hit.field, opts.kind === 'field' ? undefined : opts.kind);
145
+ if (!editor)
146
+ return false;
147
+ setEditing({
148
+ key,
149
+ path,
150
+ editor,
151
+ point: opts.point,
152
+ el: opts.anchor ?? targets.find(key, path)?.el,
153
+ });
154
+ return true;
155
+ }, [session, editors, targets, notify]);
156
+ const ctx = useMemo(() => session && {
157
+ session,
158
+ snap,
159
+ renderer,
160
+ media,
161
+ editors,
162
+ targets,
163
+ links,
164
+ t,
165
+ panel,
166
+ setPanel,
167
+ editing,
168
+ setEditing,
169
+ selected,
170
+ setSelected,
171
+ docKeys,
172
+ isLive,
173
+ registerClientDoc,
174
+ rendering: renders > 0,
175
+ edit,
176
+ rerender: (refs) => rerender(refs),
177
+ notify,
178
+ addGhost,
179
+ }, [
180
+ session,
181
+ snap,
182
+ renderer,
183
+ media,
184
+ editors,
185
+ targets,
186
+ links,
187
+ t,
188
+ panel,
189
+ editing,
190
+ selected,
191
+ docKeys,
192
+ isLive,
193
+ registerClientDoc,
194
+ renders,
195
+ edit,
196
+ rerender,
197
+ notify,
198
+ addGhost,
199
+ ]);
200
+ useEffect(() => {
201
+ hub.set(ctx);
202
+ }, [ctx]);
203
+ useEffect(() => () => hub.set(null), []);
204
+ useEffect(() => injectStyles(), []);
205
+ usePageEvents(ctx, root);
206
+ const mounted = useSyncExternalStore(noopSubscribe, () => true, () => false);
207
+ if (!mounted || !ctx)
208
+ return null;
209
+ return (_jsxs(OnPageContext.Provider, { value: ctx, children: [createPortal(_jsxs("div", { className: "po-doc-layer", [UI]: '', children: [_jsx(Ghosts, { ghosts: ghosts }), _jsx(FieldHost, { mode: "inline" })] }), document.body), createPortal(_jsxs("div", { className: "po-layer", [UI]: '', children: [_jsx(Overlay, {}), _jsx(SettingsPanel, {}), _jsx(BlockPicker, {}), _jsx(FieldHost, { mode: "popover" }), _jsx(Dock, { flash: flash })] }), document.body)] }));
210
+ }
211
+ //# sourceMappingURL=OnPageEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OnPageEditor.js","sourceRoot":"","sources":["../../src/editor/OnPageEditor.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Ghosts: in refresh mode, committed content stays on screen (over the hidden
3
+ * original) until the server render that includes it has landed. A ghost
4
+ * records the document's save sequence when it was made; the render after a
5
+ * later save retires it. Failed saves and a TTL retire ghosts too.
6
+ */
7
+ import type { SessionSnapshot } from '@payload-onpage/core';
8
+ export interface Ghost {
9
+ id: string;
10
+ key: string;
11
+ path: string;
12
+ html: string;
13
+ className?: string;
14
+ style?: Partial<CSSStyleDeclaration>;
15
+ /** Save sequence of the document when the ghost was made. */
16
+ afterSeq: number;
17
+ until: number;
18
+ }
19
+ export declare function useGhosts(snap: SessionSnapshot | null): {
20
+ ghosts: Ghost[];
21
+ add: (g: Omit<Ghost, "id" | "until" | "afterSeq">, afterSeq: number) => void;
22
+ rendered: (key: string, seq: number) => void;
23
+ };
24
+ //# sourceMappingURL=useGhosts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGhosts.d.ts","sourceRoot":"","sources":["../../src/editor/useGhosts.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAG3D,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACpC,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAID,wBAAgB,SAAS,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;;aAGxB,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,GAAG,UAAU,CAAC,YAAY,MAAM;oBASnD,MAAM,OAAO,MAAM;EA0BvD"}
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ const TTL = 15_000;
4
+ export function useGhosts(snap) {
5
+ const [ghosts, setGhosts] = useState([]);
6
+ const add = useCallback((g, afterSeq) => {
7
+ const now = Date.now();
8
+ setGhosts((gs) => [
9
+ ...gs.filter((x) => !(x.key === g.key && x.path === g.path)),
10
+ { ...g, afterSeq, id: `${now}-${Math.random().toString(36).slice(2)}`, until: now + TTL },
11
+ ]);
12
+ }, []);
13
+ /** The page re-rendered after save `seq` of document `key`. */
14
+ const rendered = useCallback((key, seq) => {
15
+ setGhosts((gs) => gs.some((g) => g.key === key && g.afterSeq < seq)
16
+ ? gs.filter((g) => !(g.key === key && g.afterSeq < seq))
17
+ : gs);
18
+ }, []);
19
+ // Expired ghosts.
20
+ useEffect(() => {
21
+ if (!ghosts.length)
22
+ return;
23
+ const next = Math.min(...ghosts.map((g) => g.until)) - Date.now();
24
+ const timer = setTimeout(() => setGhosts((gs) => gs.filter((g) => g.until > Date.now())), Math.max(next, 0) + 10);
25
+ return () => clearTimeout(timer);
26
+ }, [ghosts]);
27
+ // A failed save will never render: don't cover the page for it.
28
+ const visible = ghosts.filter((g) => {
29
+ const status = snap?.docs[g.key]?.save.status;
30
+ return status !== 'error' && status !== 'conflict';
31
+ });
32
+ return { ghosts: visible, add, rendered };
33
+ }
34
+ //# sourceMappingURL=useGhosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGhosts.js","sourceRoot":"","sources":["../../src/editor/useGhosts.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AASZ,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAcxD,MAAM,GAAG,GAAG,MAAM,CAAA;AAElB,MAAM,UAAU,SAAS,CAAC,IAA4B;IACpD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAU,EAAE,CAAC,CAAA;IAEjD,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAA2C,EAAE,QAAgB,EAAE,EAAE;QACxF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;YAChB,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5D,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE;SAC1F,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE;QACxD,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CACf,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;YACxD,CAAC,CAAC,EAAE,CACP,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,kBAAkB;IAClB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAM;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACjE,MAAM,KAAK,GAAG,UAAU,CACtB,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAC/D,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,CACvB,CAAA;QACD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,gEAAgE;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAA;QAC7C,OAAO,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,UAAU,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { OnPageContextValue } from '../types.ts';
2
+ export declare function usePageEvents(ctx: OnPageContextValue | null, root: () => ParentNode | null): void;
3
+ //# sourceMappingURL=usePageEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePageEvents.d.ts","sourceRoot":"","sources":["../../src/editor/usePageEvents.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAIrD,wBAAgB,aAAa,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CA8IjG"}
@@ -0,0 +1,164 @@
1
+ 'use client';
2
+ /**
3
+ * Page-level input for the editor:
4
+ * - click a field to edit it, a row to select it (⌥-click uses the page normally)
5
+ * - keyboard: every target is focusable; Enter edits a field or selects a row,
6
+ * ⌥↑/⌥↓ move the selected row, ⌥⌫ deletes it, Escape clears; ⌘Z/⇧⌘Z undo/redo
7
+ * - a warning before leaving with unsaved changes
8
+ */
9
+ import { useEvent } from "../useEvent.js";
10
+ import { moveItem, refKey, removeItem, resolveRow, updateArray } from '@payload-onpage/core';
11
+ import { useEffect } from 'react';
12
+ import { isOurs, isTyping } from "../dom.js";
13
+ import { isFieldTarget, isRowTarget, targetsAt } from "../targets.js";
14
+ const FOCUSABLE_FLAG = 'data-onpage-focusable';
15
+ export function usePageEvents(ctx, root) {
16
+ const onClick = useEvent((e) => {
17
+ if (!ctx || e.altKey || e.button !== 0)
18
+ return;
19
+ const t = e.target;
20
+ if (!(t instanceof Element) || isOurs(t))
21
+ return;
22
+ const r = root();
23
+ if (r && !r.contains(t))
24
+ return;
25
+ const { field, rows } = targetsAt(ctx.targets, t);
26
+ const row = rows[0];
27
+ const inControl = !!t.closest('a,button,label,summary,[role="button"]');
28
+ if (row)
29
+ ctx.setSelected({ key: refKey(row.ref), path: row.path });
30
+ else if (!field)
31
+ ctx.setSelected(null);
32
+ if (field &&
33
+ ctx.edit(refKey(field.ref), field.path, {
34
+ point: { x: e.clientX, y: e.clientY },
35
+ kind: field.kind,
36
+ anchor: field.el,
37
+ })) {
38
+ e.preventDefault();
39
+ e.stopPropagation();
40
+ }
41
+ else if ((field || row) && inControl) {
42
+ e.preventDefault(); // don't navigate away from the editor by accident
43
+ }
44
+ });
45
+ const moveSelected = (dir) => {
46
+ if (!ctx?.selected)
47
+ return false;
48
+ const { key, path } = ctx.selected;
49
+ const state = ctx.snap.docs[key];
50
+ const info = state?.schema && state.doc ? resolveRow(state.schema, state.doc, path) : null;
51
+ if (!info)
52
+ return false;
53
+ if (dir === 'delete') {
54
+ if (info.length <= (info.listField.minRows ?? 0))
55
+ return true;
56
+ ctx.session.apply(key, (d) => updateArray(d, info.listPath, (a) => removeItem(a, info.index)));
57
+ ctx.setSelected(null);
58
+ return true;
59
+ }
60
+ const to = info.index + dir;
61
+ if (to < 0 || to >= info.length)
62
+ return true;
63
+ ctx.session.apply(key, (d) => updateArray(d, info.listPath, (a) => moveItem(a, info.index, to)));
64
+ ctx.setSelected({ key, path: `${info.listPath}.${to}` });
65
+ return true;
66
+ };
67
+ const onKey = useEvent((e) => {
68
+ if (!ctx)
69
+ return;
70
+ const mod = e.metaKey || e.ctrlKey;
71
+ if (e.key === 'Escape') {
72
+ ctx.setPanel(null);
73
+ ctx.setSelected(null);
74
+ return;
75
+ }
76
+ if (isTyping(e.target))
77
+ return;
78
+ if (mod && e.key.toLowerCase() === 'z') {
79
+ e.preventDefault();
80
+ if (e.shiftKey)
81
+ ctx.session.redo();
82
+ else
83
+ ctx.session.undo();
84
+ return;
85
+ }
86
+ if (mod && e.key.toLowerCase() === 'y') {
87
+ e.preventDefault();
88
+ ctx.session.redo();
89
+ return;
90
+ }
91
+ if (e.altKey &&
92
+ (e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'Backspace' || e.key === 'Delete')) {
93
+ if (moveSelected(e.key === 'ArrowUp' ? -1 : e.key === 'ArrowDown' ? 1 : 'delete'))
94
+ e.preventDefault();
95
+ return;
96
+ }
97
+ if ((e.key === 'Enter' || e.key === 'F2') &&
98
+ e.target instanceof Element &&
99
+ e.target.hasAttribute(FOCUSABLE_FLAG)) {
100
+ const own = ctx.targets.at(e.target);
101
+ const field = own.find(isFieldTarget);
102
+ const row = own.find(isRowTarget);
103
+ if (field && ctx.edit(refKey(field.ref), field.path, { kind: field.kind, anchor: field.el }))
104
+ e.preventDefault();
105
+ else if (row) {
106
+ ctx.setSelected({ key: refKey(row.ref), path: row.path });
107
+ e.preventDefault();
108
+ }
109
+ }
110
+ });
111
+ const onFocus = useEvent((e) => {
112
+ if (!ctx || !(e.target instanceof Element) || !e.target.hasAttribute(FOCUSABLE_FLAG))
113
+ return;
114
+ const row = ctx.targets.at(e.target).find(isRowTarget);
115
+ if (row)
116
+ ctx.setSelected({ key: refKey(row.ref), path: row.path });
117
+ });
118
+ const onUnload = useEvent((e) => {
119
+ if (!ctx?.session.hasPendingSaves)
120
+ return;
121
+ void ctx.session.flush();
122
+ e.preventDefault();
123
+ });
124
+ useEffect(() => {
125
+ document.documentElement.setAttribute('data-onpage-editing', '');
126
+ const click = (e) => onClick(e);
127
+ const key = (e) => onKey(e);
128
+ const focus = (e) => onFocus(e);
129
+ const unload = (e) => onUnload(e);
130
+ document.addEventListener('click', click, true);
131
+ document.addEventListener('keydown', key);
132
+ document.addEventListener('focusin', focus);
133
+ window.addEventListener('beforeunload', unload);
134
+ return () => {
135
+ document.documentElement.removeAttribute('data-onpage-editing');
136
+ document.removeEventListener('click', click, true);
137
+ document.removeEventListener('keydown', key);
138
+ document.removeEventListener('focusin', focus);
139
+ window.removeEventListener('beforeunload', unload);
140
+ };
141
+ }, [onClick, onFocus, onKey, onUnload]);
142
+ // Make every target reachable by keyboard (restored when the editor goes away).
143
+ const targets = ctx?.targets;
144
+ useEffect(() => {
145
+ const touched = [];
146
+ for (const t of targets?.all ?? []) {
147
+ if (t.kind === 'list' || !(t.el instanceof HTMLElement) || t.el.hasAttribute('tabindex'))
148
+ continue;
149
+ t.el.setAttribute('tabindex', '0');
150
+ t.el.setAttribute(FOCUSABLE_FLAG, '');
151
+ if (t.label)
152
+ t.el.setAttribute('aria-description', t.label);
153
+ touched.push(t.el);
154
+ }
155
+ return () => {
156
+ for (const el of touched) {
157
+ el.removeAttribute('tabindex');
158
+ el.removeAttribute(FOCUSABLE_FLAG);
159
+ el.removeAttribute('aria-description');
160
+ }
161
+ };
162
+ }, [targets]);
163
+ }
164
+ //# sourceMappingURL=usePageEvents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePageEvents.js","sourceRoot":"","sources":["../../src/editor/usePageEvents.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAGrE,MAAM,cAAc,GAAG,uBAAuB,CAAA;AAE9C,MAAM,UAAU,aAAa,CAAC,GAA8B,EAAE,IAA6B;IACzF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAa,EAAE,EAAE;QACzC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;QAClB,IAAI,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC;YAAE,OAAM;QAChD,MAAM,CAAC,GAAG,IAAI,EAAE,CAAA;QAChB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAM;QAC/B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAA;QACvE,IAAI,GAAG;YAAE,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;aAC7D,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACtC,IACE,KAAK;YACL,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE;gBACtC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;gBACrC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,KAAK,CAAC,EAAE;aACjB,CAAC,EACF,CAAC;YACD,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,CAAC,CAAC,eAAe,EAAE,CAAA;QACrB,CAAC;aAAM,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YACvC,CAAC,CAAC,cAAc,EAAE,CAAA,CAAC,kDAAkD;QACvE,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG,CAAC,GAAsB,EAAE,EAAE;QAC9C,IAAI,CAAC,GAAG,EAAE,QAAQ;YAAE,OAAO,KAAK,CAAA;QAChC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAA;QAClC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC1F,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QACvB,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAA;YAC7D,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YAC9F,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACrB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,GAAG,GAAG,CAAA;QAC3B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAC5C,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QAChG,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACxD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAgB,EAAE,EAAE;QAC1C,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAA;QAClC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAClB,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACrB,OAAM;QACR,CAAC;QACD,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;YAAE,OAAM;QAC9B,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACvC,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,IAAI,CAAC,CAAC,QAAQ;gBAAE,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;;gBAC7B,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YACvB,OAAM;QACR,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACvC,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QACD,IACE,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,EAC7F,CAAC;YACD,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC/E,CAAC,CAAC,cAAc,EAAE,CAAA;YACpB,OAAM;QACR,CAAC;QACD,IACE,CAAC,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC;YACrC,CAAC,CAAC,MAAM,YAAY,OAAO;YAC3B,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,EACrC,CAAC;YACD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YACpC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACrC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YACjC,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC1F,CAAC,CAAC,cAAc,EAAE,CAAA;iBACf,IAAI,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;gBACzD,CAAC,CAAC,cAAc,EAAE,CAAA;YACpB,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAa,EAAE,EAAE;QACzC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,YAAY,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC;YAAE,OAAM;QAC5F,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACtD,IAAI,GAAG;YAAE,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAoB,EAAE,EAAE;QACjD,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,eAAe;YAAE,OAAM;QACzC,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QACxB,CAAC,CAAC,cAAc,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAA;QAChE,MAAM,KAAK,GAAG,CAAC,CAAa,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAC3C,MAAM,GAAG,GAAG,CAAC,CAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,KAAK,GAAG,CAAC,CAAa,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG,CAAC,CAAoB,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACpD,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;QAC/C,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;QACzC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QAC3C,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;QAC/C,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,eAAe,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAA;YAC/D,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YAClD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;YAC5C,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YAC9C,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;QACpD,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEvC,gFAAgF;IAChF,MAAM,OAAO,GAAG,GAAG,EAAE,OAAO,CAAA;IAC5B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAkB,EAAE,CAAA;QACjC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;gBACtF,SAAQ;YACV,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;YAClC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,CAAC,CAAA;YACrC,IAAI,CAAC,CAAC,KAAK;gBAAE,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACpB,CAAC;QACD,OAAO,GAAG,EAAE;YACV,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;gBACzB,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;gBAC9B,EAAE,CAAC,eAAe,CAAC,cAAc,CAAC,CAAA;gBAClC,EAAE,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAA;YACxC,CAAC;QACH,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;AACf,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @payload-onpage/react/editor-kit — building blocks for custom field editors
3
+ * (the default editors and @payload-onpage/lexical use exactly these).
4
+ *
5
+ * function JsonEditor({ field, value, element, commit, close, t }: FieldEditorProps) {
6
+ * return <Dialog variant="popover" anchor={element} title={field.label} onClose={close} t={t}>…</Dialog>
7
+ * }
8
+ */
9
+ export { Dialog, type DialogProps } from './ui/Dialog.tsx';
10
+ export { useOnPage } from './context.tsx';
11
+ export { useDebouncedSearch } from './editors/useDebouncedSearch.ts';
12
+ export { escapeHtml } from './editors/InlineText.tsx';
13
+ export { HIDDEN, UI, caretAt, copyTypography, placeCaret, placeOver, typographyOf, popoverPosition, } from './dom.ts';
14
+ export { useTrackElement, useLayoutTick, notifyLayout } from './layout.ts';
15
+ export { useEvent } from './useEvent.ts';
16
+ export { sanitizeHtml } from './sanitize.ts';
17
+ export type { EditorRegistry, FieldEditorDef, FieldEditorProps } from './types.ts';
18
+ export type { Translate } from './messages.ts';
19
+ //# sourceMappingURL=editor-kit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-kit.d.ts","sourceRoot":"","sources":["../src/editor-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @payload-onpage/react/editor-kit — building blocks for custom field editors
3
+ * (the default editors and @payload-onpage/lexical use exactly these).
4
+ *
5
+ * function JsonEditor({ field, value, element, commit, close, t }: FieldEditorProps) {
6
+ * return <Dialog variant="popover" anchor={element} title={field.label} onClose={close} t={t}>…</Dialog>
7
+ * }
8
+ */
9
+ export { Dialog } from "./ui/Dialog.js";
10
+ export { useOnPage } from "./context.js";
11
+ export { useDebouncedSearch } from "./editors/useDebouncedSearch.js";
12
+ export { escapeHtml } from "./editors/InlineText.js";
13
+ export { HIDDEN, UI, caretAt, copyTypography, placeCaret, placeOver, typographyOf, popoverPosition, } from "./dom.js";
14
+ export { useTrackElement, useLayoutTick, notifyLayout } from "./layout.js";
15
+ export { useEvent } from "./useEvent.js";
16
+ export { sanitizeHtml } from "./sanitize.js";
17
+ //# sourceMappingURL=editor-kit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-kit.js","sourceRoot":"","sources":["../src/editor-kit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAoB,MAAM,gBAAiB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAe,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAA0B,CAAA;AACrD,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,eAAe,GAChB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { FieldEditorProps } from '../types.ts';
2
+ export declare function CheckboxEditor({ field, value, element, commit, close, t }: FieldEditorProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=CheckboxEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckboxEditor.d.ts","sourceRoot":"","sources":["../../src/editors/CheckboxEditor.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAGnD,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BAyB3F"}
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Dialog } from "../ui/Dialog.js";
4
+ export function CheckboxEditor({ field, value, element, commit, close, t }) {
5
+ return (_jsx(Dialog, { variant: "popover", anchor: element, title: field.label, onClose: close, t: t, testId: "onpage-checkbox", children: _jsxs("label", { className: "po-check", children: [_jsx("input", { type: "checkbox", "data-autofocus": true, checked: Boolean(value ?? field.defaultValue), onChange: (e) => {
6
+ commit(e.target.checked);
7
+ close();
8
+ }, "data-testid": "onpage-checkbox-input" }), field.label] }) }));
9
+ }
10
+ //# sourceMappingURL=CheckboxEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckboxEditor.js","sourceRoot":"","sources":["../../src/editors/CheckboxEditor.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAkB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAoB;IAC1F,OAAO,CACL,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,KAAK,EACd,CAAC,EAAE,CAAC,EACJ,MAAM,EAAC,iBAAiB,YAExB,iBAAO,SAAS,EAAC,UAAU,aACzB,gBACE,IAAI,EAAC,UAAU,0BAEf,OAAO,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC,EAC7C,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;wBACd,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;wBACxB,KAAK,EAAE,CAAA;oBACT,CAAC,iBACW,uBAAuB,GACnC,EACD,KAAK,CAAC,KAAK,IACN,GACD,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { FieldEditorProps } from '../types.ts';
2
+ /** Hex color with a native picker. Use it from a text field: `admin.custom.onpage.editor: 'color'`. */
3
+ export declare function ColorEditor({ field, value, element, commit, preview, close, live, t, }: FieldEditorProps): import("react").JSX.Element;
4
+ //# sourceMappingURL=ColorEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorEditor.d.ts","sourceRoot":"","sources":["../../src/editors/ColorEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAKnD,uGAAuG;AACvG,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EACJ,CAAC,GACF,EAAE,gBAAgB,+BA6ClB"}
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { Dialog } from "../ui/Dialog.js";
5
+ const HEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
6
+ /** Hex color with a native picker. Use it from a text field: `admin.custom.onpage.editor: 'color'`. */
7
+ export function ColorEditor({ field, value, element, commit, preview, close, live, t, }) {
8
+ const [draft, setDraft] = useState(typeof value === 'string' ? value : '');
9
+ const change = (v) => {
10
+ setDraft(v);
11
+ if (live && HEX.test(v))
12
+ preview(v);
13
+ };
14
+ const save = () => {
15
+ if (draft !== (value ?? '') && (draft === '' || HEX.test(draft)))
16
+ commit(draft || null);
17
+ close();
18
+ };
19
+ return (_jsxs(Dialog, { variant: "popover", anchor: element, title: field.label, onClose: close, t: t, width: 260, testId: "onpage-color", children: [_jsxs("div", { className: "po-row po-inline-row", children: [_jsx("input", { type: "color", "aria-label": field.label, value: HEX.test(draft) && draft.length === 7 ? draft : '#000000', onChange: (e) => change(e.target.value), "data-testid": "onpage-color-picker" }), _jsx("input", { className: "po-input", "aria-label": field.label, "data-autofocus": true, value: draft, placeholder: "#1e40af", "aria-invalid": draft !== '' && !HEX.test(draft), onChange: (e) => change(e.target.value), onKeyDown: (e) => e.key === 'Enter' && save(), "data-testid": "onpage-color-input" })] }), _jsx("button", { type: "button", className: "po-btn po-primary", onClick: save, "data-testid": "onpage-apply", children: t('common.apply') })] }));
20
+ }
21
+ //# sourceMappingURL=ColorEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorEditor.js","sourceRoot":"","sources":["../../src/editors/ColorEditor.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAkB,CAAA;AAEzC,MAAM,GAAG,GAAG,iCAAiC,CAAA;AAE7C,uGAAuG;AACvG,MAAM,UAAU,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EACJ,CAAC,GACgB;IACjB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE;QAC3B,QAAQ,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACrC,CAAC,CAAA;IACD,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,KAAK,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAA;QACvF,KAAK,EAAE,CAAA;IACT,CAAC,CAAA;IACD,OAAO,CACL,MAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,KAAK,EACd,CAAC,EAAE,CAAC,EACJ,KAAK,EAAE,GAAG,EACV,MAAM,EAAC,cAAc,aAErB,eAAK,SAAS,EAAC,sBAAsB,aACnC,gBACE,IAAI,EAAC,OAAO,gBACA,KAAK,CAAC,KAAK,EACvB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAChE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,iBAC3B,qBAAqB,GACjC,EACF,gBACE,SAAS,EAAC,UAAU,gBACR,KAAK,CAAC,KAAK,0BAEvB,KAAK,EAAE,KAAK,EACZ,WAAW,EAAC,SAAS,kBACP,KAAK,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAC9C,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACvC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,EAAE,iBACjC,oBAAoB,GAChC,IACE,EACN,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,mBAAmB,EAAC,OAAO,EAAE,IAAI,iBAAc,cAAc,YAC1F,CAAC,CAAC,cAAc,CAAC,GACX,IACF,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FieldEditorProps } from '../types.ts';
2
+ export declare function DateEditor({ field, value, element, commit, close, t }: FieldEditorProps): import("react").JSX.Element;
3
+ //# sourceMappingURL=DateEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateEditor.d.ts","sourceRoot":"","sources":["../../src/editors/DateEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAanD,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,gBAAgB,+BA+CvF"}