| 41 | } |
| 42 | |
| 43 | export async function openSimPptxViewer({ |
| 44 | buffer, |
| 45 | container, |
| 46 | scrollContainer, |
| 47 | signal, |
| 48 | zipLimits = SIM_PPTX_ZIP_LIMITS, |
| 49 | listOptions = SIM_PPTX_LIST_OPTIONS, |
| 50 | onRenderStart, |
| 51 | onRenderComplete, |
| 52 | onSlideChange, |
| 53 | onSlideError, |
| 54 | onNodeError, |
| 55 | }: OpenSimPptxViewerOptions): Promise<SimPptxViewerHandle> { |
| 56 | const viewer = new PptxViewer(container, { |
| 57 | fitMode: 'contain', |
| 58 | scrollContainer, |
| 59 | zipLimits, |
| 60 | onRenderStart, |
| 61 | onRenderComplete, |
| 62 | onSlideChange, |
| 63 | onSlideError, |
| 64 | onNodeError, |
| 65 | }) |
| 66 | |
| 67 | let destroyed = false |
| 68 | const destroy = () => { |
| 69 | if (destroyed) return |
| 70 | destroyed = true |
| 71 | viewer.destroy() |
| 72 | } |
| 73 | |
| 74 | const abortDestroy = () => destroy() |
| 75 | signal?.addEventListener('abort', abortDestroy, { once: true }) |
| 76 | |
| 77 | try { |
| 78 | await viewer.open(buffer, { |
| 79 | renderMode: 'list', |
| 80 | listOptions, |
| 81 | signal, |
| 82 | }) |
| 83 | } catch (error) { |
| 84 | destroy() |
| 85 | const normalized = toError(error) |
| 86 | if (normalized.name !== 'AbortError') { |
| 87 | logger.warn('Failed to render PPTX preview', { error: normalized.message }) |
| 88 | } |
| 89 | throw normalized |
| 90 | } finally { |
| 91 | signal?.removeEventListener('abort', abortDestroy) |
| 92 | } |
| 93 | |
| 94 | return { viewer, destroy } |
| 95 | } |