@lvce-editor/api 9.28.2 → 9.29.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/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/parts/FileSystemProvider/FileSystemProvider.d.ts +0 -1
- package/dist/parts/FileSystemProviderRegistry/FileSystemProviderRegistry.d.ts +0 -2
- package/dist/parts/FileSystemProviderRegistry/FileSystemProviderRegistry.js +0 -15
- package/dist/parts/Host/Host.js +1 -9
- package/dist/parts/PublicViewletStates/PublicViewletStates.d.ts +1 -0
- package/dist/parts/PublicViewletStates/PublicViewletStates.js +1 -0
- package/dist/parts/RegisteredFileSystemProvider/RegisteredFileSystemProvider.d.ts +0 -1
- package/dist/parts/View/View.d.ts +26 -2
- package/dist/parts/ViewRegistry/ViewRegistry.d.ts +2 -0
- package/dist/parts/ViewRegistry/ViewRegistry.js +111 -7
- package/dist/parts/ViewletStates/ViewletStates.d.ts +7 -0
- package/dist/parts/ViewletStates/ViewletStates.js +38 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { executeDiagnosticProvider, getDiagnosticProviderRegistrySnapshot, regis
|
|
|
15
15
|
export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, registerFormattingProvider, resetFormattingProviderRegistry, } from './parts/Formatting/Formatting.ts';
|
|
16
16
|
export { exists, getFileHash, getFileHashes, mkdir, readAsObjectUrl, readDirWithFileTypes, readFile, readFileAsBlob, remove, stat, writeFile, type ReadAsObjectUrlResult, } from './parts/FileSystem/FileSystem.ts';
|
|
17
17
|
export { registerFileChangeHandler, type FileChangeHandler, type FileChanges } from './parts/FileChangeHandler/FileChangeHandler.ts';
|
|
18
|
-
export {
|
|
18
|
+
export { executeFileSystemProviderIsReadonly, executeFileSystemProviderMkdir, executeFileSystemProviderReadDirWithFileTypes, executeFileSystemProviderReadFile, executeFileSystemProviderRemove, executeFileSystemProviderRename, executeFileSystemProviderWriteFile, getFileSystemProviderRegistrySnapshot, registerFileSystemProvider, resetFileSystemProviderRegistry, } from './parts/FileSystemProviderRegistry/FileSystemProviderRegistry.ts';
|
|
19
19
|
export { closeUri, confirm, getRecentlyOpenedWorkspaceUris, getWorkspaceFolder, getWorkspaceUri, handleWorkspaceRefresh, openUri, setWorkspaceUri, showNotification, type NotificationType, } from './parts/Host/Host.ts';
|
|
20
20
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from './parts/Hover/Hover.ts';
|
|
21
21
|
export { executeSignatureHelpProvider, getSignatureHelpProviderRegistrySnapshot, registerSignatureHelpProvider, resetSignatureHelpProviderRegistry, } from './parts/SignatureHelp/SignatureHelp.ts';
|
|
@@ -27,10 +27,11 @@ export { getLanguageServerRegistrySnapshot, registerLanguageServer, resetLanguag
|
|
|
27
27
|
export { registerBraceCompletionProvider, registerClosingTagProvider, registerCodeActionsProvider, registerCommentProvider, registerDefinitionProvider, registerDocumentSymbolProvider, registerImplementationProvider, registerReferenceProvider, registerRenameProvider, registerSelectionProvider, registerTabCompletionProvider, registerTypeDefinitionProvider, resetLanguageProviderRegistry, } from './parts/LanguageProvider/LanguageProvider.ts';
|
|
28
28
|
export type { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolTextDocument, LanguageProvider, } from './parts/LanguageProvider/LanguageProvider.ts';
|
|
29
29
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetBadgeCount, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileBeforeUri, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from './parts/SourceControl/SourceControl.ts';
|
|
30
|
-
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, setViewInstanceActive, } from './parts/ViewRegistry/ViewRegistry.ts';
|
|
30
|
+
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewInstanceState, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, setViewInstanceState, setViewInstanceActive, } from './parts/ViewRegistry/ViewRegistry.ts';
|
|
31
|
+
export * as ViewletStates from './parts/PublicViewletStates/PublicViewletStates.ts';
|
|
31
32
|
export { createOutputChannel, getOutputChannelLogs, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry, } from './parts/OutputChannel/OutputChannel.ts';
|
|
32
33
|
export { getStatusBarItemProviderRegistrySnapshot, registerStatusBarItemProvider, resetStatusBarItemProviderRegistry, } from './parts/StatusBar/StatusBar.ts';
|
|
33
|
-
export type { RegisteredView, View, ViewAction, ViewCommand, ViewContext, ViewEvent, ViewKind, ViewPreferredLocation, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, ViewScrollPosition, ViewSelection, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
34
|
+
export type { RegisteredView, InstanceView, StatefulView, View, ViewAction, ViewCommand, ViewContext, ViewEvent, ViewKind, ViewPreferredLocation, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, ViewScrollPosition, ViewSelection, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
34
35
|
export { handleExtensionManagementMessagePort } from './parts/HandleExtensionManagementMessagePort/HandleExtensionManagementMessagePort.ts';
|
|
35
36
|
export { createNodeRpc, createRpc } from './parts/Rpc/Rpc.ts';
|
|
36
37
|
export type { Command } from './parts/Command/Command.ts';
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ export { executeDiagnosticProvider, getDiagnosticProviderRegistrySnapshot, regis
|
|
|
15
15
|
export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, registerFormattingProvider, resetFormattingProviderRegistry, } from "./parts/Formatting/Formatting.js";
|
|
16
16
|
export { exists, getFileHash, getFileHashes, mkdir, readAsObjectUrl, readDirWithFileTypes, readFile, readFileAsBlob, remove, stat, writeFile, } from "./parts/FileSystem/FileSystem.js";
|
|
17
17
|
export { registerFileChangeHandler } from "./parts/FileChangeHandler/FileChangeHandler.js";
|
|
18
|
-
export {
|
|
18
|
+
export { executeFileSystemProviderIsReadonly, executeFileSystemProviderMkdir, executeFileSystemProviderReadDirWithFileTypes, executeFileSystemProviderReadFile, executeFileSystemProviderRemove, executeFileSystemProviderRename, executeFileSystemProviderWriteFile, getFileSystemProviderRegistrySnapshot, registerFileSystemProvider, resetFileSystemProviderRegistry, } from "./parts/FileSystemProviderRegistry/FileSystemProviderRegistry.js";
|
|
19
19
|
export { closeUri, confirm, getRecentlyOpenedWorkspaceUris, getWorkspaceFolder, getWorkspaceUri, handleWorkspaceRefresh, openUri, setWorkspaceUri, showNotification, } from "./parts/Host/Host.js";
|
|
20
20
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from "./parts/Hover/Hover.js";
|
|
21
21
|
export { executeSignatureHelpProvider, getSignatureHelpProviderRegistrySnapshot, registerSignatureHelpProvider, resetSignatureHelpProviderRegistry, } from "./parts/SignatureHelp/SignatureHelp.js";
|
|
@@ -26,7 +26,8 @@ export { openDebugConsole, openOutputView, openProblemsView, } from "./parts/Pan
|
|
|
26
26
|
export { getLanguageServerRegistrySnapshot, registerLanguageServer, resetLanguageServerRegistry } from "./parts/LanguageServer/LanguageServer.js";
|
|
27
27
|
export { registerBraceCompletionProvider, registerClosingTagProvider, registerCodeActionsProvider, registerCommentProvider, registerDefinitionProvider, registerDocumentSymbolProvider, registerImplementationProvider, registerReferenceProvider, registerRenameProvider, registerSelectionProvider, registerTabCompletionProvider, registerTypeDefinitionProvider, resetLanguageProviderRegistry, } from "./parts/LanguageProvider/LanguageProvider.js";
|
|
28
28
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetBadgeCount, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileBeforeUri, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from "./parts/SourceControl/SourceControl.js";
|
|
29
|
-
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, setViewInstanceActive, } from "./parts/ViewRegistry/ViewRegistry.js";
|
|
29
|
+
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewInstanceState, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, setViewInstanceState, setViewInstanceActive, } from "./parts/ViewRegistry/ViewRegistry.js";
|
|
30
|
+
export * as ViewletStates from "./parts/PublicViewletStates/PublicViewletStates.js";
|
|
30
31
|
export { createOutputChannel, getOutputChannelLogs, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry, } from "./parts/OutputChannel/OutputChannel.js";
|
|
31
32
|
export { getStatusBarItemProviderRegistrySnapshot, registerStatusBarItemProvider, resetStatusBarItemProviderRegistry, } from "./parts/StatusBar/StatusBar.js";
|
|
32
33
|
export { handleExtensionManagementMessagePort } from "./parts/HandleExtensionManagementMessagePort/HandleExtensionManagementMessagePort.js";
|
|
@@ -3,7 +3,6 @@ export interface FileSystemProvider {
|
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly isReadonly?: () => boolean | Promise<boolean>;
|
|
5
5
|
readonly mkdir?: (uri: string) => void | Promise<void>;
|
|
6
|
-
readonly pathSeparator?: string;
|
|
7
6
|
readonly readDirWithFileTypes?: (uri: string) => readonly FileSystemDirent[] | Promise<readonly FileSystemDirent[]>;
|
|
8
7
|
readonly readFile: (uri: string) => Blob | Promise<Blob | string> | string;
|
|
9
8
|
readonly remove?: (uri: string) => void | Promise<void>;
|
|
@@ -8,8 +8,6 @@ export declare const executeFileSystemProviderRemove: (id: string, uri: string)
|
|
|
8
8
|
export declare const executeFileSystemProviderRename: (id: string, oldUri: string, newUri: string) => Promise<void>;
|
|
9
9
|
export declare const executeFileSystemProviderWriteFile: (id: string, uri: string, content: string) => Promise<void>;
|
|
10
10
|
export declare const executeFileSystemProviderReadDirWithFileTypes: (id: string, uri: string) => Promise<readonly FileSystemDirent[]>;
|
|
11
|
-
export declare const executeFileSystemProviderGetPathSeparator: (id: string) => string;
|
|
12
|
-
export declare const getFileSystemProviderPathSeparator: (id: string) => string | undefined;
|
|
13
11
|
export declare const executeFileSystemProviderIsReadonly: (id: string) => Promise<boolean>;
|
|
14
12
|
export declare const getFileSystemProviderRegistrySnapshot: () => FileSystemProviderRegistrySnapshot;
|
|
15
13
|
export declare const registerFileSystemProvider: (provider: FileSystemProvider) => Disposable;
|
|
@@ -22,9 +22,6 @@ const assertFileSystemProvider = (provider) => {
|
|
|
22
22
|
throw new ExtensionApiError(`file system provider ${provider.id} has invalid ${method} function`);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
if (provider.pathSeparator !== undefined && typeof provider.pathSeparator !== 'string') {
|
|
26
|
-
throw new ExtensionApiError(`file system provider ${provider.id} has invalid pathSeparator`);
|
|
27
|
-
}
|
|
28
25
|
if (provider.id in providers) {
|
|
29
26
|
throw new ExtensionApiError(`file system provider ${provider.id} is already registered`);
|
|
30
27
|
}
|
|
@@ -74,16 +71,6 @@ export const executeFileSystemProviderReadDirWithFileTypes = async (id, uri) =>
|
|
|
74
71
|
}
|
|
75
72
|
return provider.readDirWithFileTypes(uri);
|
|
76
73
|
};
|
|
77
|
-
export const executeFileSystemProviderGetPathSeparator = (id) => {
|
|
78
|
-
return getProvider(id).pathSeparator || '/';
|
|
79
|
-
};
|
|
80
|
-
export const getFileSystemProviderPathSeparator = (id) => {
|
|
81
|
-
const provider = providers[id];
|
|
82
|
-
if (!provider) {
|
|
83
|
-
return undefined;
|
|
84
|
-
}
|
|
85
|
-
return provider.pathSeparator || '/';
|
|
86
|
-
};
|
|
87
74
|
export const executeFileSystemProviderIsReadonly = async (id) => {
|
|
88
75
|
const provider = getProvider(id);
|
|
89
76
|
return provider.isReadonly ? provider.isReadonly() : false;
|
|
@@ -101,7 +88,6 @@ export const registerFileSystemProvider = (provider) => {
|
|
|
101
88
|
id: provider.id,
|
|
102
89
|
isReadonly: provider.isReadonly,
|
|
103
90
|
mkdir: provider.mkdir,
|
|
104
|
-
pathSeparator: provider.pathSeparator,
|
|
105
91
|
readDirWithFileTypes: provider.readDirWithFileTypes,
|
|
106
92
|
readFile: (uri) => provider.readFile(uri),
|
|
107
93
|
remove: provider.remove,
|
|
@@ -116,7 +102,6 @@ export const registerFileSystemProvider = (provider) => {
|
|
|
116
102
|
};
|
|
117
103
|
};
|
|
118
104
|
const commandMap = {
|
|
119
|
-
'ExtensionApi.executeFileSystemProviderGetPathSeparator': executeFileSystemProviderGetPathSeparator,
|
|
120
105
|
'ExtensionApi.executeFileSystemProviderIsReadonly': executeFileSystemProviderIsReadonly,
|
|
121
106
|
'ExtensionApi.executeFileSystemProviderMkdir': executeFileSystemProviderMkdir,
|
|
122
107
|
'ExtensionApi.executeFileSystemProviderReadDirWithFileTypes': executeFileSystemProviderReadDirWithFileTypes,
|
package/dist/parts/Host/Host.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ExtensionManagementWorker } from '@lvce-editor/rpc-registry';
|
|
2
2
|
import { executeCommand } from "../ExecuteCommand/ExecuteCommand.js";
|
|
3
|
-
import { getFileSystemProviderPathSeparator } from "../FileSystemProviderRegistry/FileSystemProviderRegistry.js";
|
|
4
3
|
export const closeUri = async (uri) => {
|
|
5
4
|
await executeCommand('Main.closeTabsByUris', [uri]);
|
|
6
5
|
};
|
|
@@ -26,12 +25,5 @@ export const showNotification = async (type, message) => {
|
|
|
26
25
|
await ExtensionManagementWorker.invoke('Extensions.showNotification', type, message);
|
|
27
26
|
};
|
|
28
27
|
export const setWorkspaceUri = async (uri) => {
|
|
29
|
-
|
|
30
|
-
const protocol = protocolEnd === -1 ? '' : uri.slice(0, protocolEnd);
|
|
31
|
-
const pathSeparator = getFileSystemProviderPathSeparator(protocol);
|
|
32
|
-
if (pathSeparator === undefined) {
|
|
33
|
-
await executeCommand('Workspace.setUri', uri);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
await executeCommand('Workspace.setUri', uri, pathSeparator);
|
|
28
|
+
await executeCommand('Workspace.setUri', uri);
|
|
37
29
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { get, set } from '../ViewletStates/ViewletStates.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { get, set } from "../ViewletStates/ViewletStates.js";
|
|
@@ -3,7 +3,6 @@ export interface RegisteredFileSystemProvider {
|
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly isReadonly?: () => boolean | Promise<boolean>;
|
|
5
5
|
readonly mkdir?: (uri: string) => void | Promise<void>;
|
|
6
|
-
readonly pathSeparator?: string;
|
|
7
6
|
readonly readDirWithFileTypes?: (uri: string) => readonly FileSystemDirent[] | Promise<readonly FileSystemDirent[]>;
|
|
8
7
|
readonly readFile: (uri: string) => Blob | Promise<Blob | string> | string;
|
|
9
8
|
readonly remove?: (uri: string) => void | Promise<void>;
|
|
@@ -62,9 +62,8 @@ export interface VirtualDomViewInstance {
|
|
|
62
62
|
readonly saveState?: () => unknown;
|
|
63
63
|
}
|
|
64
64
|
export type ViewCommand<State = VirtualDomViewInstance, Args extends readonly any[] = readonly any[]> = (state: State, ...args: Args) => State | Promise<State>;
|
|
65
|
-
|
|
65
|
+
interface ViewBase<State> {
|
|
66
66
|
readonly commands?: Readonly<Record<string, ViewCommand<State>>>;
|
|
67
|
-
readonly create: (context?: ViewContext) => State | Promise<State>;
|
|
68
67
|
readonly displayName?: string;
|
|
69
68
|
readonly eventListeners?: readonly DomEventListener[];
|
|
70
69
|
readonly icon?: string;
|
|
@@ -74,6 +73,29 @@ export interface View<State = unknown> {
|
|
|
74
73
|
readonly preferredLocation?: ViewPreferredLocation;
|
|
75
74
|
readonly title?: string;
|
|
76
75
|
}
|
|
76
|
+
export interface InstanceView<State = unknown> extends ViewBase<State> {
|
|
77
|
+
readonly create: (context?: ViewContext) => State | Promise<State>;
|
|
78
|
+
readonly createInitialState?: never;
|
|
79
|
+
}
|
|
80
|
+
export interface StatefulView<State = unknown> extends ViewBase<State> {
|
|
81
|
+
readonly create?: never;
|
|
82
|
+
readonly createInitialState: (context?: ViewContext) => State | Promise<State>;
|
|
83
|
+
readonly dispose?: (state: State) => unknown;
|
|
84
|
+
readonly getContext?: (state: State) => Readonly<Record<string, boolean>>;
|
|
85
|
+
readonly getCss?: (state: State) => string | Promise<string>;
|
|
86
|
+
readonly getMenuEntries?: (state: State, menuId: string) => readonly MenuEntry[] | Promise<readonly MenuEntry[]>;
|
|
87
|
+
readonly handleEvent?: (state: State, event: ViewEvent) => State | Promise<State>;
|
|
88
|
+
readonly render: (state: State) => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
|
|
89
|
+
readonly renderActions?: (state: State) => readonly ViewAction[] | Promise<readonly ViewAction[]>;
|
|
90
|
+
readonly renderActionsDom?: (state: State) => readonly VirtualDomNode[];
|
|
91
|
+
readonly renderFocus?: (state: State, oldContext: Readonly<Record<string, boolean>>, newContext: Readonly<Record<string, boolean>>) => string | Promise<string>;
|
|
92
|
+
readonly renderScrollPosition?: (state: State) => readonly [] | ViewScrollPosition | Promise<readonly [] | ViewScrollPosition>;
|
|
93
|
+
readonly renderSelections?: (state: State) => readonly ViewSelection[] | Promise<readonly ViewSelection[]>;
|
|
94
|
+
readonly renderStatusBarItems?: (state: State) => readonly StatusBarItem[] | Promise<readonly StatusBarItem[]>;
|
|
95
|
+
readonly renderTitle?: (state: State) => string | Promise<string>;
|
|
96
|
+
readonly saveState?: (state: State) => unknown;
|
|
97
|
+
}
|
|
98
|
+
export type View<State = unknown> = InstanceView<State> | StatefulView<State>;
|
|
77
99
|
export interface RegisteredView {
|
|
78
100
|
readonly displayName?: string;
|
|
79
101
|
readonly eventListeners?: readonly DomEventListener[];
|
|
@@ -82,6 +104,7 @@ export interface RegisteredView {
|
|
|
82
104
|
readonly kind?: ViewKind;
|
|
83
105
|
readonly name?: string;
|
|
84
106
|
readonly preferredLocation: ViewPreferredLocation;
|
|
107
|
+
readonly stateful?: boolean;
|
|
85
108
|
readonly title?: string;
|
|
86
109
|
}
|
|
87
110
|
export interface ViewRegistrySnapshot {
|
|
@@ -106,3 +129,4 @@ export interface ViewRenderResultPatches {
|
|
|
106
129
|
readonly type: 'setPatches';
|
|
107
130
|
}
|
|
108
131
|
export type ViewRenderResult = ViewRenderResultDom | ViewRenderResultPatches;
|
|
132
|
+
export {};
|
|
@@ -9,6 +9,8 @@ export declare const renderViewInstance: (uid: number) => Promise<ViewRenderResu
|
|
|
9
9
|
export declare const setViewInstanceActive: (uid: number, active: boolean) => Promise<void>;
|
|
10
10
|
export declare const disposeViewInstance: (uid: number) => Promise<void>;
|
|
11
11
|
export declare const saveViewInstanceState: (uid: number) => Promise<unknown>;
|
|
12
|
+
export declare const getViewInstanceState: (uid: number) => unknown;
|
|
13
|
+
export declare const setViewInstanceState: (uid: number, newState: unknown) => Promise<ViewRenderResult>;
|
|
12
14
|
export declare const getViewMenuEntries: (uid: number, menuId: string) => Promise<readonly MenuEntry[]>;
|
|
13
15
|
export declare const getViewActions: (uid: number) => Promise<readonly ViewAction[]>;
|
|
14
16
|
export declare const getViewActionsDom: (uid: number) => readonly VirtualDomNode[] | undefined;
|
|
@@ -3,6 +3,7 @@ import { diffTree, validate as validateVirtualDom } from '@lvce-editor/virtual-d
|
|
|
3
3
|
import { registerCommand } from "../CommandRegistry/CommandRegistry.js";
|
|
4
4
|
import * as ExtensionApiCommandRegistry from "../ExtensionApiCommandRegistry/ExtensionApiCommandRegistry.js";
|
|
5
5
|
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
6
|
+
import * as ViewletStates from "../ViewletStates/ViewletStates.js";
|
|
6
7
|
import * as ViewStatusBarItems from "../ViewStatusBarItems/ViewStatusBarItems.js";
|
|
7
8
|
const views = Object.create(null);
|
|
8
9
|
const instances = Object.create(null);
|
|
@@ -11,6 +12,7 @@ const renderedDoms = Object.create(null);
|
|
|
11
12
|
const contexts = Object.create(null);
|
|
12
13
|
const contextViewIds = Object.create(null);
|
|
13
14
|
const viewCommandDisposables = Object.create(null);
|
|
15
|
+
const isStatefulView = (view) => typeof view.createInitialState === 'function';
|
|
14
16
|
const assertBoolean = (value, message) => {
|
|
15
17
|
if (value !== undefined && typeof value !== 'boolean') {
|
|
16
18
|
throw new ExtensionApiError(message);
|
|
@@ -82,9 +84,13 @@ const assertView = (view) => {
|
|
|
82
84
|
if (typeof view.id !== 'string' || view.id.length === 0) {
|
|
83
85
|
throw new ExtensionApiError('view is missing id');
|
|
84
86
|
}
|
|
85
|
-
|
|
87
|
+
const candidate = view;
|
|
88
|
+
if (typeof candidate.create !== 'function' && typeof candidate.createInitialState !== 'function') {
|
|
86
89
|
throw new ExtensionApiError(`view ${view.id} is missing create function`);
|
|
87
90
|
}
|
|
91
|
+
if (typeof candidate.createInitialState === 'function' && typeof candidate.render !== 'function') {
|
|
92
|
+
throw new ExtensionApiError(`view ${view.id} is missing render function`);
|
|
93
|
+
}
|
|
88
94
|
if (view.id in views) {
|
|
89
95
|
throw new ExtensionApiError(`view ${view.id} is already registered`);
|
|
90
96
|
}
|
|
@@ -103,6 +109,7 @@ const toRegisteredView = (view) => {
|
|
|
103
109
|
id: view.id,
|
|
104
110
|
name: view.name,
|
|
105
111
|
preferredLocation: view.preferredLocation || 'sideBar',
|
|
112
|
+
...(isStatefulView(view) && { stateful: true }),
|
|
106
113
|
title: displayName,
|
|
107
114
|
};
|
|
108
115
|
if (view.kind) {
|
|
@@ -131,9 +138,16 @@ const executeViewCommand = async (view, commandId, args) => {
|
|
|
131
138
|
}
|
|
132
139
|
const [uid, instance] = activeInstance;
|
|
133
140
|
const command = view.commands[commandId];
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
if (isStatefulView(view)) {
|
|
142
|
+
const newState = await command(ViewletStates.get(uid), ...args);
|
|
143
|
+
assertViewState(view.id, newState);
|
|
144
|
+
ViewletStates.replace(uid, newState);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const newInstance = await command(instance, ...args);
|
|
148
|
+
assertVirtualDomViewInstance(view.id, newInstance);
|
|
149
|
+
instances[uid] = newInstance;
|
|
150
|
+
}
|
|
137
151
|
await ExtensionManagementWorker.invoke('Extensions.requestViewRerender', uid);
|
|
138
152
|
};
|
|
139
153
|
const registerViewCommands = (view) => {
|
|
@@ -177,7 +191,7 @@ export const executeViewProvider = (id) => {
|
|
|
177
191
|
if (!view) {
|
|
178
192
|
throw new ExtensionApiError(`view ${id} not found`);
|
|
179
193
|
}
|
|
180
|
-
return view.create();
|
|
194
|
+
return isStatefulView(view) ? view.createInitialState() : view.create();
|
|
181
195
|
};
|
|
182
196
|
const assertVirtualDomViewInstance = (id, instance) => {
|
|
183
197
|
if (!instance || typeof instance !== 'object') {
|
|
@@ -187,6 +201,62 @@ const assertVirtualDomViewInstance = (id, instance) => {
|
|
|
187
201
|
throw new ExtensionApiError(`view ${id} instance is missing render function`);
|
|
188
202
|
}
|
|
189
203
|
};
|
|
204
|
+
const assertViewState = (viewId, state) => {
|
|
205
|
+
if (!state || typeof state !== 'object' || Array.isArray(state)) {
|
|
206
|
+
throw new ExtensionApiError(`view ${viewId} state must be an object`);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const createStatefulViewInstance = (view, uid) => {
|
|
210
|
+
const instance = {
|
|
211
|
+
render() {
|
|
212
|
+
return view.render(ViewletStates.get(uid));
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
if (view.dispose) {
|
|
216
|
+
instance.dispose = () => view.dispose(ViewletStates.get(uid));
|
|
217
|
+
}
|
|
218
|
+
if (view.getContext) {
|
|
219
|
+
instance.getContext = () => view.getContext(ViewletStates.get(uid));
|
|
220
|
+
}
|
|
221
|
+
if (view.getCss) {
|
|
222
|
+
instance.getCss = () => view.getCss(ViewletStates.get(uid));
|
|
223
|
+
}
|
|
224
|
+
if (view.getMenuEntries) {
|
|
225
|
+
instance.getMenuEntries = (menuId) => view.getMenuEntries(ViewletStates.get(uid), menuId);
|
|
226
|
+
}
|
|
227
|
+
if (view.handleEvent) {
|
|
228
|
+
instance.handleEvent = async (event) => {
|
|
229
|
+
const newState = await view.handleEvent(ViewletStates.get(uid), event);
|
|
230
|
+
assertViewState(view.id, newState);
|
|
231
|
+
ViewletStates.replace(uid, newState);
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (view.renderActions) {
|
|
235
|
+
instance.renderActions = () => view.renderActions(ViewletStates.get(uid));
|
|
236
|
+
}
|
|
237
|
+
if (view.renderActionsDom) {
|
|
238
|
+
instance.renderActionsDom = () => view.renderActionsDom(ViewletStates.get(uid));
|
|
239
|
+
}
|
|
240
|
+
if (view.renderFocus) {
|
|
241
|
+
instance.renderFocus = (oldContext, newContext) => view.renderFocus(ViewletStates.get(uid), oldContext, newContext);
|
|
242
|
+
}
|
|
243
|
+
if (view.renderScrollPosition) {
|
|
244
|
+
instance.renderScrollPosition = () => view.renderScrollPosition(ViewletStates.get(uid));
|
|
245
|
+
}
|
|
246
|
+
if (view.renderSelections) {
|
|
247
|
+
instance.renderSelections = () => view.renderSelections(ViewletStates.get(uid));
|
|
248
|
+
}
|
|
249
|
+
if (view.renderStatusBarItems) {
|
|
250
|
+
instance.renderStatusBarItems = () => view.renderStatusBarItems(ViewletStates.get(uid));
|
|
251
|
+
}
|
|
252
|
+
if (view.renderTitle) {
|
|
253
|
+
instance.renderTitle = () => view.renderTitle(ViewletStates.get(uid));
|
|
254
|
+
}
|
|
255
|
+
if (view.saveState) {
|
|
256
|
+
instance.saveState = () => view.saveState(ViewletStates.get(uid));
|
|
257
|
+
}
|
|
258
|
+
return instance;
|
|
259
|
+
};
|
|
190
260
|
const getVirtualDomInstance = (uid) => {
|
|
191
261
|
const instance = instances[uid];
|
|
192
262
|
if (!instance) {
|
|
@@ -448,7 +518,7 @@ export const createViewInstance = async (viewId, uid, context) => {
|
|
|
448
518
|
if (view.kind !== 'virtualDom') {
|
|
449
519
|
throw new ExtensionApiError(`view ${viewId} is not a virtual dom view`);
|
|
450
520
|
}
|
|
451
|
-
const
|
|
521
|
+
const viewContext = {
|
|
452
522
|
...context,
|
|
453
523
|
requestRerender() {
|
|
454
524
|
return ExtensionManagementWorker.invoke('Extensions.requestViewRerender', uid);
|
|
@@ -461,7 +531,19 @@ export const createViewInstance = async (viewId, uid, context) => {
|
|
|
461
531
|
},
|
|
462
532
|
uid,
|
|
463
533
|
viewId,
|
|
464
|
-
}
|
|
534
|
+
};
|
|
535
|
+
let instance;
|
|
536
|
+
if (isStatefulView(view)) {
|
|
537
|
+
const initialState = await view.createInitialState(viewContext);
|
|
538
|
+
assertViewState(viewId, initialState);
|
|
539
|
+
ViewletStates.initialize(uid, initialState);
|
|
540
|
+
instance = createStatefulViewInstance(view, uid);
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
const createdInstance = await view.create(viewContext);
|
|
544
|
+
assertVirtualDomViewInstance(viewId, createdInstance);
|
|
545
|
+
instance = createdInstance;
|
|
546
|
+
}
|
|
465
547
|
assertVirtualDomViewInstance(viewId, instance);
|
|
466
548
|
instances[uid] = instance;
|
|
467
549
|
const instanceUids = instanceUidsByView[viewId] || new Set();
|
|
@@ -531,6 +613,7 @@ export const disposeViewInstance = async (uid) => {
|
|
|
531
613
|
delete instances[uid];
|
|
532
614
|
delete renderedDoms[uid];
|
|
533
615
|
delete contextViewIds[uid];
|
|
616
|
+
ViewletStates.remove(uid);
|
|
534
617
|
}
|
|
535
618
|
}
|
|
536
619
|
};
|
|
@@ -541,6 +624,24 @@ export const saveViewInstanceState = async (uid) => {
|
|
|
541
624
|
}
|
|
542
625
|
return instance.saveState();
|
|
543
626
|
};
|
|
627
|
+
export const getViewInstanceState = (uid) => {
|
|
628
|
+
getVirtualDomInstance(uid);
|
|
629
|
+
return ViewletStates.get(uid);
|
|
630
|
+
};
|
|
631
|
+
export const setViewInstanceState = async (uid, newState) => {
|
|
632
|
+
getVirtualDomInstance(uid);
|
|
633
|
+
const viewId = contextViewIds[uid];
|
|
634
|
+
assertViewState(viewId, newState);
|
|
635
|
+
const oldState = ViewletStates.get(uid);
|
|
636
|
+
ViewletStates.replace(uid, newState);
|
|
637
|
+
try {
|
|
638
|
+
return await renderViewInstance(uid);
|
|
639
|
+
}
|
|
640
|
+
catch (error) {
|
|
641
|
+
ViewletStates.replace(uid, oldState);
|
|
642
|
+
throw error;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
544
645
|
export const getViewMenuEntries = async (uid, menuId) => {
|
|
545
646
|
assertString(menuId, 'menuId must be a string');
|
|
546
647
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -579,14 +680,17 @@ const commandMap = {
|
|
|
579
680
|
'ExtensionApi.executeViewProvider': executeViewProvider,
|
|
580
681
|
'ExtensionApi.getViewActions': getViewActions,
|
|
581
682
|
'ExtensionApi.getViewActionsDom': getViewActionsDom,
|
|
683
|
+
'ExtensionApi.getViewInstanceState': getViewInstanceState,
|
|
582
684
|
'ExtensionApi.getViewMenuEntries': getViewMenuEntries,
|
|
583
685
|
'ExtensionApi.getViewRegistrySnapshot': getViewRegistrySnapshot,
|
|
584
686
|
'ExtensionApi.renderViewInstance': renderViewInstance,
|
|
585
687
|
'ExtensionApi.saveViewInstanceState': saveViewInstanceState,
|
|
586
688
|
'ExtensionApi.setViewInstanceActive': setViewInstanceActive,
|
|
689
|
+
'ExtensionApi.setViewInstanceState': setViewInstanceState,
|
|
587
690
|
};
|
|
588
691
|
export const resetViewRegistry = () => {
|
|
589
692
|
ViewStatusBarItems.resetViewStatusBarItems();
|
|
693
|
+
ViewletStates.reset();
|
|
590
694
|
for (const id of Object.keys(views)) {
|
|
591
695
|
for (const disposable of viewCommandDisposables[id] || []) {
|
|
592
696
|
disposable.dispose();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const has: (uid: number) => boolean;
|
|
2
|
+
export declare const get: <State = unknown>(uid: number) => State;
|
|
3
|
+
export declare const replace: (uid: number, newState: unknown) => void;
|
|
4
|
+
export declare const set: (uid: number, newState: unknown) => Promise<void>;
|
|
5
|
+
export declare const initialize: (uid: number, initialState: unknown) => void;
|
|
6
|
+
export declare const remove: (uid: number) => void;
|
|
7
|
+
export declare const reset: () => void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ExtensionManagementWorker } from '@lvce-editor/rpc-registry';
|
|
2
|
+
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
3
|
+
const states = Object.create(null);
|
|
4
|
+
const assertState = (state) => {
|
|
5
|
+
if (!state || typeof state !== 'object' || Array.isArray(state)) {
|
|
6
|
+
throw new ExtensionApiError('view state must be an object');
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
export const has = (uid) => Object.hasOwn(states, uid);
|
|
10
|
+
export const get = (uid) => {
|
|
11
|
+
if (!has(uid)) {
|
|
12
|
+
throw new ExtensionApiError(`view state ${uid} not found`);
|
|
13
|
+
}
|
|
14
|
+
return states[uid];
|
|
15
|
+
};
|
|
16
|
+
export const replace = (uid, newState) => {
|
|
17
|
+
if (!has(uid)) {
|
|
18
|
+
throw new ExtensionApiError(`view state ${uid} not found`);
|
|
19
|
+
}
|
|
20
|
+
assertState(newState);
|
|
21
|
+
states[uid] = newState;
|
|
22
|
+
};
|
|
23
|
+
export const set = async (uid, newState) => {
|
|
24
|
+
replace(uid, newState);
|
|
25
|
+
await ExtensionManagementWorker.invoke('Extensions.requestViewRerender', uid);
|
|
26
|
+
};
|
|
27
|
+
export const initialize = (uid, initialState) => {
|
|
28
|
+
assertState(initialState);
|
|
29
|
+
states[uid] = initialState;
|
|
30
|
+
};
|
|
31
|
+
export const remove = (uid) => {
|
|
32
|
+
delete states[uid];
|
|
33
|
+
};
|
|
34
|
+
export const reset = () => {
|
|
35
|
+
for (const uid of Object.keys(states)) {
|
|
36
|
+
delete states[Number(uid)];
|
|
37
|
+
}
|
|
38
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/api",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.29.0",
|
|
4
4
|
"description": "Tree-shakeable extension API for Lvce Editor extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lvce-editor",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@lvce-editor/command": "^2.0.0",
|
|
31
|
-
"@lvce-editor/rpc": "^6.
|
|
32
|
-
"@lvce-editor/rpc-registry": "^9.
|
|
33
|
-
"@lvce-editor/virtual-dom-worker": "^11.
|
|
31
|
+
"@lvce-editor/rpc": "^6.16.0",
|
|
32
|
+
"@lvce-editor/rpc-registry": "^9.48.0",
|
|
33
|
+
"@lvce-editor/virtual-dom-worker": "^11.12.1"
|
|
34
34
|
}
|
|
35
35
|
}
|