@lvce-editor/api 8.35.0 → 8.36.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.
@@ -35,6 +35,7 @@ export interface VirtualDomViewInstance {
35
35
  readonly getMenuEntries?: (menuId: string) => readonly MenuEntry[] | Promise<readonly MenuEntry[]>;
36
36
  readonly handleEvent?: (event: ViewEvent) => unknown;
37
37
  readonly render: () => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
38
+ readonly renderFocus?: (oldContext: Readonly<Record<string, boolean>>, newContext: Readonly<Record<string, boolean>>) => string | Promise<string>;
38
39
  readonly saveState?: () => unknown;
39
40
  }
40
41
  export interface View {
@@ -61,9 +62,11 @@ export interface ViewRegistrySnapshot {
61
62
  }
62
63
  export interface ViewRenderResultDom {
63
64
  readonly dom: readonly VirtualDomNode[];
65
+ readonly focusSelector?: string;
64
66
  readonly type: 'setDom';
65
67
  }
66
68
  export interface ViewRenderResultPatches {
69
+ readonly focusSelector?: string;
67
70
  readonly patches: readonly unknown[];
68
71
  readonly type: 'setPatches';
69
72
  }
@@ -182,14 +182,23 @@ const isSameContext = (oldContext, newContext) => {
182
182
  }
183
183
  return true;
184
184
  };
185
+ const unchangedContext = {
186
+ changed: false,
187
+ newContext: {},
188
+ oldContext: {},
189
+ };
185
190
  const maybeNotifyContextChanged = async (uid, viewId, instance) => {
186
191
  if (typeof instance.getContext !== 'function') {
187
- return;
192
+ return unchangedContext;
188
193
  }
189
194
  const oldContext = contexts[uid] || {};
190
195
  const newContext = normalizeContext(instance.getContext());
191
196
  if (isSameContext(oldContext, newContext)) {
192
- return;
197
+ return {
198
+ changed: false,
199
+ newContext,
200
+ oldContext,
201
+ };
193
202
  }
194
203
  if (Object.keys(newContext).length === 0) {
195
204
  delete contexts[uid];
@@ -198,6 +207,31 @@ const maybeNotifyContextChanged = async (uid, viewId, instance) => {
198
207
  contexts[uid] = newContext;
199
208
  }
200
209
  await ExtensionManagementWorker.invoke('Extensions.handleViewContextChange', uid, viewId, newContext);
210
+ return {
211
+ changed: true,
212
+ newContext,
213
+ oldContext,
214
+ };
215
+ };
216
+ const renderFocus = async (instance, contextChange) => {
217
+ if (!contextChange.changed || typeof instance.renderFocus !== 'function') {
218
+ return '';
219
+ }
220
+ const focusSelector = await instance.renderFocus(contextChange.oldContext, contextChange.newContext);
221
+ if (typeof focusSelector !== 'string') {
222
+ throw new ExtensionApiError('view renderFocus result must be a string');
223
+ }
224
+ return focusSelector;
225
+ };
226
+ const withFocusSelector = async (result, instance, contextChange) => {
227
+ const focusSelector = await renderFocus(instance, contextChange);
228
+ if (!focusSelector) {
229
+ return result;
230
+ }
231
+ return {
232
+ ...result,
233
+ focusSelector,
234
+ };
201
235
  };
202
236
  const maybeClearContext = async (uid, viewId) => {
203
237
  if (!contexts[uid]) {
@@ -233,11 +267,12 @@ export const createViewInstance = async (viewId, uid, context) => {
233
267
  contextViewIds[uid] = viewId;
234
268
  const dom = await renderDom(instance);
235
269
  renderedDoms[uid] = dom;
236
- await maybeNotifyContextChanged(uid, viewId, instance);
237
- return {
270
+ const result = {
238
271
  dom,
239
272
  type: 'setDom',
240
273
  };
274
+ const contextChange = await maybeNotifyContextChanged(uid, viewId, instance);
275
+ return withFocusSelector(result, instance, contextChange);
241
276
  };
242
277
  export const dispatchViewEvent = async (uid, event) => {
243
278
  const instance = getVirtualDomInstance(uid);
@@ -245,14 +280,14 @@ export const dispatchViewEvent = async (uid, event) => {
245
280
  await instance.handleEvent(event);
246
281
  }
247
282
  const result = await renderPatches(uid, instance);
248
- await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
249
- return result;
283
+ const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
284
+ return withFocusSelector(result, instance, contextChange);
250
285
  };
251
286
  export const renderViewInstance = async (uid) => {
252
287
  const instance = getVirtualDomInstance(uid);
253
288
  const result = await renderPatches(uid, instance);
254
- await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
255
- return result;
289
+ const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
290
+ return withFocusSelector(result, instance, contextChange);
256
291
  };
257
292
  export const disposeViewInstance = async (uid) => {
258
293
  const instance = instances[uid];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/api",
3
- "version": "8.35.0",
3
+ "version": "8.36.0",
4
4
  "description": "Tree-shakeable extension API for Lvce Editor extensions.",
5
5
  "keywords": [
6
6
  "lvce-editor",