@extend-ai/react-pptx 0.2.0 → 0.2.1
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/CHANGELOG.md +7 -0
- package/README.md +30 -0
- package/dist/index.css +0 -3
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +22 -6
- package/dist/index.js +208 -60
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9242,6 +9242,25 @@ async function renderWmfToDataUrl(buffer, maxWidth, maxHeight, optionsOrScale) {
|
|
|
9242
9242
|
}
|
|
9243
9243
|
}
|
|
9244
9244
|
|
|
9245
|
+
// src/zoom.ts
|
|
9246
|
+
var MIN_VIEWER_ZOOM = 10;
|
|
9247
|
+
var MAX_VIEWER_ZOOM = 400;
|
|
9248
|
+
function normalizeViewerZoomLevel(level) {
|
|
9249
|
+
if (typeof level !== "number") return level;
|
|
9250
|
+
if (Number.isNaN(level)) return 100;
|
|
9251
|
+
return Math.max(MIN_VIEWER_ZOOM, Math.min(MAX_VIEWER_ZOOM, level));
|
|
9252
|
+
}
|
|
9253
|
+
function resolveViewerZoom(level, viewportWidth, viewportHeight, contentWidth, contentHeight) {
|
|
9254
|
+
const normalized = normalizeViewerZoomLevel(level);
|
|
9255
|
+
if (typeof normalized === "number") return normalized;
|
|
9256
|
+
const safeContentWidth = Number.isFinite(contentWidth) && contentWidth > 0 ? contentWidth : 1;
|
|
9257
|
+
const safeContentHeight = Number.isFinite(contentHeight) && contentHeight > 0 ? contentHeight : 1;
|
|
9258
|
+
const fitWidth = (Number.isFinite(viewportWidth) && viewportWidth > 0 ? viewportWidth : safeContentWidth) / safeContentWidth * 100;
|
|
9259
|
+
const fitHeight = (Number.isFinite(viewportHeight) && viewportHeight > 0 ? viewportHeight : safeContentHeight) / safeContentHeight * 100;
|
|
9260
|
+
const resolved = normalized === "fit-width" ? fitWidth : normalized === "fit-page" ? Math.min(fitWidth, fitHeight) : Math.min(fitWidth, 100);
|
|
9261
|
+
return Math.max(MIN_VIEWER_ZOOM, Math.min(MAX_VIEWER_ZOOM, resolved));
|
|
9262
|
+
}
|
|
9263
|
+
|
|
9245
9264
|
// src/normalized-viewer.ts
|
|
9246
9265
|
var EMU_PER_CSS_PIXEL = 9525;
|
|
9247
9266
|
var DEFAULT_TEXT_HORIZONTAL_INSET_EMU = 91440;
|
|
@@ -9307,6 +9326,10 @@ function acquirePresentationAssetCache(presentation) {
|
|
|
9307
9326
|
}
|
|
9308
9327
|
var LIST_ITEM_GAP = 24;
|
|
9309
9328
|
var FALLBACK_VIEWPORT_RECT = { width: 800, height: 600 };
|
|
9329
|
+
function pixelValue(value) {
|
|
9330
|
+
const parsed = Number.parseFloat(value);
|
|
9331
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
9332
|
+
}
|
|
9310
9333
|
function scaleListAnchorOffset(offset, previousSlideHeight, nextSlideHeight) {
|
|
9311
9334
|
if (previousSlideHeight <= 0) return offset;
|
|
9312
9335
|
if (offset <= previousSlideHeight) return offset * (nextSlideHeight / previousSlideHeight);
|
|
@@ -9852,9 +9875,11 @@ var NormalizedPresentationViewer = class {
|
|
|
9852
9875
|
presentation;
|
|
9853
9876
|
callbacks;
|
|
9854
9877
|
current = 0;
|
|
9855
|
-
|
|
9856
|
-
|
|
9878
|
+
zoomLevel = "automatic";
|
|
9879
|
+
resolvedZoom = 100;
|
|
9857
9880
|
assetCache;
|
|
9881
|
+
resizeObserver;
|
|
9882
|
+
activeViewport;
|
|
9858
9883
|
listCleanup;
|
|
9859
9884
|
highlight;
|
|
9860
9885
|
activeMountResources;
|
|
@@ -9866,6 +9891,7 @@ var NormalizedPresentationViewer = class {
|
|
|
9866
9891
|
renderGeneration = 0;
|
|
9867
9892
|
navigationGeneration = 0;
|
|
9868
9893
|
lastNotifiedSlide;
|
|
9894
|
+
lastZoomNotification;
|
|
9869
9895
|
listState;
|
|
9870
9896
|
renderState;
|
|
9871
9897
|
get slideCount() {
|
|
@@ -9874,11 +9900,17 @@ var NormalizedPresentationViewer = class {
|
|
|
9874
9900
|
get currentSlideIndex() {
|
|
9875
9901
|
return this.current;
|
|
9876
9902
|
}
|
|
9903
|
+
get zoom() {
|
|
9904
|
+
return this.zoomLevel;
|
|
9905
|
+
}
|
|
9877
9906
|
get zoomPercent() {
|
|
9878
|
-
return this.
|
|
9907
|
+
return this.resolvedZoom;
|
|
9908
|
+
}
|
|
9909
|
+
get resolvedZoomPercent() {
|
|
9910
|
+
return this.resolvedZoom;
|
|
9879
9911
|
}
|
|
9880
9912
|
get fitMode() {
|
|
9881
|
-
return this.
|
|
9913
|
+
return typeof this.zoomLevel === "number" ? "none" : "contain";
|
|
9882
9914
|
}
|
|
9883
9915
|
get naturalSlideWidth() {
|
|
9884
9916
|
const width = this.presentation.size.widthEmu / EMU_PER_CSS_PIXEL;
|
|
@@ -9888,9 +9920,57 @@ var NormalizedPresentationViewer = class {
|
|
|
9888
9920
|
const height = this.presentation.size.heightEmu / EMU_PER_CSS_PIXEL;
|
|
9889
9921
|
return Number.isFinite(height) && height > 0 ? height : 1;
|
|
9890
9922
|
}
|
|
9891
|
-
|
|
9892
|
-
const
|
|
9893
|
-
|
|
9923
|
+
viewportSize(viewport) {
|
|
9924
|
+
const rect = viewport.getBoundingClientRect();
|
|
9925
|
+
let width = viewport.clientWidth || rect.width;
|
|
9926
|
+
let height = viewport.clientHeight || rect.height;
|
|
9927
|
+
if (typeof getComputedStyle === "function") {
|
|
9928
|
+
const viewportStyle = getComputedStyle(viewport);
|
|
9929
|
+
width -= pixelValue(viewportStyle.paddingLeft) + pixelValue(viewportStyle.paddingRight);
|
|
9930
|
+
height -= pixelValue(viewportStyle.paddingTop) + pixelValue(viewportStyle.paddingBottom);
|
|
9931
|
+
if (viewport !== this.container) {
|
|
9932
|
+
const containerStyle = getComputedStyle(this.container);
|
|
9933
|
+
width -= pixelValue(containerStyle.paddingLeft) + pixelValue(containerStyle.paddingRight);
|
|
9934
|
+
height -= pixelValue(containerStyle.paddingTop) + pixelValue(containerStyle.paddingBottom);
|
|
9935
|
+
}
|
|
9936
|
+
}
|
|
9937
|
+
return { width: Math.max(0, width), height: Math.max(0, height) };
|
|
9938
|
+
}
|
|
9939
|
+
resolveZoom(level, viewport = this.activeViewport ?? this.container) {
|
|
9940
|
+
const size = this.viewportSize(viewport);
|
|
9941
|
+
return resolveViewerZoom(
|
|
9942
|
+
level,
|
|
9943
|
+
size.width,
|
|
9944
|
+
size.height,
|
|
9945
|
+
this.naturalSlideWidth,
|
|
9946
|
+
this.naturalSlideHeight
|
|
9947
|
+
);
|
|
9948
|
+
}
|
|
9949
|
+
scaleForViewport(viewport) {
|
|
9950
|
+
return this.resolveZoom(this.zoomLevel, viewport) / 100;
|
|
9951
|
+
}
|
|
9952
|
+
publishZoom(resolvedZoom) {
|
|
9953
|
+
const normalized = Math.max(MIN_VIEWER_ZOOM, Math.min(MAX_VIEWER_ZOOM, resolvedZoom));
|
|
9954
|
+
const levelChanged = this.lastZoomNotification?.level !== this.zoomLevel;
|
|
9955
|
+
const resolutionChanged = this.lastZoomNotification === void 0 || Math.abs(this.lastZoomNotification.resolvedZoom - normalized) > 0.01;
|
|
9956
|
+
this.resolvedZoom = normalized;
|
|
9957
|
+
if (!levelChanged && !resolutionChanged) return;
|
|
9958
|
+
const state = { level: this.zoomLevel, resolvedZoom: normalized };
|
|
9959
|
+
this.lastZoomNotification = state;
|
|
9960
|
+
this.callbacks.onZoomChange?.(state);
|
|
9961
|
+
}
|
|
9962
|
+
observeViewport(viewport) {
|
|
9963
|
+
if (this.activeViewport === viewport && this.resizeObserver) return;
|
|
9964
|
+
this.resizeObserver?.disconnect();
|
|
9965
|
+
this.resizeObserver = void 0;
|
|
9966
|
+
this.activeViewport = viewport;
|
|
9967
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
9968
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
9969
|
+
if (this.destroyed || typeof this.zoomLevel === "number") return;
|
|
9970
|
+
void this.updateRenderedScale();
|
|
9971
|
+
});
|
|
9972
|
+
this.resizeObserver.observe(viewport);
|
|
9973
|
+
if (viewport !== this.container) this.resizeObserver.observe(this.container);
|
|
9894
9974
|
}
|
|
9895
9975
|
isRenderActive(generation) {
|
|
9896
9976
|
return !this.destroyed && generation === this.renderGeneration;
|
|
@@ -9901,6 +9981,9 @@ var NormalizedPresentationViewer = class {
|
|
|
9901
9981
|
this.navigationGeneration += 1;
|
|
9902
9982
|
this.listCleanup?.();
|
|
9903
9983
|
this.listCleanup = void 0;
|
|
9984
|
+
this.resizeObserver?.disconnect();
|
|
9985
|
+
this.resizeObserver = void 0;
|
|
9986
|
+
this.activeViewport = void 0;
|
|
9904
9987
|
this.listState = void 0;
|
|
9905
9988
|
this.clearSearchHighlights();
|
|
9906
9989
|
return generation;
|
|
@@ -10458,7 +10541,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10458
10541
|
} finally {
|
|
10459
10542
|
this.activeMountResources = previousResources;
|
|
10460
10543
|
}
|
|
10461
|
-
const effectiveScale = scale ?? this.scaleForViewport(target
|
|
10544
|
+
const effectiveScale = scale ?? this.scaleForViewport(target);
|
|
10462
10545
|
const wrapper = document.createElement("div");
|
|
10463
10546
|
wrapper.dataset.rpvSlideWrapper = String(index);
|
|
10464
10547
|
wrapper.style.position = "relative";
|
|
@@ -10550,6 +10633,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10550
10633
|
this.renderState = { mode: "single" };
|
|
10551
10634
|
const generation = this.beginRender();
|
|
10552
10635
|
if (generation === void 0) return;
|
|
10636
|
+
this.observeViewport(this.container);
|
|
10553
10637
|
this.current = Math.max(0, Math.min(this.slideCount - 1, index));
|
|
10554
10638
|
this.disposeContainerSlides();
|
|
10555
10639
|
this.container.replaceChildren();
|
|
@@ -10559,6 +10643,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10559
10643
|
if (!this.isRenderActive(generation) || this.handlesByTarget.get(this.container) !== handle) {
|
|
10560
10644
|
return;
|
|
10561
10645
|
}
|
|
10646
|
+
this.publishZoom(this.scaleForViewport(this.container) * 100);
|
|
10562
10647
|
this.notifySlideChange(this.current);
|
|
10563
10648
|
}
|
|
10564
10649
|
createListPlaceholder(index, item, generation, scale) {
|
|
@@ -10619,7 +10704,8 @@ var NormalizedPresentationViewer = class {
|
|
|
10619
10704
|
Math.min(this.slideCount - 1, options.initialSlideIndex ?? this.current)
|
|
10620
10705
|
);
|
|
10621
10706
|
const scroller = options.scrollElement ?? this.container;
|
|
10622
|
-
|
|
10707
|
+
this.observeViewport(scroller);
|
|
10708
|
+
let effectiveScale = this.scaleForViewport(scroller);
|
|
10623
10709
|
let slideHeight = this.naturalSlideHeight * effectiveScale;
|
|
10624
10710
|
let itemStride = slideHeight + LIST_ITEM_GAP;
|
|
10625
10711
|
if (!windowingEnabled) {
|
|
@@ -10634,6 +10720,8 @@ var NormalizedPresentationViewer = class {
|
|
|
10634
10720
|
const state2 = { generation, options: normalizedOptions, placeholders: placeholders2 };
|
|
10635
10721
|
state2.updateScale = () => {
|
|
10636
10722
|
if (!this.isRenderActive(generation) || this.listState !== state2) return;
|
|
10723
|
+
const previousScale = effectiveScale;
|
|
10724
|
+
const previousScrollLeft = scroller.scrollLeft;
|
|
10637
10725
|
const previousStride = itemStride;
|
|
10638
10726
|
const previousSlideHeight = slideHeight;
|
|
10639
10727
|
const listStart = scroller === this.container ? 0 : this.container.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop;
|
|
@@ -10643,13 +10731,17 @@ var NormalizedPresentationViewer = class {
|
|
|
10643
10731
|
Math.min(this.slideCount - 1, Math.floor(listOffset / previousStride))
|
|
10644
10732
|
);
|
|
10645
10733
|
const anchorOffset = listOffset - anchorIndex * previousStride;
|
|
10646
|
-
effectiveScale = this.scaleForViewport(scroller
|
|
10734
|
+
effectiveScale = this.scaleForViewport(scroller);
|
|
10647
10735
|
slideHeight = this.naturalSlideHeight * effectiveScale;
|
|
10648
10736
|
itemStride = slideHeight + LIST_ITEM_GAP;
|
|
10649
10737
|
placeholders2.forEach((placeholder) => {
|
|
10650
10738
|
placeholder.item.style.minHeight = `${slideHeight}px`;
|
|
10651
10739
|
placeholder.setScale(effectiveScale);
|
|
10652
10740
|
});
|
|
10741
|
+
if (previousScale > 0 && previousScrollLeft > 0) {
|
|
10742
|
+
scroller.scrollLeft = previousScrollLeft * (effectiveScale / previousScale);
|
|
10743
|
+
}
|
|
10744
|
+
this.publishZoom(effectiveScale * 100);
|
|
10653
10745
|
if (listOffset < 0) return;
|
|
10654
10746
|
const nextAnchorOffset = scaleListAnchorOffset(
|
|
10655
10747
|
anchorOffset,
|
|
@@ -10675,6 +10767,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10675
10767
|
initialItem.scrollIntoView?.({ behavior: "instant", block: "start" });
|
|
10676
10768
|
}
|
|
10677
10769
|
this.current = initialIndex;
|
|
10770
|
+
this.publishZoom(effectiveScale * 100);
|
|
10678
10771
|
this.notifySlideChange(initialIndex);
|
|
10679
10772
|
return;
|
|
10680
10773
|
}
|
|
@@ -10818,6 +10911,8 @@ var NormalizedPresentationViewer = class {
|
|
|
10818
10911
|
};
|
|
10819
10912
|
state.updateScale = () => {
|
|
10820
10913
|
if (!isActive()) return;
|
|
10914
|
+
const previousScale = effectiveScale;
|
|
10915
|
+
const previousScrollLeft = scroller.scrollLeft;
|
|
10821
10916
|
const previousStride = itemStride;
|
|
10822
10917
|
const previousSlideHeight = slideHeight;
|
|
10823
10918
|
const anchorIndex = this.current;
|
|
@@ -10827,7 +10922,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10827
10922
|
const previousScrollTop = Math.abs(observedIndex - anchorIndex) > 1 && intendedIndex !== void 0 && Math.abs(intendedIndex - anchorIndex) <= 1 ? lastProgrammaticTop : observedScrollTop;
|
|
10828
10923
|
const previousOffset = previousScrollTop - scrollMargin;
|
|
10829
10924
|
const anchorOffset = previousOffset - anchorIndex * previousStride;
|
|
10830
|
-
effectiveScale = this.scaleForViewport(scroller
|
|
10925
|
+
effectiveScale = this.scaleForViewport(scroller);
|
|
10831
10926
|
slideHeight = this.naturalSlideHeight * effectiveScale;
|
|
10832
10927
|
itemStride = slideHeight + LIST_ITEM_GAP;
|
|
10833
10928
|
sizer.style.height = `${this.slideCount * itemStride - LIST_ITEM_GAP}px`;
|
|
@@ -10836,6 +10931,9 @@ var NormalizedPresentationViewer = class {
|
|
|
10836
10931
|
placeholder.item.style.transform = `translateY(${index * itemStride}px)`;
|
|
10837
10932
|
placeholder.setScale(effectiveScale);
|
|
10838
10933
|
});
|
|
10934
|
+
if (previousScale > 0 && previousScrollLeft > 0) {
|
|
10935
|
+
scroller.scrollLeft = previousScrollLeft * (effectiveScale / previousScale);
|
|
10936
|
+
}
|
|
10839
10937
|
const nextAnchorOffset = scaleListAnchorOffset(
|
|
10840
10938
|
anchorOffset,
|
|
10841
10939
|
previousSlideHeight,
|
|
@@ -10848,6 +10946,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10848
10946
|
writeScrollTop(nextScrollTop);
|
|
10849
10947
|
virtualizer.setOptions({ ...virtualizer.options, overscan });
|
|
10850
10948
|
virtualizer.measure();
|
|
10949
|
+
this.publishZoom(effectiveScale * 100);
|
|
10851
10950
|
};
|
|
10852
10951
|
const teardown = virtualizer._didMount();
|
|
10853
10952
|
this.listCleanup = teardown;
|
|
@@ -10866,6 +10965,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10866
10965
|
this.container.scrollLeft = 0;
|
|
10867
10966
|
}
|
|
10868
10967
|
this.current = initialIndex;
|
|
10968
|
+
this.publishZoom(effectiveScale * 100);
|
|
10869
10969
|
this.notifySlideChange(initialIndex);
|
|
10870
10970
|
}
|
|
10871
10971
|
async goToSlide(index, scrollOptions) {
|
|
@@ -10902,10 +11002,7 @@ var NormalizedPresentationViewer = class {
|
|
|
10902
11002
|
if (!changed && this.container.querySelector(`[data-rpv-slide-index="${next}"]`)) return;
|
|
10903
11003
|
await this.renderSlide(next);
|
|
10904
11004
|
}
|
|
10905
|
-
async
|
|
10906
|
-
const next = Math.max(10, Math.min(400, percent));
|
|
10907
|
-
if (this.zoom === next) return;
|
|
10908
|
-
this.zoom = next;
|
|
11005
|
+
async updateRenderedScale() {
|
|
10909
11006
|
if (this.renderState?.mode === "continuous") {
|
|
10910
11007
|
const state = this.listState;
|
|
10911
11008
|
if (state && this.isRenderActive(state.generation) && state.updateScale) {
|
|
@@ -10915,25 +11012,34 @@ var NormalizedPresentationViewer = class {
|
|
|
10915
11012
|
}
|
|
10916
11013
|
} else if (this.renderState) {
|
|
10917
11014
|
const handle = this.handlesByTarget.get(this.container);
|
|
10918
|
-
if (handle)
|
|
10919
|
-
|
|
11015
|
+
if (handle) {
|
|
11016
|
+
const viewport = this.activeViewport ?? this.container;
|
|
11017
|
+
const previousScale = this.resolvedZoom / 100;
|
|
11018
|
+
const previousScrollTop = viewport.scrollTop;
|
|
11019
|
+
const previousScrollLeft = viewport.scrollLeft;
|
|
11020
|
+
const nextScale = this.scaleForViewport(viewport);
|
|
11021
|
+
handle.setScale(nextScale);
|
|
11022
|
+
if (previousScale > 0) {
|
|
11023
|
+
viewport.scrollTop = previousScrollTop * (nextScale / previousScale);
|
|
11024
|
+
viewport.scrollLeft = previousScrollLeft * (nextScale / previousScale);
|
|
11025
|
+
}
|
|
11026
|
+
this.publishZoom(nextScale * 100);
|
|
11027
|
+
} else await this.renderSlide(this.current);
|
|
11028
|
+
} else {
|
|
11029
|
+
this.publishZoom(this.resolveZoom(this.zoomLevel));
|
|
10920
11030
|
}
|
|
10921
11031
|
}
|
|
10922
|
-
async
|
|
10923
|
-
|
|
10924
|
-
this.
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
if (state && this.isRenderActive(state.generation) && state.updateScale) {
|
|
10928
|
-
state.updateScale();
|
|
10929
|
-
} else {
|
|
10930
|
-
await this.renderList({ ...this.renderState.options, initialSlideIndex: this.current });
|
|
10931
|
-
}
|
|
10932
|
-
} else if (this.renderState) {
|
|
10933
|
-
const handle = this.handlesByTarget.get(this.container);
|
|
10934
|
-
if (handle) handle.setScale(this.scaleForViewport(this.container.clientWidth));
|
|
10935
|
-
else await this.renderSlide(this.current);
|
|
11032
|
+
async setZoom(level) {
|
|
11033
|
+
const next = normalizeViewerZoomLevel(level);
|
|
11034
|
+
if (this.zoomLevel === next) {
|
|
11035
|
+
if (typeof next !== "number") await this.updateRenderedScale();
|
|
11036
|
+
return;
|
|
10936
11037
|
}
|
|
11038
|
+
this.zoomLevel = next;
|
|
11039
|
+
await this.updateRenderedScale();
|
|
11040
|
+
}
|
|
11041
|
+
async setFitMode(mode) {
|
|
11042
|
+
await this.setZoom(mode === "contain" ? "automatic" : 100);
|
|
10937
11043
|
}
|
|
10938
11044
|
searchText(query, options) {
|
|
10939
11045
|
return searchDocument(this.presentation, query, options);
|
|
@@ -11009,6 +11115,9 @@ var NormalizedPresentationViewer = class {
|
|
|
11009
11115
|
this.navigationGeneration += 1;
|
|
11010
11116
|
this.listCleanup?.();
|
|
11011
11117
|
this.listCleanup = void 0;
|
|
11118
|
+
this.resizeObserver?.disconnect();
|
|
11119
|
+
this.resizeObserver = void 0;
|
|
11120
|
+
this.activeViewport = void 0;
|
|
11012
11121
|
this.listState = void 0;
|
|
11013
11122
|
this.clearSearchHighlights();
|
|
11014
11123
|
this.assetCache.release();
|
|
@@ -11353,7 +11462,7 @@ function requestInitKey(value) {
|
|
|
11353
11462
|
return String(value);
|
|
11354
11463
|
}
|
|
11355
11464
|
}
|
|
11356
|
-
async function createAdapter(target, parsed, props, getCurrentProps, onCurrentSlideChange, reportWarning, isCurrent) {
|
|
11465
|
+
async function createAdapter(target, parsed, props, getCurrentProps, onCurrentSlideChange, onZoomChange, reportWarning, isCurrent) {
|
|
11357
11466
|
const fontManager = new PptxFontManager(props.fonts, (warning) => {
|
|
11358
11467
|
if (isCurrent()) reportWarning(warning);
|
|
11359
11468
|
});
|
|
@@ -11372,6 +11481,9 @@ async function createAdapter(target, parsed, props, getCurrentProps, onCurrentSl
|
|
|
11372
11481
|
onSlideChange: (index) => {
|
|
11373
11482
|
if (active()) onCurrentSlideChange(index);
|
|
11374
11483
|
},
|
|
11484
|
+
onZoomChange: (state) => {
|
|
11485
|
+
if (active()) onZoomChange(state);
|
|
11486
|
+
},
|
|
11375
11487
|
onSlideRendered: (index, element) => {
|
|
11376
11488
|
if (!active()) return;
|
|
11377
11489
|
fontManager.applyTo(element, index);
|
|
@@ -11413,8 +11525,8 @@ async function createAdapter(target, parsed, props, getCurrentProps, onCurrentSl
|
|
|
11413
11525
|
);
|
|
11414
11526
|
},
|
|
11415
11527
|
goToSlide: (index, options) => normalized.goToSlide(index, options),
|
|
11416
|
-
setZoom: (
|
|
11417
|
-
|
|
11528
|
+
setZoom: (level) => normalized.setZoom(level),
|
|
11529
|
+
resolveZoom: (level) => normalized.resolveZoom(level),
|
|
11418
11530
|
search: (query, options) => normalized.searchText(query, options),
|
|
11419
11531
|
highlight: (result, options) => normalized.highlightSearchResult(result, options),
|
|
11420
11532
|
clearHighlights: () => normalized.clearSearchHighlights(),
|
|
@@ -11482,7 +11594,7 @@ var ReactPptxViewer = forwardRef(
|
|
|
11482
11594
|
slideIndex: controlledSlide,
|
|
11483
11595
|
initialSlide = 0,
|
|
11484
11596
|
zoom: controlledZoom,
|
|
11485
|
-
defaultZoom
|
|
11597
|
+
defaultZoom,
|
|
11486
11598
|
fitMode = "contain",
|
|
11487
11599
|
showToolbar = false,
|
|
11488
11600
|
showThumbnails = false,
|
|
@@ -11513,6 +11625,7 @@ var ReactPptxViewer = forwardRef(
|
|
|
11513
11625
|
onError,
|
|
11514
11626
|
onWarning,
|
|
11515
11627
|
onSlideChange: _onSlideChange,
|
|
11628
|
+
onZoomChange: _onZoomChange,
|
|
11516
11629
|
onSlideRendered: _onSlideRendered,
|
|
11517
11630
|
onSlideUnmounted: _onSlideUnmounted,
|
|
11518
11631
|
onSearchResults,
|
|
@@ -11531,7 +11644,12 @@ var ReactPptxViewer = forwardRef(
|
|
|
11531
11644
|
const [error, setError] = useState(null);
|
|
11532
11645
|
const [loading, setLoading] = useState(true);
|
|
11533
11646
|
const [internalSlide, setInternalSlide] = useState(initialSlide);
|
|
11534
|
-
const [internalZoom, setInternalZoom] = useState(
|
|
11647
|
+
const [internalZoom, setInternalZoom] = useState(
|
|
11648
|
+
() => normalizeViewerZoomLevel(defaultZoom ?? (fitMode === "contain" ? "automatic" : 100))
|
|
11649
|
+
);
|
|
11650
|
+
const [resolvedZoom, setResolvedZoom] = useState(
|
|
11651
|
+
() => typeof defaultZoom === "number" ? normalizeViewerZoomLevel(defaultZoom) : 100
|
|
11652
|
+
);
|
|
11535
11653
|
const [results, setResults] = useState([]);
|
|
11536
11654
|
const [runtimeWarnings, setRuntimeWarnings] = useState([]);
|
|
11537
11655
|
const virtualizationOptions = typeof virtualization === "object" ? virtualization : {};
|
|
@@ -11545,14 +11663,33 @@ var ReactPptxViewer = forwardRef(
|
|
|
11545
11663
|
const parseFetchInit = parseOptions?.fetchInit;
|
|
11546
11664
|
const parseFetchInitKey = requestInitKey(parseFetchInit);
|
|
11547
11665
|
const slide = clampSlide(controlledSlide ?? internalSlide, parsed?.document.slides.length ?? 0);
|
|
11548
|
-
const zoom = controlledZoom ?? internalZoom;
|
|
11666
|
+
const zoom = normalizeViewerZoomLevel(controlledZoom ?? internalZoom);
|
|
11549
11667
|
const latestSlideRef = useRef(slide);
|
|
11550
11668
|
const latestZoomRef = useRef(zoom);
|
|
11551
|
-
const
|
|
11669
|
+
const latestResolvedZoomRef = useRef(resolvedZoom);
|
|
11670
|
+
const latestControlledZoomRef = useRef(controlledZoom);
|
|
11671
|
+
const lastPublishedZoomRef = useRef(void 0);
|
|
11552
11672
|
const lastViewerSlideRef = useRef(void 0);
|
|
11553
11673
|
latestSlideRef.current = slide;
|
|
11554
11674
|
latestZoomRef.current = zoom;
|
|
11555
|
-
|
|
11675
|
+
latestResolvedZoomRef.current = resolvedZoom;
|
|
11676
|
+
latestControlledZoomRef.current = controlledZoom;
|
|
11677
|
+
const notifyZoomChange = useCallback((state) => {
|
|
11678
|
+
const previous = lastPublishedZoomRef.current;
|
|
11679
|
+
if (previous?.level === state.level && Math.abs(previous.resolvedZoom - state.resolvedZoom) <= 0.01) {
|
|
11680
|
+
return;
|
|
11681
|
+
}
|
|
11682
|
+
lastPublishedZoomRef.current = state;
|
|
11683
|
+
latestPropsRef.current.onZoomChange?.(state);
|
|
11684
|
+
}, []);
|
|
11685
|
+
const publishZoomChange = useCallback(
|
|
11686
|
+
(state) => {
|
|
11687
|
+
setResolvedZoom(state.resolvedZoom);
|
|
11688
|
+
latestResolvedZoomRef.current = state.resolvedZoom;
|
|
11689
|
+
notifyZoomChange(state);
|
|
11690
|
+
},
|
|
11691
|
+
[notifyZoomChange]
|
|
11692
|
+
);
|
|
11556
11693
|
const thumbnailCount = showThumbnails ? parsed?.document.slides.length ?? 0 : 0;
|
|
11557
11694
|
const getThumbnailKey = useCallback(
|
|
11558
11695
|
(index) => parsed?.document.slides[index]?.id ?? index,
|
|
@@ -11593,13 +11730,28 @@ var ReactPptxViewer = forwardRef(
|
|
|
11593
11730
|
block: "center"
|
|
11594
11731
|
});
|
|
11595
11732
|
},
|
|
11596
|
-
async setZoom(
|
|
11597
|
-
const next =
|
|
11733
|
+
async setZoom(level) {
|
|
11734
|
+
const next = normalizeViewerZoomLevel(level);
|
|
11735
|
+
const adapter = adapterRef.current;
|
|
11736
|
+
if (latestControlledZoomRef.current !== void 0) {
|
|
11737
|
+
notifyZoomChange({
|
|
11738
|
+
level: next,
|
|
11739
|
+
resolvedZoom: adapter?.resolveZoom(next) ?? (typeof next === "number" ? next : latestResolvedZoomRef.current)
|
|
11740
|
+
});
|
|
11741
|
+
return;
|
|
11742
|
+
}
|
|
11598
11743
|
setInternalZoom(next);
|
|
11599
|
-
|
|
11744
|
+
latestZoomRef.current = next;
|
|
11745
|
+
if (adapter) await adapter.setZoom(next);
|
|
11746
|
+
else {
|
|
11747
|
+
publishZoomChange({
|
|
11748
|
+
level: next,
|
|
11749
|
+
resolvedZoom: typeof next === "number" ? next : latestResolvedZoomRef.current
|
|
11750
|
+
});
|
|
11751
|
+
}
|
|
11600
11752
|
},
|
|
11601
11753
|
async setFitMode(nextMode) {
|
|
11602
|
-
await
|
|
11754
|
+
await this.setZoom(nextMode === "contain" ? "automatic" : 100);
|
|
11603
11755
|
},
|
|
11604
11756
|
search(query, options) {
|
|
11605
11757
|
return adapterRef.current?.search(query, options) ?? [];
|
|
@@ -11623,9 +11775,10 @@ var ReactPptxViewer = forwardRef(
|
|
|
11623
11775
|
},
|
|
11624
11776
|
getDocument: () => parsed?.document ?? null,
|
|
11625
11777
|
getSlideIndex: () => latestSlideRef.current,
|
|
11626
|
-
getZoom: () => latestZoomRef.current
|
|
11778
|
+
getZoom: () => latestZoomRef.current,
|
|
11779
|
+
getResolvedZoom: () => latestResolvedZoomRef.current
|
|
11627
11780
|
}),
|
|
11628
|
-
[adapterState?.generation, parsed]
|
|
11781
|
+
[adapterState?.generation, notifyZoomChange, parsed, publishZoomChange]
|
|
11629
11782
|
);
|
|
11630
11783
|
useImperativeHandle(forwardedRef, () => controller, [controller]);
|
|
11631
11784
|
useEffect(() => {
|
|
@@ -11699,6 +11852,7 @@ var ReactPptxViewer = forwardRef(
|
|
|
11699
11852
|
setInternalSlide(index);
|
|
11700
11853
|
latestPropsRef.current.onSlideChange?.(index);
|
|
11701
11854
|
},
|
|
11855
|
+
publishZoomChange,
|
|
11702
11856
|
(warning) => {
|
|
11703
11857
|
if (!isCurrent()) return;
|
|
11704
11858
|
setRuntimeWarnings(
|
|
@@ -11720,11 +11874,6 @@ var ReactPptxViewer = forwardRef(
|
|
|
11720
11874
|
adapter.destroy();
|
|
11721
11875
|
return;
|
|
11722
11876
|
}
|
|
11723
|
-
await adapter.setFitMode(latestFitModeRef.current);
|
|
11724
|
-
if (!isCurrent()) {
|
|
11725
|
-
adapter.destroy();
|
|
11726
|
-
return;
|
|
11727
|
-
}
|
|
11728
11877
|
await adapter.render(mode, latestSlideRef.current);
|
|
11729
11878
|
if (!isCurrent()) {
|
|
11730
11879
|
adapter.destroy();
|
|
@@ -11762,7 +11911,7 @@ var ReactPptxViewer = forwardRef(
|
|
|
11762
11911
|
overscanViewport,
|
|
11763
11912
|
batchSize,
|
|
11764
11913
|
scrollElement,
|
|
11765
|
-
|
|
11914
|
+
publishZoomChange
|
|
11766
11915
|
]);
|
|
11767
11916
|
useEffect(() => {
|
|
11768
11917
|
if (adapterState && controlledSlide !== void 0 && slide !== lastViewerSlideRef.current) {
|
|
@@ -11770,13 +11919,12 @@ var ReactPptxViewer = forwardRef(
|
|
|
11770
11919
|
}
|
|
11771
11920
|
}, [adapterState, controlledSlide, slide]);
|
|
11772
11921
|
useEffect(() => {
|
|
11773
|
-
if (adapterState
|
|
11774
|
-
|
|
11775
|
-
}
|
|
11776
|
-
}, [adapterState, controlledZoom, zoom]);
|
|
11922
|
+
if (adapterState) void adapterState.adapter.setZoom(zoom);
|
|
11923
|
+
}, [adapterState, zoom]);
|
|
11777
11924
|
useEffect(() => {
|
|
11778
|
-
if (
|
|
11779
|
-
|
|
11925
|
+
if (controlledZoom !== void 0 || defaultZoom !== void 0) return;
|
|
11926
|
+
setInternalZoom(fitMode === "contain" ? "automatic" : 100);
|
|
11927
|
+
}, [controlledZoom, defaultZoom, fitMode]);
|
|
11780
11928
|
useEffect(() => {
|
|
11781
11929
|
const adapter = adapterState?.adapter;
|
|
11782
11930
|
if (!adapter || searchQuery === void 0 || searchQuery === "") {
|
|
@@ -11853,20 +12001,20 @@ var ReactPptxViewer = forwardRef(
|
|
|
11853
12001
|
"button",
|
|
11854
12002
|
{
|
|
11855
12003
|
type: "button",
|
|
11856
|
-
onClick: () => void controller.setZoom(
|
|
12004
|
+
onClick: () => void controller.setZoom(resolvedZoom - 10),
|
|
11857
12005
|
"aria-label": "Zoom out",
|
|
11858
12006
|
children: "\u2212"
|
|
11859
12007
|
}
|
|
11860
12008
|
),
|
|
11861
12009
|
/* @__PURE__ */ jsxs("span", { className: "rpv-toolbar__count", children: [
|
|
11862
|
-
|
|
12010
|
+
Math.round(resolvedZoom),
|
|
11863
12011
|
"%"
|
|
11864
12012
|
] }),
|
|
11865
12013
|
/* @__PURE__ */ jsx(
|
|
11866
12014
|
"button",
|
|
11867
12015
|
{
|
|
11868
12016
|
type: "button",
|
|
11869
|
-
onClick: () => void controller.setZoom(
|
|
12017
|
+
onClick: () => void controller.setZoom(resolvedZoom + 10),
|
|
11870
12018
|
"aria-label": "Zoom in",
|
|
11871
12019
|
children: "+"
|
|
11872
12020
|
}
|