pptx-react-viewer 4.52.0 → 4.52.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/{chunk-6GAWXARM.js → chunk-2AM5YYWI.js} +107 -119
  3. package/dist/chunk-2AM5YYWI.js.br +0 -0
  4. package/dist/chunk-2AM5YYWI.js.gz +0 -0
  5. package/dist/{chunk-3KXEJCMG.mjs → chunk-6436YER5.mjs} +108 -121
  6. package/dist/chunk-6436YER5.mjs.br +0 -0
  7. package/dist/chunk-6436YER5.mjs.gz +0 -0
  8. package/dist/{chunk-I63IFSNX.js → chunk-JUH4YPMU.js} +1234 -1128
  9. package/dist/chunk-JUH4YPMU.js.br +0 -0
  10. package/dist/chunk-JUH4YPMU.js.gz +0 -0
  11. package/dist/{chunk-E6A6ZBAM.mjs → chunk-L77POU5D.mjs} +170 -64
  12. package/dist/chunk-L77POU5D.mjs.br +0 -0
  13. package/dist/chunk-L77POU5D.mjs.gz +0 -0
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.js +23 -23
  16. package/dist/index.js.br +0 -0
  17. package/dist/index.js.gz +0 -0
  18. package/dist/index.mjs +2 -2
  19. package/dist/index.mjs.br +0 -0
  20. package/dist/index.mjs.gz +0 -0
  21. package/dist/internals.d.ts +26 -6
  22. package/dist/internals.js +80 -80
  23. package/dist/internals.js.br +0 -0
  24. package/dist/internals.js.gz +0 -0
  25. package/dist/internals.mjs +1 -1
  26. package/dist/internals.mjs.br +0 -0
  27. package/dist/internals.mjs.gz +0 -0
  28. package/dist/viewer/index.js +18 -18
  29. package/dist/viewer/index.js.br +0 -0
  30. package/dist/viewer/index.js.gz +0 -0
  31. package/dist/viewer/index.mjs +2 -2
  32. package/dist/viewer/index.mjs.br +0 -0
  33. package/dist/viewer/index.mjs.gz +0 -0
  34. package/package.json +3 -3
  35. package/dist/chunk-3KXEJCMG.mjs.br +0 -0
  36. package/dist/chunk-3KXEJCMG.mjs.gz +0 -0
  37. package/dist/chunk-6GAWXARM.js.br +0 -0
  38. package/dist/chunk-6GAWXARM.js.gz +0 -0
  39. package/dist/chunk-E6A6ZBAM.mjs.br +0 -0
  40. package/dist/chunk-E6A6ZBAM.mjs.gz +0 -0
  41. package/dist/chunk-I63IFSNX.js.br +0 -0
  42. package/dist/chunk-I63IFSNX.js.gz +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ A release listed with no entries carried no Conventional Commit in this package'
7
7
  scope: scripts/release-plan.mjs releases whenever any published file changes, not only on
8
8
  conventional commits.
9
9
 
10
+ ## [4.52.1](https://github.com/ChristopherVR/ooxml/releases/tag/pptx-react-viewer@4.52.1) - 2026-10-25
11
+
12
+ ### Bug Fixes
13
+
14
+ - **pptx:** Preview colour drags as one undo step ([#203](https://github.com/ChristopherVR/ooxml/issues/203)) ([27cc512](https://github.com/ChristopherVR/ooxml/commit/27cc5126cee1c351069e8eb7c2dafe4a0d7806a1))
15
+ - **pptx:** Save hyperlinks to their current targets ([#204](https://github.com/ChristopherVR/ooxml/issues/204)) ([371fe79](https://github.com/ChristopherVR/ooxml/commit/371fe799d88e4158fb7ed895a1e32b0c9b67682e))
16
+
17
+ ### Refactor
18
+
19
+ - **ui:** Run pptx find and replace on one shared session ([#202](https://github.com/ChristopherVR/ooxml/issues/202)) ([61ff51e](https://github.com/ChristopherVR/ooxml/commit/61ff51e2710edad14212132b475652b27bb05d43))
20
+
10
21
  ## [4.52.0](https://github.com/ChristopherVR/ooxml/releases/tag/pptx-react-viewer@4.52.0) - 2026-10-25
11
22
 
12
23
  ### Features
@@ -731,7 +731,11 @@ function useEditorHistory(input) {
731
731
  React17.useEffect(() => {
732
732
  onDirtyRef.current = onDirty;
733
733
  }, [onDirty]);
734
+ const untrackedDepthRef = React17.useRef(0);
734
735
  const markDirty = React17.useCallback(() => {
736
+ if (untrackedDepthRef.current > 0) {
737
+ return;
738
+ }
735
739
  setEditCommitNonce((previous) => previous + 1);
736
740
  onDirtyRef.current?.();
737
741
  }, []);
@@ -748,6 +752,14 @@ function useEditorHistory(input) {
748
752
  },
749
753
  []
750
754
  );
755
+ const withoutUndoStep = React17.useCallback((apply) => {
756
+ untrackedDepthRef.current += 1;
757
+ try {
758
+ apply();
759
+ } finally {
760
+ untrackedDepthRef.current -= 1;
761
+ }
762
+ }, []);
751
763
  const handleUndo = React17.useCallback(() => {
752
764
  if (!history.getSnapshot().canUndo) {
753
765
  return;
@@ -906,6 +918,7 @@ function useEditorHistory(input) {
906
918
  resetHistory,
907
919
  forgetHistory: history.forget,
908
920
  markDirty,
921
+ withoutUndoStep,
909
922
  buildHistorySnapshot
910
923
  };
911
924
  }
@@ -3204,109 +3217,62 @@ function usePresentationAnnotations(input) {
3204
3217
  function useFindReplace({
3205
3218
  slides,
3206
3219
  mode,
3207
- onSetActiveSlideIndex,
3208
- onSetSelectedElementId,
3220
+ onShowMatch,
3209
3221
  onUpdateSlides,
3210
3222
  onMarkDirty,
3211
3223
  keyboard
3212
3224
  }) {
3213
3225
  const [findReplaceOpen, setFindReplaceOpen] = React17.useState(false);
3214
- const [findQuery, setFindQuery] = React17.useState("");
3215
- const [replaceQuery, setReplaceQuery] = React17.useState("");
3216
- const [findMatchCase, setFindMatchCase] = React17.useState(false);
3217
- const [findIncludeNotes, setFindIncludeNotes] = React17.useState(false);
3218
- const [findIncludeChartTitles, setFindIncludeChartTitles] = React17.useState(true);
3219
- const [findIncludeChartData, setFindIncludeChartData] = React17.useState(false);
3220
- const [findResults, setFindResults] = React17.useState([]);
3221
- const [findResultIndex, setFindResultIndex] = React17.useState(-1);
3222
- const pendingRefindRef = React17.useRef(false);
3223
- React17.useEffect(() => {
3224
- if (findReplaceOpen) {
3225
- return;
3226
- }
3227
- setFindResults([]);
3228
- setFindResultIndex(-1);
3229
- pendingRefindRef.current = false;
3230
- }, [findReplaceOpen]);
3231
- const performFind = React17.useCallback(() => {
3232
- const results = pptx.findInSlides(slides, findQuery, {
3233
- matchCase: findMatchCase,
3234
- includeNotes: findIncludeNotes,
3235
- includeChartTitles: findIncludeChartTitles,
3236
- includeChartData: findIncludeChartData
3237
- });
3238
- if (!findQuery) {
3239
- setFindResults([]);
3240
- setFindResultIndex(-1);
3241
- return;
3242
- }
3243
- setFindResults(results);
3244
- setFindResultIndex(results.length > 0 ? 0 : -1);
3245
- if (results.length > 0) {
3246
- onSetActiveSlideIndex(results[0].slideIndex);
3247
- onSetSelectedElementId(results[0].elementId);
3248
- }
3249
- }, [
3250
- slides,
3251
- findQuery,
3252
- findMatchCase,
3253
- findIncludeNotes,
3254
- findIncludeChartTitles,
3255
- findIncludeChartData,
3256
- onSetActiveSlideIndex,
3257
- onSetSelectedElementId
3258
- ]);
3259
- const navigateFindResult = React17.useCallback(
3260
- (direction) => {
3261
- if (findResults.length === 0) {
3262
- return;
3263
- }
3264
- const nextIdx = (findResultIndex + direction + findResults.length) % findResults.length;
3265
- setFindResultIndex(nextIdx);
3266
- const match = findResults[nextIdx];
3267
- if (match) {
3268
- onSetActiveSlideIndex(match.slideIndex);
3269
- onSetSelectedElementId(match.elementId);
3270
- }
3271
- },
3272
- [findResults, findResultIndex, onSetActiveSlideIndex, onSetSelectedElementId]
3273
- );
3274
- const applyReplacements = React17.useCallback(
3275
- (toReplace) => {
3276
- if (toReplace.length === 0) {
3277
- return;
3278
- }
3279
- if (toReplace.some((match) => match.readOnly)) {
3280
- return;
3226
+ const [session, setSession] = React17.useState(pptx.INITIAL_FIND_REPLACE_SESSION);
3227
+ const latest = React17.useRef({ slides, onShowMatch, onUpdateSlides, onMarkDirty });
3228
+ latest.current = { slides, onShowMatch, onUpdateSlides, onMarkDirty };
3229
+ const latestSession = React17.useRef(session);
3230
+ const [actions] = React17.useState(
3231
+ () => pptx.findReplaceSessionActions(
3232
+ {
3233
+ get: () => latestSession.current,
3234
+ set: (next) => {
3235
+ latestSession.current = next;
3236
+ setSession(next);
3237
+ }
3238
+ },
3239
+ {
3240
+ slides: () => latest.current.slides,
3241
+ commit: (next) => {
3242
+ latest.current.onUpdateSlides(() => next);
3243
+ latest.current.onMarkDirty();
3244
+ },
3245
+ navigate: ({ slideIndex, elementId }) => latest.current.onShowMatch(slideIndex, elementId)
3281
3246
  }
3282
- onUpdateSlides(
3283
- (prevSlides) => pptx.applyFindReplacements(prevSlides, toReplace, replaceQuery).slides
3284
- );
3285
- onMarkDirty();
3286
- },
3287
- [replaceQuery, onUpdateSlides, onMarkDirty]
3247
+ )
3288
3248
  );
3289
- const handleReplace = React17.useCallback(() => {
3290
- if (findResults.length === 0 || findResultIndex < 0) {
3291
- return;
3292
- }
3293
- applyReplacements([findResults[findResultIndex]]);
3294
- pendingRefindRef.current = true;
3295
- }, [findResults, findResultIndex, applyReplacements]);
3296
- const handleReplaceAll = React17.useCallback(() => {
3297
- if (findResults.length === 0) {
3298
- return;
3299
- }
3300
- applyReplacements(findResults);
3301
- pendingRefindRef.current = true;
3302
- }, [findResults, applyReplacements]);
3303
3249
  React17.useEffect(() => {
3304
- if (!pendingRefindRef.current) {
3305
- return;
3250
+ if (!findReplaceOpen) {
3251
+ actions.close();
3306
3252
  }
3307
- pendingRefindRef.current = false;
3308
- performFind();
3309
- }, [performFind]);
3253
+ }, [findReplaceOpen, actions]);
3254
+ React17.useEffect(() => {
3255
+ actions.slidesChanged();
3256
+ }, [slides, actions]);
3257
+ const handlers = React17.useMemo(
3258
+ () => ({
3259
+ setFindQuery: (query) => actions.search({ query }),
3260
+ setReplaceQuery: actions.setReplacement,
3261
+ setFindMatchCase: (matchCase) => actions.search({ options: { matchCase } }),
3262
+ setFindIncludeNotes: (includeNotes) => actions.search({ options: { includeNotes } }),
3263
+ setFindIncludeChartTitles: (includeChartTitles) => actions.search({ options: { includeChartTitles } }),
3264
+ setFindIncludeChartData: (includeChartData) => actions.search({ options: { includeChartData } }),
3265
+ performFind: () => actions.search(),
3266
+ navigateFindResult: (direction) => direction > 0 ? actions.next() : actions.previous(),
3267
+ handleReplace: () => {
3268
+ actions.replaceCurrent();
3269
+ },
3270
+ handleReplaceAll: () => {
3271
+ actions.replaceAll();
3272
+ }
3273
+ }),
3274
+ [actions]
3275
+ );
3310
3276
  React17.useEffect(() => {
3311
3277
  const handler = (event) => {
3312
3278
  const { action } = pptx.mapCustomizedEditorKey(
@@ -3329,24 +3295,15 @@ function useFindReplace({
3329
3295
  return {
3330
3296
  findReplaceOpen,
3331
3297
  setFindReplaceOpen,
3332
- findQuery,
3333
- setFindQuery,
3334
- replaceQuery,
3335
- setReplaceQuery,
3336
- findMatchCase,
3337
- setFindMatchCase,
3338
- findIncludeNotes,
3339
- setFindIncludeNotes,
3340
- findIncludeChartTitles,
3341
- findIncludeChartData,
3342
- setFindIncludeChartTitles,
3343
- setFindIncludeChartData,
3344
- findResults,
3345
- findResultIndex,
3346
- performFind,
3347
- navigateFindResult,
3348
- handleReplace,
3349
- handleReplaceAll
3298
+ findQuery: session.query,
3299
+ replaceQuery: session.replacement,
3300
+ findMatchCase: session.options.matchCase,
3301
+ findIncludeNotes: session.options.includeNotes,
3302
+ findIncludeChartTitles: session.options.includeChartTitles,
3303
+ findIncludeChartData: session.options.includeChartData,
3304
+ findResults: session.matches,
3305
+ findResultIndex: session.current,
3306
+ ...handlers
3350
3307
  };
3351
3308
  }
3352
3309
  function useModalDismissDrag(onClose, threshold = 120) {
@@ -4006,6 +3963,35 @@ function useInlineEditingState(onTextChange) {
4006
3963
  registerInlineEditReader
4007
3964
  };
4008
3965
  }
3966
+ function useSlideChangeSelection({
3967
+ setActiveSlideIndex,
3968
+ setSelectedElementId,
3969
+ setSelectedElementIds
3970
+ }) {
3971
+ const slideSelectionRef = React17.useRef(null);
3972
+ const showSlideSelection = React17.useCallback(
3973
+ (slideIndex, elementId) => {
3974
+ slideSelectionRef.current = slideIndex;
3975
+ setActiveSlideIndex(slideIndex);
3976
+ setSelectedElementId(elementId);
3977
+ setSelectedElementIds([]);
3978
+ },
3979
+ [setActiveSlideIndex, setSelectedElementId, setSelectedElementIds]
3980
+ );
3981
+ return { slideSelectionRef, showSlideSelection };
3982
+ }
3983
+ function useClearSelectionOnSlideChange(state, activeSlideIndex) {
3984
+ React17.useEffect(() => {
3985
+ const kept = state.slideSelectionRef.current === activeSlideIndex;
3986
+ state.slideSelectionRef.current = null;
3987
+ state.setInlineEditingElementId(null);
3988
+ if (kept) {
3989
+ return;
3990
+ }
3991
+ state.setSelectedElementId(null);
3992
+ state.setSelectedElementIds([]);
3993
+ }, [activeSlideIndex]);
3994
+ }
4009
3995
  function useSlideState() {
4010
3996
  const [renderedSlides, setRenderedSlides] = React17.useState([]);
4011
3997
  const slidesRef = React17.useRef(renderedSlides);
@@ -4045,6 +4031,11 @@ function useViewerCoreState(_input) {
4045
4031
  const [activeSlideIndex, setActiveSlideIndex] = React17.useState(0);
4046
4032
  const [selectedElementId, setSelectedElementId] = React17.useState(null);
4047
4033
  const [selectedElementIds, setSelectedElementIds] = React17.useState([]);
4034
+ const slideChangeSelection = useSlideChangeSelection({
4035
+ setActiveSlideIndex,
4036
+ setSelectedElementId,
4037
+ setSelectedElementIds
4038
+ });
4048
4039
  const [isDirty, setIsDirty] = React17.useState(false);
4049
4040
  const autosaveDraftSinkRef = React17.useRef(null);
4050
4041
  const publishInlineText = React17.useCallback(
@@ -4148,6 +4139,7 @@ function useViewerCoreState(_input) {
4148
4139
  setSelectedElementId,
4149
4140
  selectedElementIds,
4150
4141
  setSelectedElementIds,
4142
+ ...slideChangeSelection,
4151
4143
  isDirty,
4152
4144
  setIsDirty,
4153
4145
  editTemplateMode,
@@ -9801,8 +9793,7 @@ function useEditorOperations(input) {
9801
9793
  const findReplace = useFindReplace({
9802
9794
  slides,
9803
9795
  mode,
9804
- onSetActiveSlideIndex: state.setActiveSlideIndex,
9805
- onSetSelectedElementId: state.setSelectedElementId,
9796
+ onShowMatch: state.showSlideSelection,
9806
9797
  onUpdateSlides: ops.updateSlides,
9807
9798
  onMarkDirty: history.markDirty,
9808
9799
  keyboard
@@ -12876,11 +12867,7 @@ function useViewerBuildingBlocksState(input) {
12876
12867
  });
12877
12868
  const readOnlyRec = useReadOnlyRecommendationState(content);
12878
12869
  const compatToastsState = useCompatibilityToastsState();
12879
- React17.useEffect(() => {
12880
- state.setSelectedElementId(null);
12881
- state.setSelectedElementIds([]);
12882
- state.setInlineEditingElementId(null);
12883
- }, [activeSlideIndex]);
12870
+ useClearSelectionOnSlideChange(state, activeSlideIndex);
12884
12871
  const editorOps = useEditorOperations({
12885
12872
  state,
12886
12873
  history,
@@ -18763,6 +18750,7 @@ exports.useBroadcastFollower = useBroadcastFollower;
18763
18750
  exports.useCanvasInteractions = useCanvasInteractions;
18764
18751
  exports.useChartFormatContext = useChartFormatContext;
18765
18752
  exports.useChartPartSelection = useChartPartSelection;
18753
+ exports.useClearSelectionOnSlideChange = useClearSelectionOnSlideChange;
18766
18754
  exports.useClipboardHandlers = useClipboardHandlers;
18767
18755
  exports.useCollaboration = useCollaboration;
18768
18756
  exports.useCollaborationDocumentSync = useCollaborationDocumentSync;
Binary file
Binary file