@lvce-editor/api 9.29.1 → 9.30.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.
@@ -73,9 +73,11 @@ interface ViewBase<State> {
73
73
  readonly preferredLocation?: ViewPreferredLocation;
74
74
  readonly title?: string;
75
75
  }
76
- export interface InstanceView<State = unknown> extends ViewBase<State> {
76
+ export interface InstanceView<State = unknown, ComponentState = unknown> extends ViewBase<State> {
77
77
  readonly create: (context?: ViewContext) => State | Promise<State>;
78
78
  readonly createInitialState?: never;
79
+ readonly getComponentState?: (instance: State) => ComponentState | Promise<ComponentState>;
80
+ readonly setComponentState?: (instance: State, state: ComponentState) => void | Promise<void>;
79
81
  }
80
82
  export interface StatefulView<State = unknown> extends ViewBase<State> {
81
83
  readonly create?: never;
@@ -95,7 +97,7 @@ export interface StatefulView<State = unknown> extends ViewBase<State> {
95
97
  readonly renderTitle?: (state: State) => string | Promise<string>;
96
98
  readonly saveState?: (state: State) => unknown;
97
99
  }
98
- export type View<State = unknown> = InstanceView<State> | StatefulView<State>;
100
+ export type View<State = unknown, ComponentState = unknown> = InstanceView<State, ComponentState> | StatefulView<State>;
99
101
  export interface RegisteredView {
100
102
  readonly displayName?: string;
101
103
  readonly eventListeners?: readonly DomEventListener[];
@@ -1,7 +1,7 @@
1
1
  import { type VirtualDomNode } from '@lvce-editor/virtual-dom-worker';
2
2
  import type { Disposable } from '../Disposable/Disposable.ts';
3
3
  import type { MenuEntry, View, ViewAction, ViewContext, ViewEvent, ViewRegistrySnapshot, ViewRenderResult } from '../View/View.ts';
4
- export declare const registerView: <State>(view: View<State>) => Disposable;
4
+ export declare const registerView: <State, ComponentState = unknown>(view: View<State, ComponentState>) => Disposable;
5
5
  export declare const executeViewProvider: (id: string) => unknown;
6
6
  export declare const createViewInstance: (viewId: string, uid: number, context?: ViewContext) => Promise<ViewRenderResult>;
7
7
  export declare const dispatchViewEvent: (uid: number, event: ViewEvent) => Promise<ViewRenderResult>;
@@ -91,6 +91,11 @@ const assertView = (view) => {
91
91
  if (typeof candidate.createInitialState === 'function' && typeof candidate.render !== 'function') {
92
92
  throw new ExtensionApiError(`view ${view.id} is missing render function`);
93
93
  }
94
+ if (!isStatefulView(view) &&
95
+ (view.getComponentState !== undefined || view.setComponentState !== undefined) &&
96
+ (typeof view.getComponentState !== 'function' || typeof view.setComponentState !== 'function')) {
97
+ throw new ExtensionApiError(`view ${view.id} component state requires getComponentState and setComponentState`);
98
+ }
94
99
  if (view.id in views) {
95
100
  throw new ExtensionApiError(`view ${view.id} is already registered`);
96
101
  }
@@ -109,7 +114,7 @@ const toRegisteredView = (view) => {
109
114
  id: view.id,
110
115
  name: view.name,
111
116
  preferredLocation: view.preferredLocation || 'sideBar',
112
- ...(isStatefulView(view) && { stateful: true }),
117
+ ...((isStatefulView(view) || typeof view.getComponentState === 'function') && { stateful: true }),
113
118
  title: displayName,
114
119
  };
115
120
  if (view.kind) {
@@ -625,13 +630,29 @@ export const saveViewInstanceState = async (uid) => {
625
630
  return instance.saveState();
626
631
  };
627
632
  export const getViewInstanceState = (uid) => {
628
- getVirtualDomInstance(uid);
633
+ const instance = getVirtualDomInstance(uid);
634
+ const view = views[contextViewIds[uid]];
635
+ if (!isStatefulView(view) && view.getComponentState) {
636
+ return view.getComponentState(instance);
637
+ }
629
638
  return ViewletStates.get(uid);
630
639
  };
631
640
  export const setViewInstanceState = async (uid, newState) => {
632
- getVirtualDomInstance(uid);
641
+ const instance = getVirtualDomInstance(uid);
633
642
  const viewId = contextViewIds[uid];
643
+ const view = views[viewId];
634
644
  assertViewState(viewId, newState);
645
+ if (!isStatefulView(view) && view.getComponentState && view.setComponentState) {
646
+ const oldState = structuredClone(await view.getComponentState(instance));
647
+ try {
648
+ await view.setComponentState(instance, newState);
649
+ return await renderViewInstance(uid);
650
+ }
651
+ catch (error) {
652
+ await view.setComponentState(instance, oldState);
653
+ throw error;
654
+ }
655
+ }
635
656
  const oldState = ViewletStates.get(uid);
636
657
  ViewletStates.replace(uid, newState);
637
658
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/api",
3
- "version": "9.29.1",
3
+ "version": "9.30.0",
4
4
  "description": "Tree-shakeable extension API for Lvce Editor extensions.",
5
5
  "keywords": [
6
6
  "lvce-editor",