Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/viewer-demo/scripts/verify-pptx-slideshow.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,15 @@ await page.waitForFunction(
{ timeout: 5_000 }
)
assert.equal(await call('overlayCount'), 1, 'shadow viewer should be presenting')
await page.waitForFunction(
() => window.__slideshowTest.presentationIsVisible('shadow'),
null,
{ timeout: 5_000 }
)
assert.equal(await call('presentationIsVisible', 'shadow'), true, 'shadow viewer should show its active slide')
await call('exitFullscreen')
await waitOverlay(0, 5_000)
console.log('13) shadow-root native fullscreen exit closes the overlay')
console.log('13) shadow-root fullscreen shows the slide and browser exit closes the overlay')

// 14) Enter/Space on the focused exit button activates it, not the slide.
await call('enter', 'default')
Expand Down
34 changes: 34 additions & 0 deletions apps/viewer-demo/src/slideshow-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface SlideshowTestApi {
presenting: (name: ViewerName) => boolean
activeNumber: (name: ViewerName) => number
activeSlideHasContent: (name: ViewerName) => boolean
presentationIsVisible: (name: ViewerName) => boolean
counter: (name: ViewerName) => string
transform: (name: ViewerName) => string
overlayCount: () => number
Expand Down Expand Up @@ -177,6 +178,39 @@ const init = async () => {
: active
return Boolean(slide && slide.classList.contains('slide') && slide.textContent?.trim())
},
presentationIsVisible: name => {
const overlay = overlayFor(name) as HTMLElement | null
const viewer = viewers.get(name)
if (!overlay || !viewer) {
return false
}
const containers = Array.from(
viewer.content.querySelectorAll<HTMLElement>(':scope > .flyfish-pptx-slide-slot, :scope > .slide')
)
const active = containers.find(container => container.classList.contains('is-active-slide'))
const slide = active?.classList.contains('flyfish-pptx-slide-slot')
? active.firstElementChild as HTMLElement | null
: active
if (!slide) {
return false
}
const root = overlay.getRootNode()
const hasViewerStyles = root instanceof ShadowRoot
? Boolean(root.querySelector('#flyfish-pptx-native-style'))
: Boolean(document.getElementById('flyfish-pptx-native-style'))
const overlayRect = overlay.getBoundingClientRect()
const slideRect = slide.getBoundingClientRect()
const slideStyle = getComputedStyle(slide)
const intersectsOverlay = slideRect.right > overlayRect.left &&
slideRect.left < overlayRect.right &&
slideRect.bottom > overlayRect.top &&
slideRect.top < overlayRect.bottom
return hasViewerStyles &&
slideStyle.display !== 'none' &&
slideRect.width > 0 &&
slideRect.height > 0 &&
intersectsOverlay
},
counter: name => overlayFor(name)?.querySelector('.flyfish-pptx-presentation-counter')?.textContent ?? '',
transform: name => viewers.get(name)?.content.style.transform ?? '',
overlayCount: () => deepAll('.flyfish-pptx-presentation').length,
Expand Down
24 changes: 16 additions & 8 deletions packages/renderers/pptx/src/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,27 @@ export class PptxViewer {
return this.presentation?.slideNumber ?? 1;
}

private get styleRoot(): Document | ShadowRoot {
if (this.options.styleRoot) {
return this.options.styleRoot;
}
const documentRef = this.target.ownerDocument || document;
const root = this.target.getRootNode();
const ShadowRootCtor = documentRef.defaultView?.ShadowRoot;
return ShadowRootCtor && root instanceof ShadowRootCtor
? root as ShadowRoot
: documentRef;
}

/**
* Where the slideshow overlay is mounted. It has to share a root with the injected slide styles,
* or the engine's scoped CSS stops applying once the slides move into the overlay.
*/
get presentationRoot(): ShadowRoot | HTMLElement {
const documentRef = this.target.ownerDocument || document;
if (this.options.styleRoot) {
return this.options.styleRoot;
}
const root = this.target.getRootNode();
const ShadowRootCtor = documentRef.defaultView?.ShadowRoot;
if (ShadowRootCtor && root instanceof ShadowRootCtor) {
return root as ShadowRoot;
const styleRoot = this.styleRoot;
if (styleRoot !== documentRef) {
return styleRoot as ShadowRoot;
}
return documentRef.body || documentRef.documentElement;
}
Expand Down Expand Up @@ -325,7 +333,7 @@ export class PptxViewer {

async open() {
ensureZipWithinLimits(this.buffer, this.options);
ensurePptxViewerStyles(this.target.ownerDocument || document, this.options.styleRoot);
ensurePptxViewerStyles(this.target.ownerDocument || document, this.styleRoot);
this.target.replaceChildren(this.scaleBox);
this.attachResizeObserver();
this.attachSlideWindowListeners();
Expand Down