@netless/app-presentation 0.1.13-beta.4 → 0.1.14

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/README-zh.md CHANGED
@@ -32,6 +32,17 @@ install(register, {
32
32
  })
33
33
  ```
34
34
 
35
+ ### 依赖边界与本地开发
36
+
37
+ 库代码通过 `import type` 引用 WindowManager 和 White SDK 类型;运行时由宿主通过
38
+ `AppContext` 和 `install(register)` 提供。`install()` 也可以直接接收
39
+ `WindowManager.register`。Fastboard 仅用于集成示例中的房间创建和 UI。
40
+
41
+ 使用 `pnpm install` 安装库构建依赖。运行 Fastboard 示例时,再执行
42
+ `pnpm --dir e2e install`,然后运行 `pnpm dev:e2e`;房间的 `VITE_*` 配置放在
43
+ 仓库根目录的 `.env.local`。Fastboard 和教具插件依赖由独立的 `e2e` 私有包管理,
44
+ 不会随库发布。库构建会拒绝对宿主包的运行时导入。
45
+
35
46
  ### 将应用插入房间
36
47
 
37
48
  如果你以 `{ as: 'DocsViewer' }` 的方式安装了这个应用,请调用 [`fastboard.insertDocs()`](https://github.com/netless-io/fastboard#insert-pdf-ppt-and-pptx)。
package/README.md CHANGED
@@ -34,6 +34,19 @@ install(register, {
34
34
  })
35
35
  ```
36
36
 
37
+ ### Dependency boundary and local development
38
+
39
+ The library imports WindowManager and White SDK types with `import type`; their
40
+ runtime is supplied by the host through `AppContext` and `install(register)`.
41
+ `install()` also accepts `WindowManager.register` directly. Fastboard is only
42
+ needed by the integration demo, where it creates the room and UI.
43
+
44
+ Install the library build dependencies with `pnpm install`. To run the Fastboard
45
+ demo, also run `pnpm --dir e2e install`, then `pnpm dev:e2e`. Configure its
46
+ `VITE_*` room settings in the repository's `.env.local`. The private `e2e`
47
+ package owns the Fastboard and appliance plugin dependencies and is not published.
48
+ The library build rejects runtime imports of host packages.
49
+
37
50
  ### Insert This App Into Room
38
51
 
39
52
  Call [`fastboard.insertDocs()`](https://github.com/netless-io/fastboard#insert-pdf-ppt-and-pptx)
package/build.ts CHANGED
@@ -46,6 +46,20 @@ const lazyload = (): esbuild.Plugin => ({
46
46
  }
47
47
  })
48
48
 
49
+ // Host APIs are provided by AppContext or install(register), never imported at runtime.
50
+ const hostTypesOnly = (): esbuild.Plugin => ({
51
+ name: 'host-types-only',
52
+ setup({ onResolve }) {
53
+ onResolve({
54
+ filter: /^(?:@netless\/(?:window-manager|fastboard(?:-[^/]+)?|appliance-plugin)|white-web-sdk)(?:\/|$)/,
55
+ }, args => ({
56
+ errors: [{
57
+ text: `Presentation cannot import ${args.path} at runtime. Use import type for host types; keep host runtime imports in e2e.`,
58
+ }],
59
+ }))
60
+ },
61
+ })
62
+
49
63
  fs.rmSync('dist', { recursive: true, force: true })
50
64
 
51
65
  let bundle = await rollup.rollup({
@@ -62,17 +76,11 @@ let bundle = await rollup.rollup({
62
76
  sourcemap: true,
63
77
  write: false,
64
78
  target: ['es2017'],
65
- plugins: [sass(), lazyload()],
79
+ plugins: [hostTypesOnly(), sass(), lazyload()],
66
80
  define: {
67
81
  __VERSION__: JSON.stringify(version)
68
82
  },
69
- external: Object.keys({
70
- '@netless/window-manager': '*',
71
- '@netless/appliance-plugin': '*',
72
- '@netless/fastboard': '*',
73
- 'white-web-sdk': '*',
74
- ...peerDependencies,
75
- })
83
+ external: Object.keys(peerDependencies)
76
84
  })
77
85
  let code: any, map: any
78
86
  for (const { path, text } of outputFiles) {
@@ -98,4 +106,6 @@ code = code.replace(`await import('jspdf')`, `jspdf`)
98
106
  fs.writeFileSync('dist/index.global.js', code)
99
107
 
100
108
  if (process.env.DTS != '0')
101
- await dts.build('src/index.ts', 'dist/index.d.ts', { exclude: ['@netless/window-manager'] })
109
+ await dts.build('src/index.ts', 'dist/index.d.ts', {
110
+ exclude: ['@netless/window-manager', 'white-web-sdk'],
111
+ })
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { View, NetlessApp, Size, AppContext, WindowManager } from '@netless/window-manager';
1
+ import { View, NetlessApp, AppContext, WindowManager } from '@netless/window-manager';
2
+ import { Size } from 'white-web-sdk';
2
3
 
3
4
  /**
4
5
  * A combination of {@link Disposer} and {@link IDisposable}.
@@ -276,6 +277,7 @@ interface PresentationConfig {
276
277
  readonly pages: PresentationPage[];
277
278
  readonly readonly?: boolean;
278
279
  readonly thumbnail?: (src: string) => string;
280
+ readonly onThumbnailError?: (error: unknown) => void;
279
281
  }
280
282
  /**
281
283
  * Standalone presentation slide viewer.
@@ -316,6 +318,7 @@ declare class Presentation implements IDisposable<void> {
316
318
  readonly dispose: DisposableStore;
317
319
  readonly pages: PresentationPage[];
318
320
  readonly preload: Preload;
321
+ readonly onThumbnailError?: (error: unknown) => void;
319
322
  dom: Element | DocumentFragment;
320
323
  contentDOM: HTMLDivElement;
321
324
  previewDOM: HTMLDivElement;
@@ -429,6 +432,13 @@ declare class Scrollbar {
429
432
  }
430
433
 
431
434
  type Logger = (...data: any[]) => void;
435
+ interface PresentationDiagnosticLogger {
436
+ info(event: string, payload?: unknown): void;
437
+ warn(event: string, payload?: unknown): void;
438
+ error(event: string, error: unknown, payload?: unknown): void;
439
+ debouncedInfo(event: string, payload?: unknown): void;
440
+ flush(): void;
441
+ }
432
442
  interface PresentationAttributes {
433
443
  /** Shared logical camera reference size. New pages are proportionally contained within it. */
434
444
  originSize?: Size | null;
@@ -555,6 +565,7 @@ declare const setupBlurThumbnailDegradation: (config: {
555
565
  app: Presentation;
556
566
  dispose: ReturnType<typeof disposableStore>;
557
567
  }) => void;
568
+ declare const createDiagnosticLogger: (context: AppContext) => PresentationDiagnosticLogger;
558
569
  declare const NetlessAppPresentation: NetlessApp<PresentationAttributes, {}, PresentationAppOptions, PresentationController> & {
559
570
  teardown(context: AppContext): void;
560
571
  };
@@ -582,5 +593,5 @@ declare const install: (register: RegisterFn, options?: InstallOptions) => Promi
582
593
 
583
594
  declare const version: string;
584
595
 
585
- export { NetlessAppPresentation, Presentation, Scrollbar, NetlessAppPresentation as default, install, setupBlurThumbnailDegradation, version };
596
+ export { NetlessAppPresentation, Presentation, Scrollbar, createDiagnosticLogger, NetlessAppPresentation as default, install, setupBlurThumbnailDegradation, version };
586
597
  export type { InstallOptions, Logger, PresentationAppOptions, PresentationAttributes, PresentationConfig, PresentationController, PresentationPage, RegisterFn, ScrollbarEventCallback, ScrollbarOption };
@@ -1304,6 +1304,7 @@ var NetlessAppPresentation = (function (exports) {
1304
1304
  var _a;
1305
1305
  this.pages = config.pages;
1306
1306
  this.preload = new Preload(this.pages);
1307
+ this.onThumbnailError = config.onThumbnailError;
1307
1308
  if (config.thumbnail)
1308
1309
  this.thumbnail = config.thumbnail;
1309
1310
  this.dispose.add(this.preload);
@@ -1519,12 +1520,16 @@ var NetlessAppPresentation = (function (exports) {
1519
1520
  }
1520
1521
  /** Returns a modified URL that points to the thumbnail image. */
1521
1522
  thumbnail(src) {
1523
+ var _a;
1522
1524
  try {
1523
1525
  const url = new URL(src);
1524
1526
  url.searchParams.set("x-oss-process", "image/resize,l_50");
1525
1527
  return url.toString();
1526
1528
  } catch (err) {
1527
- console.error(err);
1529
+ try {
1530
+ (_a = this.onThumbnailError) == null ? void 0 : _a.call(this, err);
1531
+ } catch (e) {
1532
+ }
1528
1533
  return src;
1529
1534
  }
1530
1535
  }
@@ -2119,7 +2124,8 @@ var NetlessAppPresentation = (function (exports) {
2119
2124
  const box = context.getBox();
2120
2125
  const boxBlurClass = box.wrapClassName("blur");
2121
2126
  let blurEpisode = false;
2122
- let reDegradeEnabled = false;
2127
+ let failedThumbnailPageIndex = null;
2128
+ const canReDegrade = () => blurEpisode && failedThumbnailPageIndex !== pageIndex$.value;
2123
2129
  let previewSuspended = false;
2124
2130
  let appliedFocusState = true;
2125
2131
  let logicalFocused = true;
@@ -2176,15 +2182,16 @@ var NetlessAppPresentation = (function (exports) {
2176
2182
  app.suspendPreviewResources();
2177
2183
  }
2178
2184
  const page = pages[pageIndex$.value];
2179
- if (!page || !hasUsableThumbnail(page) || reDegradeEnabled) {
2185
+ if (!page || !hasUsableThumbnail(page) || canReDegrade()) {
2180
2186
  degrade();
2181
2187
  }
2182
2188
  };
2183
2189
  const restoreFocusedResources = () => {
2190
+ appliedFocusState = true;
2184
2191
  if (!blurEpisode)
2185
2192
  return;
2186
2193
  blurEpisode = false;
2187
- reDegradeEnabled = false;
2194
+ failedThumbnailPageIndex = null;
2188
2195
  previewSuspended = false;
2189
2196
  restore2();
2190
2197
  app.preload.resume(pageIndex$.value);
@@ -2203,18 +2210,22 @@ var NetlessAppPresentation = (function (exports) {
2203
2210
  return !!(el && el.contains(target));
2204
2211
  };
2205
2212
  const onImgLoad = (ev) => {
2206
- if (!blurEpisode || !reDegradeEnabled)
2213
+ if (!canReDegrade())
2207
2214
  return;
2208
2215
  if (!ownsTarget(ev.target))
2209
2216
  return;
2210
2217
  degrade();
2211
2218
  };
2212
2219
  const onImgError = (ev) => {
2213
- if (!blurEpisode || !reDegradeEnabled)
2220
+ var _a;
2221
+ if (!canReDegrade())
2214
2222
  return;
2215
2223
  if (!ownsTarget(ev.target))
2216
2224
  return;
2217
- reDegradeEnabled = false;
2225
+ const thumbnailURL = (_a = pages[pageIndex$.value]) == null ? void 0 : _a.thumbnail;
2226
+ if (thumbnailURL && resolveImageUrl(ev.target.src) === resolveImageUrl(thumbnailURL)) {
2227
+ failedThumbnailPageIndex = pageIndex$.value;
2228
+ }
2218
2229
  };
2219
2230
  const applyActivity = () => {
2220
2231
  var _a;
@@ -2228,7 +2239,7 @@ var NetlessAppPresentation = (function (exports) {
2228
2239
  restoreFocusedResources();
2229
2240
  } else {
2230
2241
  blurEpisode = true;
2231
- reDegradeEnabled = true;
2242
+ failedThumbnailPageIndex = null;
2232
2243
  degrade();
2233
2244
  app.preload.pause();
2234
2245
  suspendCachedResources();
@@ -2275,26 +2286,21 @@ var NetlessAppPresentation = (function (exports) {
2275
2286
  document.removeEventListener("error", onImgError, true);
2276
2287
  });
2277
2288
  };
2278
- var createLogger = (room) => {
2279
- if (room && room.logger) {
2280
- return (...args) => room.logger.info(...args);
2281
- } else {
2282
- return (...args) => console.log(...args);
2283
- }
2289
+ var getLogger = (context) => {
2290
+ var _a, _b, _c;
2291
+ return (_c = (_a = context.getWindowManager()) == null ? void 0 : _a.Logger) != null ? _c : (_b = context.getRoom()) == null ? void 0 : _b.logger;
2292
+ };
2293
+ var createLogger = (context) => {
2294
+ return (...args) => {
2295
+ var _a, _b;
2296
+ return (_b = (_a = getLogger(context)) == null ? void 0 : _a.info) == null ? void 0 : _b.call(_a, ...args);
2297
+ };
2284
2298
  };
2285
2299
  var createDiagnosticLogger = (context) => {
2286
- var _a;
2287
- const createAppLogger = context.createLogger;
2288
- if (typeof createAppLogger === "function") {
2289
- return createAppLogger.call(context, "camera", {
2290
- debounceTime: 300,
2291
- maxWaitTime: 2e3
2292
- });
2293
- }
2294
- const roomLogger = (_a = context.getRoom()) == null ? void 0 : _a.logger;
2295
2300
  const prefix = `[Presentation][${context.appId}][camera]`;
2296
2301
  const emit = (level, event, ...data) => {
2297
2302
  try {
2303
+ const roomLogger = getLogger(context);
2298
2304
  const printer = roomLogger == null ? void 0 : roomLogger[level];
2299
2305
  if (typeof printer === "function")
2300
2306
  printer.call(roomLogger, `${prefix}[${event}]`, ...data);
@@ -2359,9 +2365,11 @@ var NetlessAppPresentation = (function (exports) {
2359
2365
  );
2360
2366
  const options = context.getAppOptions() || {};
2361
2367
  const room = context.getRoom();
2362
- const log = options.log || createLogger(room);
2363
- const roomLogger = room == null ? void 0 : room.logger;
2364
- const warn = (...data) => (roomLogger == null ? void 0 : roomLogger.warn) ? roomLogger.warn(...data) : log(...data);
2368
+ const log = options.log || createLogger(context);
2369
+ const warn = (...data) => {
2370
+ var _a2, _b2;
2371
+ return (_b2 = (_a2 = getLogger(context)) == null ? void 0 : _a2.warn) == null ? void 0 : _b2.call(_a2, ...data);
2372
+ };
2365
2373
  const configuredOriginSize = context.storage.state.originSize;
2366
2374
  const originSize = isValidSize(configuredOriginSize) ? {
2367
2375
  width: configuredOriginSize.width,
@@ -2693,10 +2701,14 @@ var NetlessAppPresentation = (function (exports) {
2693
2701
  pageIndex$,
2694
2702
  view,
2695
2703
  options.thumbnail,
2696
- options.useClipView
2704
+ options.useClipView,
2705
+ (error) => {
2706
+ var _a2, _b2;
2707
+ return (_b2 = (_a2 = getLogger(context)) == null ? void 0 : _a2.error) == null ? void 0 : _b2.call(_a2, "[Presentation] thumbnail URL parsing failed", context.appId, error);
2708
+ }
2697
2709
  )
2698
2710
  );
2699
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.4";
2711
+ app.contentDOM.dataset.appPresentationVersion = "0.1.14";
2700
2712
  app.scaleDocsToFit = scaleDocsToFit;
2701
2713
  app.log = log;
2702
2714
  app.warn = warn;
@@ -3176,10 +3188,7 @@ var NetlessAppPresentation = (function (exports) {
3176
3188
  );
3177
3189
  if (disposed)
3178
3190
  throw new Error("[Presentation] disposed before setup ready");
3179
- if (result === "error" && context.waitForActualSetupReady) {
3180
- throw new Error("[Presentation] setup page image failed to load");
3181
- }
3182
- if (result === "error" && !disposed) {
3191
+ if (result === "error") {
3183
3192
  warn("[Presentation] setup page image failed to load; continuing setup");
3184
3193
  }
3185
3194
  return controller;
@@ -3215,13 +3224,14 @@ var NetlessAppPresentation = (function (exports) {
3215
3224
  }
3216
3225
  }
3217
3226
  };
3218
- function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, useClipView) {
3227
+ function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, useClipView, onThumbnailError) {
3219
3228
  box.mountStyles(style_default);
3220
3229
  const app = new AppPresentation({
3221
3230
  pages,
3222
3231
  readonly: box.readonly,
3223
3232
  jumpPage,
3224
- thumbnail
3233
+ thumbnail,
3234
+ onThumbnailError
3225
3235
  });
3226
3236
  app.box = box;
3227
3237
  box.mountContent(app.contentDOM);
@@ -3269,11 +3279,12 @@ var NetlessAppPresentation = (function (exports) {
3269
3279
  };
3270
3280
 
3271
3281
  // src/index.ts
3272
- var version = "0.1.13-beta.4";
3282
+ var version = "0.1.14";
3273
3283
 
3274
3284
  exports.NetlessAppPresentation = NetlessAppPresentation;
3275
3285
  exports.Presentation = Presentation;
3276
3286
  exports.Scrollbar = Scrollbar;
3287
+ exports.createDiagnosticLogger = createDiagnosticLogger;
3277
3288
  exports.default = NetlessAppPresentation;
3278
3289
  exports.install = install;
3279
3290
  exports.setupBlurThumbnailDegradation = setupBlurThumbnailDegradation;
package/dist/index.js CHANGED
@@ -1305,6 +1305,7 @@ var Presentation = class {
1305
1305
  var _a;
1306
1306
  this.pages = config.pages;
1307
1307
  this.preload = new Preload(this.pages);
1308
+ this.onThumbnailError = config.onThumbnailError;
1308
1309
  if (config.thumbnail)
1309
1310
  this.thumbnail = config.thumbnail;
1310
1311
  this.dispose.add(this.preload);
@@ -1520,12 +1521,16 @@ var Presentation = class {
1520
1521
  }
1521
1522
  /** Returns a modified URL that points to the thumbnail image. */
1522
1523
  thumbnail(src) {
1524
+ var _a;
1523
1525
  try {
1524
1526
  const url = new URL(src);
1525
1527
  url.searchParams.set("x-oss-process", "image/resize,l_50");
1526
1528
  return url.toString();
1527
1529
  } catch (err) {
1528
- console.error(err);
1530
+ try {
1531
+ (_a = this.onThumbnailError) == null ? void 0 : _a.call(this, err);
1532
+ } catch (e) {
1533
+ }
1529
1534
  return src;
1530
1535
  }
1531
1536
  }
@@ -2120,7 +2125,8 @@ var setupBlurThumbnailDegradation = (config) => {
2120
2125
  const box = context.getBox();
2121
2126
  const boxBlurClass = box.wrapClassName("blur");
2122
2127
  let blurEpisode = false;
2123
- let reDegradeEnabled = false;
2128
+ let failedThumbnailPageIndex = null;
2129
+ const canReDegrade = () => blurEpisode && failedThumbnailPageIndex !== pageIndex$.value;
2124
2130
  let previewSuspended = false;
2125
2131
  let appliedFocusState = true;
2126
2132
  let logicalFocused = true;
@@ -2177,15 +2183,16 @@ var setupBlurThumbnailDegradation = (config) => {
2177
2183
  app.suspendPreviewResources();
2178
2184
  }
2179
2185
  const page = pages[pageIndex$.value];
2180
- if (!page || !hasUsableThumbnail(page) || reDegradeEnabled) {
2186
+ if (!page || !hasUsableThumbnail(page) || canReDegrade()) {
2181
2187
  degrade();
2182
2188
  }
2183
2189
  };
2184
2190
  const restoreFocusedResources = () => {
2191
+ appliedFocusState = true;
2185
2192
  if (!blurEpisode)
2186
2193
  return;
2187
2194
  blurEpisode = false;
2188
- reDegradeEnabled = false;
2195
+ failedThumbnailPageIndex = null;
2189
2196
  previewSuspended = false;
2190
2197
  restore2();
2191
2198
  app.preload.resume(pageIndex$.value);
@@ -2204,18 +2211,22 @@ var setupBlurThumbnailDegradation = (config) => {
2204
2211
  return !!(el && el.contains(target));
2205
2212
  };
2206
2213
  const onImgLoad = (ev) => {
2207
- if (!blurEpisode || !reDegradeEnabled)
2214
+ if (!canReDegrade())
2208
2215
  return;
2209
2216
  if (!ownsTarget(ev.target))
2210
2217
  return;
2211
2218
  degrade();
2212
2219
  };
2213
2220
  const onImgError = (ev) => {
2214
- if (!blurEpisode || !reDegradeEnabled)
2221
+ var _a;
2222
+ if (!canReDegrade())
2215
2223
  return;
2216
2224
  if (!ownsTarget(ev.target))
2217
2225
  return;
2218
- reDegradeEnabled = false;
2226
+ const thumbnailURL = (_a = pages[pageIndex$.value]) == null ? void 0 : _a.thumbnail;
2227
+ if (thumbnailURL && resolveImageUrl(ev.target.src) === resolveImageUrl(thumbnailURL)) {
2228
+ failedThumbnailPageIndex = pageIndex$.value;
2229
+ }
2219
2230
  };
2220
2231
  const applyActivity = () => {
2221
2232
  var _a;
@@ -2229,7 +2240,7 @@ var setupBlurThumbnailDegradation = (config) => {
2229
2240
  restoreFocusedResources();
2230
2241
  } else {
2231
2242
  blurEpisode = true;
2232
- reDegradeEnabled = true;
2243
+ failedThumbnailPageIndex = null;
2233
2244
  degrade();
2234
2245
  app.preload.pause();
2235
2246
  suspendCachedResources();
@@ -2276,26 +2287,21 @@ var setupBlurThumbnailDegradation = (config) => {
2276
2287
  document.removeEventListener("error", onImgError, true);
2277
2288
  });
2278
2289
  };
2279
- var createLogger = (room) => {
2280
- if (room && room.logger) {
2281
- return (...args) => room.logger.info(...args);
2282
- } else {
2283
- return (...args) => console.log(...args);
2284
- }
2290
+ var getLogger = (context) => {
2291
+ var _a, _b, _c;
2292
+ return (_c = (_a = context.getWindowManager()) == null ? void 0 : _a.Logger) != null ? _c : (_b = context.getRoom()) == null ? void 0 : _b.logger;
2293
+ };
2294
+ var createLogger = (context) => {
2295
+ return (...args) => {
2296
+ var _a, _b;
2297
+ return (_b = (_a = getLogger(context)) == null ? void 0 : _a.info) == null ? void 0 : _b.call(_a, ...args);
2298
+ };
2285
2299
  };
2286
2300
  var createDiagnosticLogger = (context) => {
2287
- var _a;
2288
- const createAppLogger = context.createLogger;
2289
- if (typeof createAppLogger === "function") {
2290
- return createAppLogger.call(context, "camera", {
2291
- debounceTime: 300,
2292
- maxWaitTime: 2e3
2293
- });
2294
- }
2295
- const roomLogger = (_a = context.getRoom()) == null ? void 0 : _a.logger;
2296
2301
  const prefix = `[Presentation][${context.appId}][camera]`;
2297
2302
  const emit = (level, event, ...data) => {
2298
2303
  try {
2304
+ const roomLogger = getLogger(context);
2299
2305
  const printer = roomLogger == null ? void 0 : roomLogger[level];
2300
2306
  if (typeof printer === "function")
2301
2307
  printer.call(roomLogger, `${prefix}[${event}]`, ...data);
@@ -2360,9 +2366,11 @@ var NetlessAppPresentation = {
2360
2366
  );
2361
2367
  const options = context.getAppOptions() || {};
2362
2368
  const room = context.getRoom();
2363
- const log = options.log || createLogger(room);
2364
- const roomLogger = room == null ? void 0 : room.logger;
2365
- const warn = (...data) => (roomLogger == null ? void 0 : roomLogger.warn) ? roomLogger.warn(...data) : log(...data);
2369
+ const log = options.log || createLogger(context);
2370
+ const warn = (...data) => {
2371
+ var _a2, _b2;
2372
+ return (_b2 = (_a2 = getLogger(context)) == null ? void 0 : _a2.warn) == null ? void 0 : _b2.call(_a2, ...data);
2373
+ };
2366
2374
  const configuredOriginSize = context.storage.state.originSize;
2367
2375
  const originSize = isValidSize(configuredOriginSize) ? {
2368
2376
  width: configuredOriginSize.width,
@@ -2694,10 +2702,14 @@ var NetlessAppPresentation = {
2694
2702
  pageIndex$,
2695
2703
  view,
2696
2704
  options.thumbnail,
2697
- options.useClipView
2705
+ options.useClipView,
2706
+ (error) => {
2707
+ var _a2, _b2;
2708
+ return (_b2 = (_a2 = getLogger(context)) == null ? void 0 : _a2.error) == null ? void 0 : _b2.call(_a2, "[Presentation] thumbnail URL parsing failed", context.appId, error);
2709
+ }
2698
2710
  )
2699
2711
  );
2700
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.4";
2712
+ app.contentDOM.dataset.appPresentationVersion = "0.1.14";
2701
2713
  app.scaleDocsToFit = scaleDocsToFit;
2702
2714
  app.log = log;
2703
2715
  app.warn = warn;
@@ -3177,10 +3189,7 @@ var NetlessAppPresentation = {
3177
3189
  );
3178
3190
  if (disposed)
3179
3191
  throw new Error("[Presentation] disposed before setup ready");
3180
- if (result === "error" && context.waitForActualSetupReady) {
3181
- throw new Error("[Presentation] setup page image failed to load");
3182
- }
3183
- if (result === "error" && !disposed) {
3192
+ if (result === "error") {
3184
3193
  warn("[Presentation] setup page image failed to load; continuing setup");
3185
3194
  }
3186
3195
  return controller;
@@ -3216,13 +3225,14 @@ var AppPresentation = class extends Presentation {
3216
3225
  }
3217
3226
  }
3218
3227
  };
3219
- function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, useClipView) {
3228
+ function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, useClipView, onThumbnailError) {
3220
3229
  box.mountStyles(style_default);
3221
3230
  const app = new AppPresentation({
3222
3231
  pages,
3223
3232
  readonly: box.readonly,
3224
3233
  jumpPage,
3225
- thumbnail
3234
+ thumbnail,
3235
+ onThumbnailError
3226
3236
  });
3227
3237
  app.box = box;
3228
3238
  box.mountContent(app.contentDOM);
@@ -3270,11 +3280,12 @@ var install = (register, options = {}) => {
3270
3280
  };
3271
3281
 
3272
3282
  // src/index.ts
3273
- var version = "0.1.13-beta.4";
3283
+ var version = "0.1.14";
3274
3284
 
3275
3285
  exports.NetlessAppPresentation = NetlessAppPresentation;
3276
3286
  exports.Presentation = Presentation;
3277
3287
  exports.Scrollbar = Scrollbar;
3288
+ exports.createDiagnosticLogger = createDiagnosticLogger;
3278
3289
  exports.default = NetlessAppPresentation;
3279
3290
  exports.install = install;
3280
3291
  exports.setupBlurThumbnailDegradation = setupBlurThumbnailDegradation;