@lvce-editor/api 9.38.0 → 9.39.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.
|
@@ -51,6 +51,8 @@ export interface VirtualDomViewInstance {
|
|
|
51
51
|
readonly getCss?: () => string | Promise<string>;
|
|
52
52
|
readonly getMenuEntries?: (menuId: string) => readonly MenuEntry[] | Promise<readonly MenuEntry[]>;
|
|
53
53
|
readonly handleEvent?: (event: ViewEvent) => unknown;
|
|
54
|
+
/** Whether this document has edits that have not been saved. */
|
|
55
|
+
readonly isDirty?: () => boolean;
|
|
54
56
|
readonly render: () => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
|
|
55
57
|
readonly renderActions?: () => readonly ViewAction[] | Promise<readonly ViewAction[]>;
|
|
56
58
|
readonly renderActionsDom?: () => readonly VirtualDomNode[];
|
|
@@ -59,6 +61,8 @@ export interface VirtualDomViewInstance {
|
|
|
59
61
|
readonly renderSelections?: () => readonly ViewSelection[] | Promise<readonly ViewSelection[]>;
|
|
60
62
|
readonly renderStatusBarItems?: () => readonly StatusBarItem[] | Promise<readonly StatusBarItem[]>;
|
|
61
63
|
readonly renderTitle?: () => string | Promise<string>;
|
|
64
|
+
/** Persist committed edits. Reject on failure and retain dirty state until persistence succeeds. */
|
|
65
|
+
readonly save?: () => void | Promise<void>;
|
|
62
66
|
readonly saveState?: () => unknown;
|
|
63
67
|
}
|
|
64
68
|
export type ViewCommand<State = VirtualDomViewInstance, Args extends readonly any[] = readonly any[]> = (state: State, ...args: Args) => State | Promise<State>;
|
|
@@ -87,6 +91,7 @@ export interface StatefulView<State = unknown> extends ViewBase<State> {
|
|
|
87
91
|
readonly getCss?: (state: State) => string | Promise<string>;
|
|
88
92
|
readonly getMenuEntries?: (state: State, menuId: string) => readonly MenuEntry[] | Promise<readonly MenuEntry[]>;
|
|
89
93
|
readonly handleEvent?: (state: State, event: ViewEvent) => State | Promise<State>;
|
|
94
|
+
readonly isDirty?: (state: State) => boolean;
|
|
90
95
|
readonly render: (state: State) => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
|
|
91
96
|
readonly renderActions?: (state: State) => readonly ViewAction[] | Promise<readonly ViewAction[]>;
|
|
92
97
|
readonly renderActionsDom?: (state: State) => readonly VirtualDomNode[];
|
|
@@ -95,6 +100,7 @@ export interface StatefulView<State = unknown> extends ViewBase<State> {
|
|
|
95
100
|
readonly renderSelections?: (state: State) => readonly ViewSelection[] | Promise<readonly ViewSelection[]>;
|
|
96
101
|
readonly renderStatusBarItems?: (state: State) => readonly StatusBarItem[] | Promise<readonly StatusBarItem[]>;
|
|
97
102
|
readonly renderTitle?: (state: State) => string | Promise<string>;
|
|
103
|
+
readonly save?: (state: State) => State | Promise<State>;
|
|
98
104
|
readonly saveState?: (state: State) => unknown;
|
|
99
105
|
}
|
|
100
106
|
export type View<State = unknown, ComponentState = unknown> = InstanceView<State, ComponentState> | StatefulView<State>;
|
|
@@ -116,6 +122,7 @@ export interface ViewRenderResultDom {
|
|
|
116
122
|
readonly css?: string;
|
|
117
123
|
readonly dom: readonly VirtualDomNode[];
|
|
118
124
|
readonly focusSelector?: string;
|
|
125
|
+
readonly modified?: boolean;
|
|
119
126
|
readonly scrollPosition?: ViewScrollPosition;
|
|
120
127
|
readonly selections?: readonly ViewSelection[];
|
|
121
128
|
readonly title?: string;
|
|
@@ -124,6 +131,7 @@ export interface ViewRenderResultDom {
|
|
|
124
131
|
export interface ViewRenderResultPatches {
|
|
125
132
|
readonly css?: string;
|
|
126
133
|
readonly focusSelector?: string;
|
|
134
|
+
readonly modified?: boolean;
|
|
127
135
|
readonly patches: readonly unknown[];
|
|
128
136
|
readonly scrollPosition?: ViewScrollPosition;
|
|
129
137
|
readonly selections?: readonly ViewSelection[];
|
|
@@ -236,6 +236,16 @@ const createStatefulViewInstance = (view, uid) => {
|
|
|
236
236
|
ViewletStates.replace(uid, newState);
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
|
+
if (view.isDirty) {
|
|
240
|
+
instance.isDirty = () => view.isDirty(ViewletStates.get(uid));
|
|
241
|
+
}
|
|
242
|
+
if (view.save) {
|
|
243
|
+
instance.save = async () => {
|
|
244
|
+
const newState = await view.save(ViewletStates.get(uid));
|
|
245
|
+
assertViewState(view.id, newState);
|
|
246
|
+
ViewletStates.replace(uid, newState);
|
|
247
|
+
};
|
|
248
|
+
}
|
|
239
249
|
if (view.renderActions) {
|
|
240
250
|
instance.renderActions = () => view.renderActions(ViewletStates.get(uid));
|
|
241
251
|
}
|
|
@@ -506,7 +516,14 @@ const withRenderMetadata = async (uid, viewId, result, instance, contextChange)
|
|
|
506
516
|
const resultWithScrollPosition = await withScrollPosition(resultWithSelections, instance);
|
|
507
517
|
const resultWithTitle = await withTitle(resultWithScrollPosition, instance);
|
|
508
518
|
await ViewStatusBarItems.renderViewStatusBarItems(uid, viewId, instance);
|
|
509
|
-
|
|
519
|
+
if (typeof instance.isDirty !== 'function') {
|
|
520
|
+
return resultWithTitle;
|
|
521
|
+
}
|
|
522
|
+
const modified = instance.isDirty();
|
|
523
|
+
if (typeof modified !== 'boolean') {
|
|
524
|
+
throw new ExtensionApiError('view isDirty result must be a boolean');
|
|
525
|
+
}
|
|
526
|
+
return { ...resultWithTitle, modified };
|
|
510
527
|
};
|
|
511
528
|
const maybeClearContext = async (uid, viewId) => {
|
|
512
529
|
if (!contexts[uid]) {
|