@kubohiroya/turbowarp-extension-data-editor 0.5.0 → 0.7.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/README.ja.md +9 -4
- package/README.md +7 -4
- package/dist/build-info.json +3 -3
- package/dist/descendants.js +1 -0
- package/dist/dialog-window.d.ts +8 -0
- package/dist/dialog-window.js +155 -0
- package/dist/preview.d.ts +3 -0
- package/dist/preview.js +100 -0
- package/dist/react.css +70 -0
- package/dist/react.d.ts +3 -0
- package/dist/react.js +12 -4
- package/dist/registry.d.ts +3 -0
- package/dist/registry.js +38 -9
- package/dist/rjsf.d.ts +2 -1
- package/dist/rjsf.js +10 -0
- package/dist/session.d.ts +1 -0
- package/dist/session.js +6 -0
- package/dist/turbowarp/bridge.js +42 -1
- package/dist/turbowarp/fixed-fields.d.ts +1 -1
- package/dist/turbowarp/fixed-fields.js +7 -2
- package/dist/turbowarp/icon.d.ts +3 -1
- package/dist/turbowarp/icon.js +5 -1
- package/dist/turbowarp.d.ts +2 -0
- package/dist/types.d.ts +8 -0
- package/dist/view.js +1 -0
- package/dist/webpack4/index.js +1 -1
- package/dist/webpack4/metafile.json +57 -31
- package/dist/webpack4/react.js +173 -4
- package/dist/webpack4/react.js.map +3 -3
- package/dist/webpack4/rjsf.js +13 -1
- package/dist/webpack4/rjsf.js.map +2 -2
- package/dist/webpack4/{shared-QIOZ73LT.js → shared-FW4MRLXW.js} +148 -8
- package/dist/webpack4/shared-FW4MRLXW.js.map +7 -0
- package/dist/webpack4/turbowarp.js +55 -5
- package/dist/webpack4/turbowarp.js.map +2 -2
- package/docs/README.md +3 -3
- package/docs/block-editor-descendants.md +1 -1
- package/docs/block-editor-e2e.md +6 -122
- package/docs/block-editor.md +1 -1
- package/docs/block-preview.md +45 -0
- package/docs/ci-success-gate.md +9 -29
- package/docs/dialog-window.md +50 -0
- package/docs/fixed-input-contracts.md +3 -1
- package/docs/github-pages.md +21 -57
- package/docs/package-distribution.md +3 -3
- package/docs/shared-extension-security.ja.md +6 -6
- package/package.json +2 -6
- package/dist/webpack4/shared-QIOZ73LT.js.map +0 -7
package/README.ja.md
CHANGED
|
@@ -10,8 +10,13 @@ TurboWarp拡張が扱う構造化データを、フォームや独自UIで編集
|
|
|
10
10
|
|
|
11
11
|
タブ・グループ・グリッドは[共通レイアウトガイド](docs/common-layout.ja.md)を参照してください。標準RJSFとSource/Formで同じJSON宣言を使用し、ホストの起動時フラグ `commonLayout` で有効にします(既定OFF)。
|
|
12
12
|
|
|
13
|
-
[
|
|
14
|
-
|
|
13
|
+
既存フォームと下書きを共有する視覚プレビュー、アイコンのホバー表示は[ブロックプレビュー](docs/block-preview.md)を参照してください。
|
|
14
|
+
|
|
15
|
+
本パッケージはライブラリです。統合したEditorのビルド・検証・GitHub Pages配信は、下流の [TurboWarp-Plus-Editor](https://github.com/kubohiroya/turbowarp-plus-editor) が所有します。本リポジトリのGitHub Pages提供は廃止し、旧URLでEditorやリダイレクトを提供しません。
|
|
16
|
+
|
|
17
|
+
<p><a class="twpe-edit-button" href="https://kubohiroya.github.io/turbowarp-plus-editor/editor.html?lang=ja"><img src="https://kubohiroya.github.io/turbowarp-plus-editor/assets/icon.svg" width="32" height="32" alt=""> TurboWarp-Plus-Editorで編集</a></p>
|
|
18
|
+
|
|
19
|
+
ボタンのHTMLとスタイルは [TurboWarp-Plus-EditorのREADME](https://github.com/kubohiroya/turbowarp-plus-editor#edit-button) を参照してください。
|
|
15
20
|
|
|
16
21
|
## 標準の JSON Schema エディター
|
|
17
22
|
|
|
@@ -127,12 +132,12 @@ npm install --save-exact @kubohiroya/turbowarp-extension-data-editor@0.2.2
|
|
|
127
132
|
|
|
128
133
|
対応GUIはダイアログ、ソースフォーム、共通レイアウト、固定入力、子孫編集、一括セキュリティ確認を標準で提供します。
|
|
129
134
|
通常の `editor.html?lang=ja` で利用でき、有効化用URLスイッチは不要です。低水準APIのhost能力交渉は維持します。
|
|
130
|
-
切戻しはGUI
|
|
135
|
+
切戻しはGUIの変更とTurboWarp-Plus-Editorの固定ソース設定を対応させてrevertします。
|
|
131
136
|
確定値は既存引数へ保存し、UI・下書き・関数・revision をプロジェクトデータへ追加しません。
|
|
132
137
|
|
|
133
138
|
## webpack 4 / E2E
|
|
134
139
|
|
|
135
|
-
[webpack 4配布物と設定API](docs/webpack4.md)、[GUI接続E2EとCIの実行手順](docs/block-editor-e2e.md)
|
|
140
|
+
[webpack 4配布物と設定API](docs/webpack4.md)、[GUI接続E2EとCIの実行手順](docs/block-editor-e2e.md)を参照。本リポジトリは専用編集UIと互換ビルドを管理します。GUIはホスト接続、TurboWarp-Plus-Editorは統合ビルド・E2E・配信を管理します。
|
|
136
141
|
|
|
137
142
|
## Schemaの共通型と診断変換
|
|
138
143
|
|
package/README.md
CHANGED
|
@@ -10,8 +10,11 @@ Japanese guides for usage, APIs, GUI integration, publishing, and validation rec
|
|
|
10
10
|
|
|
11
11
|
For tabs, groups, and grids, see the [shared layout guide (Japanese)](docs/common-layout.ja.md). Standard RJSF and Source/Form use the same JSON declarations, enabled by the host's startup flag `commonLayout` (off by default).
|
|
12
12
|
|
|
13
|
-
This
|
|
14
|
-
|
|
13
|
+
This package is a library. The downstream [TurboWarp-Plus-Editor](https://github.com/kubohiroya/turbowarp-plus-editor) owns the integrated Editor build, validation and GitHub Pages distribution. This repository no longer provides GitHub Pages; its former URL does not serve an Editor or a redirect.
|
|
14
|
+
|
|
15
|
+
<p><a class="twpe-edit-button" href="https://kubohiroya.github.io/turbowarp-plus-editor/editor.html?lang=en"><img src="https://kubohiroya.github.io/turbowarp-plus-editor/assets/icon.svg" width="32" height="32" alt=""> Edit in TurboWarp-Plus-Editor</a></p>
|
|
16
|
+
|
|
17
|
+
See the [TurboWarp-Plus-Editor README](https://github.com/kubohiroya/turbowarp-plus-editor#edit-button) for the reusable button HTML and stylesheet.
|
|
15
18
|
|
|
16
19
|
## Standard JSON Schema editor
|
|
17
20
|
|
|
@@ -127,12 +130,12 @@ For `.sb3` saving, reloading through `project_url` and the OS file picker, Engli
|
|
|
127
130
|
|
|
128
131
|
Supported GUIs provide dialogs, source forms, shared layouts, fixed inputs, descendant editing, and batch security confirmation by default.
|
|
129
132
|
These are available at the normal `editor.html?lang=ja` URL without activation switches. Low-level API host capability negotiation remains in place.
|
|
130
|
-
To roll back, revert the GUI changes together with
|
|
133
|
+
To roll back, revert the GUI changes together with TurboWarp-Plus-Editor's pinned source configuration.
|
|
131
134
|
Committed values are stored in existing arguments. UI state, drafts, functions, and revisions are not added to project data.
|
|
132
135
|
|
|
133
136
|
## webpack 4 / E2E
|
|
134
137
|
|
|
135
|
-
See the [webpack 4 distribution and configuration API (Japanese)](docs/webpack4.md) and [GUI integration E2E and CI procedures (Japanese)](docs/block-editor-e2e.md). This shared repository manages the custom editor UI
|
|
138
|
+
See the [webpack 4 distribution and configuration API (Japanese)](docs/webpack4.md) and [GUI integration E2E and CI procedures (Japanese)](docs/block-editor-e2e.md). This shared repository manages the custom editor UI and compatibility builds. The GUI owns host integration, and TurboWarp-Plus-Editor owns integrated builds, E2E tests and distribution.
|
|
136
139
|
|
|
137
140
|
## Shared Schema types and diagnostic conversion
|
|
138
141
|
|
package/dist/build-info.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubohiroya/turbowarp-extension-data-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"repository": "https://github.com/kubohiroya/turbowarp-extension-data-editor",
|
|
5
|
-
"revision": "
|
|
5
|
+
"revision": "d96532a91bc6046d4a3fda878425b30d6d10483e",
|
|
6
6
|
"sourceState": "commit",
|
|
7
|
-
"sourceSha256": "
|
|
7
|
+
"sourceSha256": "daf5c14dd2a7eafbc5208413f168eb42fc817978e8517a66c31838dc48aa1841",
|
|
8
8
|
"capabilities": {
|
|
9
9
|
"preparedSource": 1
|
|
10
10
|
}
|
package/dist/descendants.js
CHANGED
|
@@ -260,6 +260,7 @@ _DescendantSession_snapshot = new WeakMap(), _DescendantSession_host = new WeakM
|
|
|
260
260
|
const listeners = new Set();
|
|
261
261
|
const editor = Object.freeze({
|
|
262
262
|
reference: descriptor.reference,
|
|
263
|
+
getSnapshot: () => snapshot,
|
|
263
264
|
getDraft: () => { __classPrivateFieldGet(this, _DescendantSession_instances, "m", _DescendantSession_assertOpen).call(this); return cloneJson(record.draft); },
|
|
264
265
|
setDraft: (draft) => {
|
|
265
266
|
__classPrivateFieldGet(this, _DescendantSession_instances, "m", _DescendantSession_assertEditable).call(this);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface WindowLabels {
|
|
2
|
+
readonly headerClassName?: string | undefined;
|
|
3
|
+
readonly maximize?: string | undefined;
|
|
4
|
+
readonly restore?: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
/** Add window controls to the injected host frame without depending on GUI internals. */
|
|
7
|
+
export declare function attachEditorDialogWindow(body: HTMLElement, labels: WindowLabels): (() => void) | undefined;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** Add window controls to the injected host frame without depending on GUI internals. */
|
|
2
|
+
export function attachEditorDialogWindow(body, labels) {
|
|
3
|
+
var _a;
|
|
4
|
+
const dialog = body.closest('[role="dialog"]');
|
|
5
|
+
const header = (labels.headerClassName ? dialog === null || dialog === void 0 ? void 0 : dialog.getElementsByClassName(labels.headerClassName)[0] :
|
|
6
|
+
dialog === null || dialog === void 0 ? void 0 : dialog.querySelector('header'));
|
|
7
|
+
const content = body.closest('[data-block-editor-body]');
|
|
8
|
+
if (!dialog || !header || !content || !((_a = header.parentElement) === null || _a === void 0 ? void 0 : _a.contains(content)))
|
|
9
|
+
return;
|
|
10
|
+
const doc = dialog.ownerDocument, win = doc.defaultView;
|
|
11
|
+
if (!win)
|
|
12
|
+
return;
|
|
13
|
+
const frame = header.parentElement;
|
|
14
|
+
const initialStyle = dialog.style.cssText;
|
|
15
|
+
const language = doc.documentElement.lang || new URLSearchParams(win.location.search).get('lang') || win.navigator.language;
|
|
16
|
+
const japanese = language.startsWith('ja');
|
|
17
|
+
const maximizeLabel = labels.maximize || (japanese ? '全画面化' : 'Maximize');
|
|
18
|
+
const restoreLabel = labels.restore || (japanese ? '元のサイズに戻す' : 'Restore window');
|
|
19
|
+
let restoreBounds = null;
|
|
20
|
+
let gesture = null;
|
|
21
|
+
const handles = [];
|
|
22
|
+
dialog.setAttribute('data-block-editor-window', '');
|
|
23
|
+
if (frame !== dialog)
|
|
24
|
+
frame.setAttribute('data-block-editor-window-frame', '');
|
|
25
|
+
header.setAttribute('data-block-editor-titlebar', '');
|
|
26
|
+
const maximize = doc.createElement('button');
|
|
27
|
+
maximize.type = 'button';
|
|
28
|
+
maximize.setAttribute('data-block-editor-maximize', '');
|
|
29
|
+
const closeContainer = header.lastElementChild;
|
|
30
|
+
if (closeContainer === null || closeContainer === void 0 ? void 0 : closeContainer.querySelector('button, [role="button"]'))
|
|
31
|
+
closeContainer.prepend(maximize);
|
|
32
|
+
else
|
|
33
|
+
header.insertBefore(maximize, closeContainer);
|
|
34
|
+
const viewport = () => ({ width: win.innerWidth, height: win.innerHeight });
|
|
35
|
+
const bounds = () => {
|
|
36
|
+
const { x, y, width, height } = dialog.getBoundingClientRect();
|
|
37
|
+
return { x, y, width, height };
|
|
38
|
+
};
|
|
39
|
+
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
40
|
+
function fit(rect) {
|
|
41
|
+
const view = viewport();
|
|
42
|
+
const width = clamp(rect.width, Math.min(360, view.width), view.width);
|
|
43
|
+
const height = clamp(rect.height, Math.min(280, view.height), view.height);
|
|
44
|
+
return { width, height, x: clamp(rect.x, 0, view.width - width), y: clamp(rect.y, 0, view.height - height) };
|
|
45
|
+
}
|
|
46
|
+
function place(rect) {
|
|
47
|
+
Object.assign(dialog.style, { margin: '0', inset: 'auto', transform: 'none', maxHeight: '100dvh',
|
|
48
|
+
left: `${rect.x}px`, top: `${rect.y}px`, width: `${rect.width}px`, height: `${rect.height}px` });
|
|
49
|
+
}
|
|
50
|
+
function stop(event) {
|
|
51
|
+
if (!gesture || (event && 'pointerId' in event && event.pointerId !== gesture.id))
|
|
52
|
+
return;
|
|
53
|
+
const { target, id } = gesture;
|
|
54
|
+
gesture = null;
|
|
55
|
+
if (target.hasPointerCapture(id))
|
|
56
|
+
target.releasePointerCapture(id);
|
|
57
|
+
dialog.removeAttribute('data-block-editor-dragging');
|
|
58
|
+
}
|
|
59
|
+
function start(event, edge) {
|
|
60
|
+
if (restoreBounds || gesture || event.button !== 0 || !event.isPrimary)
|
|
61
|
+
return;
|
|
62
|
+
if (!edge && event.target.closest('button, a, input, select, textarea, [role="button"]'))
|
|
63
|
+
return;
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
const target = event.currentTarget;
|
|
66
|
+
gesture = { id: event.pointerId, target, edge, x: event.clientX, y: event.clientY, rect: fit(bounds()) };
|
|
67
|
+
place(gesture.rect);
|
|
68
|
+
target.setPointerCapture(event.pointerId);
|
|
69
|
+
dialog.setAttribute('data-block-editor-dragging', '');
|
|
70
|
+
}
|
|
71
|
+
function move(event) {
|
|
72
|
+
if (!gesture || event.pointerId !== gesture.id)
|
|
73
|
+
return;
|
|
74
|
+
const { rect, edge } = gesture, view = viewport();
|
|
75
|
+
const dx = event.clientX - gesture.x, dy = event.clientY - gesture.y;
|
|
76
|
+
if (!edge) {
|
|
77
|
+
place(fit({ ...rect, x: rect.x + dx, y: rect.y + dy }));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const minWidth = Math.min(360, view.width), minHeight = Math.min(280, view.height);
|
|
81
|
+
let left = rect.x, top = rect.y, right = rect.x + rect.width, bottom = rect.y + rect.height;
|
|
82
|
+
if (edge.includes('w'))
|
|
83
|
+
left = clamp(left + dx, 0, right - minWidth);
|
|
84
|
+
if (edge.includes('e'))
|
|
85
|
+
right = clamp(right + dx, left + minWidth, view.width);
|
|
86
|
+
if (edge.includes('n'))
|
|
87
|
+
top = clamp(top + dy, 0, bottom - minHeight);
|
|
88
|
+
if (edge.includes('s'))
|
|
89
|
+
bottom = clamp(bottom + dy, top + minHeight, view.height);
|
|
90
|
+
place({ x: left, y: top, width: right - left, height: bottom - top });
|
|
91
|
+
}
|
|
92
|
+
const startMove = (event) => start(event, '');
|
|
93
|
+
header.addEventListener('pointerdown', startMove);
|
|
94
|
+
for (const edge of ['n', 'e', 's', 'w', 'ne', 'se', 'sw', 'nw']) {
|
|
95
|
+
const handle = doc.createElement('div');
|
|
96
|
+
handle.setAttribute('data-block-editor-resize', edge);
|
|
97
|
+
handle.setAttribute('aria-hidden', 'true');
|
|
98
|
+
handle.addEventListener('pointerdown', event => start(event, edge));
|
|
99
|
+
dialog.append(handle);
|
|
100
|
+
handles.push(handle);
|
|
101
|
+
}
|
|
102
|
+
function updateButton() {
|
|
103
|
+
const label = restoreBounds ? restoreLabel : maximizeLabel;
|
|
104
|
+
maximize.setAttribute('aria-label', label);
|
|
105
|
+
maximize.setAttribute('aria-pressed', String(Boolean(restoreBounds)));
|
|
106
|
+
maximize.title = label;
|
|
107
|
+
maximize.textContent = restoreBounds ? '❐' : '⛶';
|
|
108
|
+
dialog.toggleAttribute('data-block-editor-maximized', Boolean(restoreBounds));
|
|
109
|
+
}
|
|
110
|
+
function toggle() {
|
|
111
|
+
stop();
|
|
112
|
+
if (restoreBounds) {
|
|
113
|
+
place(fit(restoreBounds));
|
|
114
|
+
restoreBounds = null;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
restoreBounds = bounds();
|
|
118
|
+
place({ x: 0, y: 0, ...viewport() });
|
|
119
|
+
}
|
|
120
|
+
updateButton();
|
|
121
|
+
}
|
|
122
|
+
function resize() {
|
|
123
|
+
stop();
|
|
124
|
+
if (restoreBounds)
|
|
125
|
+
place({ x: 0, y: 0, ...viewport() });
|
|
126
|
+
else
|
|
127
|
+
place(fit(bounds()));
|
|
128
|
+
}
|
|
129
|
+
maximize.addEventListener('click', toggle);
|
|
130
|
+
win.addEventListener('pointermove', move);
|
|
131
|
+
win.addEventListener('pointerup', stop);
|
|
132
|
+
win.addEventListener('pointercancel', stop);
|
|
133
|
+
win.addEventListener('blur', stop);
|
|
134
|
+
win.addEventListener('resize', resize);
|
|
135
|
+
dialog.addEventListener('lostpointercapture', stop);
|
|
136
|
+
updateButton();
|
|
137
|
+
return () => {
|
|
138
|
+
stop();
|
|
139
|
+
header.removeEventListener('pointerdown', startMove);
|
|
140
|
+
win.removeEventListener('pointermove', move);
|
|
141
|
+
win.removeEventListener('pointerup', stop);
|
|
142
|
+
win.removeEventListener('pointercancel', stop);
|
|
143
|
+
win.removeEventListener('blur', stop);
|
|
144
|
+
win.removeEventListener('resize', resize);
|
|
145
|
+
dialog.removeEventListener('lostpointercapture', stop);
|
|
146
|
+
maximize.remove();
|
|
147
|
+
handles.forEach(handle => handle.remove());
|
|
148
|
+
dialog.style.cssText = initialStyle;
|
|
149
|
+
for (const name of ['window', 'maximized', 'dragging'])
|
|
150
|
+
dialog.removeAttribute(`data-block-editor-${name}`);
|
|
151
|
+
if (frame !== dialog)
|
|
152
|
+
frame.removeAttribute('data-block-editor-window-frame');
|
|
153
|
+
header.removeAttribute('data-block-editor-titlebar');
|
|
154
|
+
};
|
|
155
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BlockPreviewDefinition, EditorDefinition } from './types.js';
|
|
2
|
+
/** Compose presentation only; the original definition retains sole authority over persistence. */
|
|
3
|
+
export declare function withBlockPreview(original: EditorDefinition | undefined, preview: BlockPreviewDefinition, opcode: string): EditorDefinition;
|
package/dist/preview.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const cache = new WeakMap();
|
|
2
|
+
/** Compose presentation only; the original definition retains sole authority over persistence. */
|
|
3
|
+
export function withBlockPreview(original, preview, opcode) {
|
|
4
|
+
let entries = cache.get(preview);
|
|
5
|
+
if (!entries) {
|
|
6
|
+
entries = new Map();
|
|
7
|
+
cache.set(preview, entries);
|
|
8
|
+
}
|
|
9
|
+
const previous = entries.get(opcode);
|
|
10
|
+
if (previous && previous.original === original)
|
|
11
|
+
return previous.result;
|
|
12
|
+
const fallback = {
|
|
13
|
+
apiVersion: 1, extensionId: preview.extensionId, editorId: 'block-preview', opcodes: [opcode], editableArguments: [],
|
|
14
|
+
read: () => ({}), validate: () => [], createPatch: () => []
|
|
15
|
+
};
|
|
16
|
+
const result = Object.freeze({ ...original !== null && original !== void 0 ? original : fallback, mount(container, context) {
|
|
17
|
+
var _a;
|
|
18
|
+
const snapshot = (_a = context.getSnapshot) === null || _a === void 0 ? void 0 : _a.call(context);
|
|
19
|
+
if (!snapshot)
|
|
20
|
+
throw new TypeError('Block preview requires a captured snapshot.');
|
|
21
|
+
const document = container.ownerDocument;
|
|
22
|
+
const layout = document.createElement('div');
|
|
23
|
+
layout.dataset.blockPreviewLayout = '';
|
|
24
|
+
layout.dataset.blockPreviewHasForm = String(typeof (original === null || original === void 0 ? void 0 : original.mount) === 'function');
|
|
25
|
+
const style = document.createElement('style');
|
|
26
|
+
style.textContent = `
|
|
27
|
+
[data-block-preview-layout] {
|
|
28
|
+
display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px;
|
|
29
|
+
min-width: 0; width: 100%; align-items: start;
|
|
30
|
+
}
|
|
31
|
+
[data-block-preview-layout] > [data-block-preview-visual],
|
|
32
|
+
[data-block-preview-layout] > [data-block-preview-form] {
|
|
33
|
+
min-width: 0; max-width: 100%; overflow-wrap: anywhere;
|
|
34
|
+
}
|
|
35
|
+
@media (min-width: 900px) {
|
|
36
|
+
[data-block-preview-layout][data-block-preview-has-form="true"] {
|
|
37
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
38
|
+
}
|
|
39
|
+
[data-block-preview-layout][data-block-preview-has-form="true"] > [data-block-preview-visual] {
|
|
40
|
+
position: sticky; top: 0; align-self: start;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
const visual = document.createElement('div');
|
|
45
|
+
visual.dataset.blockPreviewVisual = '';
|
|
46
|
+
const form = document.createElement('div');
|
|
47
|
+
form.dataset.blockPreviewForm = '';
|
|
48
|
+
form.hidden = typeof (original === null || original === void 0 ? void 0 : original.mount) !== 'function';
|
|
49
|
+
layout.append(visual, form);
|
|
50
|
+
container.append(style, layout);
|
|
51
|
+
const removeLayout = () => { layout.remove(); style.remove(); };
|
|
52
|
+
let removeForm;
|
|
53
|
+
let removePreview;
|
|
54
|
+
try {
|
|
55
|
+
if (original === null || original === void 0 ? void 0 : original.mount) {
|
|
56
|
+
const cleanup = original.mount(form, context);
|
|
57
|
+
if (typeof cleanup !== 'function')
|
|
58
|
+
throw new TypeError('mount() must return a cleanup function.');
|
|
59
|
+
removeForm = cleanup;
|
|
60
|
+
}
|
|
61
|
+
const cleanup = preview.mount(visual, context, snapshot);
|
|
62
|
+
if (typeof cleanup !== 'function')
|
|
63
|
+
throw new TypeError('preview.mount() must return a cleanup function.');
|
|
64
|
+
removePreview = cleanup;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
try {
|
|
68
|
+
removePreview === null || removePreview === void 0 ? void 0 : removePreview();
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
try {
|
|
72
|
+
removeForm === null || removeForm === void 0 ? void 0 : removeForm();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
removeLayout();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
let active = true;
|
|
81
|
+
return () => {
|
|
82
|
+
if (!active)
|
|
83
|
+
return;
|
|
84
|
+
active = false;
|
|
85
|
+
try {
|
|
86
|
+
removePreview === null || removePreview === void 0 ? void 0 : removePreview();
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
try {
|
|
90
|
+
removeForm === null || removeForm === void 0 ? void 0 : removeForm();
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
removeLayout();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
} });
|
|
98
|
+
entries.set(opcode, { original, result });
|
|
99
|
+
return result;
|
|
100
|
+
}
|
package/dist/react.css
CHANGED
|
@@ -349,3 +349,73 @@
|
|
|
349
349
|
color: var(--block-editor-error-text, #a61b1b);
|
|
350
350
|
margin-bottom: 0;
|
|
351
351
|
}
|
|
352
|
+
|
|
353
|
+
/* Window controls also work with a host modal rendered through a portal. */
|
|
354
|
+
:global([data-block-editor-window]) {
|
|
355
|
+
position: fixed;
|
|
356
|
+
top: min(60px, 5vh);
|
|
357
|
+
left: 50%;
|
|
358
|
+
transform: translateX(-50%);
|
|
359
|
+
display: flex;
|
|
360
|
+
flex-direction: column;
|
|
361
|
+
box-sizing: border-box;
|
|
362
|
+
margin: 0;
|
|
363
|
+
max-width: 100vw;
|
|
364
|
+
max-height: calc(100dvh - min(60px, 5vh) - 16px);
|
|
365
|
+
}
|
|
366
|
+
:global([data-block-editor-window-frame]) {
|
|
367
|
+
display: flex;
|
|
368
|
+
flex: 1 1 auto;
|
|
369
|
+
flex-direction: column;
|
|
370
|
+
min-width: 0;
|
|
371
|
+
min-height: 0;
|
|
372
|
+
}
|
|
373
|
+
:global([data-block-editor-titlebar]) {
|
|
374
|
+
flex: 0 0 auto;
|
|
375
|
+
cursor: move;
|
|
376
|
+
touch-action: none;
|
|
377
|
+
user-select: none;
|
|
378
|
+
}
|
|
379
|
+
:global([data-block-editor-titlebar]) > div:first-child { cursor: inherit; }
|
|
380
|
+
:global([data-block-editor-window]) :global([data-block-editor-body]) {
|
|
381
|
+
flex: 1 1 auto;
|
|
382
|
+
min-height: 0;
|
|
383
|
+
max-height: none;
|
|
384
|
+
box-sizing: border-box;
|
|
385
|
+
}
|
|
386
|
+
:global([data-block-editor-window]) .editor-body { flex: 1 1 auto; }
|
|
387
|
+
:global([data-block-editor-maximize]) {
|
|
388
|
+
display: inline-grid;
|
|
389
|
+
flex: 0 0 auto;
|
|
390
|
+
place-items: center;
|
|
391
|
+
width: 34px;
|
|
392
|
+
height: 34px;
|
|
393
|
+
margin-inline-end: 8px;
|
|
394
|
+
padding: 0;
|
|
395
|
+
border: 1px solid currentColor;
|
|
396
|
+
border-radius: 5px;
|
|
397
|
+
background: transparent;
|
|
398
|
+
color: inherit;
|
|
399
|
+
font: 24px/1 system-ui, sans-serif;
|
|
400
|
+
cursor: pointer;
|
|
401
|
+
}
|
|
402
|
+
:global([data-block-editor-maximize]):focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
|
|
403
|
+
:global([data-block-editor-maximized]) { border-radius: 0; max-height: 100dvh; }
|
|
404
|
+
:global([data-block-editor-maximized]) :global([data-block-editor-titlebar]) { cursor: default; }
|
|
405
|
+
:global([data-block-editor-dragging]), :global([data-block-editor-dragging]) * { user-select: none; }
|
|
406
|
+
:global([data-block-editor-resize]) { position: absolute; z-index: 10; touch-action: none; }
|
|
407
|
+
:global([data-block-editor-resize="n"]), :global([data-block-editor-resize="s"]) { left: 9px; right: 9px; height: 7px; cursor: ns-resize; }
|
|
408
|
+
:global([data-block-editor-resize="n"]) { top: 0; }
|
|
409
|
+
:global([data-block-editor-resize="s"]) { bottom: 0; }
|
|
410
|
+
:global([data-block-editor-resize="e"]), :global([data-block-editor-resize="w"]) { top: 9px; bottom: 9px; width: 7px; cursor: ew-resize; }
|
|
411
|
+
:global([data-block-editor-resize="e"]) { right: 0; }
|
|
412
|
+
:global([data-block-editor-resize="w"]) { left: 0; }
|
|
413
|
+
:global([data-block-editor-resize="ne"]), :global([data-block-editor-resize="se"]),
|
|
414
|
+
:global([data-block-editor-resize="sw"]), :global([data-block-editor-resize="nw"]) { width: 10px; height: 10px; }
|
|
415
|
+
:global([data-block-editor-resize="ne"]), :global([data-block-editor-resize="nw"]) { top: 0; }
|
|
416
|
+
:global([data-block-editor-resize="se"]), :global([data-block-editor-resize="sw"]) { bottom: 0; }
|
|
417
|
+
:global([data-block-editor-resize="ne"]), :global([data-block-editor-resize="se"]) { right: 0; }
|
|
418
|
+
:global([data-block-editor-resize="nw"]), :global([data-block-editor-resize="sw"]) { left: 0; }
|
|
419
|
+
:global([data-block-editor-resize="ne"]), :global([data-block-editor-resize="sw"]) { cursor: nesw-resize; }
|
|
420
|
+
:global([data-block-editor-resize="nw"]), :global([data-block-editor-resize="se"]) { cursor: nwse-resize; }
|
|
421
|
+
:global([data-block-editor-maximized]) > :global([data-block-editor-resize]) { display: none; }
|
package/dist/react.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface EditorDialogMessages {
|
|
|
35
35
|
readonly structuralNode: string;
|
|
36
36
|
/** Fixed forms retain technical diagnostics in the API while showing a localized summary. */
|
|
37
37
|
readonly invalidInput?: string;
|
|
38
|
+
readonly maximize?: string;
|
|
39
|
+
readonly restore?: string;
|
|
38
40
|
}
|
|
39
41
|
export interface EditorNodeAppearance {
|
|
40
42
|
readonly name?: string;
|
|
@@ -75,6 +77,7 @@ export declare class BlockEditorDialog extends React.Component<BlockEditorDialog
|
|
|
75
77
|
private removeListener;
|
|
76
78
|
private unmountBody;
|
|
77
79
|
private stopFieldErrors;
|
|
80
|
+
private stopWindow;
|
|
78
81
|
constructor(props: BlockEditorDialogProps);
|
|
79
82
|
componentDidMount(): void;
|
|
80
83
|
componentWillUnmount(): void;
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import bindBlockEditorFieldErrors from './field-errors.js';
|
|
2
|
+
import { attachEditorDialogWindow } from './dialog-window.js';
|
|
2
3
|
export { default as bindBlockEditorFieldErrors } from './field-errors.js';
|
|
3
4
|
import * as React from 'react';
|
|
4
5
|
import { BlockEditorConflictError } from './types.js';
|
|
@@ -164,18 +165,19 @@ export class BlockEditorDialog extends React.Component {
|
|
|
164
165
|
this.mountBody();
|
|
165
166
|
}
|
|
166
167
|
componentWillUnmount() {
|
|
167
|
-
var _a, _b, _c, _d;
|
|
168
|
+
var _a, _b, _c, _d, _e;
|
|
168
169
|
this.unmounting = true;
|
|
169
170
|
this.mounted = false;
|
|
170
171
|
if (this.focusFrame !== undefined)
|
|
171
172
|
cancelAnimationFrame(this.focusFrame);
|
|
172
173
|
this.removeListener();
|
|
173
174
|
(_a = this.stopFieldErrors) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
175
|
+
(_b = this.stopWindow) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
174
176
|
try {
|
|
175
|
-
(
|
|
177
|
+
(_c = this.unmountBody) === null || _c === void 0 ? void 0 : _c.call(this);
|
|
176
178
|
}
|
|
177
179
|
catch (error) {
|
|
178
|
-
(
|
|
180
|
+
(_e = (_d = this.props).onError) === null || _e === void 0 ? void 0 : _e.call(_d, error);
|
|
179
181
|
}
|
|
180
182
|
finally {
|
|
181
183
|
this.props.session.dispose();
|
|
@@ -185,6 +187,12 @@ export class BlockEditorDialog extends React.Component {
|
|
|
185
187
|
if (!this.body || this.unmountBody || this.state.mountFailed)
|
|
186
188
|
return;
|
|
187
189
|
try {
|
|
190
|
+
if (!this.stopWindow)
|
|
191
|
+
this.stopWindow = attachEditorDialogWindow(this.body, {
|
|
192
|
+
headerClassName: this.props.styles.header,
|
|
193
|
+
maximize: this.props.messages.maximize,
|
|
194
|
+
restore: this.props.messages.restore
|
|
195
|
+
});
|
|
188
196
|
if (!this.stopFieldErrors)
|
|
189
197
|
this.stopFieldErrors = bindBlockEditorFieldErrors(this.body);
|
|
190
198
|
if (typeof this.props.session.getNodes !== 'function')
|
|
@@ -224,7 +232,7 @@ export class BlockEditorDialog extends React.Component {
|
|
|
224
232
|
/ブロック|block/i.test(messages.title) ? messages.title.replace(/ブロック|block/i, () => name) :
|
|
225
233
|
`${name}: ${messages.title}` : messages.title;
|
|
226
234
|
return React.createElement(ModalComponent, { className: `${styles.modalContent || ''} ${hierarchy ? styles.hierarchyModal : ''} ${this.props.className || ''}`, contentLabel: title, ...((appearance === null || appearance === void 0 ? void 0 : appearance.iconURI) ? { headerImage: appearance.iconURI } : {}), headerClassName: styles.header, id: "blockEditorModal", onRequestClose: this.handleClose },
|
|
227
|
-
React.createElement("div", { "aria-busy": saving, className: styles.body, onCompositionStart: () => { this.composing = true; }, onCompositionEnd: () => { this.composing = false; }, onKeyDownCapture: event => {
|
|
235
|
+
React.createElement("div", { "aria-busy": saving, className: styles.body, "data-block-editor-body": "", onCompositionStart: () => { this.composing = true; }, onCompositionEnd: () => { this.composing = false; }, onKeyDownCapture: event => {
|
|
228
236
|
if (this.composing || event.nativeEvent.isComposing || event.keyCode === 229)
|
|
229
237
|
event.stopPropagation();
|
|
230
238
|
} },
|
package/dist/registry.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BlockPreviewDefinition } from './types.js';
|
|
1
2
|
import { EditorSession } from './session.js';
|
|
2
3
|
import { DescendantSession } from './descendants.js';
|
|
3
4
|
import type { DescendantLimits } from './descendant-types.js';
|
|
@@ -6,6 +7,8 @@ import type { PreparedEditorDefinition } from './prepared-types.js';
|
|
|
6
7
|
import type { FixedInputDeclaration, FixedInputEditorDefinition } from './fixed-input-types.js';
|
|
7
8
|
export declare class EditorRegistry {
|
|
8
9
|
#private;
|
|
10
|
+
registerPreview(definition: BlockPreviewDefinition): () => void;
|
|
11
|
+
resolvePreview(opcode: string): BlockPreviewDefinition | undefined;
|
|
9
12
|
register(definition: EditorDefinition): () => void;
|
|
10
13
|
registerPrepared(definition: PreparedEditorDefinition): () => void;
|
|
11
14
|
registerFixed<C = null>(definition: FixedInputEditorDefinition<C>): () => void;
|
package/dist/registry.js
CHANGED
|
@@ -3,8 +3,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
3
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _EditorRegistry_instances, _EditorRegistry_editors, _EditorRegistry_opcodes, _EditorRegistry_fixedDeclarations, _EditorRegistry_changes, _EditorRegistry_register, _EditorRegistry_notifyChanges;
|
|
6
|
+
var _EditorRegistry_instances, _EditorRegistry_previews, _EditorRegistry_editors, _EditorRegistry_opcodes, _EditorRegistry_fixedDeclarations, _EditorRegistry_changes, _EditorRegistry_definition, _EditorRegistry_register, _EditorRegistry_notifyChanges;
|
|
7
7
|
import { captureReference, captureSnapshot } from './data.js';
|
|
8
|
+
import { withBlockPreview } from './preview.js';
|
|
8
9
|
import { EditorSession } from './session.js';
|
|
9
10
|
import { DescendantSession } from './descendants.js';
|
|
10
11
|
import { supportsDescendantEditing } from './descendant-types.js';
|
|
@@ -17,11 +18,35 @@ import { supportsFixedInputEditing } from './fixed-input-types.js';
|
|
|
17
18
|
export class EditorRegistry {
|
|
18
19
|
constructor() {
|
|
19
20
|
_EditorRegistry_instances.add(this);
|
|
21
|
+
_EditorRegistry_previews.set(this, new Map());
|
|
20
22
|
_EditorRegistry_editors.set(this, new Map());
|
|
21
23
|
_EditorRegistry_opcodes.set(this, new Map());
|
|
22
24
|
_EditorRegistry_fixedDeclarations.set(this, new Map());
|
|
23
25
|
_EditorRegistry_changes.set(this, new Set());
|
|
24
26
|
}
|
|
27
|
+
registerPreview(definition) {
|
|
28
|
+
if (!definition || !/^[a-z0-9]+$/i.test(definition.extensionId) ||
|
|
29
|
+
!Array.isArray(definition.opcodes) || !definition.opcodes.length ||
|
|
30
|
+
new Set(definition.opcodes).size !== definition.opcodes.length ||
|
|
31
|
+
definition.opcodes.some(op => typeof op !== 'string' || !op.startsWith(`${definition.extensionId}_`) ||
|
|
32
|
+
op === `${definition.extensionId}_` || __classPrivateFieldGet(this, _EditorRegistry_previews, "f").has(op)) ||
|
|
33
|
+
typeof definition.mount !== 'function' ||
|
|
34
|
+
(definition.hover !== undefined && typeof definition.hover !== 'function')) {
|
|
35
|
+
throw new TypeError('Invalid or duplicate block preview.');
|
|
36
|
+
}
|
|
37
|
+
const entry = Object.freeze({ ...definition, opcodes: Object.freeze([...definition.opcodes]) });
|
|
38
|
+
for (const op of entry.opcodes)
|
|
39
|
+
__classPrivateFieldGet(this, _EditorRegistry_previews, "f").set(op, entry);
|
|
40
|
+
__classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_notifyChanges).call(this);
|
|
41
|
+
return () => {
|
|
42
|
+
if (__classPrivateFieldGet(this, _EditorRegistry_previews, "f").get(entry.opcodes[0]) !== entry)
|
|
43
|
+
return;
|
|
44
|
+
for (const op of entry.opcodes)
|
|
45
|
+
__classPrivateFieldGet(this, _EditorRegistry_previews, "f").delete(op);
|
|
46
|
+
__classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_notifyChanges).call(this);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
resolvePreview(opcode) { return __classPrivateFieldGet(this, _EditorRegistry_previews, "f").get(opcode); }
|
|
25
50
|
register(definition) {
|
|
26
51
|
if (isFixedInputEditor(definition))
|
|
27
52
|
throw new TypeError('Fixed input editors require registerFixed().');
|
|
@@ -39,7 +64,7 @@ export class EditorRegistry {
|
|
|
39
64
|
return __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_register).call(this, captureFixedInputEditorDefinition(definition));
|
|
40
65
|
}
|
|
41
66
|
resolve(opcode) {
|
|
42
|
-
const entry = __classPrivateFieldGet(this,
|
|
67
|
+
const entry = __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, opcode);
|
|
43
68
|
if (!entry)
|
|
44
69
|
return undefined;
|
|
45
70
|
return Object.freeze({
|
|
@@ -57,7 +82,7 @@ export class EditorRegistry {
|
|
|
57
82
|
const live = host.readBlock(capturedReference);
|
|
58
83
|
if (!live)
|
|
59
84
|
return undefined;
|
|
60
|
-
const entry = __classPrivateFieldGet(this,
|
|
85
|
+
const entry = __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, live.opcode);
|
|
61
86
|
if (!entry) {
|
|
62
87
|
// Preserve legacy snapshot validation even when no editor is registered.
|
|
63
88
|
captureSnapshot(live, capturedReference);
|
|
@@ -70,14 +95,14 @@ export class EditorRegistry {
|
|
|
70
95
|
if (!fixed || fixed.opcode !== live.opcode)
|
|
71
96
|
return undefined;
|
|
72
97
|
const snapshot = captureFixedSnapshot(fixed, capturedReference, entry);
|
|
73
|
-
return new EditorSession(entry, snapshot, host, () => __classPrivateFieldGet(this,
|
|
98
|
+
return new EditorSession(entry, snapshot, host, () => __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, snapshot.opcode) === entry, listener => {
|
|
74
99
|
__classPrivateFieldGet(this, _EditorRegistry_changes, "f").add(listener);
|
|
75
100
|
return () => { __classPrivateFieldGet(this, _EditorRegistry_changes, "f").delete(listener); };
|
|
76
101
|
});
|
|
77
102
|
}
|
|
78
103
|
const snapshot = captureSnapshot(live, capturedReference);
|
|
79
|
-
return new EditorSession(entry, snapshot, host, isPreparedEditor(entry)
|
|
80
|
-
? () => __classPrivateFieldGet(this,
|
|
104
|
+
return new EditorSession(entry, snapshot, host, isPreparedEditor(entry) || __classPrivateFieldGet(this, _EditorRegistry_previews, "f").has(snapshot.opcode)
|
|
105
|
+
? () => __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, snapshot.opcode) === entry : undefined);
|
|
81
106
|
}
|
|
82
107
|
openDescendants(reference, host, limits) {
|
|
83
108
|
if (!supportsDescendantEditing(host))
|
|
@@ -89,11 +114,11 @@ export class EditorRegistry {
|
|
|
89
114
|
if (!live)
|
|
90
115
|
return undefined;
|
|
91
116
|
const captured = captureSubtree(live, capturedReference, resolvedLimits);
|
|
92
|
-
const root = __classPrivateFieldGet(this,
|
|
117
|
+
const root = __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, captured.snapshot.nodes[0].block.opcode);
|
|
93
118
|
if (!root || isFixedInputEditor(root))
|
|
94
119
|
return undefined;
|
|
95
120
|
return new DescendantSession(captured, port, opcode => {
|
|
96
|
-
const entry = __classPrivateFieldGet(this,
|
|
121
|
+
const entry = __classPrivateFieldGet(this, _EditorRegistry_instances, "m", _EditorRegistry_definition).call(this, opcode);
|
|
97
122
|
return entry && !isFixedInputEditor(entry) ? entry : undefined;
|
|
98
123
|
}, listener => {
|
|
99
124
|
__classPrivateFieldGet(this, _EditorRegistry_changes, "f").add(listener);
|
|
@@ -101,7 +126,11 @@ export class EditorRegistry {
|
|
|
101
126
|
}, resolvedLimits);
|
|
102
127
|
}
|
|
103
128
|
}
|
|
104
|
-
_EditorRegistry_editors = new WeakMap(), _EditorRegistry_opcodes = new WeakMap(), _EditorRegistry_fixedDeclarations = new WeakMap(), _EditorRegistry_changes = new WeakMap(), _EditorRegistry_instances = new WeakSet(),
|
|
129
|
+
_EditorRegistry_previews = new WeakMap(), _EditorRegistry_editors = new WeakMap(), _EditorRegistry_opcodes = new WeakMap(), _EditorRegistry_fixedDeclarations = new WeakMap(), _EditorRegistry_changes = new WeakMap(), _EditorRegistry_instances = new WeakSet(), _EditorRegistry_definition = function _EditorRegistry_definition(opcode) {
|
|
130
|
+
const original = __classPrivateFieldGet(this, _EditorRegistry_opcodes, "f").get(opcode);
|
|
131
|
+
const preview = __classPrivateFieldGet(this, _EditorRegistry_previews, "f").get(opcode);
|
|
132
|
+
return preview ? withBlockPreview(original, preview, opcode) : original;
|
|
133
|
+
}, _EditorRegistry_register = function _EditorRegistry_register(definition) {
|
|
105
134
|
if (definition.apiVersion !== EDITOR_API_VERSION)
|
|
106
135
|
throw new TypeError('Unsupported editor API version.');
|
|
107
136
|
if (!/^[a-z0-9]+$/i.test(definition.extensionId) ||
|
package/dist/rjsf.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { SchemaBundle, SchemaJsonObject, SchemaValidationContext, SyncOwner
|
|
|
16
16
|
import type { SourceFormat } from './codec.js';
|
|
17
17
|
import { EditorRegistry } from './registry.js';
|
|
18
18
|
import { EDITOR_API_VERSION } from './types.js';
|
|
19
|
-
import type { BlockSnapshot, EditorDefinition, JsonValue, ValidationIssue } from './types.js';
|
|
19
|
+
import type { BlockPreviewDefinition, BlockSnapshot, EditorDefinition, JsonValue, ValidationIssue } from './types.js';
|
|
20
20
|
export interface SchemaEditorOptions {
|
|
21
21
|
readonly apiVersion: typeof EDITOR_API_VERSION;
|
|
22
22
|
readonly extensionId: string;
|
|
@@ -41,6 +41,7 @@ export declare function createSchemaBundleEditor<C>(options: SchemaBundleEditorO
|
|
|
41
41
|
export interface BlockEditorRegistrationAPI {
|
|
42
42
|
readonly apiVersion: typeof EDITOR_API_VERSION;
|
|
43
43
|
register(definition: EditorDefinition | SchemaEditorOptions): () => void;
|
|
44
|
+
registerPreview?(definition: BlockPreviewDefinition): () => void;
|
|
44
45
|
registerSchema(definition: SchemaEditorOptions): () => void;
|
|
45
46
|
registerSchemaBundle?<C>(definition: SchemaBundleEditorOptions<C>): () => void;
|
|
46
47
|
registerSourceEditor?<C = null>(definition: SourceEditorOptions<C>): () => void;
|