@monimesl/dot-webview 0.1.0-alpha.3 → 0.1.0-alpha.4

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
@@ -18,9 +18,11 @@ export declare class PageController {
18
18
  #private;
19
19
  readonly pageId: string;
20
20
  readonly pageInstanceId: number;
21
- readonly viewRenderer: ViewRender$1;
22
21
  readonly pageOptions: PageLaunchOptions;
23
22
  constructor(instanceId: number, id: string, options: PageLaunchOptions, viewRenderer: ViewRender$1, dispatch: Dispatch);
23
+ get viewRenderer(): ViewRender$1;
24
+ /** Draws the page again from a newer build's view, as a hot reload does, keeping its state. */
25
+ replaceView(view: ViewRender$1): void;
24
26
  readonly getState: () => PageState$1 | null;
25
27
  readonly subscribe: (listener: () => void) => (() => void);
26
28
  on(handler: string, data?: Readonly<Record<string, unknown>>): (event: DotEvent$1) => void;
@@ -71,6 +73,8 @@ declare class Webview {
71
73
  preparePlugin(plugin: WebviewPlugin): this;
72
74
  start(): () => void;
73
75
  mount(container: Element): () => void;
76
+ /** Swaps in the views of a newer build of the dot, as a hot reload does, redrawing open pages. */
77
+ replaceViews(views: Record<string, ViewRender$1>): void;
74
78
  get stack(): readonly PageController[];
75
79
  locatePage(instanceId: number): PageController | undefined;
76
80
  }
@@ -80,6 +84,11 @@ export interface StartOptions extends WebviewOptions {
80
84
  container: Element;
81
85
  }
82
86
  export declare function startWebview({ container, ...options }: StartOptions): Webview;
87
+ export interface RunWebviewOptions {
88
+ renderer: () => Renderer;
89
+ views: Record<string, ViewRender$1>;
90
+ }
91
+ export declare function runWebview({ renderer, views }: RunWebviewOptions): Webview;
83
92
  //#endregion
84
93
  export { type ColorScheme, type DotContext, type DotEvent, type PageState, type ReadonlyStore, type RenderContext, type Renderer, type SystemContext, type Theme, type Transport, type ViewRender, type WebviewChannel, type WebviewHooks, type WebviewOptions, type WebviewPlugin, hostTransport };
85
94
  //# sourceMappingURL=index.d.ts.map
@@ -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,cAAc;WACd,aAAa;EAKpB,YAAA,oBACA,YACA,SAAS,mBACT,cAAc,cACd,UAAU;WASH,gBAAQ;WAER,YAAS;EAElB,GAAG,iBAAiB,OAAO,SAAS,4BAA4B,OAAO;EAYvE,gBAAgB,OAAO;EAIvB,YAAY,SAAS;;;;UC7CN;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;MAMb,kBAAkB;EAkHtB,WAAW,qBAAqB;;;;iBCrNjB,qBAAqB;EACpC,WAAW;;wBAGG,eAAe,cAAc,WAAW,eAAe"}
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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DEFAULT_SYSTEM_CONTEXT, EventEmitter, MessageChannel, applyChanges, hostTransport } from "@monimesl/dot-core";
1
+ import { DEFAULT_SYSTEM_CONTEXT, EventEmitter, MessageChannel, applyChanges, hostTransport, hostTransport as hostTransport$1 } from "@monimesl/dot-core";
2
2
  //#region src/store.ts
3
3
  var Store = class {
4
4
  #value;
@@ -22,8 +22,8 @@ var PageController = class {
22
22
  pageId;
23
23
  #dispatch;
24
24
  pageInstanceId;
25
- viewRenderer;
26
25
  pageOptions;
26
+ #viewRenderer;
27
27
  #state = new Store(null);
28
28
  #callbacks = /* @__PURE__ */ new Map();
29
29
  constructor(instanceId, id, options, viewRenderer, dispatch) {
@@ -31,7 +31,16 @@ var PageController = class {
31
31
  this.pageOptions = options;
32
32
  this.#dispatch = dispatch;
33
33
  this.pageInstanceId = instanceId;
34
- this.viewRenderer = viewRenderer;
34
+ this.#viewRenderer = viewRenderer;
35
+ }
36
+ get viewRenderer() {
37
+ return this.#viewRenderer;
38
+ }
39
+ /** Draws the page again from a newer build's view, as a hot reload does, keeping its state. */
40
+ replaceView(view) {
41
+ this.#viewRenderer = view;
42
+ const state = this.#state.get();
43
+ if (state) this.#state.set({ ...state });
35
44
  }
36
45
  getState = this.#state.get;
37
46
  subscribe = this.#state.subscribe;
@@ -124,6 +133,14 @@ var Webview = class {
124
133
  this.#reconcile(this.#pending);
125
134
  return () => this.#reconcile([]);
126
135
  }
136
+ /** Swaps in the views of a newer build of the dot, as a hot reload does, redrawing open pages. */
137
+ replaceViews(views) {
138
+ this.#viewByPageId = views;
139
+ for (const { page } of this.#openPages) {
140
+ const view = views[page.pageId];
141
+ if (view) page.replaceView(view);
142
+ }
143
+ }
127
144
  get stack() {
128
145
  return this.#openPages.map(({ page }) => page);
129
146
  }
@@ -213,7 +230,26 @@ function startWebview({ container, ...options }) {
213
230
  webview.mount(container);
214
231
  return webview;
215
232
  }
233
+ const RUNNING_WEBVIEW = Symbol.for("dot.webview");
234
+ function runWebview({ renderer, views }) {
235
+ const scope = globalThis;
236
+ const running = scope[RUNNING_WEBVIEW];
237
+ if (running) {
238
+ running.replaceViews(views);
239
+ return running;
240
+ }
241
+ const container = document.getElementById("root");
242
+ if (!container) throw new Error("The dot's page has no element with the id \"root\" to show it in");
243
+ const webview = startWebview({
244
+ container,
245
+ transport: hostTransport$1(),
246
+ renderer: renderer(),
247
+ views
248
+ });
249
+ scope[RUNNING_WEBVIEW] = webview;
250
+ return webview;
251
+ }
216
252
  //#endregion
217
- export { PageController, Store, hostTransport, startWebview };
253
+ export { PageController, Store, hostTransport, runWebview, startWebview };
218
254
 
219
255
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"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 viewRenderer: ViewRender;\n readonly pageOptions: PageLaunchOptions;\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 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 readonly #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 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 { 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"],"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/**\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-webview",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
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.3"
27
+ "@monimesl/dot-core": "0.1.0-alpha.4"
28
28
  },
29
29
  "devDependencies": {
30
30
  "jsdom": "^30.1.1",