payload-better-editor 1.0.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 +57 -0
- package/dist/admin/ErrorBoundary.d.ts +17 -0
- package/dist/admin/ErrorBoundary.js +62 -0
- package/dist/admin/ErrorBoundary.js.map +1 -0
- package/dist/admin/LiveEditorOverlay.d.ts +12 -0
- package/dist/admin/LiveEditorOverlay.js +160 -0
- package/dist/admin/LiveEditorOverlay.js.map +1 -0
- package/dist/admin/LiveEditorToggle.d.ts +7 -0
- package/dist/admin/LiveEditorToggle.js +84 -0
- package/dist/admin/LiveEditorToggle.js.map +1 -0
- package/dist/admin/PreviewFrame.d.ts +22 -0
- package/dist/admin/PreviewFrame.js +137 -0
- package/dist/admin/PreviewFrame.js.map +1 -0
- package/dist/admin/PreviewToolbar.d.ts +16 -0
- package/dist/admin/PreviewToolbar.js +90 -0
- package/dist/admin/PreviewToolbar.js.map +1 -0
- package/dist/admin/SettingsBanner.d.ts +3 -0
- package/dist/admin/SettingsBanner.js +105 -0
- package/dist/admin/SettingsBanner.js.map +1 -0
- package/dist/admin/ViewportToggle.d.ts +7 -0
- package/dist/admin/ViewportToggle.js +79 -0
- package/dist/admin/ViewportToggle.js.map +1 -0
- package/dist/admin/blocks/AddBlockDrawer.d.ts +9 -0
- package/dist/admin/blocks/AddBlockDrawer.js +16 -0
- package/dist/admin/blocks/AddBlockDrawer.js.map +1 -0
- package/dist/admin/blocks/BlockActionsToolbar.d.ts +15 -0
- package/dist/admin/blocks/BlockActionsToolbar.js +102 -0
- package/dist/admin/blocks/BlockActionsToolbar.js.map +1 -0
- package/dist/admin/blocks/BlockEmptyState.d.ts +6 -0
- package/dist/admin/blocks/BlockEmptyState.js +26 -0
- package/dist/admin/blocks/BlockEmptyState.js.map +1 -0
- package/dist/admin/blocks/BlockHeader.d.ts +7 -0
- package/dist/admin/blocks/BlockHeader.js +32 -0
- package/dist/admin/blocks/BlockHeader.js.map +1 -0
- package/dist/admin/blocks/schema.d.ts +19 -0
- package/dist/admin/blocks/schema.js +80 -0
- package/dist/admin/blocks/schema.js.map +1 -0
- package/dist/admin/blocks/useBlockActions.d.ts +24 -0
- package/dist/admin/blocks/useBlockActions.js +100 -0
- package/dist/admin/blocks/useBlockActions.js.map +1 -0
- package/dist/admin/icons.d.ts +24 -0
- package/dist/admin/icons.js +36 -0
- package/dist/admin/icons.js.map +1 -0
- package/dist/admin/sidebar/BlockSettingsTab.d.ts +10 -0
- package/dist/admin/sidebar/BlockSettingsTab.js +153 -0
- package/dist/admin/sidebar/BlockSettingsTab.js.map +1 -0
- package/dist/admin/sidebar/DocumentFieldsTab.d.ts +8 -0
- package/dist/admin/sidebar/DocumentFieldsTab.js +38 -0
- package/dist/admin/sidebar/DocumentFieldsTab.js.map +1 -0
- package/dist/admin/sidebar/DocumentMetaTab.d.ts +2 -0
- package/dist/admin/sidebar/DocumentMetaTab.js +11 -0
- package/dist/admin/sidebar/DocumentMetaTab.js.map +1 -0
- package/dist/admin/sidebar/DocumentSettingsTab.d.ts +2 -0
- package/dist/admin/sidebar/DocumentSettingsTab.js +48 -0
- package/dist/admin/sidebar/DocumentSettingsTab.js.map +1 -0
- package/dist/admin/sidebar/Sidebar.d.ts +10 -0
- package/dist/admin/sidebar/Sidebar.js +92 -0
- package/dist/admin/sidebar/Sidebar.js.map +1 -0
- package/dist/client.d.ts +34 -0
- package/dist/client.js +30 -0
- package/dist/client.js.map +1 -0
- package/dist/global.d.ts +4 -0
- package/dist/global.js +200 -0
- package/dist/global.js.map +1 -0
- package/dist/hooks/useAddBlockDrawer.d.ts +14 -0
- package/dist/hooks/useAddBlockDrawer.js +26 -0
- package/dist/hooks/useAddBlockDrawer.js.map +1 -0
- package/dist/hooks/useBlockActionMessages.d.ts +8 -0
- package/dist/hooks/useBlockActionMessages.js +107 -0
- package/dist/hooks/useBlockActionMessages.js.map +1 -0
- package/dist/hooks/useDocConfig.d.ts +6 -0
- package/dist/hooks/useDocConfig.js +18 -0
- package/dist/hooks/useDocConfig.js.map +1 -0
- package/dist/hooks/useFocusTrap.d.ts +2 -0
- package/dist/hooks/useFocusTrap.js +84 -0
- package/dist/hooks/useFocusTrap.js.map +1 -0
- package/dist/hooks/useFullscreenOverlay.d.ts +2 -0
- package/dist/hooks/useFullscreenOverlay.js +30 -0
- package/dist/hooks/useFullscreenOverlay.js.map +1 -0
- package/dist/hooks/useIframeResizeObserver.d.ts +2 -0
- package/dist/hooks/useIframeResizeObserver.js +20 -0
- package/dist/hooks/useIframeResizeObserver.js.map +1 -0
- package/dist/hooks/useLatestRef.d.ts +6 -0
- package/dist/hooks/useLatestRef.js +12 -0
- package/dist/hooks/useLatestRef.js.map +1 -0
- package/dist/hooks/useMainWrapperPortal.d.ts +1 -0
- package/dist/hooks/useMainWrapperPortal.js +64 -0
- package/dist/hooks/useMainWrapperPortal.js.map +1 -0
- package/dist/hooks/useOverlayKeyboard.d.ts +6 -0
- package/dist/hooks/useOverlayKeyboard.js +43 -0
- package/dist/hooks/useOverlayKeyboard.js.map +1 -0
- package/dist/hooks/usePreviewBinding.d.ts +28 -0
- package/dist/hooks/usePreviewBinding.js +108 -0
- package/dist/hooks/usePreviewBinding.js.map +1 -0
- package/dist/hooks/usePreviewHandleDrag.d.ts +11 -0
- package/dist/hooks/usePreviewHandleDrag.js +53 -0
- package/dist/hooks/usePreviewHandleDrag.js.map +1 -0
- package/dist/hooks/usePreviewSelectionSync.d.ts +15 -0
- package/dist/hooks/usePreviewSelectionSync.js +80 -0
- package/dist/hooks/usePreviewSelectionSync.js.map +1 -0
- package/dist/hooks/usePreviewSettingsSync.d.ts +17 -0
- package/dist/hooks/usePreviewSettingsSync.js +55 -0
- package/dist/hooks/usePreviewSettingsSync.js.map +1 -0
- package/dist/hooks/useSidebarResize.d.ts +8 -0
- package/dist/hooks/useSidebarResize.js +101 -0
- package/dist/hooks/useSidebarResize.js.map +1 -0
- package/dist/hooks/useViewportState.d.ts +10 -0
- package/dist/hooks/useViewportState.js +44 -0
- package/dist/hooks/useViewportState.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/constants.d.ts +22 -0
- package/dist/internal/constants.js +38 -0
- package/dist/internal/constants.js.map +1 -0
- package/dist/internal/dom.d.ts +4 -0
- package/dist/internal/dom.js +6 -0
- package/dist/internal/dom.js.map +1 -0
- package/dist/internal/iframe.d.ts +5 -0
- package/dist/internal/iframe.js +12 -0
- package/dist/internal/iframe.js.map +1 -0
- package/dist/internal/limits.d.ts +9 -0
- package/dist/internal/limits.js +11 -0
- package/dist/internal/limits.js.map +1 -0
- package/dist/internal/path.d.ts +5 -0
- package/dist/internal/path.js +12 -0
- package/dist/internal/path.js.map +1 -0
- package/dist/internal/postmessage.d.ts +3 -0
- package/dist/internal/postmessage.js +21 -0
- package/dist/internal/postmessage.js.map +1 -0
- package/dist/internal/storage-keys.d.ts +8 -0
- package/dist/internal/storage-keys.js +9 -0
- package/dist/internal/storage-keys.js.map +1 -0
- package/dist/internal/storage.d.ts +2 -0
- package/dist/internal/storage.js +20 -0
- package/dist/internal/storage.js.map +1 -0
- package/dist/preview/HoverToolbar.d.ts +8 -0
- package/dist/preview/HoverToolbar.js +48 -0
- package/dist/preview/HoverToolbar.js.map +1 -0
- package/dist/preview/HoverToolbarController.d.ts +31 -0
- package/dist/preview/HoverToolbarController.js +160 -0
- package/dist/preview/HoverToolbarController.js.map +1 -0
- package/dist/preview/hover-css.d.ts +11 -0
- package/dist/preview/hover-css.js +94 -0
- package/dist/preview/hover-css.js.map +1 -0
- package/dist/preview/installClickToFocus.d.ts +6 -0
- package/dist/preview/installClickToFocus.js +21 -0
- package/dist/preview/installClickToFocus.js.map +1 -0
- package/dist/preview/installHoverStyles.d.ts +2 -0
- package/dist/preview/installHoverStyles.js +15 -0
- package/dist/preview/installHoverStyles.js.map +1 -0
- package/dist/preview/protocol.d.ts +11 -0
- package/dist/preview/protocol.js +19 -0
- package/dist/preview/protocol.js.map +1 -0
- package/dist/preview/toolbar-position.d.ts +20 -0
- package/dist/preview/toolbar-position.js +22 -0
- package/dist/preview/toolbar-position.js.map +1 -0
- package/dist/providers/BetterEditorConfigProvider.d.ts +14 -0
- package/dist/providers/BetterEditorConfigProvider.js +26 -0
- package/dist/providers/BetterEditorConfigProvider.js.map +1 -0
- package/dist/providers/OverlayProviders.d.ts +8 -0
- package/dist/providers/OverlayProviders.js +22 -0
- package/dist/providers/OverlayProviders.js.map +1 -0
- package/dist/state/useBetterEditorSettings.d.ts +18 -0
- package/dist/state/useBetterEditorSettings.js +65 -0
- package/dist/state/useBetterEditorSettings.js.map +1 -0
- package/dist/state/useEditorHistory.d.ts +16 -0
- package/dist/state/useEditorHistory.js +157 -0
- package/dist/state/useEditorHistory.js.map +1 -0
- package/dist/styles/blocks-tab.css +163 -0
- package/dist/styles/overlay.css +133 -0
- package/dist/styles/preview.css +211 -0
- package/dist/styles/settings-banner.css +73 -0
- package/dist/styles/sidebar.css +88 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +117 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 scorpio-99
|
|
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
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# payload-better-editor
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/payload-better-editor)
|
|
4
|
+
[](https://www.npmjs.com/package/payload-better-editor)
|
|
5
|
+
[](https://github.com/scorpio-99/payload-better-editor)
|
|
6
|
+
|
|
7
|
+
Block editor plugin for [Payload CMS](https://payloadcms.com) that adds a side-by-side live-preview iframe and sidebar to the edit view.
|
|
8
|
+
|
|
9
|
+
## Skip the giant form - pick a block, edit just that block
|
|
10
|
+
|
|
11
|
+
Open the editor from any document's edit view. The preview iframe loads your live frontend; clicking a block selects it and opens its real Payload fields in the sidebar - no schema duplication, no custom components.
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
## Floating in-iframe toolbar
|
|
16
|
+
|
|
17
|
+
Hover any block in the preview to surface its floating action toolbar - move up, move down, duplicate, add-below, delete. All actions go through Payload's form state and are tracked by the plugin's undo/redo history.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
## Viewports & layout controls
|
|
22
|
+
|
|
23
|
+
Switch between Desktop, Tablet, Mobile, and Responsive (drag-resizable). The fullscreen button is independent - it puts the whole editor (preview + sidebar) into fullscreen while the iframe keeps the viewport size you picked. The sidebar itself can be drag-resized to any width or collapsed entirely to give the preview the full canvas.
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
## Further features
|
|
28
|
+
|
|
29
|
+
- **Page, Blocks, Settings tabs** auto-derived from your document's tab structure
|
|
30
|
+
- **`BetterEditorSettings` global** so admins can change sidebar position, hover colours, tablet/mobile breakpoints, and hover-toolbar placement live - no re-deploy
|
|
31
|
+
- **Block actions in the sidebar too** - the same move / duplicate / add-below / delete actions are mirrored in the sidebar's Blocks tab, so power users don't have to reach for the iframe toolbar
|
|
32
|
+
- **Undo and Redo** with `Cmd/Ctrl+Z` and `Cmd/Ctrl+Shift+Z` - snapshot-based, covers every block mutation
|
|
33
|
+
- **Interact mode** toggle so clicks pass through to forms, accordions, links inside the preview
|
|
34
|
+
- **Loading skeleton** in the iframe and an error boundary so a single bad block can't take the admin down
|
|
35
|
+
- **Click-to-edit** works at arbitrary nesting depth - clicking a deeply nested block walks up to its innermost wrapper
|
|
36
|
+
- **Real Payload fields** in the sidebar via `RenderFields`, so custom field components, validations, and access control all just work
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pnpm add payload-better-editor
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
See [DEVELOPERS.md](./DEVELOPERS.md) for setup, plugin options, runtime settings, and architecture notes.
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- Payload `>=3.81.0`
|
|
49
|
+
- React 19
|
|
50
|
+
|
|
51
|
+
> **Found a bug?** Early-stage plugin, feedback is appreciated. [Open an issue](https://github.com/scorpio-99/payload-better-editor/issues/new) with steps to reproduce, your Payload version, and a minimal example. PRs welcome.
|
|
52
|
+
|
|
53
|
+
## Contributors
|
|
54
|
+
|
|
55
|
+
<a href="https://github.com/scorpio-99/payload-better-editor/graphs/contributors">
|
|
56
|
+
<img src="https://contrib.rocks/image?repo=scorpio-99/payload-better-editor" />
|
|
57
|
+
</a>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onReset?: () => void;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
type State = {
|
|
8
|
+
error: Error | null;
|
|
9
|
+
};
|
|
10
|
+
export declare class OverlayErrorBoundary extends React.Component<Props, State> {
|
|
11
|
+
state: State;
|
|
12
|
+
static getDerivedStateFromError(error: Error): State;
|
|
13
|
+
componentDidCatch(error: Error, info: React.ErrorInfo): void;
|
|
14
|
+
private reset;
|
|
15
|
+
render(): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const isDev = process.env.NODE_ENV !== 'production';
|
|
5
|
+
export class OverlayErrorBoundary extends React.Component {
|
|
6
|
+
state = {
|
|
7
|
+
error: null
|
|
8
|
+
};
|
|
9
|
+
static getDerivedStateFromError(error) {
|
|
10
|
+
return {
|
|
11
|
+
error
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
componentDidCatch(error, info) {
|
|
15
|
+
console.error('[better-editor] overlay crashed', error, info);
|
|
16
|
+
}
|
|
17
|
+
reset = ()=>{
|
|
18
|
+
this.props.onReset?.();
|
|
19
|
+
this.setState({
|
|
20
|
+
error: null
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
render() {
|
|
24
|
+
const { error } = this.state;
|
|
25
|
+
if (!error) return this.props.children;
|
|
26
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
27
|
+
className: "better-editor better-editor--errored",
|
|
28
|
+
role: "alert",
|
|
29
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
30
|
+
className: "better-editor__error",
|
|
31
|
+
children: [
|
|
32
|
+
/*#__PURE__*/ _jsx("h3", {
|
|
33
|
+
children: "Better Editor crashed"
|
|
34
|
+
}),
|
|
35
|
+
/*#__PURE__*/ _jsx("p", {
|
|
36
|
+
children: error.message || 'Unknown error.'
|
|
37
|
+
}),
|
|
38
|
+
isDev && error.stack ? /*#__PURE__*/ _jsx("pre", {
|
|
39
|
+
children: error.stack
|
|
40
|
+
}) : null,
|
|
41
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
42
|
+
className: "better-editor__error-actions",
|
|
43
|
+
children: [
|
|
44
|
+
/*#__PURE__*/ _jsx("button", {
|
|
45
|
+
type: "button",
|
|
46
|
+
onClick: this.reset,
|
|
47
|
+
children: "Try again"
|
|
48
|
+
}),
|
|
49
|
+
/*#__PURE__*/ _jsx("button", {
|
|
50
|
+
type: "button",
|
|
51
|
+
onClick: this.props.onClose,
|
|
52
|
+
children: "Close editor"
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=ErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/admin/ErrorBoundary.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\ntype Props = {\n onClose: () => void\n onReset?: () => void\n children: React.ReactNode\n}\n\ntype State = {\n error: Error | null\n}\n\nconst isDev = process.env.NODE_ENV !== 'production'\n\nexport class OverlayErrorBoundary extends React.Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(error: Error): State {\n return { error }\n }\n\n componentDidCatch(error: Error, info: React.ErrorInfo) {\n console.error('[better-editor] overlay crashed', error, info)\n }\n\n private reset = () => {\n this.props.onReset?.()\n this.setState({ error: null })\n }\n\n render() {\n const { error } = this.state\n if (!error) return this.props.children\n\n return (\n <div className=\"better-editor better-editor--errored\" role=\"alert\">\n <div className=\"better-editor__error\">\n <h3>Better Editor crashed</h3>\n <p>{error.message || 'Unknown error.'}</p>\n {isDev && error.stack ? <pre>{error.stack}</pre> : null}\n <div className=\"better-editor__error-actions\">\n <button type=\"button\" onClick={this.reset}>\n Try again\n </button>\n <button type=\"button\" onClick={this.props.onClose}>\n Close editor\n </button>\n </div>\n </div>\n </div>\n )\n }\n}\n"],"names":["React","isDev","process","env","NODE_ENV","OverlayErrorBoundary","Component","state","error","getDerivedStateFromError","componentDidCatch","info","console","reset","props","onReset","setState","render","children","div","className","role","h3","p","message","stack","pre","button","type","onClick","onClose"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAYzB,MAAMC,QAAQC,QAAQC,GAAG,CAACC,QAAQ,KAAK;AAEvC,OAAO,MAAMC,6BAA6BL,MAAMM,SAAS;IACvDC,QAAe;QAAEC,OAAO;IAAK,EAAC;IAE9B,OAAOC,yBAAyBD,KAAY,EAAS;QACnD,OAAO;YAAEA;QAAM;IACjB;IAEAE,kBAAkBF,KAAY,EAAEG,IAAqB,EAAE;QACrDC,QAAQJ,KAAK,CAAC,mCAAmCA,OAAOG;IAC1D;IAEQE,QAAQ;QACd,IAAI,CAACC,KAAK,CAACC,OAAO;QAClB,IAAI,CAACC,QAAQ,CAAC;YAAER,OAAO;QAAK;IAC9B,EAAC;IAEDS,SAAS;QACP,MAAM,EAAET,KAAK,EAAE,GAAG,IAAI,CAACD,KAAK;QAC5B,IAAI,CAACC,OAAO,OAAO,IAAI,CAACM,KAAK,CAACI,QAAQ;QAEtC,qBACE,KAACC;YAAIC,WAAU;YAAuCC,MAAK;sBACzD,cAAA,MAACF;gBAAIC,WAAU;;kCACb,KAACE;kCAAG;;kCACJ,KAACC;kCAAGf,MAAMgB,OAAO,IAAI;;oBACpBvB,SAASO,MAAMiB,KAAK,iBAAG,KAACC;kCAAKlB,MAAMiB,KAAK;yBAAU;kCACnD,MAACN;wBAAIC,WAAU;;0CACb,KAACO;gCAAOC,MAAK;gCAASC,SAAS,IAAI,CAAChB,KAAK;0CAAE;;0CAG3C,KAACc;gCAAOC,MAAK;gCAASC,SAAS,IAAI,CAACf,KAAK,CAACgB,OAAO;0CAAE;;;;;;;IAO7D;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../styles/overlay.css';
|
|
3
|
+
import '../styles/preview.css';
|
|
4
|
+
import '../styles/sidebar.css';
|
|
5
|
+
import '../styles/blocks-tab.css';
|
|
6
|
+
export type LiveEditorOverlayProps = {
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
blocksField: string;
|
|
9
|
+
storageNamespace?: string;
|
|
10
|
+
adminPortalSelector?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const LiveEditorOverlay: React.FC<LiveEditorOverlayProps>;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useState } from 'react';
|
|
4
|
+
import { useLivePreviewContext } from '@payloadcms/ui';
|
|
5
|
+
import { PreviewFrame } from './PreviewFrame';
|
|
6
|
+
import { PreviewToolbar } from './PreviewToolbar';
|
|
7
|
+
import { Sidebar } from './sidebar/Sidebar';
|
|
8
|
+
import { useBetterEditorSettings } from '../state/useBetterEditorSettings';
|
|
9
|
+
import { useEditorHistory } from '../state/useEditorHistory';
|
|
10
|
+
import { useSidebarResize } from '../hooks/useSidebarResize';
|
|
11
|
+
import { useViewportState } from '../hooks/useViewportState';
|
|
12
|
+
import { useFullscreenOverlay } from '../hooks/useFullscreenOverlay';
|
|
13
|
+
import { useBlockActionMessages } from '../hooks/useBlockActionMessages';
|
|
14
|
+
import { useOverlayKeyboard } from '../hooks/useOverlayKeyboard';
|
|
15
|
+
import { useFocusTrap } from '../hooks/useFocusTrap';
|
|
16
|
+
import { OverlayProviders } from '../providers/OverlayProviders';
|
|
17
|
+
import '../styles/overlay.css';
|
|
18
|
+
import '../styles/preview.css';
|
|
19
|
+
import '../styles/sidebar.css';
|
|
20
|
+
import '../styles/blocks-tab.css';
|
|
21
|
+
const RESIZE_HANDLE_PX = 6;
|
|
22
|
+
const classes = (...parts)=>parts.filter(Boolean).join(' ');
|
|
23
|
+
export const LiveEditorOverlay = ({ onClose, blocksField, storageNamespace, adminPortalSelector })=>{
|
|
24
|
+
// Selection state lives outside OverlayProviders so the error boundary's
|
|
25
|
+
// onReset can clear it without remounting providers.
|
|
26
|
+
const [selectedBlockPath, setSelectedBlockPath] = useState(null);
|
|
27
|
+
const clearSelection = useCallback(()=>setSelectedBlockPath(null), []);
|
|
28
|
+
return /*#__PURE__*/ _jsx(OverlayProviders, {
|
|
29
|
+
onClose: onClose,
|
|
30
|
+
onReset: clearSelection,
|
|
31
|
+
storageNamespace: storageNamespace,
|
|
32
|
+
adminPortalSelector: adminPortalSelector,
|
|
33
|
+
children: /*#__PURE__*/ _jsx(LiveEditorOverlayInner, {
|
|
34
|
+
onClose: onClose,
|
|
35
|
+
blocksField: blocksField,
|
|
36
|
+
selectedBlockPath: selectedBlockPath,
|
|
37
|
+
setSelectedBlockPath: setSelectedBlockPath
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const LiveEditorOverlayInner = ({ onClose, blocksField, selectedBlockPath, setSelectedBlockPath })=>{
|
|
42
|
+
const settings = useBetterEditorSettings();
|
|
43
|
+
const history = useEditorHistory();
|
|
44
|
+
const { previewURL } = useLivePreviewContext();
|
|
45
|
+
const { sidebarWidth, isResizing, onResizeStart, onResizeKeyDown } = useSidebarResize(settings.sidebarPosition);
|
|
46
|
+
const { viewport, setViewport, setResponsiveWidth, viewportWidth } = useViewportState(settings);
|
|
47
|
+
// Live-observed iframe width; PreviewFrame reports it via the
|
|
48
|
+
// ResizeObserver, the toolbar's width-chip reads it.
|
|
49
|
+
const [iframeWidth, setIframeWidth] = useState(null);
|
|
50
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
51
|
+
const toggleFullscreen = useCallback(()=>setIsFullscreen((v)=>!v), []);
|
|
52
|
+
const exitFullscreen = useCallback(()=>setIsFullscreen(false), []);
|
|
53
|
+
const overlayRef = useFullscreenOverlay(isFullscreen, exitFullscreen);
|
|
54
|
+
useFocusTrap(overlayRef);
|
|
55
|
+
const clearSelection = useCallback(()=>setSelectedBlockPath(null), [
|
|
56
|
+
setSelectedBlockPath
|
|
57
|
+
]);
|
|
58
|
+
const { addBelowRequestId } = useBlockActionMessages({
|
|
59
|
+
selectedBlockPath,
|
|
60
|
+
setSelectedBlockPath
|
|
61
|
+
});
|
|
62
|
+
useOverlayKeyboard({
|
|
63
|
+
onClose,
|
|
64
|
+
history
|
|
65
|
+
});
|
|
66
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
67
|
+
const toggleSidebar = useCallback(()=>setSidebarCollapsed((v)=>!v), []);
|
|
68
|
+
const [interactMode, setInteractMode] = useState(false);
|
|
69
|
+
const toggleInteractMode = useCallback(()=>setInteractMode((v)=>!v), []);
|
|
70
|
+
const isLeft = settings.sidebarPosition === 'left';
|
|
71
|
+
const showSidebar = !sidebarCollapsed;
|
|
72
|
+
const gridTemplateColumns = !showSidebar ? '1fr' : isLeft ? `${sidebarWidth}px ${RESIZE_HANDLE_PX}px 1fr` : `1fr ${RESIZE_HANDLE_PX}px ${sidebarWidth}px`;
|
|
73
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
74
|
+
ref: overlayRef,
|
|
75
|
+
className: classes('better-editor', isResizing && 'better-editor--resizing', isFullscreen && 'better-editor--fullscreen'),
|
|
76
|
+
role: "dialog",
|
|
77
|
+
"aria-modal": "true",
|
|
78
|
+
"aria-label": "Better Editor",
|
|
79
|
+
tabIndex: -1,
|
|
80
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
81
|
+
className: "better-editor__body",
|
|
82
|
+
style: {
|
|
83
|
+
gridTemplateColumns
|
|
84
|
+
},
|
|
85
|
+
children: [
|
|
86
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
87
|
+
className: "better-editor__preview",
|
|
88
|
+
style: {
|
|
89
|
+
order: isLeft ? 2 : 0
|
|
90
|
+
},
|
|
91
|
+
children: [
|
|
92
|
+
/*#__PURE__*/ _jsx(PreviewToolbar, {
|
|
93
|
+
history: history,
|
|
94
|
+
viewport: viewport,
|
|
95
|
+
onViewportChange: setViewport,
|
|
96
|
+
iframeWidth: iframeWidth,
|
|
97
|
+
isFullscreen: isFullscreen,
|
|
98
|
+
onFullscreenToggle: toggleFullscreen,
|
|
99
|
+
interactMode: interactMode,
|
|
100
|
+
onInteractToggle: toggleInteractMode,
|
|
101
|
+
sidebarCollapsed: sidebarCollapsed,
|
|
102
|
+
onSidebarToggle: toggleSidebar
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ _jsx("div", {
|
|
105
|
+
className: "better-editor__preview-stage",
|
|
106
|
+
children: /*#__PURE__*/ _jsx(PreviewFrame, {
|
|
107
|
+
previewURL: previewURL,
|
|
108
|
+
hoverColorTopLevel: settings.hoverColorTopLevel,
|
|
109
|
+
hoverColorNested: settings.hoverColorNested,
|
|
110
|
+
hoverOutlineWidth: settings.hoverOutlineWidth,
|
|
111
|
+
showHoverToolbar: settings.showHoverToolbar,
|
|
112
|
+
hoverToolbarPosition: settings.hoverToolbarPosition,
|
|
113
|
+
selectedBlockPath: selectedBlockPath,
|
|
114
|
+
interactMode: interactMode,
|
|
115
|
+
viewport: viewport,
|
|
116
|
+
viewportWidth: viewportWidth,
|
|
117
|
+
resizable: viewport === 'responsive',
|
|
118
|
+
onResize: setResponsiveWidth,
|
|
119
|
+
onIframeWidthChange: setIframeWidth
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
]
|
|
123
|
+
}),
|
|
124
|
+
showSidebar ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
125
|
+
children: [
|
|
126
|
+
/*#__PURE__*/ _jsx("div", {
|
|
127
|
+
className: "better-editor__resize-handle",
|
|
128
|
+
style: {
|
|
129
|
+
order: 1
|
|
130
|
+
},
|
|
131
|
+
role: "separator",
|
|
132
|
+
"aria-orientation": "vertical",
|
|
133
|
+
"aria-label": "Resize sidebar (use ← / → arrow keys)",
|
|
134
|
+
"aria-valuenow": sidebarWidth,
|
|
135
|
+
tabIndex: 0,
|
|
136
|
+
onMouseDown: onResizeStart,
|
|
137
|
+
onKeyDown: onResizeKeyDown
|
|
138
|
+
}),
|
|
139
|
+
/*#__PURE__*/ _jsx("aside", {
|
|
140
|
+
className: "better-editor__sidebar",
|
|
141
|
+
style: {
|
|
142
|
+
order: isLeft ? 0 : 2
|
|
143
|
+
},
|
|
144
|
+
children: /*#__PURE__*/ _jsx(Sidebar, {
|
|
145
|
+
selectedBlockPath: selectedBlockPath,
|
|
146
|
+
onClearSelection: clearSelection,
|
|
147
|
+
onSelectPath: setSelectedBlockPath,
|
|
148
|
+
forceFullWidthFields: settings.forceFullWidthFields,
|
|
149
|
+
blocksField: blocksField,
|
|
150
|
+
addBelowRequestId: addBelowRequestId
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
]
|
|
154
|
+
}) : null
|
|
155
|
+
]
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
//# sourceMappingURL=LiveEditorOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/admin/LiveEditorOverlay.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useState } from 'react'\nimport { useLivePreviewContext } from '@payloadcms/ui'\nimport { PreviewFrame } from './PreviewFrame'\nimport { PreviewToolbar } from './PreviewToolbar'\nimport { Sidebar } from './sidebar/Sidebar'\nimport { useBetterEditorSettings } from '../state/useBetterEditorSettings'\nimport { useEditorHistory } from '../state/useEditorHistory'\nimport { useSidebarResize } from '../hooks/useSidebarResize'\nimport { useViewportState } from '../hooks/useViewportState'\nimport { useFullscreenOverlay } from '../hooks/useFullscreenOverlay'\nimport { useBlockActionMessages } from '../hooks/useBlockActionMessages'\nimport { useOverlayKeyboard } from '../hooks/useOverlayKeyboard'\nimport { useFocusTrap } from '../hooks/useFocusTrap'\nimport { OverlayProviders } from '../providers/OverlayProviders'\nimport '../styles/overlay.css'\nimport '../styles/preview.css'\nimport '../styles/sidebar.css'\nimport '../styles/blocks-tab.css'\n\nexport type LiveEditorOverlayProps = {\n onClose: () => void\n blocksField: string\n storageNamespace?: string\n adminPortalSelector?: string\n}\n\nconst RESIZE_HANDLE_PX = 6\n\nconst classes = (...parts: Array<string | false | null | undefined>): string =>\n parts.filter(Boolean).join(' ')\n\nexport const LiveEditorOverlay: React.FC<LiveEditorOverlayProps> = ({\n onClose,\n blocksField,\n storageNamespace,\n adminPortalSelector,\n}) => {\n // Selection state lives outside OverlayProviders so the error boundary's\n // onReset can clear it without remounting providers.\n const [selectedBlockPath, setSelectedBlockPath] = useState<string | null>(null)\n const clearSelection = useCallback(() => setSelectedBlockPath(null), [])\n\n return (\n <OverlayProviders\n onClose={onClose}\n onReset={clearSelection}\n storageNamespace={storageNamespace}\n adminPortalSelector={adminPortalSelector}\n >\n <LiveEditorOverlayInner\n onClose={onClose}\n blocksField={blocksField}\n selectedBlockPath={selectedBlockPath}\n setSelectedBlockPath={setSelectedBlockPath}\n />\n </OverlayProviders>\n )\n}\n\ntype InnerProps = LiveEditorOverlayProps & {\n selectedBlockPath: string | null\n setSelectedBlockPath: React.Dispatch<React.SetStateAction<string | null>>\n}\n\nconst LiveEditorOverlayInner: React.FC<InnerProps> = ({\n onClose,\n blocksField,\n selectedBlockPath,\n setSelectedBlockPath,\n}) => {\n const settings = useBetterEditorSettings()\n const history = useEditorHistory()\n const { previewURL } = useLivePreviewContext()\n\n const { sidebarWidth, isResizing, onResizeStart, onResizeKeyDown } = useSidebarResize(\n settings.sidebarPosition,\n )\n const {\n viewport,\n setViewport,\n setResponsiveWidth,\n viewportWidth,\n } = useViewportState(settings)\n // Live-observed iframe width; PreviewFrame reports it via the\n // ResizeObserver, the toolbar's width-chip reads it.\n const [iframeWidth, setIframeWidth] = useState<number | null>(null)\n\n const [isFullscreen, setIsFullscreen] = useState(false)\n const toggleFullscreen = useCallback(() => setIsFullscreen((v) => !v), [])\n const exitFullscreen = useCallback(() => setIsFullscreen(false), [])\n const overlayRef = useFullscreenOverlay(isFullscreen, exitFullscreen)\n useFocusTrap(overlayRef)\n\n const clearSelection = useCallback(\n () => setSelectedBlockPath(null),\n [setSelectedBlockPath],\n )\n\n const { addBelowRequestId } = useBlockActionMessages({\n selectedBlockPath,\n setSelectedBlockPath,\n })\n\n useOverlayKeyboard({ onClose, history })\n\n const [sidebarCollapsed, setSidebarCollapsed] = useState(false)\n const toggleSidebar = useCallback(() => setSidebarCollapsed((v) => !v), [])\n\n const [interactMode, setInteractMode] = useState(false)\n const toggleInteractMode = useCallback(() => setInteractMode((v) => !v), [])\n\n const isLeft = settings.sidebarPosition === 'left'\n const showSidebar = !sidebarCollapsed\n const gridTemplateColumns = !showSidebar\n ? '1fr'\n : isLeft\n ? `${sidebarWidth}px ${RESIZE_HANDLE_PX}px 1fr`\n : `1fr ${RESIZE_HANDLE_PX}px ${sidebarWidth}px`\n\n return (\n <div\n ref={overlayRef}\n className={classes(\n 'better-editor',\n isResizing && 'better-editor--resizing',\n isFullscreen && 'better-editor--fullscreen',\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Better Editor\"\n tabIndex={-1}\n >\n <div className=\"better-editor__body\" style={{ gridTemplateColumns }}>\n <div className=\"better-editor__preview\" style={{ order: isLeft ? 2 : 0 }}>\n <PreviewToolbar\n history={history}\n viewport={viewport}\n onViewportChange={setViewport}\n iframeWidth={iframeWidth}\n isFullscreen={isFullscreen}\n onFullscreenToggle={toggleFullscreen}\n interactMode={interactMode}\n onInteractToggle={toggleInteractMode}\n sidebarCollapsed={sidebarCollapsed}\n onSidebarToggle={toggleSidebar}\n />\n <div className=\"better-editor__preview-stage\">\n <PreviewFrame\n previewURL={previewURL}\n hoverColorTopLevel={settings.hoverColorTopLevel}\n hoverColorNested={settings.hoverColorNested}\n hoverOutlineWidth={settings.hoverOutlineWidth}\n showHoverToolbar={settings.showHoverToolbar}\n hoverToolbarPosition={settings.hoverToolbarPosition}\n selectedBlockPath={selectedBlockPath}\n interactMode={interactMode}\n viewport={viewport}\n viewportWidth={viewportWidth}\n resizable={viewport === 'responsive'}\n onResize={setResponsiveWidth}\n onIframeWidthChange={setIframeWidth}\n />\n </div>\n </div>\n {showSidebar ? (\n <>\n <div\n className=\"better-editor__resize-handle\"\n style={{ order: 1 }}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize sidebar (use ← / → arrow keys)\"\n aria-valuenow={sidebarWidth}\n tabIndex={0}\n onMouseDown={onResizeStart}\n onKeyDown={onResizeKeyDown}\n />\n <aside\n className=\"better-editor__sidebar\"\n style={{ order: isLeft ? 0 : 2 }}\n >\n <Sidebar\n selectedBlockPath={selectedBlockPath}\n onClearSelection={clearSelection}\n onSelectPath={setSelectedBlockPath}\n forceFullWidthFields={settings.forceFullWidthFields}\n blocksField={blocksField}\n addBelowRequestId={addBelowRequestId}\n />\n </aside>\n </>\n ) : null}\n </div>\n </div>\n )\n}\n\n"],"names":["React","useCallback","useState","useLivePreviewContext","PreviewFrame","PreviewToolbar","Sidebar","useBetterEditorSettings","useEditorHistory","useSidebarResize","useViewportState","useFullscreenOverlay","useBlockActionMessages","useOverlayKeyboard","useFocusTrap","OverlayProviders","RESIZE_HANDLE_PX","classes","parts","filter","Boolean","join","LiveEditorOverlay","onClose","blocksField","storageNamespace","adminPortalSelector","selectedBlockPath","setSelectedBlockPath","clearSelection","onReset","LiveEditorOverlayInner","settings","history","previewURL","sidebarWidth","isResizing","onResizeStart","onResizeKeyDown","sidebarPosition","viewport","setViewport","setResponsiveWidth","viewportWidth","iframeWidth","setIframeWidth","isFullscreen","setIsFullscreen","toggleFullscreen","v","exitFullscreen","overlayRef","addBelowRequestId","sidebarCollapsed","setSidebarCollapsed","toggleSidebar","interactMode","setInteractMode","toggleInteractMode","isLeft","showSidebar","gridTemplateColumns","div","ref","className","role","aria-modal","aria-label","tabIndex","style","order","onViewportChange","onFullscreenToggle","onInteractToggle","onSidebarToggle","hoverColorTopLevel","hoverColorNested","hoverOutlineWidth","showHoverToolbar","hoverToolbarPosition","resizable","onResize","onIframeWidthChange","aria-orientation","aria-valuenow","onMouseDown","onKeyDown","aside","onClearSelection","onSelectPath","forceFullWidthFields"],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { useDocumentInfo, useLivePreviewContext, usePreferences } from '@payloadcms/ui';
|
|
6
|
+
import { LiveEditorOverlay } from './LiveEditorOverlay';
|
|
7
|
+
import { useMainWrapperPortal } from '../hooks/useMainWrapperPortal';
|
|
8
|
+
import { buildStorageKeys } from '../internal/storage-keys';
|
|
9
|
+
import { LayoutIcon } from './icons';
|
|
10
|
+
export const LiveEditorToggle = ({ blocksField, adminPortalSelector, storageNamespace })=>{
|
|
11
|
+
const [open, setOpen] = useState(false);
|
|
12
|
+
const { collectionSlug, globalSlug } = useDocumentInfo();
|
|
13
|
+
const { previewURL } = useLivePreviewContext();
|
|
14
|
+
const { getPreference, setPreference } = usePreferences();
|
|
15
|
+
const storageKeys = useMemo(()=>buildStorageKeys(storageNamespace), [
|
|
16
|
+
storageNamespace
|
|
17
|
+
]);
|
|
18
|
+
const prefKey = storageKeys.togglePreference(collectionSlug, globalSlug);
|
|
19
|
+
// Tracks the prefKey we've successfully hydrated against so persistence
|
|
20
|
+
// can't fire with the initial `false` before the read resolves, and so
|
|
21
|
+
// switching documents reseeds without clobbering the new doc's pref.
|
|
22
|
+
const hydratedKeyRef = useRef(null);
|
|
23
|
+
useEffect(()=>{
|
|
24
|
+
let cancelled = false;
|
|
25
|
+
hydratedKeyRef.current = null;
|
|
26
|
+
void getPreference(prefKey).then((pref)=>{
|
|
27
|
+
if (cancelled) return;
|
|
28
|
+
hydratedKeyRef.current = prefKey;
|
|
29
|
+
setOpen(Boolean(pref?.open));
|
|
30
|
+
});
|
|
31
|
+
return ()=>{
|
|
32
|
+
cancelled = true;
|
|
33
|
+
};
|
|
34
|
+
}, [
|
|
35
|
+
prefKey,
|
|
36
|
+
getPreference
|
|
37
|
+
]);
|
|
38
|
+
useEffect(()=>{
|
|
39
|
+
if (hydratedKeyRef.current !== prefKey) return;
|
|
40
|
+
void setPreference(prefKey, {
|
|
41
|
+
open
|
|
42
|
+
}, true);
|
|
43
|
+
}, [
|
|
44
|
+
open,
|
|
45
|
+
prefKey,
|
|
46
|
+
setPreference
|
|
47
|
+
]);
|
|
48
|
+
const handleToggle = useCallback(()=>setOpen((v)=>!v), []);
|
|
49
|
+
const handleClose = useCallback(()=>setOpen(false), []);
|
|
50
|
+
const mountNode = useMainWrapperPortal(open, adminPortalSelector);
|
|
51
|
+
const label = open ? 'Close Better Editor' : 'Open Better Editor';
|
|
52
|
+
// Mirror Payload's official live-preview behaviour: only surface the
|
|
53
|
+
// toggle once a previewURL is actually resolvable (collection has
|
|
54
|
+
// `admin.livePreview.url` configured AND the document has the data
|
|
55
|
+
// the URL function depends on, e.g. slug). Hiding the button avoids
|
|
56
|
+
// the misleading "Loading preview URL…" / "not configured" empty
|
|
57
|
+
// states inside the overlay entirely.
|
|
58
|
+
if (!previewURL) return null;
|
|
59
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ _jsx("button", {
|
|
62
|
+
"aria-label": label,
|
|
63
|
+
"aria-pressed": open,
|
|
64
|
+
className: "preview-btn",
|
|
65
|
+
onClick: handleToggle,
|
|
66
|
+
title: label,
|
|
67
|
+
type: "button",
|
|
68
|
+
style: open ? {
|
|
69
|
+
borderColor: 'var(--theme-elevation-300)',
|
|
70
|
+
backgroundColor: 'var(--theme-elevation-100)'
|
|
71
|
+
} : undefined,
|
|
72
|
+
children: /*#__PURE__*/ _jsx(LayoutIcon, {})
|
|
73
|
+
}),
|
|
74
|
+
open && mountNode ? /*#__PURE__*/ createPortal(/*#__PURE__*/ _jsx(LiveEditorOverlay, {
|
|
75
|
+
onClose: handleClose,
|
|
76
|
+
blocksField: blocksField,
|
|
77
|
+
storageNamespace: storageNamespace,
|
|
78
|
+
adminPortalSelector: adminPortalSelector
|
|
79
|
+
}), mountNode) : null
|
|
80
|
+
]
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=LiveEditorToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/admin/LiveEditorToggle.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useDocumentInfo, useLivePreviewContext, usePreferences } from '@payloadcms/ui'\nimport { LiveEditorOverlay } from './LiveEditorOverlay'\nimport { useMainWrapperPortal } from '../hooks/useMainWrapperPortal'\nimport { buildStorageKeys } from '../internal/storage-keys'\nimport { LayoutIcon } from './icons'\n\ntype Pref = { open?: boolean }\n\nexport type LiveEditorToggleProps = {\n blocksField: string\n adminPortalSelector?: string\n storageNamespace?: string\n}\n\nexport const LiveEditorToggle: React.FC<LiveEditorToggleProps> = ({\n blocksField,\n adminPortalSelector,\n storageNamespace,\n}) => {\n const [open, setOpen] = useState(false)\n const { collectionSlug, globalSlug } = useDocumentInfo()\n const { previewURL } = useLivePreviewContext()\n const { getPreference, setPreference } = usePreferences()\n const storageKeys = useMemo(() => buildStorageKeys(storageNamespace), [storageNamespace])\n const prefKey = storageKeys.togglePreference(collectionSlug, globalSlug)\n\n // Tracks the prefKey we've successfully hydrated against so persistence\n // can't fire with the initial `false` before the read resolves, and so\n // switching documents reseeds without clobbering the new doc's pref.\n const hydratedKeyRef = useRef<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n hydratedKeyRef.current = null\n void getPreference<Pref>(prefKey).then((pref) => {\n if (cancelled) return\n hydratedKeyRef.current = prefKey\n setOpen(Boolean(pref?.open))\n })\n return () => {\n cancelled = true\n }\n }, [prefKey, getPreference])\n\n useEffect(() => {\n if (hydratedKeyRef.current !== prefKey) return\n void setPreference<Pref>(prefKey, { open }, true)\n }, [open, prefKey, setPreference])\n\n const handleToggle = useCallback(() => setOpen((v) => !v), [])\n const handleClose = useCallback(() => setOpen(false), [])\n\n const mountNode = useMainWrapperPortal(open, adminPortalSelector)\n const label = open ? 'Close Better Editor' : 'Open Better Editor'\n\n // Mirror Payload's official live-preview behaviour: only surface the\n // toggle once a previewURL is actually resolvable (collection has\n // `admin.livePreview.url` configured AND the document has the data\n // the URL function depends on, e.g. slug). Hiding the button avoids\n // the misleading \"Loading preview URL…\" / \"not configured\" empty\n // states inside the overlay entirely.\n if (!previewURL) return null\n\n return (\n <>\n <button\n aria-label={label}\n aria-pressed={open}\n className=\"preview-btn\"\n onClick={handleToggle}\n title={label}\n type=\"button\"\n style={\n open\n ? {\n borderColor: 'var(--theme-elevation-300)',\n backgroundColor: 'var(--theme-elevation-100)',\n }\n : undefined\n }\n >\n <LayoutIcon />\n </button>\n\n {open && mountNode\n ? createPortal(\n <LiveEditorOverlay\n onClose={handleClose}\n blocksField={blocksField}\n storageNamespace={storageNamespace}\n adminPortalSelector={adminPortalSelector}\n />,\n mountNode,\n )\n : null}\n </>\n )\n}\n"],"names":["React","useCallback","useEffect","useMemo","useRef","useState","createPortal","useDocumentInfo","useLivePreviewContext","usePreferences","LiveEditorOverlay","useMainWrapperPortal","buildStorageKeys","LayoutIcon","LiveEditorToggle","blocksField","adminPortalSelector","storageNamespace","open","setOpen","collectionSlug","globalSlug","previewURL","getPreference","setPreference","storageKeys","prefKey","togglePreference","hydratedKeyRef","cancelled","current","then","pref","Boolean","handleToggle","v","handleClose","mountNode","label","button","aria-label","aria-pressed","className","onClick","title","type","style","borderColor","backgroundColor","undefined","onClose"],"mappings":"AAAA;;AAEA,OAAOA,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChF,SAASC,YAAY,QAAQ,YAAW;AACxC,SAASC,eAAe,EAAEC,qBAAqB,EAAEC,cAAc,QAAQ,iBAAgB;AACvF,SAASC,iBAAiB,QAAQ,sBAAqB;AACvD,SAASC,oBAAoB,QAAQ,gCAA+B;AACpE,SAASC,gBAAgB,QAAQ,2BAA0B;AAC3D,SAASC,UAAU,QAAQ,UAAS;AAUpC,OAAO,MAAMC,mBAAoD,CAAC,EAChEC,WAAW,EACXC,mBAAmB,EACnBC,gBAAgB,EACjB;IACC,MAAM,CAACC,MAAMC,QAAQ,GAAGd,SAAS;IACjC,MAAM,EAAEe,cAAc,EAAEC,UAAU,EAAE,GAAGd;IACvC,MAAM,EAAEe,UAAU,EAAE,GAAGd;IACvB,MAAM,EAAEe,aAAa,EAAEC,aAAa,EAAE,GAAGf;IACzC,MAAMgB,cAActB,QAAQ,IAAMS,iBAAiBK,mBAAmB;QAACA;KAAiB;IACxF,MAAMS,UAAUD,YAAYE,gBAAgB,CAACP,gBAAgBC;IAE7D,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,MAAMO,iBAAiBxB,OAAsB;IAE7CF,UAAU;QACR,IAAI2B,YAAY;QAChBD,eAAeE,OAAO,GAAG;QACzB,KAAKP,cAAoBG,SAASK,IAAI,CAAC,CAACC;YACtC,IAAIH,WAAW;YACfD,eAAeE,OAAO,GAAGJ;YACzBP,QAAQc,QAAQD,MAAMd;QACxB;QACA,OAAO;YACLW,YAAY;QACd;IACF,GAAG;QAACH;QAASH;KAAc;IAE3BrB,UAAU;QACR,IAAI0B,eAAeE,OAAO,KAAKJ,SAAS;QACxC,KAAKF,cAAoBE,SAAS;YAAER;QAAK,GAAG;IAC9C,GAAG;QAACA;QAAMQ;QAASF;KAAc;IAEjC,MAAMU,eAAejC,YAAY,IAAMkB,QAAQ,CAACgB,IAAM,CAACA,IAAI,EAAE;IAC7D,MAAMC,cAAcnC,YAAY,IAAMkB,QAAQ,QAAQ,EAAE;IAExD,MAAMkB,YAAY1B,qBAAqBO,MAAMF;IAC7C,MAAMsB,QAAQpB,OAAO,wBAAwB;IAE7C,qEAAqE;IACrE,kEAAkE;IAClE,mEAAmE;IACnE,oEAAoE;IACpE,iEAAiE;IACjE,sCAAsC;IACtC,IAAI,CAACI,YAAY,OAAO;IAExB,qBACE;;0BACE,KAACiB;gBACCC,cAAYF;gBACZG,gBAAcvB;gBACdwB,WAAU;gBACVC,SAAST;gBACTU,OAAON;gBACPO,MAAK;gBACLC,OACE5B,OACI;oBACE6B,aAAa;oBACbC,iBAAiB;gBACnB,IACAC;0BAGN,cAAA,KAACpC;;YAGFK,QAAQmB,0BACL/B,2BACE,KAACI;gBACCwC,SAASd;gBACTrB,aAAaA;gBACbE,kBAAkBA;gBAClBD,qBAAqBA;gBAEvBqB,aAEF;;;AAGV,EAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { HoverToolbarPosition } from '../internal/constants';
|
|
3
|
+
import type { Viewport } from './ViewportToggle';
|
|
4
|
+
export type PreviewFrameProps = {
|
|
5
|
+
previewURL: string | undefined;
|
|
6
|
+
hoverColorTopLevel: string;
|
|
7
|
+
hoverColorNested: string;
|
|
8
|
+
hoverOutlineWidth: number;
|
|
9
|
+
showHoverToolbar: boolean;
|
|
10
|
+
hoverToolbarPosition: HoverToolbarPosition;
|
|
11
|
+
selectedBlockPath: string | null;
|
|
12
|
+
/** When true, clicks pass through to the consumer page and the
|
|
13
|
+
* hover/selection affordances are suppressed so users can interact
|
|
14
|
+
* with forms, accordions, links inside the preview. */
|
|
15
|
+
interactMode: boolean;
|
|
16
|
+
viewport?: Viewport;
|
|
17
|
+
viewportWidth?: number | null;
|
|
18
|
+
resizable?: boolean;
|
|
19
|
+
onResize?: (next: number) => void;
|
|
20
|
+
onIframeWidthChange?: (width: number) => void;
|
|
21
|
+
};
|
|
22
|
+
export declare const PreviewFrame: React.FC<PreviewFrameProps>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { postToParent } from '../internal/postmessage';
|
|
5
|
+
import { useIframeResizeObserver } from '../hooks/useIframeResizeObserver';
|
|
6
|
+
import { usePreviewHandleDrag } from '../hooks/usePreviewHandleDrag';
|
|
7
|
+
import { useLatestRef } from '../hooks/useLatestRef';
|
|
8
|
+
import { usePreviewBinding } from '../hooks/usePreviewBinding';
|
|
9
|
+
import { usePreviewSettingsSync } from '../hooks/usePreviewSettingsSync';
|
|
10
|
+
import { usePreviewSelectionSync } from '../hooks/usePreviewSelectionSync';
|
|
11
|
+
export const PreviewFrame = ({ previewURL, hoverColorTopLevel, hoverColorNested, hoverOutlineWidth, showHoverToolbar, hoverToolbarPosition, selectedBlockPath, interactMode, viewport, viewportWidth, resizable = false, onResize, onIframeWidthChange })=>{
|
|
12
|
+
const iframeRef = useRef(null);
|
|
13
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
14
|
+
const interactModeRef = useLatestRef(interactMode);
|
|
15
|
+
const { isResizing, onHandleMouseDown } = usePreviewHandleDrag({
|
|
16
|
+
resizable,
|
|
17
|
+
viewportWidth,
|
|
18
|
+
onResize
|
|
19
|
+
});
|
|
20
|
+
useIframeResizeObserver(iframeRef, onIframeWidthChange);
|
|
21
|
+
useEffect(()=>{
|
|
22
|
+
setIsLoading(true);
|
|
23
|
+
}, [
|
|
24
|
+
previewURL
|
|
25
|
+
]);
|
|
26
|
+
const onFocusBlock = useCallback((id)=>{
|
|
27
|
+
postToParent({
|
|
28
|
+
type: 'focus-block',
|
|
29
|
+
id
|
|
30
|
+
});
|
|
31
|
+
}, []);
|
|
32
|
+
const onBlockAction = useCallback((id, action)=>{
|
|
33
|
+
postToParent({
|
|
34
|
+
type: 'block-action',
|
|
35
|
+
id,
|
|
36
|
+
action
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
const settings = useMemo(()=>({
|
|
40
|
+
hoverColorTopLevel,
|
|
41
|
+
hoverColorNested,
|
|
42
|
+
hoverOutlineWidth,
|
|
43
|
+
showHoverToolbar,
|
|
44
|
+
hoverToolbarPosition
|
|
45
|
+
}), [
|
|
46
|
+
hoverColorTopLevel,
|
|
47
|
+
hoverColorNested,
|
|
48
|
+
hoverOutlineWidth,
|
|
49
|
+
showHoverToolbar,
|
|
50
|
+
hoverToolbarPosition
|
|
51
|
+
]);
|
|
52
|
+
const { controllerRef, isBoundRef } = usePreviewBinding({
|
|
53
|
+
iframeRef,
|
|
54
|
+
settings,
|
|
55
|
+
interactModeRef,
|
|
56
|
+
onFocusBlock,
|
|
57
|
+
onBlockAction,
|
|
58
|
+
onLoadingChange: setIsLoading
|
|
59
|
+
});
|
|
60
|
+
usePreviewSettingsSync({
|
|
61
|
+
iframeRef,
|
|
62
|
+
controllerRef,
|
|
63
|
+
isBoundRef,
|
|
64
|
+
settings,
|
|
65
|
+
onBlockAction
|
|
66
|
+
});
|
|
67
|
+
usePreviewSelectionSync({
|
|
68
|
+
iframeRef,
|
|
69
|
+
controllerRef,
|
|
70
|
+
selectedBlockPath,
|
|
71
|
+
interactMode,
|
|
72
|
+
previewURL
|
|
73
|
+
});
|
|
74
|
+
const constrained = typeof viewportWidth === 'number' && viewportWidth > 0;
|
|
75
|
+
const viewportClassName = [
|
|
76
|
+
'better-editor-frame__viewport',
|
|
77
|
+
constrained && 'better-editor-frame__viewport--constrained',
|
|
78
|
+
constrained && viewport === 'tablet' && 'better-editor-frame__viewport--tablet',
|
|
79
|
+
constrained && viewport === 'mobile' && 'better-editor-frame__viewport--mobile',
|
|
80
|
+
resizable && 'better-editor-frame__viewport--resizable',
|
|
81
|
+
isResizing && 'better-editor-frame__viewport--resizing'
|
|
82
|
+
].filter(Boolean).join(' ');
|
|
83
|
+
const iframeStyle = constrained ? {
|
|
84
|
+
width: `${viewportWidth}px`,
|
|
85
|
+
maxWidth: '100%'
|
|
86
|
+
} : undefined;
|
|
87
|
+
// The iframe stays in the same wrapper across viewport modes so React
|
|
88
|
+
// doesn't remount it — that would reload the page and drop the
|
|
89
|
+
// ResizeObserver.
|
|
90
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
91
|
+
className: viewportClassName,
|
|
92
|
+
children: [
|
|
93
|
+
resizable ? /*#__PURE__*/ _jsx("div", {
|
|
94
|
+
className: "better-editor-frame__handle better-editor-frame__handle--left",
|
|
95
|
+
role: "separator",
|
|
96
|
+
"aria-orientation": "vertical",
|
|
97
|
+
"aria-label": "Resize preview from left",
|
|
98
|
+
onMouseDown: onHandleMouseDown('left')
|
|
99
|
+
}) : null,
|
|
100
|
+
/*#__PURE__*/ _jsx("iframe", {
|
|
101
|
+
ref: iframeRef,
|
|
102
|
+
className: "better-editor-frame",
|
|
103
|
+
src: previewURL,
|
|
104
|
+
title: "Better Editor preview",
|
|
105
|
+
style: iframeStyle
|
|
106
|
+
}),
|
|
107
|
+
isLoading ? /*#__PURE__*/ _jsxs("div", {
|
|
108
|
+
className: "better-editor-frame__skeleton",
|
|
109
|
+
role: "status",
|
|
110
|
+
"aria-label": "Loading preview",
|
|
111
|
+
children: [
|
|
112
|
+
/*#__PURE__*/ _jsx("div", {
|
|
113
|
+
className: "better-editor-frame__skeleton-bar better-editor-frame__skeleton-bar--lg"
|
|
114
|
+
}),
|
|
115
|
+
/*#__PURE__*/ _jsx("div", {
|
|
116
|
+
className: "better-editor-frame__skeleton-bar"
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsx("div", {
|
|
119
|
+
className: "better-editor-frame__skeleton-bar better-editor-frame__skeleton-bar--sm"
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ _jsx("div", {
|
|
122
|
+
className: "better-editor-frame__skeleton-block"
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
}) : null,
|
|
126
|
+
resizable ? /*#__PURE__*/ _jsx("div", {
|
|
127
|
+
className: "better-editor-frame__handle better-editor-frame__handle--right",
|
|
128
|
+
role: "separator",
|
|
129
|
+
"aria-orientation": "vertical",
|
|
130
|
+
"aria-label": "Resize preview from right",
|
|
131
|
+
onMouseDown: onHandleMouseDown('right')
|
|
132
|
+
}) : null
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=PreviewFrame.js.map
|