@monimesl/dot-webview 0.1.0-alpha.7 → 0.1.0-alpha.9

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 CHANGED
@@ -1,17 +1,4 @@
1
1
  import { ColorScheme, DotEvent, DotEvent as DotEvent$1, Envelope, EventEmitter, HostLayerMessages, LogicLayerMessages, MessageChannel, PageLaunchOptions, PageState, PageState as PageState$1, RenderContext, SystemContext, SystemContext as SystemContext$1, Theme, Theme as Theme$1, Transport, Transport as Transport$1, UILayerMessages, ViewRender, ViewRender as ViewRender$1, hostTransport } from "@monimesl/dot-core";
2
- //#region src/store.d.ts
3
- interface ReadonlyStore<T> {
4
- readonly get: () => T;
5
- readonly subscribe: (listener: () => void) => () => void;
6
- }
7
- export declare class Store<T> implements ReadonlyStore<T> {
8
- #private;
9
- constructor(value: T);
10
- readonly get: () => T;
11
- readonly subscribe: (listener: () => void) => (() => void);
12
- set(value: T): void;
13
- }
14
- //#endregion
15
2
  //#region src/page.d.ts
16
3
  type Dispatch = (instanceId: number, handler: string, event: DotEvent$1) => void;
17
4
  export declare class PageController {
@@ -21,7 +8,6 @@ export declare class PageController {
21
8
  readonly pageOptions: PageLaunchOptions;
22
9
  constructor(instanceId: number, id: string, options: PageLaunchOptions, viewRenderer: ViewRender$1, dispatch: Dispatch);
23
10
  get viewRenderer(): ViewRender$1;
24
- /** Draws the page again from a newer build's view, as a hot reload does, keeping its state. */
25
11
  replaceView(view: ViewRender$1): void;
26
12
  readonly getState: () => PageState$1 | null;
27
13
  readonly subscribe: (listener: () => void) => (() => void);
@@ -30,6 +16,19 @@ export declare class PageController {
30
16
  updateState(changes: PageState$1): void;
31
17
  }
32
18
  //#endregion
19
+ //#region src/store.d.ts
20
+ interface ReadonlyStore<T> {
21
+ readonly get: () => T;
22
+ readonly subscribe: (listener: () => void) => () => void;
23
+ }
24
+ export declare class Store<T> implements ReadonlyStore<T> {
25
+ #private;
26
+ constructor(value: T);
27
+ readonly get: () => T;
28
+ readonly subscribe: (listener: () => void) => (() => void);
29
+ set(value: T): void;
30
+ }
31
+ //#endregion
33
32
  //#region src/renderer.d.ts
34
33
  interface DotContext {
35
34
  readonly theme: ReadonlyStore<Theme$1>;
@@ -57,11 +56,6 @@ interface WebviewOptions {
57
56
  plugins?: readonly WebviewPlugin[];
58
57
  views: Record<string, ViewRender$1>;
59
58
  }
60
- /**
61
- * The view layer: shows the navigation stack the host announces, keeps each open page in sync with
62
- * the service, and hands pages to the renderer. Every open page gets its own element in the
63
- * container; only the top one is visible, so going back is instant and keeps its UI.
64
- */
65
59
  declare class Webview {
66
60
  #private;
67
61
  readonly pageRenderer: Renderer;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/store.ts","../src/page.ts","../src/renderer.ts","../src/webview.ts","../src/index.ts"],"mappings":";;UAAiB,cAAc;WACpB,WAAW;WACX,YAAY;;qBAGV,MAAM,cAAc,cAAc;;EAIjC,YAAA,OAAO;WAIV,WAAU;WAEV,YAAa;EAKtB,IAAI,OAAO;;;;KChBR,YAAY,oBAAoB,iBAAiB,OAAO;qBAEhD;;WACF;WAEA;WACA,aAAa;EAMpB,YAAA,oBACA,YACA,SAAS,mBACT,cAAc,cACd,UAAU;MASR,gBAAgB;;EAKpB,YAAY,MAAM;WAST,gBAAQ;WAER,YAAS;EAElB,GAAG,iBAAiB,OAAO,SAAS,4BAA4B,OAAO;EAYvE,gBAAgB,OAAO;EAIvB,YAAY,SAAS;;;;UC3DN;WACN,OAAO,cAAc;WACrB,eAAe,cAAc;;UAGvB;WACN;EACT,MAAM,WAAW,SAAS,MAAM,gBAAgB,YAAY;;;;KCMlD,iBAAiB,eAC3B,iBACA,qBAAqB;UAGN;EACf,SAAS,MAAM;EAEf,UAAU,MAAM;EAEhB,MAAM,gBAAgB,SAAS;;UAGhB;WACN;EAET,MAAM,SAAS;;UAGA;EACf,UAAU;EACV,WAAW;EACX,mBAAmB;EACnB,OAAO,eAAe;;;;;;;cAcX;;WACF,cAAc;WACd,SAAS;WACT,OAAK,aAAA;WACL,OAAK,MAAA;WACL,eAAa,MAAA;EASV,cAAE,WAAW,UAAU,OAAO,WAAgB;EAgC1D,cAAc,QAAQ;EAKtB;EASA,MAAM,WAAW;;EAOjB,aAAa,OAAO,eAAe;MAU/B,kBAAkB;EAkHtB,WAAW,qBAAqB;;;;iBC5NjB,qBAAqB;EACpC,WAAW;;wBAGG,eAAe,cAAc,WAAW,eAAe;iBAUtD;EAEf,gBAAgB;EAChB,OAAO,eAAe;;wBAIR,aAAa,UAAU,SAAS,oBAAoB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/page.ts","../src/store.ts","../src/renderer.ts","../src/webview.ts","../src/index.ts"],"mappings":";;KAIK,YAAY,oBAAoB,iBAAiB,OAAO;qBAEhD;;WACF;WAEA;WACA,aAAa;EAMpB,YAAA,oBACA,YACA,SAAS,mBACT,cAAc,cACd,UAAU;MASR,gBAAgB;EAKpB,YAAY,MAAM;WAST,gBAAQ;WAER,YAAS;EAElB,GAAG,iBAAiB,OAAO,SAAS,4BAA4B,OAAO;EAYvE,gBAAgB,OAAO;EAIvB,YAAY,SAAS;;;;UC/DN,cAAc;WACpB,WAAW;WACX,YAAY;;qBAGV,MAAM,cAAc,cAAc;;EAIjC,YAAA,OAAO;WAIV,WAAU;WAEV,YAAa;EAKtB,IAAI,OAAO;;;;UChBI;WACN,OAAO,cAAc;WACrB,eAAe,cAAc;;UAGvB;WACN;EACT,MAAM,WAAW,SAAS,MAAM,gBAAgB,YAAY;;;;KCMlD,iBAAiB,eAC3B,iBACA,qBAAqB;UAGN;EACf,SAAS,MAAM;EAEf,UAAU,MAAM;EAEhB,MAAM,gBAAgB,SAAS;;UAGhB;WACN;EAET,MAAM,SAAS;;UAGA;EACf,UAAU;EACV,WAAW;EACX,mBAAmB;EACnB,OAAO,eAAe;;cAWX;;WACF,cAAc;WACd,SAAS;WACT,OAAK,aAAA;WACL,OAAK,MAAA;WACL,eAAa,MAAA;EASV,cAAE,WAAW,UAAU,OAAO,WAAgB;EAgC1D,cAAc,QAAQ;EAKtB;EASA,MAAM,WAAW;;EAOjB,aAAa,OAAO,eAAe;MAU/B,kBAAkB;EA+GtB,WAAW,qBAAqB;;;;iBCtNjB,qBAAqB;EACpC,WAAW;;wBAGG,eAAe,cAAc,WAAW,eAAe;iBAUtD;EAEf,gBAAgB;EAChB,OAAO,eAAe;;wBAIR,aAAa,UAAU,SAAS,oBAAoB"}
package/dist/index.js CHANGED
@@ -36,7 +36,6 @@ var PageController = class {
36
36
  get viewRenderer() {
37
37
  return this.#viewRenderer;
38
38
  }
39
- /** Draws the page again from a newer build's view, as a hot reload does, keeping its state. */
40
39
  replaceView(view) {
41
40
  this.#viewRenderer = view;
42
41
  const state = this.#state.get();
@@ -66,11 +65,6 @@ var PageController = class {
66
65
  };
67
66
  //#endregion
68
67
  //#region src/webview.ts
69
- /**
70
- * The view layer: shows the navigation stack the host announces, keeps each open page in sync with
71
- * the service, and hands pages to the renderer. Every open page gets its own element in the
72
- * container; only the top one is visible, so going back is instant and keeps its UI.
73
- */
74
68
  var Webview = class {
75
69
  pageRenderer;
76
70
  channel;
@@ -195,17 +189,18 @@ var Webview = class {
195
189
  handler,
196
190
  event
197
191
  }));
198
- const element = this.#container.ownerDocument.createElement("div");
192
+ const container = this.#container;
193
+ const element = container.ownerDocument.createElement("div");
199
194
  element.dataset.page = id;
200
195
  element.hidden = true;
201
- this.#container.append(element);
202
- const open = {
196
+ container.append(element);
197
+ const unmount = this.pageRenderer.mount(element, page, this.#dotContext);
198
+ this.hooks.emit("pageOpen", page);
199
+ return {
203
200
  page,
204
201
  element,
205
- unmount: this.pageRenderer.mount(element, page, this.#dotContext)
202
+ unmount
206
203
  };
207
- this.hooks.emit("pageOpen", page);
208
- return open;
209
204
  }
210
205
  #close(open) {
211
206
  if (this.#shownPage === open) this.#shownPage = void 0;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["hostTransport"],"sources":["../src/store.ts","../src/page.ts","../src/webview.ts","../src/index.ts"],"sourcesContent":["export interface ReadonlyStore<T> {\n readonly get: () => T;\n readonly subscribe: (listener: () => void) => () => void;\n}\n\nexport class Store<T> implements ReadonlyStore<T> {\n #value: T;\n readonly #listeners = new Set<() => void>();\n\n constructor(value: T) {\n this.#value = value;\n }\n\n readonly get = (): T => this.#value;\n\n readonly subscribe = (listener: () => void): (() => void) => {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n };\n\n set(value: T): void {\n this.#value = value;\n this.#listeners.forEach((listener) => listener());\n }\n}\n","import { Store } from './store';\nimport type { DotEvent, PageLaunchOptions, PageState, ViewRender } from '@monimesl/dot-core';\nimport { applyChanges } from '@monimesl/dot-core';\n\ntype Dispatch = (instanceId: number, handler: string, event: DotEvent) => void;\n\nexport class PageController {\n readonly pageId: string;\n readonly #dispatch: Dispatch;\n readonly pageInstanceId: number;\n readonly pageOptions: PageLaunchOptions;\n #viewRenderer: ViewRender;\n readonly #state = new Store<PageState | null>(null);\n readonly #callbacks = new Map<string, (event: DotEvent) => void>();\n\n constructor(\n instanceId: number,\n id: string,\n options: PageLaunchOptions,\n viewRenderer: ViewRender,\n dispatch: Dispatch,\n ) {\n this.pageId = id;\n this.pageOptions = options;\n this.#dispatch = dispatch;\n this.pageInstanceId = instanceId;\n this.#viewRenderer = viewRenderer;\n }\n\n get viewRenderer(): ViewRender {\n return this.#viewRenderer;\n }\n\n /** Draws the page again from a newer build's view, as a hot reload does, keeping its state. */\n replaceView(view: ViewRender): void {\n this.#viewRenderer = view;\n const state = this.#state.get();\n if (state) {\n // A new object, which is what tells the renderer to draw again.\n this.#state.set({ ...state });\n }\n }\n\n readonly getState = this.#state.get;\n\n readonly subscribe = this.#state.subscribe;\n\n on(handler: string, data?: Readonly<Record<string, unknown>>): (event: DotEvent) => void {\n if (data) {\n return (event) => this.#dispatch(this.pageInstanceId, handler, { ...event, data });\n }\n let callback = this.#callbacks.get(handler);\n if (!callback) {\n callback = (event) => this.#dispatch(this.pageInstanceId, handler, event);\n this.#callbacks.set(handler, callback);\n }\n return callback;\n }\n\n initializeState(state: PageState): void {\n this.#state.set(state);\n }\n\n updateState(changes: PageState): void {\n const state = this.#state.get();\n if (state) {\n this.#state.set(applyChanges(state, changes));\n }\n }\n}\n","import type {\n Envelope,\n HostLayerMessages,\n LogicLayerMessages,\n StackEntry,\n SystemContext,\n Theme,\n Transport,\n UILayerMessages,\n ViewRender,\n} from '@monimesl/dot-core';\nimport { DEFAULT_SYSTEM_CONTEXT, EventEmitter, MessageChannel } from '@monimesl/dot-core';\n\nimport { Store } from './store';\nimport { PageController } from './page';\nimport type { DotContext, Renderer } from './renderer';\n\nexport type WebviewChannel = MessageChannel<\n UILayerMessages,\n LogicLayerMessages & HostLayerMessages\n>;\n\nexport interface WebviewHooks {\n pageOpen(page: PageController): void;\n\n pageClose(page: PageController): void;\n\n error(error: unknown, message: Envelope): void;\n}\n\nexport interface WebviewPlugin {\n readonly name: string;\n\n setup(webview: Webview): void;\n}\n\nexport interface WebviewOptions {\n renderer: Renderer;\n transport: Transport;\n plugins?: readonly WebviewPlugin[];\n views: Record<string, ViewRender>;\n}\n\ninterface OpenPage {\n readonly page: PageController;\n readonly element: HTMLElement;\n readonly unmount: () => void;\n}\n\n/**\n * The view layer: shows the navigation stack the host announces, keeps each open page in sync with\n * the service, and hands pages to the renderer. Every open page gets its own element in the\n * container; only the top one is visible, so going back is instant and keeps its UI.\n */\nexport class Webview {\n readonly pageRenderer: Renderer;\n readonly channel: WebviewChannel;\n readonly hooks = new EventEmitter<WebviewHooks>();\n readonly theme = new Store<Theme>({});\n readonly systemContext = new Store<SystemContext>(DEFAULT_SYSTEM_CONTEXT);\n readonly #dotContext: DotContext = { theme: this.theme, systemContext: this.systemContext };\n #viewByPageId: Record<string, ViewRender>;\n #openPages: OpenPage[] = [];\n // The page the service was last told is showing: the top one, while the app is active.\n #shownPage: OpenPage | undefined;\n #pending: readonly StackEntry[] = [];\n #container: Element | null = null;\n\n constructor({ transport, renderer, views, plugins = [] }: WebviewOptions) {\n this.pageRenderer = renderer;\n this.#viewByPageId = views;\n this.channel = new MessageChannel(transport);\n this.channel.handle('setTheme', ({ theme }) => {\n this.theme.set(theme);\n });\n this.channel.handle('initPageState', ({ instanceId, state }) => {\n this.locatePage(instanceId)?.initializeState(state);\n });\n this.channel.handle('setPageState', ({ instanceId, patchState }) => {\n this.locatePage(instanceId)?.updateState(patchState);\n });\n this.channel.handle('syncStack', ({ pages }) => {\n this.#reconcile(pages);\n });\n this.channel.handle('syncSystemContext', (context) => {\n this.systemContext.set(context);\n this.#showTopPage();\n });\n this.channel.handle('error', ({ instanceId, message }) => {\n if (instanceId === undefined) {\n console.error(`[dot] service error: ${message}`);\n return;\n }\n // The page may have closed before its error arrived; its instance id is all that is left.\n const pageName = this.locatePage(instanceId)?.pageId ?? `#${instanceId}`;\n console.error(`[dot] service error in page \"${pageName}\": ${message}`);\n });\n plugins.forEach((plugin) => this.preparePlugin(plugin));\n }\n\n preparePlugin(plugin: WebviewPlugin): this {\n plugin.setup(this);\n return this;\n }\n\n start(): () => void {\n const stopListening = this.channel.listen((error, message) => {\n this.hooks.emit('error', error, message);\n console.error('[dot] webview error', error);\n });\n this.channel.send('connect', {});\n return stopListening;\n }\n\n mount(container: Element): () => void {\n this.#container = container;\n this.#reconcile(this.#pending);\n return () => this.#reconcile([]);\n }\n\n /** Swaps in the views of a newer build of the dot, as a hot reload does, redrawing open pages. */\n replaceViews(views: Record<string, ViewRender>): void {\n this.#viewByPageId = views;\n for (const { page } of this.#openPages) {\n const view = views[page.pageId];\n if (view) {\n page.replaceView(view);\n }\n }\n }\n\n get stack(): readonly PageController[] {\n return this.#openPages.map(({ page }) => page);\n }\n\n // Makes the open pages match the stack the host announced.\n #reconcile(pages: readonly StackEntry[]): void {\n if (!this.#container) {\n this.#pending = pages;\n return;\n }\n this.#closePagesNotIn(pages);\n // The page being covered hides before the new one loads, as on a device.\n if (this.#shownPage?.page.pageInstanceId !== pages.at(-1)?.instanceId) {\n this.#showOnly(undefined);\n }\n this.#openPagesIn(pages);\n const top = this.#top();\n for (const open of this.#openPages) {\n open.element.hidden = open !== top;\n }\n this.#showTopPage();\n }\n\n // The top page shows while the app is active, and hides while the person is away from Dash.\n // Its element stays visible either way, so the app switcher's snapshot shows it.\n #showTopPage(): void {\n if (this.systemContext.get().appState === 'active') {\n this.#showOnly(this.#top());\n } else {\n this.#showOnly(undefined);\n }\n }\n\n #showOnly(open: OpenPage | undefined): void {\n if (open === this.#shownPage) {\n return;\n }\n if (this.#shownPage) {\n this.channel.send('hide', { instanceId: this.#shownPage.page.pageInstanceId });\n }\n this.#shownPage = open;\n if (open) {\n this.channel.send('show', { instanceId: open.page.pageInstanceId });\n }\n }\n\n #closePagesNotIn(pages: readonly StackEntry[]): void {\n const instanceIdsToKeep = new Set(pages.map((entry) => entry.instanceId));\n // Close from the top of the stack down, the order a device closes pages in.\n for (const open of [...this.#openPages].reverse()) {\n if (!instanceIdsToKeep.has(open.page.pageInstanceId)) {\n this.#close(open);\n }\n }\n }\n\n #openPagesIn(pages: readonly StackEntry[]): void {\n const kept = new Map(this.#openPages.map((open) => [open.page.pageInstanceId, open]));\n const opened: OpenPage[] = [];\n this.#openPages = pages.map((entry) => {\n let open = kept.get(entry.instanceId);\n if (!open) {\n open = this.#open(entry);\n opened.push(open);\n }\n return open;\n });\n // Only now, with every page in the stack, can the service's replies find their page.\n for (const { page } of opened) {\n this.channel.send('load', {\n instanceId: page.pageInstanceId,\n page: page.pageId,\n options: page.pageOptions,\n });\n }\n }\n\n #open({ instanceId, page: id, options }: StackEntry): OpenPage {\n const view = this.#viewByPageId[id];\n if (!view) {\n throw new Error(`Unknown page \"${id}\"`);\n }\n const page = new PageController(instanceId, id, options, view, (instanceId, handler, event) =>\n this.channel.send('event', { instanceId, handler, event }),\n );\n const element = this.#container!.ownerDocument.createElement('div');\n element.dataset.page = id;\n element.hidden = true;\n this.#container!.append(element);\n const open: OpenPage = {\n page,\n element,\n unmount: this.pageRenderer.mount(element, page, this.#dotContext),\n };\n this.hooks.emit('pageOpen', page);\n return open;\n }\n\n #close(open: OpenPage): void {\n // A closing page unloads rather than hides.\n if (this.#shownPage === open) {\n this.#shownPage = undefined;\n }\n open.unmount();\n open.element.remove();\n this.#openPages = this.#openPages.filter((other) => other !== open);\n this.channel.send('unload', { instanceId: open.page.pageInstanceId });\n this.hooks.emit('pageClose', open.page);\n }\n\n #top(): OpenPage | undefined {\n return this.#openPages.at(-1);\n }\n\n locatePage(instanceId: number): PageController | undefined {\n return this.#openPages.find(({ page }) => page.pageInstanceId === instanceId)?.page;\n }\n}\n","export { Store } from './store';\nimport type { ViewRender } from '@monimesl/dot-core';\nimport { hostTransport } from '@monimesl/dot-core';\n\nimport type { Renderer } from './renderer';\nimport type { WebviewOptions } from './webview';\nimport { Webview } from './webview';\n\nexport { PageController } from './page';\nexport type { ReadonlyStore } from './store';\n\nexport { hostTransport } from '@monimesl/dot-core';\nexport type { DotContext, Renderer } from './renderer';\nexport type { WebviewHooks, WebviewOptions, WebviewPlugin, WebviewChannel } from './webview';\nexport type {\n ColorScheme,\n DotEvent,\n PageState,\n RenderContext,\n SystemContext,\n Theme,\n Transport,\n ViewRender,\n} from '@monimesl/dot-core';\n\nexport interface StartOptions extends WebviewOptions {\n container: Element;\n}\n\nexport function startWebview({ container, ...options }: StartOptions): Webview {\n const webview = new Webview(options);\n webview.start();\n webview.mount(container);\n return webview;\n}\n\n// Where the running webview is found by the next build of the dot, run in the same page.\nconst RUNNING_WEBVIEW = Symbol.for('dot.webview');\n\nexport interface RunWebviewOptions {\n // Called only when the webview starts.\n renderer: () => Renderer;\n views: Record<string, ViewRender>;\n}\n\n// Starts the webview in `#root`, or hands a newer build's views to the one already running, as a hot reload does.\nexport function runWebview({ renderer, views }: RunWebviewOptions): Webview {\n const scope = globalThis as unknown as Record<symbol, Webview | undefined>;\n const running = scope[RUNNING_WEBVIEW];\n if (running) {\n running.replaceViews(views);\n return running;\n }\n const container = document.getElementById('root');\n if (!container) {\n throw new Error('The dot\\'s page has no element with the id \"root\" to show it in');\n }\n const webview = startWebview({\n container,\n transport: hostTransport(),\n renderer: renderer(),\n views,\n });\n scope[RUNNING_WEBVIEW] = webview;\n return webview;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["hostTransport"],"sources":["../src/store.ts","../src/page.ts","../src/webview.ts","../src/index.ts"],"sourcesContent":["export interface ReadonlyStore<T> {\n readonly get: () => T;\n readonly subscribe: (listener: () => void) => () => void;\n}\n\nexport class Store<T> implements ReadonlyStore<T> {\n #value: T;\n readonly #listeners = new Set<() => void>();\n\n constructor(value: T) {\n this.#value = value;\n }\n\n readonly get = (): T => this.#value;\n\n readonly subscribe = (listener: () => void): (() => void) => {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n };\n\n set(value: T): void {\n this.#value = value;\n this.#listeners.forEach((listener) => listener());\n }\n}\n","import { Store } from './store';\nimport type { DotEvent, PageLaunchOptions, PageState, ViewRender } from '@monimesl/dot-core';\nimport { applyChanges } from '@monimesl/dot-core';\n\ntype Dispatch = (instanceId: number, handler: string, event: DotEvent) => void;\n\nexport class PageController {\n readonly pageId: string;\n readonly #dispatch: Dispatch;\n readonly pageInstanceId: number;\n readonly pageOptions: PageLaunchOptions;\n #viewRenderer: ViewRender;\n readonly #state = new Store<PageState | null>(null);\n readonly #callbacks = new Map<string, (event: DotEvent) => void>();\n\n constructor(\n instanceId: number,\n id: string,\n options: PageLaunchOptions,\n viewRenderer: ViewRender,\n dispatch: Dispatch,\n ) {\n this.pageId = id;\n this.pageOptions = options;\n this.#dispatch = dispatch;\n this.pageInstanceId = instanceId;\n this.#viewRenderer = viewRenderer;\n }\n\n get viewRenderer(): ViewRender {\n return this.#viewRenderer;\n }\n\n // Draws the page again from a newer build's view, as a hot reload does, keeping its state.\n replaceView(view: ViewRender): void {\n this.#viewRenderer = view;\n const state = this.#state.get();\n if (state) {\n // A new object, which is what tells the renderer to draw again.\n this.#state.set({ ...state });\n }\n }\n\n readonly getState = this.#state.get;\n\n readonly subscribe = this.#state.subscribe;\n\n on(handler: string, data?: Readonly<Record<string, unknown>>): (event: DotEvent) => void {\n if (data) {\n return (event) => this.#dispatch(this.pageInstanceId, handler, { ...event, data });\n }\n let callback = this.#callbacks.get(handler);\n if (!callback) {\n callback = (event) => this.#dispatch(this.pageInstanceId, handler, event);\n this.#callbacks.set(handler, callback);\n }\n return callback;\n }\n\n initializeState(state: PageState): void {\n this.#state.set(state);\n }\n\n updateState(changes: PageState): void {\n const state = this.#state.get();\n if (state) {\n this.#state.set(applyChanges(state, changes));\n }\n }\n}\n","import type {\n Envelope,\n HostLayerMessages,\n LogicLayerMessages,\n StackEntry,\n SystemContext,\n Theme,\n Transport,\n UILayerMessages,\n ViewRender,\n} from '@monimesl/dot-core';\nimport { DEFAULT_SYSTEM_CONTEXT, EventEmitter, MessageChannel } from '@monimesl/dot-core';\n\nimport { Store } from './store';\nimport { PageController } from './page';\nimport type { DotContext, Renderer } from './renderer';\n\nexport type WebviewChannel = MessageChannel<\n UILayerMessages,\n LogicLayerMessages & HostLayerMessages\n>;\n\nexport interface WebviewHooks {\n pageOpen(page: PageController): void;\n\n pageClose(page: PageController): void;\n\n error(error: unknown, message: Envelope): void;\n}\n\nexport interface WebviewPlugin {\n readonly name: string;\n\n setup(webview: Webview): void;\n}\n\nexport interface WebviewOptions {\n renderer: Renderer;\n transport: Transport;\n plugins?: readonly WebviewPlugin[];\n views: Record<string, ViewRender>;\n}\n\ninterface OpenPage {\n readonly page: PageController;\n readonly element: HTMLElement;\n readonly unmount: () => void;\n}\n\n// Shows the stack the host announces. Each open page keeps its own element and only the top one is\n// visible, so going back is instant and keeps its UI.\nexport class Webview {\n readonly pageRenderer: Renderer;\n readonly channel: WebviewChannel;\n readonly hooks = new EventEmitter<WebviewHooks>();\n readonly theme = new Store<Theme>({});\n readonly systemContext = new Store<SystemContext>(DEFAULT_SYSTEM_CONTEXT);\n readonly #dotContext: DotContext = { theme: this.theme, systemContext: this.systemContext };\n #viewByPageId: Record<string, ViewRender>;\n #openPages: OpenPage[] = [];\n // The page the service was last told is showing: the top one, while the app is active.\n #shownPage: OpenPage | undefined;\n #pending: readonly StackEntry[] = [];\n #container: Element | null = null;\n\n constructor({ transport, renderer, views, plugins = [] }: WebviewOptions) {\n this.pageRenderer = renderer;\n this.#viewByPageId = views;\n this.channel = new MessageChannel(transport);\n this.channel.handle('setTheme', ({ theme }) => {\n this.theme.set(theme);\n });\n this.channel.handle('initPageState', ({ instanceId, state }) => {\n this.locatePage(instanceId)?.initializeState(state);\n });\n this.channel.handle('setPageState', ({ instanceId, patchState }) => {\n this.locatePage(instanceId)?.updateState(patchState);\n });\n this.channel.handle('syncStack', ({ pages }) => {\n this.#reconcile(pages);\n });\n this.channel.handle('syncSystemContext', (context) => {\n this.systemContext.set(context);\n this.#showTopPage();\n });\n this.channel.handle('error', ({ instanceId, message }) => {\n if (instanceId === undefined) {\n console.error(`[dot] service error: ${message}`);\n return;\n }\n // The page may have closed before its error arrived; its instance id is all that is left.\n const pageName = this.locatePage(instanceId)?.pageId ?? `#${instanceId}`;\n console.error(`[dot] service error in page \"${pageName}\": ${message}`);\n });\n plugins.forEach((plugin) => this.preparePlugin(plugin));\n }\n\n preparePlugin(plugin: WebviewPlugin): this {\n plugin.setup(this);\n return this;\n }\n\n start(): () => void {\n const stopListening = this.channel.listen((error, message) => {\n this.hooks.emit('error', error, message);\n console.error('[dot] webview error', error);\n });\n this.channel.send('connect', {});\n return stopListening;\n }\n\n mount(container: Element): () => void {\n this.#container = container;\n this.#reconcile(this.#pending);\n return () => this.#reconcile([]);\n }\n\n /** Swaps in the views of a newer build of the dot, as a hot reload does, redrawing open pages. */\n replaceViews(views: Record<string, ViewRender>): void {\n this.#viewByPageId = views;\n for (const { page } of this.#openPages) {\n const view = views[page.pageId];\n if (view) {\n page.replaceView(view);\n }\n }\n }\n\n get stack(): readonly PageController[] {\n return this.#openPages.map(({ page }) => page);\n }\n\n // Makes the open pages match the stack the host announced.\n #reconcile(pages: readonly StackEntry[]): void {\n if (!this.#container) {\n this.#pending = pages;\n return;\n }\n this.#closePagesNotIn(pages);\n // The page being covered hides before the new one loads, as on a device.\n if (this.#shownPage?.page.pageInstanceId !== pages.at(-1)?.instanceId) {\n this.#showOnly(undefined);\n }\n this.#openPagesIn(pages);\n const top = this.#top();\n for (const open of this.#openPages) {\n open.element.hidden = open !== top;\n }\n this.#showTopPage();\n }\n\n // The top page shows while the app is active, and hides while the person is away from Dash.\n // Its element stays visible either way, so the app switcher's snapshot shows it.\n #showTopPage(): void {\n if (this.systemContext.get().appState === 'active') {\n this.#showOnly(this.#top());\n } else {\n this.#showOnly(undefined);\n }\n }\n\n #showOnly(open: OpenPage | undefined): void {\n if (open === this.#shownPage) {\n return;\n }\n if (this.#shownPage) {\n this.channel.send('hide', { instanceId: this.#shownPage.page.pageInstanceId });\n }\n this.#shownPage = open;\n if (open) {\n this.channel.send('show', { instanceId: open.page.pageInstanceId });\n }\n }\n\n #closePagesNotIn(pages: readonly StackEntry[]): void {\n const instanceIdsToKeep = new Set(pages.map((entry) => entry.instanceId));\n // Close from the top of the stack down, the order a device closes pages in.\n for (const open of [...this.#openPages].reverse()) {\n if (!instanceIdsToKeep.has(open.page.pageInstanceId)) {\n this.#close(open);\n }\n }\n }\n\n #openPagesIn(pages: readonly StackEntry[]): void {\n const kept = new Map(this.#openPages.map((open) => [open.page.pageInstanceId, open]));\n const opened: OpenPage[] = [];\n this.#openPages = pages.map((entry) => {\n let open = kept.get(entry.instanceId);\n if (!open) {\n open = this.#open(entry);\n opened.push(open);\n }\n return open;\n });\n // Only now, with every page in the stack, can the service's replies find their page.\n for (const { page } of opened) {\n this.channel.send('load', {\n instanceId: page.pageInstanceId,\n page: page.pageId,\n options: page.pageOptions,\n });\n }\n }\n\n #open({ instanceId, page: id, options }: StackEntry): OpenPage {\n const view = this.#viewByPageId[id];\n if (!view) {\n throw new Error(`Unknown page \"${id}\"`);\n }\n const page = new PageController(instanceId, id, options, view, (instanceId, handler, event) =>\n this.channel.send('event', { instanceId, handler, event }),\n );\n const container = this.#container!;\n const element = container.ownerDocument.createElement('div');\n element.dataset.page = id;\n element.hidden = true;\n container.append(element);\n const unmount = this.pageRenderer.mount(element, page, this.#dotContext);\n this.hooks.emit('pageOpen', page);\n return { page, element, unmount };\n }\n\n #close(open: OpenPage): void {\n // A closing page unloads rather than hides.\n if (this.#shownPage === open) {\n this.#shownPage = undefined;\n }\n open.unmount();\n open.element.remove();\n this.#openPages = this.#openPages.filter((other) => other !== open);\n this.channel.send('unload', { instanceId: open.page.pageInstanceId });\n this.hooks.emit('pageClose', open.page);\n }\n\n #top(): OpenPage | undefined {\n return this.#openPages.at(-1);\n }\n\n locatePage(instanceId: number): PageController | undefined {\n return this.#openPages.find(({ page }) => page.pageInstanceId === instanceId)?.page;\n }\n}\n","import type { ViewRender } from '@monimesl/dot-core';\nimport { hostTransport } from '@monimesl/dot-core';\n\nimport type { Renderer } from './renderer';\nimport type { WebviewOptions } from './webview';\nimport { Webview } from './webview';\n\nexport { PageController } from './page';\nexport { Store } from './store';\nexport type { ReadonlyStore } from './store';\n\nexport { hostTransport } from '@monimesl/dot-core';\nexport type { DotContext, Renderer } from './renderer';\nexport type { WebviewHooks, WebviewOptions, WebviewPlugin, WebviewChannel } from './webview';\nexport type {\n ColorScheme,\n DotEvent,\n PageState,\n RenderContext,\n SystemContext,\n Theme,\n Transport,\n ViewRender,\n} from '@monimesl/dot-core';\n\nexport interface StartOptions extends WebviewOptions {\n container: Element;\n}\n\nexport function startWebview({ container, ...options }: StartOptions): Webview {\n const webview = new Webview(options);\n webview.start();\n webview.mount(container);\n return webview;\n}\n\n// Where the running webview is found by the next build of the dot, run in the same page.\nconst RUNNING_WEBVIEW = Symbol.for('dot.webview');\n\nexport interface RunWebviewOptions {\n // Called only when the webview starts.\n renderer: () => Renderer;\n views: Record<string, ViewRender>;\n}\n\n// Starts the webview in `#root`, or hands a newer build's views to the one already running, as a hot reload does.\nexport function runWebview({ renderer, views }: RunWebviewOptions): Webview {\n const scope = globalThis as unknown as Record<symbol, Webview | undefined>;\n const running = scope[RUNNING_WEBVIEW];\n if (running) {\n running.replaceViews(views);\n return running;\n }\n const container = document.getElementById('root');\n if (!container) {\n throw new Error('The dot\\'s page has no element with the id \"root\" to show it in');\n }\n const webview = startWebview({\n container,\n transport: hostTransport(),\n renderer: renderer(),\n views,\n });\n scope[RUNNING_WEBVIEW] = webview;\n return webview;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-webview",
3
- "version": "0.1.0-alpha.7",
3
+ "version": "0.1.0-alpha.9",
4
4
  "description": "Dot view layer: keeps pages in sync with the logic and hands them to a renderer",
5
5
  "type": "module",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "main": "./dist/index.js",
25
25
  "types": "./dist/index.d.ts",
26
26
  "dependencies": {
27
- "@monimesl/dot-core": "0.1.0-alpha.7"
27
+ "@monimesl/dot-core": "0.1.0-alpha.9"
28
28
  },
29
29
  "devDependencies": {
30
30
  "jsdom": "^30.1.1",