pptx-angular-viewer 2.6.0 → 2.6.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 CHANGED
@@ -4,6 +4,8 @@ All notable changes to this project are documented here.
4
4
  This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
5
5
  by [git-cliff](https://git-cliff.org); do not edit it by hand.
6
6
 
7
+ ## [2.6.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@2.6.0) - 2026-07-27
8
+
7
9
  ## [2.5.3](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@2.5.3) - 2026-07-27
8
10
 
9
11
  ### Dependencies
@@ -1,4 +1,4 @@
1
- import { t as toChatSummary } from './pptx-angular-viewer-pptx-angular-viewer-DflEskoR.mjs';
1
+ import { t as toChatSummary } from './pptx-angular-viewer-pptx-angular-viewer-xlxMwvvj.mjs';
2
2
 
3
3
  /**
4
4
  * IndexedDB backend for {@link createChatHistoryStore}. Kept in its own module
@@ -103,4 +103,4 @@ function createIdbBackend(db) {
103
103
  }
104
104
 
105
105
  export { CHAT_STORE, createIdbBackend, openChatDb };
106
- //# sourceMappingURL=pptx-angular-viewer-chat-history-idb-_19vnONP.mjs.map
106
+ //# sourceMappingURL=pptx-angular-viewer-chat-history-idb-BvftE8pq.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pptx-angular-viewer-chat-history-idb-_19vnONP.mjs","sources":["../../src/internal/shared-src/ai/chat-history-idb.ts"],"sourcesContent":["/**\n * IndexedDB backend for {@link createChatHistoryStore}. Kept in its own module\n * so the localStorage fallback and the public factory stay within the per-file\n * size budget. Uses the raw IndexedDB API with tiny promise wrappers so no new\n * runtime dependency is pulled in.\n *\n * Every browser global is touched lazily from inside a function, never at module\n * load, so importing this file in a non-DOM environment (Node, SSR) never throws.\n */\n\nimport type { ChatBackend, PptxAiChatSummary, PptxAiStoredChat } from './chat-history-store';\nimport { toChatSummary } from './chat-history-store';\n\n/** Object store holding one record per chat, keyed by `id`. */\nexport const CHAT_STORE = 'chats';\n/** Index over the optional `deckId` key path, used for per-deck filtering. */\nconst DECK_INDEX = 'deckId';\n\n/** Resolve an `IDBRequest` to a promise. */\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n\treturn new Promise<T>((resolve, reject) => {\n\t\trequest.onsuccess = () => resolve(request.result);\n\t\trequest.onerror = () => reject(request.error ?? new Error('IndexedDB request failed.'));\n\t});\n}\n\n/** Resolve when a transaction commits (or reject on error/abort). */\nfunction transactionDone(tx: IDBTransaction): Promise<void> {\n\treturn new Promise<void>((resolve, reject) => {\n\t\ttx.oncomplete = () => resolve();\n\t\ttx.onerror = () => reject(tx.error ?? new Error('IndexedDB transaction failed.'));\n\t\ttx.onabort = () => reject(tx.error ?? new Error('IndexedDB transaction aborted.'));\n\t});\n}\n\n/**\n * Open (and if needed create/upgrade) the chat database. Throws when there is no\n * `indexedDB` global so the caller can transparently fall back to localStorage.\n */\nexport function openChatDb(dbName: string): Promise<IDBDatabase> {\n\tconst idb = typeof indexedDB !== 'undefined' ? indexedDB : undefined;\n\tif (!idb) {\n\t\tthrow new Error('IndexedDB is not available in this environment.');\n\t}\n\treturn new Promise<IDBDatabase>((resolve, reject) => {\n\t\tconst open = idb.open(dbName, 1);\n\t\topen.onupgradeneeded = () => {\n\t\t\tconst db = open.result;\n\t\t\tif (!db.objectStoreNames.contains(CHAT_STORE)) {\n\t\t\t\tconst store = db.createObjectStore(CHAT_STORE, { keyPath: 'id' });\n\t\t\t\tstore.createIndex(DECK_INDEX, 'deckId', { unique: false });\n\t\t\t}\n\t\t};\n\t\topen.onsuccess = () => resolve(open.result);\n\t\topen.onerror = () => reject(open.error ?? new Error('Failed to open IndexedDB.'));\n\t\topen.onblocked = () => reject(new Error('IndexedDB open blocked by another connection.'));\n\t});\n}\n\n/** Read every stored chat (newest-first ordering is applied by the caller). */\nasync function readAll(db: IDBDatabase, deckId: string | undefined): Promise<PptxAiStoredChat[]> {\n\tconst tx = db.transaction(CHAT_STORE, 'readonly');\n\tconst store = tx.objectStore(CHAT_STORE);\n\tconst source =\n\t\tdeckId === undefined\n\t\t\t? store.getAll()\n\t\t\t: store.index(DECK_INDEX).getAll(IDBKeyRange.only(deckId));\n\tconst rows = await requestToPromise<PptxAiStoredChat[]>(source);\n\tawait transactionDone(tx);\n\treturn rows;\n}\n\n/** Create an IndexedDB-backed {@link ChatBackend}. */\nexport function createIdbBackend(db: IDBDatabase): ChatBackend {\n\treturn {\n\t\tasync list(deckId: string | undefined): Promise<PptxAiChatSummary[]> {\n\t\t\tconst rows = await readAll(db, deckId);\n\t\t\treturn rows.map(toChatSummary).sort((a, b) => b.updatedAt - a.updatedAt);\n\t\t},\n\t\tasync load(id: string): Promise<PptxAiStoredChat | null> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readonly');\n\t\t\tconst row = await requestToPromise<PptxAiStoredChat | undefined>(\n\t\t\t\ttx.objectStore(CHAT_STORE).get(id),\n\t\t\t);\n\t\t\tawait transactionDone(tx);\n\t\t\treturn row ?? null;\n\t\t},\n\t\tasync save(chat: PptxAiStoredChat): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\ttx.objectStore(CHAT_STORE).put(chat);\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t\tasync remove(id: string): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\ttx.objectStore(CHAT_STORE).delete(id);\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t\tasync clear(deckId: string | undefined): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\tconst store = tx.objectStore(CHAT_STORE);\n\t\t\tif (deckId === undefined) {\n\t\t\t\tstore.clear();\n\t\t\t} else {\n\t\t\t\tconst ids = await requestToPromise<IDBValidKey[]>(\n\t\t\t\t\tstore.index(DECK_INDEX).getAllKeys(IDBKeyRange.only(deckId)),\n\t\t\t\t);\n\t\t\t\tfor (const id of ids) {\n\t\t\t\t\tstore.delete(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t};\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pptx-angular-viewer-chat-history-idb-BvftE8pq.mjs","sources":["../../src/internal/shared-src/ai/chat-history-idb.ts"],"sourcesContent":["/**\n * IndexedDB backend for {@link createChatHistoryStore}. Kept in its own module\n * so the localStorage fallback and the public factory stay within the per-file\n * size budget. Uses the raw IndexedDB API with tiny promise wrappers so no new\n * runtime dependency is pulled in.\n *\n * Every browser global is touched lazily from inside a function, never at module\n * load, so importing this file in a non-DOM environment (Node, SSR) never throws.\n */\n\nimport type { ChatBackend, PptxAiChatSummary, PptxAiStoredChat } from './chat-history-store';\nimport { toChatSummary } from './chat-history-store';\n\n/** Object store holding one record per chat, keyed by `id`. */\nexport const CHAT_STORE = 'chats';\n/** Index over the optional `deckId` key path, used for per-deck filtering. */\nconst DECK_INDEX = 'deckId';\n\n/** Resolve an `IDBRequest` to a promise. */\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n\treturn new Promise<T>((resolve, reject) => {\n\t\trequest.onsuccess = () => resolve(request.result);\n\t\trequest.onerror = () => reject(request.error ?? new Error('IndexedDB request failed.'));\n\t});\n}\n\n/** Resolve when a transaction commits (or reject on error/abort). */\nfunction transactionDone(tx: IDBTransaction): Promise<void> {\n\treturn new Promise<void>((resolve, reject) => {\n\t\ttx.oncomplete = () => resolve();\n\t\ttx.onerror = () => reject(tx.error ?? new Error('IndexedDB transaction failed.'));\n\t\ttx.onabort = () => reject(tx.error ?? new Error('IndexedDB transaction aborted.'));\n\t});\n}\n\n/**\n * Open (and if needed create/upgrade) the chat database. Throws when there is no\n * `indexedDB` global so the caller can transparently fall back to localStorage.\n */\nexport function openChatDb(dbName: string): Promise<IDBDatabase> {\n\tconst idb = typeof indexedDB !== 'undefined' ? indexedDB : undefined;\n\tif (!idb) {\n\t\tthrow new Error('IndexedDB is not available in this environment.');\n\t}\n\treturn new Promise<IDBDatabase>((resolve, reject) => {\n\t\tconst open = idb.open(dbName, 1);\n\t\topen.onupgradeneeded = () => {\n\t\t\tconst db = open.result;\n\t\t\tif (!db.objectStoreNames.contains(CHAT_STORE)) {\n\t\t\t\tconst store = db.createObjectStore(CHAT_STORE, { keyPath: 'id' });\n\t\t\t\tstore.createIndex(DECK_INDEX, 'deckId', { unique: false });\n\t\t\t}\n\t\t};\n\t\topen.onsuccess = () => resolve(open.result);\n\t\topen.onerror = () => reject(open.error ?? new Error('Failed to open IndexedDB.'));\n\t\topen.onblocked = () => reject(new Error('IndexedDB open blocked by another connection.'));\n\t});\n}\n\n/** Read every stored chat (newest-first ordering is applied by the caller). */\nasync function readAll(db: IDBDatabase, deckId: string | undefined): Promise<PptxAiStoredChat[]> {\n\tconst tx = db.transaction(CHAT_STORE, 'readonly');\n\tconst store = tx.objectStore(CHAT_STORE);\n\tconst source =\n\t\tdeckId === undefined\n\t\t\t? store.getAll()\n\t\t\t: store.index(DECK_INDEX).getAll(IDBKeyRange.only(deckId));\n\tconst rows = await requestToPromise<PptxAiStoredChat[]>(source);\n\tawait transactionDone(tx);\n\treturn rows;\n}\n\n/** Create an IndexedDB-backed {@link ChatBackend}. */\nexport function createIdbBackend(db: IDBDatabase): ChatBackend {\n\treturn {\n\t\tasync list(deckId: string | undefined): Promise<PptxAiChatSummary[]> {\n\t\t\tconst rows = await readAll(db, deckId);\n\t\t\treturn rows.map(toChatSummary).sort((a, b) => b.updatedAt - a.updatedAt);\n\t\t},\n\t\tasync load(id: string): Promise<PptxAiStoredChat | null> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readonly');\n\t\t\tconst row = await requestToPromise<PptxAiStoredChat | undefined>(\n\t\t\t\ttx.objectStore(CHAT_STORE).get(id),\n\t\t\t);\n\t\t\tawait transactionDone(tx);\n\t\t\treturn row ?? null;\n\t\t},\n\t\tasync save(chat: PptxAiStoredChat): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\ttx.objectStore(CHAT_STORE).put(chat);\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t\tasync remove(id: string): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\ttx.objectStore(CHAT_STORE).delete(id);\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t\tasync clear(deckId: string | undefined): Promise<void> {\n\t\t\tconst tx = db.transaction(CHAT_STORE, 'readwrite');\n\t\t\tconst store = tx.objectStore(CHAT_STORE);\n\t\t\tif (deckId === undefined) {\n\t\t\t\tstore.clear();\n\t\t\t} else {\n\t\t\t\tconst ids = await requestToPromise<IDBValidKey[]>(\n\t\t\t\t\tstore.index(DECK_INDEX).getAllKeys(IDBKeyRange.only(deckId)),\n\t\t\t\t);\n\t\t\t\tfor (const id of ids) {\n\t\t\t\t\tstore.delete(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait transactionDone(tx);\n\t\t},\n\t};\n}\n"],"names":[],"mappings":"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"}
@@ -25941,6 +25941,7 @@ function buildParagraphs(element, fieldContext) {
25941
25941
  // Suppress bullets for paragraphs with no visible text content.
25942
25942
  const hasVisibleTextContent = paraSegments.some((seg) => seg !== markerSegment && Boolean(seg.text) && seg.text.trim().length > 0);
25943
25943
  const bullet = hasVisibleTextContent ? bulletResult : undefined;
25944
+ const indent = resolveParagraphIndent(paragraphIndents?.[paraIndex], firstSeg?.paragraphLevel);
25944
25945
  const bulletStyle = {};
25945
25946
  if (bullet) {
25946
25947
  if (bullet.color) {
@@ -25956,8 +25957,25 @@ function buildParagraphs(element, fieldContext) {
25956
25957
  else if (typeof bullet.sizePercent === 'number' && typeof runFontSize === 'number') {
25957
25958
  bulletStyle.fontSize = `${runFontSize * (bullet.sizePercent / 100)}px`;
25958
25959
  }
25960
+ // PowerPoint draws the marker at `marL + indent` and starts the text
25961
+ // at `marL`, so the marker's box is exactly the hanging distance
25962
+ // wide. Reserving it here is what makes the runs line up on the
25963
+ // indent stop instead of butting straight against the glyph, and it
25964
+ // removes the need for a spacer character after the marker: a
25965
+ // non-breaking space inherits the marker's font, and Wingdings maps
25966
+ // U+00A0 to a visible dot, which painted a second bullet
25967
+ // (issue #131, slides 13-14).
25968
+ const hangPx = typeof indent.textIndentPx === 'number' && indent.textIndentPx < 0
25969
+ ? -indent.textIndentPx
25970
+ : undefined;
25971
+ bulletStyle.display = 'inline-block';
25972
+ if (hangPx !== undefined) {
25973
+ bulletStyle.minWidth = `${hangPx}px`;
25974
+ }
25975
+ else {
25976
+ bulletStyle.marginInlineEnd = '0.35em';
25977
+ }
25959
25978
  }
25960
- const indent = resolveParagraphIndent(paragraphIndents?.[paraIndex], firstSeg?.paragraphLevel);
25961
25979
  const spacing = resolveParagraphSpacing$1(firstSeg?.paragraphProperties);
25962
25980
  const strutFontSizePx = resolveParagraphStrutFontSize(paraSegments, hasTextProperties(element) ? element.textStyle?.fontSize : undefined);
25963
25981
  return {
@@ -25973,10 +25991,22 @@ function buildParagraphs(element, fieldContext) {
25973
25991
  strutFontSizePx,
25974
25992
  };
25975
25993
  });
25976
- return result.filter((p) => p.runs.length > 0 ||
25977
- p.bulletMarker !== undefined ||
25978
- p.bulletPicture !== undefined ||
25979
- result.length === 1);
25994
+ const hasContent = (p) => p.runs.length > 0 || p.bulletMarker !== undefined || p.bulletPicture !== undefined;
25995
+ // An authored blank line between two paragraphs is real vertical spacing in
25996
+ // PowerPoint and has to survive to the renderer. Blank paragraphs AFTER the
25997
+ // last content are dropped: the load and edit-remap paths both leave a
25998
+ // trailing separator behind, and honouring those would grow every text body
25999
+ // (and shift anything vertically centred) for markup the deck never drew.
26000
+ let lastContent = -1;
26001
+ for (let i = 0; i < result.length; i++) {
26002
+ if (hasContent(result[i])) {
26003
+ lastContent = i;
26004
+ }
26005
+ }
26006
+ if (lastContent < 0) {
26007
+ return result.length === 1 ? result : [];
26008
+ }
26009
+ return result.slice(0, lastContent + 1).map((p) => (hasContent(p) ? p : { ...p, isEmpty: true }));
25980
26010
  }
25981
26011
 
25982
26012
  // ---------------------------------------------------------------------------
@@ -26515,16 +26545,23 @@ function matchMorphElementsFull(fromSlide, toSlide) {
26515
26545
  }
26516
26546
  }
26517
26547
  }
26518
- // Pass 2: match by element ID
26548
+ // Pass 2: match by the shape's native OOXML id (`p:cNvPr/@id`), which
26549
+ // PowerPoint preserves when a slide is duplicated and is what it pairs on.
26550
+ //
26551
+ // This deliberately does NOT compare `element.id`: that is the loader's
26552
+ // synthetic identity and embeds the slide path
26553
+ // (`ppt/slides/slide3.xml-shape-1`), so it can never be equal across two
26554
+ // slides and the pass was dead code. `shapeId` is only unique WITHIN a
26555
+ // slide, hence the `usedFrom`/`usedTo` guards below.
26519
26556
  for (const fromEl of fromSlide.elements) {
26520
- if (usedFrom.has(fromEl.id)) {
26557
+ if (usedFrom.has(fromEl.id) || !fromEl.shapeId) {
26521
26558
  continue;
26522
26559
  }
26523
26560
  for (const toEl of toSlide.elements) {
26524
26561
  if (usedTo.has(toEl.id)) {
26525
26562
  continue;
26526
26563
  }
26527
- if (fromEl.id === toEl.id) {
26564
+ if (toEl.shapeId && fromEl.shapeId === toEl.shapeId && fromEl.type === toEl.type) {
26528
26565
  pairs.push({ fromElement: fromEl, toElement: toEl });
26529
26566
  usedFrom.add(fromEl.id);
26530
26567
  usedTo.add(toEl.id);
@@ -26932,6 +26969,45 @@ function buildStrokeInterpolationProps(fromElement, toElement) {
26932
26969
  };
26933
26970
  }
26934
26971
  // ---------------------------------------------------------------------------
26972
+ // Appearance comparison (drives the matched-pair crossfade)
26973
+ // ---------------------------------------------------------------------------
26974
+ /**
26975
+ * A compact description of everything about an element that is actually
26976
+ * PAINTED, used to decide whether a matched morph pair has to crossfade.
26977
+ *
26978
+ * Two matched shapes that differ only in geometry can simply glide (the
26979
+ * incoming element is already the right colour). Two that differ in fill,
26980
+ * outline, picture or text look like a hard cut if we just swap them, because
26981
+ * the outgoing appearance is never drawn: the incoming element is rendered at
26982
+ * its final appearance from the very first frame.
26983
+ */
26984
+ function appearanceSignature(element) {
26985
+ const parts = [element.type];
26986
+ if (hasShapeProperties(element)) {
26987
+ const style = element.shapeStyle;
26988
+ parts.push(element.shapeType ?? '', style?.fillMode ?? '', style?.fillColor ?? '', style?.fillGradient ?? '', String(style?.fillOpacity ?? ''), style?.strokeColor ?? '', String(style?.strokeWidth ?? ''));
26989
+ }
26990
+ const image = element;
26991
+ parts.push(image.imagePath ?? '', image.svgPath ?? '');
26992
+ if (hasTextProperties(element)) {
26993
+ parts.push(element.text ?? '', element.textStyle?.color ?? '');
26994
+ }
26995
+ return parts.join('');
26996
+ }
26997
+ /**
26998
+ * Whether a matched pair needs a crossfade rather than a plain glide.
26999
+ *
27000
+ * PowerPoint's Morph dissolves a shape's appearance into its counterpart's
27001
+ * while it travels. Without this, a deck whose slides are near-duplicates (the
27002
+ * usual Morph authoring pattern: duplicate the slide, then restyle one shape)
27003
+ * appeared to have no transition at all, because every persisting shape was
27004
+ * painted in its FINAL state on frame 1 and only the handful of genuinely new
27005
+ * or departing shapes faded (issue #131).
27006
+ */
27007
+ function morphPairNeedsCrossfade(fromElement, toElement) {
27008
+ return appearanceSignature(fromElement) !== appearanceSignature(toElement);
27009
+ }
27010
+ // ---------------------------------------------------------------------------
26935
27011
  // Generate CSS keyframes for morph pairs
26936
27012
  // ---------------------------------------------------------------------------
26937
27013
  /**
@@ -26958,10 +27034,14 @@ function generateMorphAnimations(pairs, durationMs, _mode = 'object') {
26958
27034
  const dr = (fromElement.rotation ?? 0) - (toElement.rotation ?? 0);
26959
27035
  const fromOpacity = fromElement.opacity ?? 1;
26960
27036
  const toOpacity = toElement.opacity ?? 1;
27037
+ // A pair whose appearance changes fades IN over its outgoing ghost (see
27038
+ // `generateMorphGhostAnimations`); one that only moves stays fully
27039
+ // opaque so the glide reads as a single continuous object.
27040
+ const crossfades = morphPairNeedsCrossfade(fromElement, toElement);
26961
27041
  // Build from/to property blocks
26962
27042
  const fromProps = [
26963
27043
  `\t\ttransform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${dr}deg);`,
26964
- `\t\topacity: ${fromOpacity};`,
27044
+ `\t\topacity: ${crossfades ? 0 : fromOpacity};`,
26965
27045
  ];
26966
27046
  const toProps = [
26967
27047
  '\t\ttransform: translate(0, 0) scale(1, 1) rotate(0deg);',
@@ -26996,6 +27076,67 @@ ${toProps.join('\n')}
26996
27076
  }
26997
27077
  return animations;
26998
27078
  }
27079
+ /**
27080
+ * Generate the OUTGOING half of every matched pair.
27081
+ *
27082
+ * The returned animations target the outgoing element, which a binding paints
27083
+ * in its transition overlay above the live stage. Each ghost travels the same
27084
+ * path as its incoming counterpart - from its own geometry to the pair's final
27085
+ * geometry - so the overlay stays a faithful, moving copy of the outgoing
27086
+ * slide for the whole transition.
27087
+ *
27088
+ * A pair whose APPEARANCE changed fades to nothing on the way, dissolving into
27089
+ * the counterpart rendered underneath. A pair that only moved keeps its opacity
27090
+ * and simply lands on the incoming geometry, where the two are pixel-identical
27091
+ * and the overlay can be torn down without a visible seam. Emitting the second
27092
+ * kind matters because the overlay is a flat layer above the stage: a
27093
+ * full-slide background that IS crossfading would otherwise hide every
27094
+ * unchanged shape until it had faded, making them pop in mid-transition.
27095
+ *
27096
+ * `transform-origin` is pinned to the element's own centre in canvas
27097
+ * coordinates because the overlay wrapper spans the whole slide: without it a
27098
+ * `scale()` would pivot around the slide centre and drag the ghost across the
27099
+ * canvas.
27100
+ *
27101
+ * @param pairs - Matched pairs.
27102
+ * @param durationMs - Animation duration in milliseconds.
27103
+ * @param startIndex - Index offset for unique keyframe naming.
27104
+ * @returns Ghost animation descriptors keyed by the OUTGOING element id.
27105
+ */
27106
+ function generateMorphGhostAnimations(pairs, durationMs, startIndex) {
27107
+ const animations = [];
27108
+ for (let index = 0; index < pairs.length; index++) {
27109
+ const { fromElement, toElement } = pairs[index];
27110
+ const fadesOut = morphPairNeedsCrossfade(fromElement, toElement);
27111
+ const safeName = `pptx-morph-ghost-${startIndex + index}-${fromElement.id.replace(/[^a-zA-Z0-9]/gu, '')}`;
27112
+ const dx = toElement.x - fromElement.x;
27113
+ const dy = toElement.y - fromElement.y;
27114
+ const sx = Math.max(toElement.width, 1) / Math.max(fromElement.width, 1);
27115
+ const sy = Math.max(toElement.height, 1) / Math.max(fromElement.height, 1);
27116
+ const dr = (toElement.rotation ?? 0) - (fromElement.rotation ?? 0);
27117
+ const originX = fromElement.x + fromElement.width / 2;
27118
+ const originY = fromElement.y + fromElement.height / 2;
27119
+ const keyframes = `
27120
+ @keyframes ${safeName} {
27121
+ \tfrom {
27122
+ \t\ttransform-origin: ${originX}px ${originY}px;
27123
+ \t\ttransform: translate(0, 0) scale(1, 1) rotate(0deg);
27124
+ \t\topacity: ${fromElement.opacity ?? 1};
27125
+ \t}
27126
+ \tto {
27127
+ \t\ttransform-origin: ${originX}px ${originY}px;
27128
+ \t\ttransform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${dr}deg);
27129
+ \t\topacity: ${fadesOut ? 0 : (fromElement.opacity ?? 1)};
27130
+ \t}
27131
+ }`;
27132
+ animations.push({
27133
+ elementId: fromElement.id,
27134
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
27135
+ keyframes,
27136
+ });
27137
+ }
27138
+ return animations;
27139
+ }
26999
27140
  /**
27000
27141
  * Generate fade-out animations for elements that only exist on the outgoing slide.
27001
27142
  *
@@ -27117,11 +27258,14 @@ function generateFullMorphTransition(fromSlide, toSlide, durationMs, mode = 'obj
27117
27258
  }
27118
27259
  }
27119
27260
  }
27261
+ // Outgoing half of every restyled pair's crossfade.
27262
+ const ghosts = generateMorphGhostAnimations(matchResult.pairs, durationMs, pairAnims.length);
27263
+ allAnimations.push(...ghosts);
27120
27264
  // Generate fade-out for unmatched from elements
27121
- const fadeOuts = generateUnmatchedFadeOutAnimations(matchResult.unmatchedFrom, durationMs, pairAnims.length);
27265
+ const fadeOuts = generateUnmatchedFadeOutAnimations(matchResult.unmatchedFrom, durationMs, pairAnims.length + ghosts.length);
27122
27266
  allAnimations.push(...fadeOuts);
27123
27267
  // Generate fade-in for unmatched to elements
27124
- const fadeIns = generateUnmatchedFadeInAnimations(matchResult.unmatchedTo, durationMs, pairAnims.length + fadeOuts.length);
27268
+ const fadeIns = generateUnmatchedFadeInAnimations(matchResult.unmatchedTo, durationMs, pairAnims.length + ghosts.length + fadeOuts.length);
27125
27269
  allAnimations.push(...fadeIns);
27126
27270
  return allAnimations;
27127
27271
  }
@@ -27153,12 +27297,26 @@ function buildMorphTransitionPlan(fromSlide, toSlide, durationMs, mode = 'object
27153
27297
  return undefined;
27154
27298
  }
27155
27299
  const animations = generateFullMorphTransition(fromSlide, toSlide, durationMs, mode);
27156
- // Only the unmatched-FROM ids belong to the outgoing slide; every other
27157
- // animation targets an element the incoming slide already renders. Element
27158
- // ids embed their slide path, so the two id spaces do not overlap, but
27159
- // partitioning on this set (rather than on id shape) keeps that an
27300
+ // The overlay paints the outgoing slide as a moving copy of itself, in the
27301
+ // slide's own document order so its z-stacking is preserved:
27302
+ //
27303
+ // - shapes with no counterpart fade out in place;
27304
+ // - a matched pair's outgoing half glides onto its counterpart, dissolving
27305
+ // into it when the appearance changed and simply landing on it when only
27306
+ // the geometry did.
27307
+ //
27308
+ // Painting the unchanged halves too is what keeps a full-slide background
27309
+ // from hiding them: the overlay is one flat layer above the live stage, so
27310
+ // anything left out of it is invisible behind a crossfading backdrop until
27311
+ // that backdrop has faded. Before this, a near-duplicate slide pair (the
27312
+ // usual Morph authoring pattern) cut straight to its final look on frame 1
27313
+ // and looked like no transition at all (issue #131).
27314
+ //
27315
+ // Element ids embed their slide path, so the two id spaces do not overlap,
27316
+ // but partitioning on this set (rather than on id shape) keeps that an
27160
27317
  // implementation detail of core rather than an assumption here.
27161
- const outgoingIds = new Set(match.unmatchedFrom.map((element) => element.id));
27318
+ const outgoingElements = [...fromSlide.elements];
27319
+ const outgoingIds = new Set(outgoingElements.map((element) => element.id));
27162
27320
  const incomingAnimations = new Map();
27163
27321
  const outgoingAnimations = new Map();
27164
27322
  const keyframes = [];
@@ -27175,7 +27333,7 @@ function buildMorphTransitionPlan(fromSlide, toSlide, durationMs, mode = 'object
27175
27333
  keyframesCss: keyframes.join('\n'),
27176
27334
  incomingAnimations,
27177
27335
  outgoingAnimations,
27178
- outgoingElements: match.unmatchedFrom,
27336
+ outgoingElements,
27179
27337
  durationMs,
27180
27338
  };
27181
27339
  }
@@ -52504,7 +52662,7 @@ function createLocalStorageBackend(namespace) {
52504
52662
  /** Try IndexedDB first; fall back to localStorage on any failure. */
52505
52663
  async function resolveBackend(dbName, namespace) {
52506
52664
  try {
52507
- const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-_19vnONP.mjs');
52665
+ const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-BvftE8pq.mjs');
52508
52666
  const db = await openChatDb(dbName);
52509
52667
  return createIdbBackend(db);
52510
52668
  }
@@ -60332,6 +60490,12 @@ function resolveShapeFilterCss(fxFilter, duotone, softEdge) {
60332
60490
  function getDuotoneFilterDef(el) {
60333
60491
  return buildDuotoneFilter(el);
60334
60492
  }
60493
+ /**
60494
+ * Default text-body insets, in px. Mirrors React's `DEFAULT_BODY_INSET_*_PX`
60495
+ * (PowerPoint defaults: 0.1" left/right, 0.05" top/bottom → EMU / EMU_PER_PIXEL).
60496
+ */
60497
+ const DEFAULT_BODY_INSET_LR_PX = 91440 / 9525;
60498
+ const DEFAULT_BODY_INSET_TB_PX = 45720 / 9525;
60335
60499
  /**
60336
60500
  * Absolute container style: position, size, rotation, flip, opacity, z-index.
60337
60501
  * Mirrors the essentials of the React `getContainerStyle`.
@@ -60496,8 +60660,18 @@ function getTextBlockStyle(el) {
60496
60660
  };
60497
60661
  if (!ts) {
60498
60662
  style['color'] = DEFAULT_TEXT_COLOR$1;
60663
+ style['padding'] = `${DEFAULT_BODY_INSET_TB_PX}px ${DEFAULT_BODY_INSET_LR_PX}px`;
60499
60664
  return style;
60500
60665
  }
60666
+ // Text-body insets (`a:bodyPr/@lIns|tIns|rIns|bIns`). Angular painted text
60667
+ // flush against the shape edge because it never applied them, so a panel
60668
+ // authored with a 0.2" inset had its whole text block hard against the
60669
+ // border (issue #131, slides 13-14). React/Vue/Svelte/Vanilla already do
60670
+ // this; the defaults match PowerPoint's own.
60671
+ style['padding-top'] = `${ts.bodyInsetTop ?? DEFAULT_BODY_INSET_TB_PX}px`;
60672
+ style['padding-bottom'] = `${ts.bodyInsetBottom ?? DEFAULT_BODY_INSET_TB_PX}px`;
60673
+ style['padding-left'] = `${ts.bodyInsetLeft ?? DEFAULT_BODY_INSET_LR_PX}px`;
60674
+ style['padding-right'] = `${ts.bodyInsetRight ?? DEFAULT_BODY_INSET_LR_PX}px`;
60501
60675
  style['color'] = ts.color ?? DEFAULT_TEXT_COLOR$1;
60502
60676
  if (ts.fontFamily) {
60503
60677
  style['font-family'] = ts.fontFamily;
@@ -68566,10 +68740,16 @@ class ElementRendererComponent {
68566
68740
  ? [{ runs: [{ text: el.text, style: {} }], bulletStyle: {}, indentPx: 0 }]
68567
68741
  : [];
68568
68742
  }
68743
+ const paragraphIndents = el.paragraphIndents;
68569
68744
  const out = [{ runs: [], bulletStyle: {}, indentPx: 0 }];
68570
68745
  let paraStarted = false;
68571
68746
  for (const seg of segments) {
68572
- if (seg.isParagraphBreak) {
68747
+ // A bare `"\n"` segment is the slide-LOAD path's paragraph separator;
68748
+ // `isParagraphBreak` is only set by the edit remap. Matching on the
68749
+ // former alone meant a freshly loaded deck arrived here as a single
68750
+ // paragraph, so only its first line got a bullet and every authored
68751
+ // blank line vanished (issue #131). Mirrors shared `buildParagraphs`.
68752
+ if (seg.isParagraphBreak || (seg.text === '\n' && !seg.isLineBreak)) {
68573
68753
  out.push({ runs: [], bulletStyle: {}, indentPx: 0 });
68574
68754
  paraStarted = false;
68575
68755
  continue;
@@ -68578,7 +68758,9 @@ class ElementRendererComponent {
68578
68758
  // The first segment of each paragraph carries its bullet + outline level.
68579
68759
  if (!paraStarted) {
68580
68760
  paraStarted = true;
68581
- current.indentPx = bulletIndentPx(seg.paragraphLevel);
68761
+ const indent = resolveParagraphIndent(paragraphIndents?.[out.length - 1], seg.paragraphLevel);
68762
+ current.indentPx = indent.marginLeftPx ?? 0;
68763
+ current.textIndentPx = indent.textIndentPx;
68582
68764
  // Per-paragraph line-height / space-before / space-after from this
68583
68765
  // paragraph's own `a:pPr` (#69), mirroring shared `buildParagraphs`.
68584
68766
  const spacing = resolveParagraphSpacing(seg.paragraphProperties);
@@ -68597,6 +68779,27 @@ class ElementRendererComponent {
68597
68779
  current.bulletMarker = bullet.marker;
68598
68780
  current.bulletPicture = bullet.picture;
68599
68781
  Object.assign(current.bulletStyle, bullet.style);
68782
+ // PowerPoint draws the marker at `marL + indent` and starts
68783
+ // the text at `marL`, so the marker's box is exactly the
68784
+ // hanging distance wide. Reserving it lines the runs up on
68785
+ // the indent stop and removes the need for a spacer after
68786
+ // the glyph. Mirrors shared `buildParagraphs`.
68787
+ current.bulletStyle['display'] = 'inline-block';
68788
+ if (indent.textIndentPx !== undefined && indent.textIndentPx < 0) {
68789
+ current.bulletStyle['min-width'] = `${-indent.textIndentPx}px`;
68790
+ }
68791
+ else {
68792
+ current.bulletStyle['margin-inline-end'] = '0.35em';
68793
+ }
68794
+ // The slide-load path inserts a DEDICATED marker segment whose
68795
+ // text is the precomputed glyph; the marker is rendered from
68796
+ // `bulletMarker` above, so keeping the segment as a run painted
68797
+ // the bullet twice. A run that merely carries `bulletInfo` but
68798
+ // holds real content (the edit-remap path) is kept. Mirrors
68799
+ // shared `buildParagraphs`.
68800
+ if (seg.bulletInfo && bullet.marker && seg.text.trim() === bullet.marker.trim()) {
68801
+ continue;
68802
+ }
68600
68803
  }
68601
68804
  }
68602
68805
  if (seg.equationXml) {
@@ -68641,10 +68844,26 @@ class ElementRendererComponent {
68641
68844
  p.strutFontSizePx = undefined;
68642
68845
  }
68643
68846
  }
68644
- return out.filter((p) => p.runs.length > 0 ||
68645
- p.bulletMarker !== undefined ||
68646
- p.bulletPicture !== undefined ||
68647
- out.length === 1);
68847
+ // An authored blank line between two paragraphs is real vertical spacing
68848
+ // and must survive; blank paragraphs AFTER the last content are dropped,
68849
+ // since both the load and edit-remap paths leave a trailing separator
68850
+ // behind. Mirrors shared `buildParagraphs`.
68851
+ const hasContent = (p) => p.runs.length > 0 || p.bulletMarker !== undefined || p.bulletPicture !== undefined;
68852
+ let lastContent = -1;
68853
+ for (let i = 0; i < out.length; i++) {
68854
+ if (hasContent(out[i])) {
68855
+ lastContent = i;
68856
+ }
68857
+ }
68858
+ if (lastContent < 0) {
68859
+ return out.length === 1 ? out : [];
68860
+ }
68861
+ return out.slice(0, lastContent + 1).map((p) => {
68862
+ if (!hasContent(p)) {
68863
+ p.isEmpty = true;
68864
+ }
68865
+ return p;
68866
+ });
68648
68867
  }, /* @ts-ignore */
68649
68868
  ...(ngDevMode ? [{ debugName: "paragraphs" }] : /* istanbul ignore next */ []));
68650
68869
  hasText = computed(() => this.paragraphs().some((p) => p.runs.length > 0 || p.bulletMarker !== undefined || p.bulletPicture !== undefined), /* @ts-ignore */
@@ -68852,6 +69071,7 @@ class ElementRendererComponent {
68852
69071
  <p
68853
69072
  class="pptx-ng-para"
68854
69073
  [style.padding-left.px]="para.indentPx"
69074
+ [style.text-indent.px]="para.textIndentPx ?? null"
68855
69075
  [style.line-height]="para.lineHeight ?? null"
68856
69076
  [style.margin-top.px]="para.spaceBeforePx ?? null"
68857
69077
  [style.margin-bottom.px]="para.spaceAfterPx ?? null"
@@ -68869,7 +69089,7 @@ class ElementRendererComponent {
68869
69089
  } @else if (para.bulletMarker) {
68870
69090
  <span class="pptx-ng-bullet" [ngStyle]="para.bulletStyle"
68871
69091
  [attr.aria-label]="para.bulletPicture?.accessibleLabel ?? null"
68872
- >{{ para.bulletMarker }}&nbsp;</span
69092
+ >{{ para.bulletMarker }}</span
68873
69093
  >
68874
69094
  }
68875
69095
  @if (textBuildSpecs()[$index]; as spec) {
@@ -68918,6 +69138,12 @@ class ElementRendererComponent {
68918
69138
  }
68919
69139
  }
68920
69140
  }
69141
+ @if (para.isEmpty) {
69142
+ <!-- An authored blank line has no runs, so without this the
69143
+ <p> collapses to zero height and the gap a deck puts
69144
+ between a heading and its bullet list disappears. -->
69145
+ <br />
69146
+ }
68921
69147
  </p>
68922
69148
  }
68923
69149
  </div>
@@ -69213,6 +69439,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
69213
69439
  <p
69214
69440
  class="pptx-ng-para"
69215
69441
  [style.padding-left.px]="para.indentPx"
69442
+ [style.text-indent.px]="para.textIndentPx ?? null"
69216
69443
  [style.line-height]="para.lineHeight ?? null"
69217
69444
  [style.margin-top.px]="para.spaceBeforePx ?? null"
69218
69445
  [style.margin-bottom.px]="para.spaceAfterPx ?? null"
@@ -69230,7 +69457,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
69230
69457
  } @else if (para.bulletMarker) {
69231
69458
  <span class="pptx-ng-bullet" [ngStyle]="para.bulletStyle"
69232
69459
  [attr.aria-label]="para.bulletPicture?.accessibleLabel ?? null"
69233
- >{{ para.bulletMarker }}&nbsp;</span
69460
+ >{{ para.bulletMarker }}</span
69234
69461
  >
69235
69462
  }
69236
69463
  @if (textBuildSpecs()[$index]; as spec) {
@@ -69279,6 +69506,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
69279
69506
  }
69280
69507
  }
69281
69508
  }
69509
+ @if (para.isEmpty) {
69510
+ <!-- An authored blank line has no runs, so without this the
69511
+ <p> collapses to zero height and the gap a deck puts
69512
+ between a heading and its bullet list disappears. -->
69513
+ <br />
69514
+ }
69282
69515
  </p>
69283
69516
  }
69284
69517
  </div>
@@ -79175,9 +79408,11 @@ class PresentationTransitionOverlayComponent {
79175
79408
  * Active Morph plan, or `undefined` for every other transition.
79176
79409
  *
79177
79410
  * Morph travels individual shapes between the two slides rather than wiping
79178
- * the surface, so it changes what this overlay paints: only the shapes with
79179
- * no counterpart on the arriving slide. The ones that persist are animated
79180
- * in place on the live stage by document-level rules (see `morphStyleEffect`).
79411
+ * the surface, so it changes what this overlay paints: a per-shape copy of
79412
+ * the outgoing slide, each one gliding onto its counterpart (dissolving into
79413
+ * it when its appearance changed) or fading out in place when it has none.
79414
+ * The incoming halves are animated on the live stage by document-level rules
79415
+ * (see `morphStyleEffect`).
79181
79416
  */
79182
79417
  morphPlan = computed(() => this.transition().type === 'morph'
79183
79418
  ? buildMorphTransitionPlan(this.outgoingSlide(), this.incomingSlide(), this.resolvedDurationMs(), morphOptionToMode(this.transition().morphOption))
@@ -85059,7 +85294,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
85059
85294
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }] } });
85060
85295
 
85061
85296
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
85062
- const PPTX_ANGULAR_VIEWER_VERSION = "2.5.3";
85297
+ const PPTX_ANGULAR_VIEWER_VERSION = "2.6.0";
85063
85298
 
85064
85299
  /**
85065
85300
  * account-page.component.ts: File > Account content.
@@ -113913,4 +114148,4 @@ function cn(...values) {
113913
114148
  */
113914
114149
 
113915
114150
  export { DATA_TABLE_KEY_W as $, ALIGN_OPTIONS as A, BroadcastDialogComponent as B, CHART_EDITOR_STYLES as C, ChartAxisOptionsComponent as D, ChartAxisStyleOptionsComponent as E, ChartComboTypeOptionsComponent as F, ChartDataEditorComponent as G, ChartDataLabelOptionsComponent as H, ChartDatapointOptionsComponent as I, ChartDisplayOptionsComponent as J, ChartElementViewComponent as K, ChartErrorBarOptionsComponent as L, ChartMarkerOptionsComponent as M, ChartPartSelectionService as N, ChartPrimitivesComponent as O, ChartRendererComponent as P, ChartTrendlineOptionsComponent as Q, CollaborationCursorsComponent as R, CollaborationService as S, ColorChangedImageComponent as T, CommentsPanelComponent as U, CommentsService as V, ComparePanelComponent as W, ConnectorRendererComponent as X, ConnectorTextOverlayComponent as Y, CustomShowsComponent as Z, DATA_TABLE_HEADER_H as _, AUDIENCE_HASH as a, MIN_ZOOM_SCALE as a$, DATA_TABLE_PADDING as a0, DATA_TABLE_ROW_H as a1, DEFAULT_BOUNDS as a2, DEFAULT_BROADCAST_SERVER_URL as a3, DEFAULT_CANVAS_HEIGHT as a4, DEFAULT_CANVAS_WIDTH as a5, DEFAULT_COLOR_SCHEME as a6, DEFAULT_FILL_COLOR as a7, DEFAULT_LAYOUT as a8, DEFAULT_PALETTE$1 as a9, ExportProgressModalComponent as aA, ExportService as aB, FieldContextService as aC, FindBarComponent as aD, FindReplaceBarComponent as aE, FollowModeBarComponent as aF, FontEmbeddingListComponent as aG, FontEmbeddingPanelComponent as aH, GALLERY_THEME_PRESETS as aI, GradientPickerComponent as aJ, HANDOUT_OPTIONS as aK, HeaderFooterDialogComponent as aL, HyperlinkDialogComponent as aM, ImagePropertiesPanelComponent as aN, InkDrawingService as aO, InkRendererComponent as aP, InsertSmartArtDialogComponent as aQ, InspectorPaneHeaderComponent as aR, InspectorPanelComponent as aS, IsMobileService as aT, KeepAnnotationsDialogComponent as aU, LOCALE_CATALOG as aV, LONG_PRESS_DURATION_MS as aW, LONG_PRESS_MOVE_TOLERANCE_PX as aX, LoadContentService as aY, LocalPresencePublisher as aZ, MAX_ZOOM_SCALE as a_, DEFAULT_PRINT_SETTINGS as aa, DEFAULT_SLIDE_BACKGROUND as ab, DEFAULT_STROKE_COLOR as ac, DEFAULT_STYLE as ad, DEFAULT_TABLE_ROW_HEIGHT as ae, DEFAULT_TEXT_COLOR$1 as af, DEFAULT_VIEWER_PROFILE as ag, DIRECTIONAL_PRESETS as ah, DIRECTION_OPTIONS as ai, DocumentPropertiesCardComponent as aj, EMBEDDED_FONTS_STYLE_ID as ak, EMPHASIS_PRESETS as al, ENTRANCE_PRESETS as am, TEMPLATES as an, EXIT_PRESETS as ao, EditorContextMenuComponent as ap, EditorHistory as aq, EditorStateService as ar, EditorToolbarComponent as as, EffectsPanelComponent as at, ElementRendererComponent as au, EmbeddedFontsService as av, EncryptedFileDialogComponent as aw, EquationEditorDialogComponent as ax, EquationRendererComponent as ay, EquationTemplateGalleryComponent as az, AUDIENCE_NONCE_KEY as b, SLIDE_PX_PER_INCH as b$, MediaPreviewComponent as b0, MediaPropertiesPanelComponent as b1, MediaRendererComponent as b2, MediaTrimTimelineComponent as b3, MobileBottomBarComponent as b4, MobileMenuSheetComponent as b5, MobilePresenterViewComponent as b6, MobileSheetComponent as b7, MobileSlidesSheetComponent as b8, MobileToolbarComponent as b9, RESIZE_HANDLES as bA, RULER_THICKNESS as bB, RemoteSelectionOverlayComponent as bC, RibbonAnimationsSectionComponent as bD, RibbonArrangeSectionComponent as bE, RibbonColorPopoverComponent as bF, RibbonComponent as bG, RibbonDesignSectionComponent as bH, RibbonDrawSectionComponent as bI, RibbonDrawingGroupComponent as bJ, RibbonEditingSectionComponent as bK, RibbonFileSectionComponent as bL, RibbonFontControlsComponent as bM, RibbonHomeSectionComponent as bN, RibbonInsertFieldsComponent as bO, RibbonInsertSectionComponent as bP, RibbonParagraphControlsComponent as bQ, RibbonPrimaryRowComponent as bR, RibbonReviewSectionComponent as bS, RibbonSlideshowSectionComponent as bT, RibbonTransitionsSectionComponent as bU, RibbonViewSectionComponent as bV, RulerGuidesService as bW, SEQUENCE_OPTIONS as bX, SEVERITY_GROUPS as bY, SEVERITY_LABELS as bZ, SHORTCUT_REFERENCE_ITEMS as b_, ModalDialogComponent as ba, Model3DRendererComponent as bb, NotesHandoutCardComponent as bc, NotesPanelComponent as bd, NotesToolbarComponent as be, OleRendererComponent as bf, POWER_POINT_VIEWER_PROVIDERS as bg, PRESENTER_CHANNEL_NAME as bh, PRESENTER_MSG_ORIGIN as bi, PasswordProtectionDialogComponent as bj, PasswordStrengthMeterComponent as bk, PowerPointViewerComponent as bl, PresentationAnnotationOverlayComponent as bm, PresentationAnnotationsService as bn, PresentationOverlayComponent as bo, PresentationPropertiesPanelComponent as bp, PresentationSettingsCardComponent as bq, PresentationSubtitleBarComponent as br, PresentationTransitionOverlayComponent as bs, PresenterViewComponent as bt, PresenterWindowService as bu, PrintDialogComponent as bv, PrintService as bw, PrintSettingsPanelComponent as bx, PropertiesDialogComponent as by, REPEAT_MODE_OPTIONS as bz, AVATAR_COLOR_SWATCHES as c, ViewerDocumentPropertiesService as c$, SLIDE_TRANSITION_KEYFRAMES as c0, DEFAULT_PALETTE as c1, PALETTES$1 as c2, SMART_ART_COLOR_SCHEMES as c3, SMART_ART_STYLE_OPTIONS as c4, SUB_ITEM_LABEL as c5, SVG_WARP_PRESETS as c6, SWIPE_MAX_VERTICAL_PX as c7, SWIPE_THRESHOLD_PX as c8, SelectionPaneComponent as c9, TABLE_STRUCTURE_TOGGLES as cA, TEXT_DIRECTION_OPTIONS$1 as cB, THEME_CATALOG as cC, TIMING_CURVE_OPTIONS as cD, TRIGGER_OPTIONS as cE, TYPE_LABELS as cF, TableCellAdvancedFillComponent as cG, TableCellFormattingComponent as cH, TableDataEditorComponent as cI, TablePropertiesComponent as cJ, TableRendererComponent as cK, TableResizeOverlayComponent as cL, TableSelectionService as cM, TextAdvancedPanelComponent as cN, ThemeEditorFieldsComponent as cO, ThemeGalleryComponent as cP, ThemeSelectorCardComponent as cQ, TitleBarComponent as cR, VALIGN_OPTIONS as cS, VIEWER_THEME as cT, VersionHistoryPanelComponent as cU, ViewerCanvasEditingService as cV, ViewerCollabCursorService as cW, ViewerCollaborationSessionService as cX, ViewerCompareService as cY, ViewerCustomShowsService as cZ, ViewerDialogsService as c_, SetUpSlideShowDialogComponent as ca, SettingsAppearanceTabComponent as cb, SettingsDialogComponent as cc, SettingsLanguageTabComponent as cd, ShareDialogComponent as ce, ShortcutPanelComponent as cf, ShowOptionsFieldsetComponent as cg, ShowSlidesFieldsetComponent as ch, SignatureStrippedDialogComponent as ci, SignaturesPanelComponent as cj, SignaturesService as ck, SlideCanvasComponent as cl, SlideDefaultInspectorComponent as cm, SlideDiffChangesComponent as cn, SlideDiffRowComponent as co, SlideDiffThumbnailsComponent as cp, SlideSizeCardComponent as cq, SlideSorterOverlayComponent as cr, SlideThemeOverridePanelComponent as cs, SlidesPanelComponent as ct, SmartArt3DRendererComponent as cu, SmartArt3DService as cv, SmartArtPreviewComponent as cw, SmartArtPropertiesComponent as cx, SmartArtRendererComponent as cy, StatusBarComponent as cz, AccessibilityPanelComponent as d, buildFallbackViewModel as d$, ViewerExportService as d0, ViewerExtraDialogsComponent as d1, ViewerFileIOService as d2, ViewerFindReplaceService as d3, ViewerFormatPainterService as d4, ViewerInspectorPanelService as d5, ViewerKeyboardService as d6, ViewerMobileSheetService as d7, ViewerPresentationModeService as d8, ViewerThemeGalleryService as d9, asMediaElement as dA, assignUserColor as dB, attachTouchGestures as dC, beginNodeEdit as dD, boolFromEvent as dE, bringForward as dF, bringToFront as dG, buildBarActions as dH, buildBroadcastConfig as dI, buildBroadcastViewerUrl as dJ, buildCategoryLabels as dK, buildCellParagraphs as dL, buildChartViewModel as dM, buildChatLogExport as dN, buildChatLogMarkdown as dO, buildChromeStyle as dP, buildClearHyperlinkPatch as dQ, buildClickGroups as dR, buildColStyles as dS, buildCollaborationConfig as dT, buildComboViewModel as dU, buildCssGradientFromShapeStyle as dV, buildDuotoneFilter as dW, buildDuotoneFilterId as dX, buildEmbeddedFontStyles as dY, buildEquationElement as dZ, buildEquationSegment as d_, ViewerTouchGesturesService as da, ViewerZoomService as db, WEBM_MIME_CANDIDATES as dc, WriteBackScheduler as dd, ZoomNavigationService as de, ZoomRendererComponent as df, ZoomTargetService as dg, addCategory as dh, addCommentToList as di, addGradientStopPatch as dj, addItem as dk, addSeries as dl, addSubItem as dm, advanceStep as dn, aiToggleVisible as dp, alignPatch as dq, animationFor as dr, annotationMapToInkInserts as ds, applyAcceptedDiff as dt, applyAnimationPreset as du, applyFindReplacements as dv, applyFormatToElement as dw, applyMove as dx, applyResize as dy, applyTableStylePreset as dz, AccessibilityService as e, computeDataTablePrimitives as e$, buildFontFaceRule as e0, buildGradientFillCss as e1, buildGridlinesAndLabels as e2, buildHyperlinkPatch as e3, buildInkContainerStyle as e4, buildInkStrokes as e5, buildLegend as e6, buildModel3DContainerStyle as e7, buildModel3DViewModel as e8, buildOleActionModel as e9, cellStyleToStyleMap as eA, cellTdStyle as eB, changeCountLabel as eC, changeIcon as eD, characterSpacingPatch as eE, checkFontAvailable as eF, clampCursorPosition as eG, clampGifDimensions as eH, clampIndex as eI, clampNotesFontSize as eJ, clampScale as eK, clampStep as eL, clearAllLocalViewerData as eM, clearAudienceContent as eN, cn as eO, collectAccessibilityIssues as eP, collectElementText as eQ, collectSlideText as eR, collectStoredChats as eS, collectUsedFontFamilies as eT, columnWidthStyle as eU, commitNodeText as eV, computeAlign as eW, computeAxisTitlePrimitives as eX, computeBarRects as eY, computeBubbleRadius as eZ, computeCornerHandle as e_, buildOleInfoRows as ea, buildPatternFillCss as eb, buildPrintHtmlDocument as ec, buildPropertiesPatch as ed, buildRegionMapViewModel as ee, buildSaveSlides as ef, buildShareUrl as eg, buildSmartArtInsertElement as eh, buildSmartArtNodes as ei, buildStockViewModel as ej, buildSurfaceViewModel as ek, buildTableViewModel as el, buildTreemapViewModel as em, buildTrimFragment as en, buildWaterfallViewModel as eo, buildZeroLine as ep, buildZoomContainerStyle as eq, buildZoomViewModel as er, bulletIndentPx as es, canAddTopLevelNode as et, canRemoveTopLevelNode as eu, canStartBroadcast as ev, canStartShare as ew, canUseClipboard as ex, captionDisplayText as ey, cellRunStyle as ez, AccountPageComponent as f, encodeGif as f$, computeDistribute as f0, computeDrawingViewBox as f1, computeErrorBarPrimitives as f2, computeFocusTargets as f3, computeHandleBoxes as f4, computeHandoutLayout as f5, computeIsMobile as f6, computeIsTablet as f7, computeLinePoints as f8, computeLinearRegression as f9, createWebsocketBundle as fA, cssObjectToStyleMap as fB, currentColorScheme as fC, currentLayout as fD, currentStyle as fE, defaultCssVars as fF, defaultRadius as fG, defaultThemeColors as fH, deleteElementsByIds as fI, deleteVersion as fJ, demoteNode as fK, deriveModel3DBlobUrl as fL, derivePresenceList as fM, describeSmartArtBounds as fN, disableGlowPatch as fO, disableInnerShadowPatch as fP, disableOuterShadowPatch as fQ, disableReflectionPatch as fR, disableSoftEdgePatch as fS, duplicateElementById as fT, durationOf as fU, effectsStateOf as fV, enableGlowPatch as fW, enableInnerShadowPatch as fX, enableOuterShadowPatch as fY, enableReflectionPatch as fZ, enableSoftEdgePatch as f_, computePageCount as fa, computePieLayout as fb, computePieSlicePath as fc, computePieSlices as fd, computePlotLayout as fe, computeRSquared as ff, computeRadarPoints as fg, computeScatterDots as fh, computeSelectionBoxes as fi, computeSingleSelected as fj, computeSlideIndices as fk, computeSnap as fl, computeStackedBarRects as fm, computeStackedValueRange as fn, computeTextLines as fo, computeTimerProgress as fp, computeTrendlinePrimitives as fq, computeValueRange as fr, convertOmmlToMathMl as fs, copyFormatFromElement as ft, countAccessibilityIssues as fu, countAnnotationStrokes as fv, createAngularAiBridge as fw, createCustomShow as fx, createSwipeDismissDrag as fy, createWebrtcBundle as fz, ActionSettingsPanelComponent as g, hasAnimation as g$, estimatePageCount as g0, evenColumnWidths as g1, evenRowHeights as g2, exitPresentationFullscreen as g3, exportAiChatLogs as g4, extractPathPoints as g5, eyedropperAvailable as g6, fillColorOf as g7, findInSlides as g8, findOwningSlideIndex as g9, getOleBadgeLabel as gA, getOleDisplayName as gB, getOleDownloadFileName as gC, getOleTypeColor as gD, getOleTypeLabel as gE, getPasswordStrength as gF, getPatternSvg as gG, getPlaceholderStyle as gH, getVersions as gI, getResolvedShapeClipPath as gJ, getResolvedShapeClipPathFor as gK, getShapeFillStrokeStyle as gL, getSlideBackgroundStyle as gM, getSlideTransitionAnimations as gN, getSmartArtNodeBounds as gO, getSpeechRecognitionCtor as gP, getTextBlockStyle as gQ, getTextWarp as gR, getTouchDistance as gS, getWarpCategory as gT, getWarpPath as gU, gradientStateFromStyle as gV, gradientStateOf as gW, gradientStatePatch as gX, gridColumns as gY, groupElements as gZ, groupIssuesBySeverity as g_, findSlideIndexByElementId as ga, fitPolynomial as gb, fitZoom as gc, focusTargetChips as gd, fontMimeForFormat as ge, fontSizeOf as gf, formatAutoNumber as gg, formatAxisValue as gh, formatBytes as gi, formatCursorLabel as gj, formatElapsed as gk, formatFileSize as gl, formatPropertyDate as gm, formatTime as gn, fpsToFrameIntervalMs as go, generateBroadcastRoomId as gp, generateCommentId as gq, generateCustomShowId as gr, generatePressureCircles as gs, generateRulerTicks as gt, getClrChangeParams as gu, getContainerStyle as gv, getDuotoneFilterDef as gw, getImageSrc as gx, getLocalStorageUsageSummary as gy, getOleAriaLabel as gz, AdvancedChartEditorComponent as h, normalizeValue as h$, hasCopyableFormat as h0, hasExistingLink as h1, hasExitedFullscreen as h2, hasGradientFill as h3, hasPressureVariation as h4, hasVisibleSlideAfter as h5, headerLabel as h6, inkViewBox as h7, insertColumn as h8, insertRow as h9, mergeDown as hA, mergeRight as hB, mergeSelection as hC, moveElementBy as hD, moveNodeDown as hE, moveNodeUp as hF, msToFrameDelayCs as hG, narrowToCircle as hH, narrowToPolygon as hI, narrowToRect as hJ, newChartElement as hK, newEquationElement as hL, newPresetShapeElement as hM, newShapeElement as hN, newSmartArtElement as hO, newTableElement as hP, newTextElement as hQ, nextVisibleIndex as hR, nodeBold as hS, nodeEditBox as hT, nodeFillColor as hU, nodeFontColor as hV, nodeIdFromKey as hW, nodeItalic as hX, nodeStyle as hY, normalizeFontFormat as hZ, normalizeSlidesPerPage as h_, interpolateWidth as ha, isAudienceTab as hb, isBold as hc, isBrowserOpenableMime as hd, isChildNode as he, isElementInteractive as hf, isInjectableUrl as hg, isItalic as hh, isPpactionUrl as hi, isPresenterMessage as hj, isSigned as hk, isTextElement as hl, isTwoTableFocus as hm, isUnderline as hn, isUrlSafe as ho, isValidRoomId as hp, isViewportBackgroundPressTarget as hq, isZoomActivationKey as hr, issueTrackKey as hs, issueTypeLabel as ht, keyToLabel as hu, latexToMathml as hv, linePointsToSvgString as hw, lineSpacingPatch as hx, loadAudienceContent as hy, mergeCaptionResults as hz, AiChangeOverlayComponent as i, revealedElementStyles as i$, numFromEvent as i0, ommlToMathml as i1, ooxmlDashToCssBorderStyle as i2, openNativeEyeDropper as i3, overallStatus as i4, paletteColor as i5, parseAudienceNonce as i6, parseNodeTextarea as i7, partitionSlides as i8, patchChartData as i9, removeCommentFromList as iA, removeElementAnimation as iB, removeGradientStopPatch as iC, removeNode as iD, removeRow as iE, removeSeries as iF, renderToCanvas as iG, reorderAnimationDown as iH, reorderAnimationUp as iI, replaceInSlides as iJ, replaceMatch as iK, requestPresentationFullscreen as iL, resizeElement as iM, resolveCaptionTracks as iN, resolveChartKind as iO, resolveFontVariant as iP, resolveHyperlinkHref as iQ, resolveInteractiveElementId as iR, resolveMediaSrc as iS, resolveOleType as iT, resolveParagraphBullet as iU, resolvePresenterNotes as iV, resolveProfileInitial as iW, resolveRegionCode as iX, resolvePalette as iY, resolveThemeCatalogEntry as iZ, resolveTransitionDuration as i_, patchChartStyle as ia, patchTableData as ib, patchTextStyle as ic, pendingElementStyles as id, pickColorByClickFallback as ie, pickSupportedMimeType as ig, planGifFrames as ih, planVideoSegments as ii, pointsToSvgPathD as ij, presenceToCursors as ik, presetByLayout as il, presetsForCategory as im, pressuresToWidths as io, prevVisibleIndex as ip, projectDrawingShapes as iq, promoteNode as ir, provideViewerTheme as is, radarAngle as it, radarRingPoints as iu, recordWebm as iv, redistributeColumnWidth as iw, removeAnimation as ix, removeCategory as iy, removeColumn as iz, AiChatPanelComponent as j, signatureCountLabel as j$, routeOrthogonalConnector as j0, rowStyle as j1, sampleColorFromSlide as j2, sanitizeColor as j3, sanitizeSlideIndex as j4, sanitizeUserName as j5, saveViewerProfile as j6, scanAvailableFonts as j7, searchSlides as j8, seedBroadcastFields as j9, setElementPosition as jA, setGridlineStyle as jB, setLayout as jC, setLegend as jD, setNodeStyle as jE, setNodeText as jF, setRepeatCount as jG, setRepeatMode as jH, setSequence as jI, setSeriesChartType as jJ, setSeriesColor as jK, setSeriesErrorBars as jL, setSeriesMarker as jM, setSeriesName as jN, setSeriesTrendline as jO, setSeriesValue as jP, setStyle as jQ, setTimingCurve as jR, setTitle as jS, setTrigger as jT, setTriggerShapeId as jU, shapeStylePatch as jV, sheetAfterNavigate as jW, shouldBlockClickAdvance as jX, shouldUseSvgWarp as jY, showDirectionPicker as jZ, showsTemplateAffordance as j_, seedHyperlinkDraft as ja, seedPropertiesDraft as jb, seedShareFields as jc, segmentFrameCount as jd, selectValue$2 as je, sendBackward as jf, sendToBack as jg, sequentialColorScale as jh, serializeWriteBack as ji, seriesColor as jj, setAnimationEmphasis as jk, setAnimationEntrance as jl, setAnimationExit as jm, setAxis as jn, setAxisLogScale as jo, setAxisTitleStyle as jp, setCategoryLabel as jq, setCellText as jr, setColorScheme as js, setDataLabels as jt, setDataPointExplosion as ju, setDataPointFill as jv, setDataPointLabel as jw, setDelay as jx, setDirection as jy, setDuration as jz, AiChatService as k, signatureKey as k0, signatureTimestamp as k1, signerName as k2, statusLabel as k3, slideNumberOf as k4, smartArtNodes as k5, paletteColour as k6, snapToGridStep as k7, splitCursorCell as k8, splitMergedCell as k9, updateElementById as kA, updateGlowPatch as kB, updateGradientStopPatch as kC, updateInnerShadowPatch as kD, updateOuterShadowPatch as kE, updateReflectionPatch as kF, vAlignPatch as kG, validatePassword as kH, validatePrintSettings as kI, validateRoomId as kJ, valueToY as kK, vermilionDarkColors as kL, vermilionDarkTheme as kM, vermilionLightColors as kN, vermilionLightTheme as kO, vermilionRadius as kP, waypointsToPathD as kQ, worstStatus as kR, zoomTargetSlideIndex as kS, statusKind as ka, statusLabel$1 as kb, storeAudienceContent as kc, stringFromEvent$5 as kd, strokeColorOf as ke, strokeToInkElement as kf, styleShadowFilter as kg, textAdvancedPatch as kh, textAdvancedStateFromStyle as ki, textAdvancedStateOf as kj, textColorOf as kk, textDirectionPatch as kl, textStyleOf as km, textStylePatch as kn, themeStyle as ko, themeToCssVars as kp, thumbnailHeight as kq, thumbnailZoom as kr, toggleCommentResolvedInList as ks, toggleNodeBold as kt, toggleNodeItalic as ku, toggleSheet as kv, topLevelNodeCount as kw, transformSelectedTextCase as kx, translationsEn as ky, ungroupElements as kz, AiComposerComponent as l, AiFocusBarComponent as m, AiFocusHighlightOverlayComponent as n, AiMessageListComponent as o, AiPanelStore as p, AiProposalCardComponent as q, AiSettingsSectionComponent as r, AiToolCallCardComponent as s, toChatSummary as t, AnimationAuthorPanelComponent as u, AnimationPanelComponent as v, AnimationPlaybackService as w, AutosaveService as x, CURSOR_PALETTE as y, CanvasFitService as z };
113916
- //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-DflEskoR.mjs.map
114151
+ //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-xlxMwvvj.mjs.map