pptx-angular-viewer 3.5.1 → 3.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.
@@ -1,8 +1,8 @@
1
1
  import { NgStyle, NgTemplateOutlet, NgClass } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { InjectionToken, input, output, inject, computed, ChangeDetectionStrategy, Component, signal, Injectable, DestroyRef, viewChild, effect, Injector, ElementRef, HostListener, afterNextRender, Renderer2, ViewEncapsulation, forwardRef, untracked, Directive } from '@angular/core';
3
+ import { InjectionToken, input, output, inject, computed, ChangeDetectionStrategy, Component, signal, Injectable, DestroyRef, viewChild, effect, Injector, untracked, ElementRef, HostListener, afterNextRender, Renderer2, ViewEncapsulation, forwardRef, Directive } from '@angular/core';
4
4
  import { TranslateService, TranslatePipe, translate } from '@ngx-translate/core';
5
- import { THEME_PRESETS, guideEmuToPx, getShapeClipPath, getAdjustmentAwareClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$1, customGeometryPathsToSvgSubpaths, evaluatePresetShape, hasShapeProperties, ooxmlGradientAngleToCssDegrees, getShapeType, isImageLikeElement, getElementTextContent, getRoundRectRadiusPx as getRoundRectRadiusPx$1, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, getSubstituteFontFamily, parsePanoseString, hasTextProperties, stripXmlOrderSuffix, orderedXmlKey, chartDataChangeType, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, rebuildTableStructureInRawXml, updateCellTextInRawXml, deepCloneData, cloneTemplateElementsBySlideId, cloneSlide, EMU_PER_PX as EMU_PER_PX$2, DEFAULT_POWERPOINT_TABLE_STYLE_ID, DEFAULT_SCHEME_COLOR_MAP as DEFAULT_SCHEME_COLOR_MAP$1, formatAutoNumberMarker, getLinkedTextBoxSegments, deriveSlideTitle, svgPathToPolygons, THEME_COLOR_SCHEME_KEYS, createBuiltinVariables, resolveCoordinate, lookupPresetShape, normalizeStShapeType, evaluateGuides, PptxHandler, styleStroke, strokeFor, fitFontSize, nodeTextStyle, truncate, nodeOpacity, nodeStroke, nodeFill, styleShadow, buildTree, treeWidth, treeDepth, gearPoints, flattenNodes, interpretSmartArtLayout, addSmartArtNode, removeSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, parseDataUrlToBytes, deobfuscateFont, detectFontFormat, createEditorId, makeStoreAwareId, reassignDescendantIds, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, renameSlideMaster, deleteSlideMaster, duplicateSlideMaster, insertSlideMaster, renameLayout, deleteLayout, duplicateLayout, insertLayout, detectFileFormat, cloneElement, duplicateElement, serializePptxToJson, PPTX_JSON_MIME_TYPE, PptxMarkdownConverter, ThemePresets, formatCommentTimestamp as formatCommentTimestamp$1, EncryptedFileError, decodeXmlEntities, parseSignatureXml, groupElements, ungroupElements, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, isZoomElement, SvgExporter, applyThemeToData, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointMarker, setChartDataPointExplosion, getOleObjectTypeLabel, addSmartArtNodeAsChild, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, TRANSITION_VALID_DIRECTIONS } from 'pptx-viewer-core';
5
+ import { THEME_PRESETS, guideEmuToPx, getShapeClipPath, getAdjustmentAwareClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$1, customGeometryPathsToSvgSubpaths, evaluatePresetShape, hasShapeProperties, ooxmlGradientAngleToCssDegrees, getShapeType, isImageLikeElement, getElementTextContent, getRoundRectRadiusPx as getRoundRectRadiusPx$1, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, getSubstituteFontFamily, parsePanoseString, hasTextProperties, stripXmlOrderSuffix, orderedXmlKey, chartDataChangeType, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, rebuildTableStructureInRawXml, updateCellTextInRawXml, deepCloneData, cloneTemplateElementsBySlideId, cloneSlide, EMU_PER_PX as EMU_PER_PX$2, formatAutoNumberMarker, DEFAULT_POWERPOINT_TABLE_STYLE_ID, DEFAULT_SCHEME_COLOR_MAP as DEFAULT_SCHEME_COLOR_MAP$1, getLinkedTextBoxSegments, deriveSlideTitle, svgPathToPolygons, THEME_COLOR_SCHEME_KEYS, createBuiltinVariables, resolveCoordinate, lookupPresetShape, normalizeStShapeType, evaluateGuides, PptxHandler, styleStroke, strokeFor, fitFontSize, nodeTextStyle, truncate, nodeOpacity, nodeStroke, nodeFill, styleShadow, buildTree, treeWidth, treeDepth, gearPoints, flattenNodes, interpretSmartArtLayout, addSmartArtNode, removeSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, parseDataUrlToBytes, deobfuscateFont, detectFontFormat, createEditorId, makeStoreAwareId, reassignDescendantIds, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, renameSlideMaster, deleteSlideMaster, duplicateSlideMaster, insertSlideMaster, renameLayout, deleteLayout, duplicateLayout, insertLayout, detectFileFormat, cloneElement, duplicateElement, serializePptxToJson, PPTX_JSON_MIME_TYPE, PptxMarkdownConverter, ThemePresets, formatCommentTimestamp as formatCommentTimestamp$1, EncryptedFileError, decodeXmlEntities, parseSignatureXml, groupElements, ungroupElements, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, isZoomElement, SvgExporter, applyThemeToData, reResolveElementColors, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointMarker, setChartDataPointExplosion, getOleObjectTypeLabel, addSmartArtNodeAsChild, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, TRANSITION_VALID_DIRECTIONS } from 'pptx-viewer-core';
6
6
  import DOMPurify from 'dompurify';
7
7
  import { z } from 'zod';
8
8
  import * as mcp from 'pptx-viewer-mcp';
@@ -32179,6 +32179,25 @@ function filterInteractableIds(ids, lookup, interaction) {
32179
32179
  return ids.filter((id) => canInteractWithElement(lookup(id), interaction));
32180
32180
  }
32181
32181
 
32182
+ /**
32183
+ * Whether an element's resize/rotate/adjustment handles should be shown.
32184
+ *
32185
+ * Handles stay visible and draggable while the SAME element is actively
32186
+ * inline-edited (PowerPoint keeps a text box's handles live mid-edit; you can
32187
+ * grab a corner without first clicking out of edit mode). Every handle's own
32188
+ * hit target is a small button at the box's edge/corner with `stopPropagation`
32189
+ * on its own pointer-down, and the handle host itself is `pointer-events:
32190
+ * none` everywhere else, so leaving handles mounted during inline edit does
32191
+ * not capture clicks meant for caret placement in the interior of the text.
32192
+ * There is nothing to gate on an inline-edit flag here: only whether the
32193
+ * canvas is editable, the element is the (single) selection, and - for the
32194
+ * unclipped overlay variant - it isn't a connector/line, which renders its
32195
+ * own handles inside its own (already unclipped) element instead.
32196
+ */
32197
+ function shouldShowElementHandles(isEditableCanvas, isSelected, selectedCount) {
32198
+ return isEditableCanvas && isSelected && selectedCount <= 1;
32199
+ }
32200
+
32182
32201
  /** Union of all selected element boxes, or null for an empty selection. */
32183
32202
  function selectionBounds(boxes) {
32184
32203
  if (boxes.length === 0) {
@@ -32498,6 +32517,350 @@ function round6(value) {
32498
32517
  * childAbsX = childRelX + groupX
32499
32518
  */
32500
32519
 
32520
+ /**
32521
+ * Auto-numbering helpers for paragraph bullets (framework-agnostic).
32522
+ *
32523
+ * Numbering schemes follow the OOXML `ST_TextAutonumberScheme` enumeration
32524
+ * (ECMA-376 §20.1.10.61). The implementation lives in `pptx-viewer-core`
32525
+ * (`core/utils/auto-number-format`) because the LOAD path needs the identical
32526
+ * string: core stamps the marker onto the parsed bullet segment and the
32527
+ * renderer resolves it again from `BulletInfo`, and the paragraph builder drops
32528
+ * core's segment only when the two agree. While this module carried its own
32529
+ * table the two disagreed for every East-Asian / Thai / Hindi / Hebrew scheme
32530
+ * and painted a DOUBLE marker (`一.1. Item`). Core is the only package both
32531
+ * sides can depend on (shared already depends on core; the reverse would be a
32532
+ * cycle), so it owns the single copy and this module re-exports it.
32533
+ */
32534
+
32535
+ /**
32536
+ * Pure paragraph bullet / list-marker + indent helpers (framework-agnostic).
32537
+ *
32538
+ * Mirrors React's paragraph + bullet renderer (`text-paragraph-render.tsx` +
32539
+ * `text-segment-render.tsx`): bullet-glyph selection, auto-numbering (see
32540
+ * {@link ./bullet-autonum}), bullet font/size/colour, and the marginLeft /
32541
+ * hanging-indent layout. Shared by the React/Vue/Angular bindings.
32542
+ */
32543
+ /** Resolve React-compatible picture-bullet sizing and fallback metadata. */
32544
+ function resolvePictureBullet(info, baseFontSize) {
32545
+ if (!info.imageDataUrl && !info.imageRelId && !info.imageBlipFillXml) {
32546
+ return undefined;
32547
+ }
32548
+ const sizePx = typeof info.sizePts === 'number'
32549
+ ? info.sizePts
32550
+ : typeof info.sizePercent === 'number'
32551
+ ? baseFontSize * (info.sizePercent / 100)
32552
+ : baseFontSize;
32553
+ return {
32554
+ ...(info.imageDataUrl ? { src: info.imageDataUrl } : {}),
32555
+ sizePx,
32556
+ fallbackMarker: '•',
32557
+ accessibleLabel: 'Bullet',
32558
+ ...(info.imageRelId ? { imageRelId: info.imageRelId } : {}),
32559
+ };
32560
+ }
32561
+ /**
32562
+ * Resolve the bullet marker for the first segment of a paragraph.
32563
+ *
32564
+ * Returns `undefined` when the segment is absent or carries no `bulletInfo`,
32565
+ * when `bulletInfo.none`/`listType:'none'` suppresses it, or when neither a
32566
+ * character bullet nor an auto-number type is present. For auto-numbered
32567
+ * bullets the 1-based sequence index is `autoNumStartAt` (default 1) plus the
32568
+ * 0-based `paragraphIndex`.
32569
+ */
32570
+ function resolveParagraphBullet(firstSegment, baseFontSize = firstSegment?.style?.fontSize ?? 16) {
32571
+ if (!firstSegment) {
32572
+ return undefined;
32573
+ }
32574
+ // listType on the first segment's style can explicitly suppress bullets.
32575
+ if (firstSegment.style?.listType === 'none') {
32576
+ return undefined;
32577
+ }
32578
+ const info = firstSegment.bulletInfo;
32579
+ if (!info || info.none) {
32580
+ return undefined;
32581
+ }
32582
+ const color = info.color;
32583
+ const fontFamily = info.fontFamily;
32584
+ const sizePts = typeof info.sizePts === 'number' ? info.sizePts : undefined;
32585
+ const sizePercent = typeof info.sizePercent === 'number' ? info.sizePercent : undefined;
32586
+ const picture = resolvePictureBullet(info, baseFontSize);
32587
+ if (picture) {
32588
+ return {
32589
+ marker: picture.fallbackMarker,
32590
+ isNumbered: false,
32591
+ color,
32592
+ fontFamily,
32593
+ sizePts,
32594
+ sizePercent,
32595
+ picture,
32596
+ };
32597
+ }
32598
+ // ── Auto-numbered list ──
32599
+ if (info.autoNumType) {
32600
+ const startAt = typeof info.autoNumStartAt === 'number' ? info.autoNumStartAt : 1;
32601
+ const paraIdx = typeof info.paragraphIndex === 'number' ? info.paragraphIndex : 0;
32602
+ const seqNum = Math.max(1, startAt + paraIdx);
32603
+ return {
32604
+ marker: formatAutoNumberMarker(info.autoNumType, seqNum),
32605
+ isNumbered: true,
32606
+ color,
32607
+ fontFamily,
32608
+ sizePts,
32609
+ sizePercent,
32610
+ };
32611
+ }
32612
+ // ── Character bullet ──
32613
+ if (info.char) {
32614
+ return { marker: info.char, isNumbered: false, color, fontFamily, sizePts, sizePercent };
32615
+ }
32616
+ // Unsupported cases have no marker to show as text.
32617
+ return undefined;
32618
+ }
32619
+ /** Pixels of left-padding to apply per list nesting level. */
32620
+ const INDENT_PX_PER_LEVEL = 18;
32621
+ /**
32622
+ * Return the left-indent in pixels for the given 0-based list nesting level
32623
+ * (OOXML `a:p/@lvl`). `undefined`/negative is treated as level 0. Used as a
32624
+ * fallback when the element carries no explicit per-paragraph `marginLeft`.
32625
+ */
32626
+ function bulletIndentPx(level) {
32627
+ const lvl = typeof level === 'number' && level > 0 ? level : 0;
32628
+ return lvl * INDENT_PX_PER_LEVEL;
32629
+ }
32630
+ /**
32631
+ * Resolve the hanging-indent layout for a paragraph (mirrors React's
32632
+ * `text-paragraph-render.tsx`). Explicit `paragraphIndents[paraIndex]`
32633
+ * `marginLeft`/`indent` are used verbatim (zeros omitted); otherwise falls back
32634
+ * to the per-level indent derived from `paragraphLevel`.
32635
+ */
32636
+ function resolveParagraphIndent(paraIndent, paragraphLevel) {
32637
+ const marginLeft = typeof paraIndent?.marginLeft === 'number' && paraIndent.marginLeft !== 0
32638
+ ? paraIndent.marginLeft
32639
+ : undefined;
32640
+ const textIndent = typeof paraIndent?.indent === 'number' && paraIndent.indent !== 0
32641
+ ? paraIndent.indent
32642
+ : undefined;
32643
+ if (marginLeft === undefined && textIndent === undefined) {
32644
+ const levelPx = bulletIndentPx(paragraphLevel);
32645
+ return levelPx > 0 ? { marginLeftPx: levelPx } : {};
32646
+ }
32647
+ return { marginLeftPx: marginLeft, textIndentPx: textIndent };
32648
+ }
32649
+
32650
+ /**
32651
+ * Bullet / numbered-list toggling for the ribbon's paragraph buttons.
32652
+ *
32653
+ * The renderer (`resolveParagraphBullet`) and the save writer
32654
+ * (`applyBulletProperties`) both read a paragraph's list state from the
32655
+ * `bulletInfo` of its FIRST segment; `TextStyle.listType` is consulted for
32656
+ * nothing but the `'none'` suppression. Every binding's Bullets / Numbering
32657
+ * button used to write `listType: 'bullet' | 'numbered'` onto the element's
32658
+ * `textStyle`, a field nothing downstream reads, so the buttons were dead.
32659
+ *
32660
+ * These helpers author the real thing: a `BulletInfo` on each paragraph's
32661
+ * first segment (`a:buChar` / `a:buAutoNum` / `a:buNone` on save), with the
32662
+ * inert `listType` cleared so a stale `'none'` cannot suppress the new marker.
32663
+ *
32664
+ * On load core prefixes a display-only marker segment (text "• " / "1.") to a
32665
+ * listed paragraph; the renderer drops it when its text matches the marker it
32666
+ * would draw, and the save writer drops it because the paragraph properties
32667
+ * already express it. Switching a bullet to a number (or off) would leave the
32668
+ * old glyph behind as literal text, so the previous marker is removed and a
32669
+ * fresh one authored in the same shape core uses.
32670
+ */
32671
+ /** The default character bullet PowerPoint inserts (`a:buChar char="•"`). */
32672
+ const DEFAULT_BULLET_CHAR = '•';
32673
+ /** The default numbering scheme PowerPoint inserts (`a:buAutoNum type="arabicPeriod"`). */
32674
+ const DEFAULT_AUTONUM_TYPE = 'arabicPeriod';
32675
+ /**
32676
+ * The `BulletInfo` that authors `kind`.
32677
+ *
32678
+ * @param ordinal - Zero-based position of the paragraph within its numbered
32679
+ * run, published as `paragraphIndex` so the renderer counts "1. 2. 3." (see
32680
+ * `BulletInfo.paragraphIndex`). Ignored for the other kinds.
32681
+ */
32682
+ function bulletInfoForKind(kind, ordinal = 0) {
32683
+ switch (kind) {
32684
+ case 'bullet':
32685
+ return { char: DEFAULT_BULLET_CHAR };
32686
+ case 'numbered':
32687
+ return { autoNumType: DEFAULT_AUTONUM_TYPE, autoNumStartAt: 1, paragraphIndex: ordinal };
32688
+ case 'none':
32689
+ return { none: true };
32690
+ }
32691
+ }
32692
+ /**
32693
+ * Whether a segment is the display-only marker core inserts on load (mirrors
32694
+ * the save writer's `isRenderedBulletMarker`): it carries `bulletInfo` and its
32695
+ * text is exactly the glyph the renderer would draw for that info.
32696
+ */
32697
+ function isBulletMarkerSegment(segment) {
32698
+ const bullet = segment.bulletInfo;
32699
+ if (!bullet || bullet.none) {
32700
+ return false;
32701
+ }
32702
+ const resolved = resolveParagraphBullet(segment);
32703
+ if (!resolved) {
32704
+ return false;
32705
+ }
32706
+ return segment.text.trim() === resolved.marker.trim() && segment.text.trim().length > 0;
32707
+ }
32708
+ /**
32709
+ * The current list state of one paragraph (its segments, separators excluded),
32710
+ * derived from the resolved bullet of its first segment so an inherited
32711
+ * (master / layout) bullet that core resolved on load counts as `'bullet'`.
32712
+ */
32713
+ function paragraphBulletKind(paragraph) {
32714
+ const resolved = resolveParagraphBullet(paragraph[0]);
32715
+ if (!resolved) {
32716
+ return 'none';
32717
+ }
32718
+ return resolved.isNumbered ? 'numbered' : 'bullet';
32719
+ }
32720
+ /** Copy of `style` without the inert `listType` flag. */
32721
+ function withoutListType(style) {
32722
+ const next = { ...(style ?? {}) };
32723
+ delete next.listType;
32724
+ return next;
32725
+ }
32726
+ function paragraphMeta(segment) {
32727
+ const meta = {};
32728
+ if (segment?.paragraphLevel !== undefined) {
32729
+ meta.paragraphLevel = segment.paragraphLevel;
32730
+ }
32731
+ if (segment?.paragraphProperties !== undefined) {
32732
+ meta.paragraphProperties = segment.paragraphProperties;
32733
+ }
32734
+ if (segment?.endParaRunProperties !== undefined) {
32735
+ meta.endParaRunProperties = segment.endParaRunProperties;
32736
+ }
32737
+ return meta;
32738
+ }
32739
+ /** The display text of the marker segment for a bullet / numbered `info`. */
32740
+ function markerText(info) {
32741
+ if (info.char) {
32742
+ return `${info.char} `;
32743
+ }
32744
+ const ordinal = (info.autoNumStartAt ?? 1) + (info.paragraphIndex ?? 0);
32745
+ return formatAutoNumberMarker(info.autoNumType ?? DEFAULT_AUTONUM_TYPE, ordinal);
32746
+ }
32747
+ /**
32748
+ * Set one paragraph's list state to `kind`, returning the paragraph's new
32749
+ * segments.
32750
+ *
32751
+ * The result uses the same shape core produces on load, so the renderer and
32752
+ * the save writer treat an authored list exactly like a parsed one: for
32753
+ * `'bullet'` / `'numbered'` a display-only marker segment carrying the new
32754
+ * `bulletInfo` (and the paragraph-level fields) is placed first, followed by
32755
+ * the content runs with any previous marker removed; for `'none'` the marker
32756
+ * is dropped and the first content segment carries `{ none: true }`. The
32757
+ * inert `style.listType` is cleared on the touched segments. An empty
32758
+ * paragraph is returned unchanged since there is no run to carry the state.
32759
+ *
32760
+ * @param ordinal - Zero-based position within a numbered run; see
32761
+ * {@link bulletInfoForKind}.
32762
+ */
32763
+ function toggleParagraphBullet(paragraph, kind, ordinal = 0) {
32764
+ const content = paragraph.filter((segment) => !isBulletMarkerSegment(segment));
32765
+ const first = content[0];
32766
+ if (!first) {
32767
+ return [...paragraph];
32768
+ }
32769
+ const meta = paragraphMeta(paragraph[0]);
32770
+ const info = bulletInfoForKind(kind, ordinal);
32771
+ const rest = content.slice(1);
32772
+ if (kind === 'none') {
32773
+ return [{ ...first, ...meta, style: withoutListType(first.style), bulletInfo: info }, ...rest];
32774
+ }
32775
+ const marker = {
32776
+ text: markerText(info),
32777
+ style: withoutListType(first.style),
32778
+ ...meta,
32779
+ bulletInfo: info,
32780
+ };
32781
+ const body = { ...first, style: withoutListType(first.style) };
32782
+ delete body.bulletInfo;
32783
+ return [marker, body, ...rest];
32784
+ }
32785
+ function isParagraphSeparator$1(segment) {
32786
+ return Boolean(segment.isParagraphBreak) || (segment.text === '\n' && !segment.isLineBreak);
32787
+ }
32788
+ /** Split a segment list into paragraphs, keeping each paragraph's terminator. */
32789
+ function splitParagraphs(segments) {
32790
+ const paragraphs = [
32791
+ { segments: [] },
32792
+ ];
32793
+ for (const segment of segments) {
32794
+ if (isParagraphSeparator$1(segment)) {
32795
+ paragraphs[paragraphs.length - 1].terminator = segment;
32796
+ paragraphs.push({ segments: [] });
32797
+ continue;
32798
+ }
32799
+ paragraphs[paragraphs.length - 1].segments.push(segment);
32800
+ }
32801
+ return paragraphs;
32802
+ }
32803
+ /** The element's segments, synthesised from `text` when it carries none. */
32804
+ function elementSegments(element) {
32805
+ if (!hasTextProperties(element)) {
32806
+ return [];
32807
+ }
32808
+ if (element.textSegments && element.textSegments.length > 0) {
32809
+ return element.textSegments;
32810
+ }
32811
+ const style = { ...(element.textStyle ?? {}) };
32812
+ const segments = [];
32813
+ for (const [index, line] of (element.text ?? '').split('\n').entries()) {
32814
+ if (index > 0) {
32815
+ segments.push({ text: '\n', style: { ...style }, isParagraphBreak: true });
32816
+ }
32817
+ segments.push({ text: line, style: { ...style } });
32818
+ }
32819
+ return segments;
32820
+ }
32821
+ /**
32822
+ * The list state an element's ribbon buttons should show: the kind of its
32823
+ * first non-empty paragraph, since that is what a toggle would act on.
32824
+ */
32825
+ function elementBulletKind(element) {
32826
+ for (const paragraph of splitParagraphs(elementSegments(element))) {
32827
+ if (paragraph.segments.length > 0) {
32828
+ return paragraphBulletKind(paragraph.segments);
32829
+ }
32830
+ }
32831
+ return 'none';
32832
+ }
32833
+ /**
32834
+ * Set every paragraph of an element to `kind`, returning the element patch
32835
+ * (`textSegments` rewritten; `textStyle.listType` cleared so the element-level
32836
+ * flag can no longer suppress or lie about the state). Numbered paragraphs are
32837
+ * counted consecutively so the renderer shows "1. 2. 3.".
32838
+ */
32839
+ function setElementBullets(element, kind) {
32840
+ const textStyle = withoutListType(hasTextProperties(element) ? element.textStyle : undefined);
32841
+ const next = [];
32842
+ let ordinal = 0;
32843
+ for (const paragraph of splitParagraphs(elementSegments(element))) {
32844
+ if (paragraph.segments.length > 0) {
32845
+ next.push(...toggleParagraphBullet(paragraph.segments, kind, ordinal));
32846
+ ordinal += 1;
32847
+ }
32848
+ if (paragraph.terminator) {
32849
+ next.push(paragraph.terminator);
32850
+ }
32851
+ }
32852
+ return { textSegments: next, textStyle };
32853
+ }
32854
+ /**
32855
+ * The ribbon button behaviour: pressing Bullets (or Numbering) on an element
32856
+ * already in that state turns its lists off, otherwise it applies that kind
32857
+ * to every paragraph. Returns the element patch to apply through the
32858
+ * binding's update-element operation.
32859
+ */
32860
+ function toggleElementBullets(element, kind) {
32861
+ return setElementBullets(element, elementBulletKind(element) === kind ? 'none' : kind);
32862
+ }
32863
+
32501
32864
  /**
32502
32865
  * PowerPoint's Outline view, as a framework-agnostic model of the deck's text.
32503
32866
  *
@@ -32661,16 +33024,17 @@ function isBulletMarker(segment) {
32661
33024
  if (!bullet) {
32662
33025
  return false;
32663
33026
  }
33027
+ if (bullet.autoNumType) {
33028
+ return bullet.paragraphIndex !== undefined && isBulletMarkerSegment(segment);
33029
+ }
32664
33030
  const marker = bullet.char
32665
33031
  ? `${bullet.char} `
32666
33032
  : bullet.imageRelId || bullet.imageDataUrl
32667
33033
  ? '\u{1F4CE} '
32668
- : bullet.autoNumType
32669
- ? undefined
32670
- : '• ';
32671
- return marker ? segment.text === marker : bullet.paragraphIndex !== undefined;
33034
+ : '• ';
33035
+ return segment.text === marker;
32672
33036
  }
32673
- function isParagraphSeparator$1(segment) {
33037
+ function isParagraphSeparator(segment) {
32674
33038
  return Boolean(segment.isParagraphBreak) || (segment.text === '\n' && !segment.isLineBreak);
32675
33039
  }
32676
33040
  /**
@@ -32691,7 +33055,7 @@ function groupElementParagraphs(element) {
32691
33055
  }
32692
33056
  const groups = [{ content: [] }];
32693
33057
  for (const segment of segments) {
32694
- if (isParagraphSeparator$1(segment)) {
33058
+ if (isParagraphSeparator(segment)) {
32695
33059
  groups.push({ content: [] });
32696
33060
  continue;
32697
33061
  }
@@ -35249,6 +35613,7 @@ const translationsEn = {
35249
35613
  'pptx.slideBackground.backgroundPreview': 'Background preview',
35250
35614
  'pptx.slideBackground.removeBackgroundImage': 'Remove background image',
35251
35615
  'pptx.slideBackground.clearBackground': 'Clear Background',
35616
+ 'pptx.slideBackground.hideBackgroundGraphics': 'Hide Background Graphics',
35252
35617
  'pptx.presentationSettings.showType': 'Show type',
35253
35618
  'pptx.presentationSettings.showTypePresented': 'Presented',
35254
35619
  'pptx.presentationSettings.showTypeBrowsed': 'Browsed',
@@ -38822,350 +39187,6 @@ function rulerDragToGuidePosition(pointerOffsetPx, scale, slideLengthPx) {
38822
39187
  return position;
38823
39188
  }
38824
39189
 
38825
- /**
38826
- * Auto-numbering helpers for paragraph bullets (framework-agnostic).
38827
- *
38828
- * Numbering schemes follow the OOXML `ST_TextAutonumberScheme` enumeration
38829
- * (ECMA-376 §20.1.10.61). The implementation lives in `pptx-viewer-core`
38830
- * (`core/utils/auto-number-format`) because the LOAD path needs the identical
38831
- * string: core stamps the marker onto the parsed bullet segment and the
38832
- * renderer resolves it again from `BulletInfo`, and the paragraph builder drops
38833
- * core's segment only when the two agree. While this module carried its own
38834
- * table the two disagreed for every East-Asian / Thai / Hindi / Hebrew scheme
38835
- * and painted a DOUBLE marker (`一.1. Item`). Core is the only package both
38836
- * sides can depend on (shared already depends on core; the reverse would be a
38837
- * cycle), so it owns the single copy and this module re-exports it.
38838
- */
38839
-
38840
- /**
38841
- * Pure paragraph bullet / list-marker + indent helpers (framework-agnostic).
38842
- *
38843
- * Mirrors React's paragraph + bullet renderer (`text-paragraph-render.tsx` +
38844
- * `text-segment-render.tsx`): bullet-glyph selection, auto-numbering (see
38845
- * {@link ./bullet-autonum}), bullet font/size/colour, and the marginLeft /
38846
- * hanging-indent layout. Shared by the React/Vue/Angular bindings.
38847
- */
38848
- /** Resolve React-compatible picture-bullet sizing and fallback metadata. */
38849
- function resolvePictureBullet(info, baseFontSize) {
38850
- if (!info.imageDataUrl && !info.imageRelId && !info.imageBlipFillXml) {
38851
- return undefined;
38852
- }
38853
- const sizePx = typeof info.sizePts === 'number'
38854
- ? info.sizePts
38855
- : typeof info.sizePercent === 'number'
38856
- ? baseFontSize * (info.sizePercent / 100)
38857
- : baseFontSize;
38858
- return {
38859
- ...(info.imageDataUrl ? { src: info.imageDataUrl } : {}),
38860
- sizePx,
38861
- fallbackMarker: '•',
38862
- accessibleLabel: 'Bullet',
38863
- ...(info.imageRelId ? { imageRelId: info.imageRelId } : {}),
38864
- };
38865
- }
38866
- /**
38867
- * Resolve the bullet marker for the first segment of a paragraph.
38868
- *
38869
- * Returns `undefined` when the segment is absent or carries no `bulletInfo`,
38870
- * when `bulletInfo.none`/`listType:'none'` suppresses it, or when neither a
38871
- * character bullet nor an auto-number type is present. For auto-numbered
38872
- * bullets the 1-based sequence index is `autoNumStartAt` (default 1) plus the
38873
- * 0-based `paragraphIndex`.
38874
- */
38875
- function resolveParagraphBullet(firstSegment, baseFontSize = firstSegment?.style?.fontSize ?? 16) {
38876
- if (!firstSegment) {
38877
- return undefined;
38878
- }
38879
- // listType on the first segment's style can explicitly suppress bullets.
38880
- if (firstSegment.style?.listType === 'none') {
38881
- return undefined;
38882
- }
38883
- const info = firstSegment.bulletInfo;
38884
- if (!info || info.none) {
38885
- return undefined;
38886
- }
38887
- const color = info.color;
38888
- const fontFamily = info.fontFamily;
38889
- const sizePts = typeof info.sizePts === 'number' ? info.sizePts : undefined;
38890
- const sizePercent = typeof info.sizePercent === 'number' ? info.sizePercent : undefined;
38891
- const picture = resolvePictureBullet(info, baseFontSize);
38892
- if (picture) {
38893
- return {
38894
- marker: picture.fallbackMarker,
38895
- isNumbered: false,
38896
- color,
38897
- fontFamily,
38898
- sizePts,
38899
- sizePercent,
38900
- picture,
38901
- };
38902
- }
38903
- // ── Auto-numbered list ──
38904
- if (info.autoNumType) {
38905
- const startAt = typeof info.autoNumStartAt === 'number' ? info.autoNumStartAt : 1;
38906
- const paraIdx = typeof info.paragraphIndex === 'number' ? info.paragraphIndex : 0;
38907
- const seqNum = Math.max(1, startAt + paraIdx);
38908
- return {
38909
- marker: formatAutoNumberMarker(info.autoNumType, seqNum),
38910
- isNumbered: true,
38911
- color,
38912
- fontFamily,
38913
- sizePts,
38914
- sizePercent,
38915
- };
38916
- }
38917
- // ── Character bullet ──
38918
- if (info.char) {
38919
- return { marker: info.char, isNumbered: false, color, fontFamily, sizePts, sizePercent };
38920
- }
38921
- // Unsupported cases have no marker to show as text.
38922
- return undefined;
38923
- }
38924
- /** Pixels of left-padding to apply per list nesting level. */
38925
- const INDENT_PX_PER_LEVEL = 18;
38926
- /**
38927
- * Return the left-indent in pixels for the given 0-based list nesting level
38928
- * (OOXML `a:p/@lvl`). `undefined`/negative is treated as level 0. Used as a
38929
- * fallback when the element carries no explicit per-paragraph `marginLeft`.
38930
- */
38931
- function bulletIndentPx(level) {
38932
- const lvl = typeof level === 'number' && level > 0 ? level : 0;
38933
- return lvl * INDENT_PX_PER_LEVEL;
38934
- }
38935
- /**
38936
- * Resolve the hanging-indent layout for a paragraph (mirrors React's
38937
- * `text-paragraph-render.tsx`). Explicit `paragraphIndents[paraIndex]`
38938
- * `marginLeft`/`indent` are used verbatim (zeros omitted); otherwise falls back
38939
- * to the per-level indent derived from `paragraphLevel`.
38940
- */
38941
- function resolveParagraphIndent(paraIndent, paragraphLevel) {
38942
- const marginLeft = typeof paraIndent?.marginLeft === 'number' && paraIndent.marginLeft !== 0
38943
- ? paraIndent.marginLeft
38944
- : undefined;
38945
- const textIndent = typeof paraIndent?.indent === 'number' && paraIndent.indent !== 0
38946
- ? paraIndent.indent
38947
- : undefined;
38948
- if (marginLeft === undefined && textIndent === undefined) {
38949
- const levelPx = bulletIndentPx(paragraphLevel);
38950
- return levelPx > 0 ? { marginLeftPx: levelPx } : {};
38951
- }
38952
- return { marginLeftPx: marginLeft, textIndentPx: textIndent };
38953
- }
38954
-
38955
- /**
38956
- * Bullet / numbered-list toggling for the ribbon's paragraph buttons.
38957
- *
38958
- * The renderer (`resolveParagraphBullet`) and the save writer
38959
- * (`applyBulletProperties`) both read a paragraph's list state from the
38960
- * `bulletInfo` of its FIRST segment; `TextStyle.listType` is consulted for
38961
- * nothing but the `'none'` suppression. Every binding's Bullets / Numbering
38962
- * button used to write `listType: 'bullet' | 'numbered'` onto the element's
38963
- * `textStyle`, a field nothing downstream reads, so the buttons were dead.
38964
- *
38965
- * These helpers author the real thing: a `BulletInfo` on each paragraph's
38966
- * first segment (`a:buChar` / `a:buAutoNum` / `a:buNone` on save), with the
38967
- * inert `listType` cleared so a stale `'none'` cannot suppress the new marker.
38968
- *
38969
- * On load core prefixes a display-only marker segment (text "• " / "1.") to a
38970
- * listed paragraph; the renderer drops it when its text matches the marker it
38971
- * would draw, and the save writer drops it because the paragraph properties
38972
- * already express it. Switching a bullet to a number (or off) would leave the
38973
- * old glyph behind as literal text, so the previous marker is removed and a
38974
- * fresh one authored in the same shape core uses.
38975
- */
38976
- /** The default character bullet PowerPoint inserts (`a:buChar char="•"`). */
38977
- const DEFAULT_BULLET_CHAR = '•';
38978
- /** The default numbering scheme PowerPoint inserts (`a:buAutoNum type="arabicPeriod"`). */
38979
- const DEFAULT_AUTONUM_TYPE = 'arabicPeriod';
38980
- /**
38981
- * The `BulletInfo` that authors `kind`.
38982
- *
38983
- * @param ordinal - Zero-based position of the paragraph within its numbered
38984
- * run, published as `paragraphIndex` so the renderer counts "1. 2. 3." (see
38985
- * `BulletInfo.paragraphIndex`). Ignored for the other kinds.
38986
- */
38987
- function bulletInfoForKind(kind, ordinal = 0) {
38988
- switch (kind) {
38989
- case 'bullet':
38990
- return { char: DEFAULT_BULLET_CHAR };
38991
- case 'numbered':
38992
- return { autoNumType: DEFAULT_AUTONUM_TYPE, autoNumStartAt: 1, paragraphIndex: ordinal };
38993
- case 'none':
38994
- return { none: true };
38995
- }
38996
- }
38997
- /**
38998
- * Whether a segment is the display-only marker core inserts on load (mirrors
38999
- * the save writer's `isRenderedBulletMarker`): it carries `bulletInfo` and its
39000
- * text is exactly the glyph the renderer would draw for that info.
39001
- */
39002
- function isBulletMarkerSegment(segment) {
39003
- const bullet = segment.bulletInfo;
39004
- if (!bullet || bullet.none) {
39005
- return false;
39006
- }
39007
- const resolved = resolveParagraphBullet(segment);
39008
- if (!resolved) {
39009
- return false;
39010
- }
39011
- return segment.text.trim() === resolved.marker.trim() && segment.text.trim().length > 0;
39012
- }
39013
- /**
39014
- * The current list state of one paragraph (its segments, separators excluded),
39015
- * derived from the resolved bullet of its first segment so an inherited
39016
- * (master / layout) bullet that core resolved on load counts as `'bullet'`.
39017
- */
39018
- function paragraphBulletKind(paragraph) {
39019
- const resolved = resolveParagraphBullet(paragraph[0]);
39020
- if (!resolved) {
39021
- return 'none';
39022
- }
39023
- return resolved.isNumbered ? 'numbered' : 'bullet';
39024
- }
39025
- /** Copy of `style` without the inert `listType` flag. */
39026
- function withoutListType(style) {
39027
- const next = { ...(style ?? {}) };
39028
- delete next.listType;
39029
- return next;
39030
- }
39031
- function paragraphMeta(segment) {
39032
- const meta = {};
39033
- if (segment?.paragraphLevel !== undefined) {
39034
- meta.paragraphLevel = segment.paragraphLevel;
39035
- }
39036
- if (segment?.paragraphProperties !== undefined) {
39037
- meta.paragraphProperties = segment.paragraphProperties;
39038
- }
39039
- if (segment?.endParaRunProperties !== undefined) {
39040
- meta.endParaRunProperties = segment.endParaRunProperties;
39041
- }
39042
- return meta;
39043
- }
39044
- /** The display text of the marker segment for a bullet / numbered `info`. */
39045
- function markerText(info) {
39046
- if (info.char) {
39047
- return `${info.char} `;
39048
- }
39049
- const ordinal = (info.autoNumStartAt ?? 1) + (info.paragraphIndex ?? 0);
39050
- return formatAutoNumberMarker(info.autoNumType ?? DEFAULT_AUTONUM_TYPE, ordinal);
39051
- }
39052
- /**
39053
- * Set one paragraph's list state to `kind`, returning the paragraph's new
39054
- * segments.
39055
- *
39056
- * The result uses the same shape core produces on load, so the renderer and
39057
- * the save writer treat an authored list exactly like a parsed one: for
39058
- * `'bullet'` / `'numbered'` a display-only marker segment carrying the new
39059
- * `bulletInfo` (and the paragraph-level fields) is placed first, followed by
39060
- * the content runs with any previous marker removed; for `'none'` the marker
39061
- * is dropped and the first content segment carries `{ none: true }`. The
39062
- * inert `style.listType` is cleared on the touched segments. An empty
39063
- * paragraph is returned unchanged since there is no run to carry the state.
39064
- *
39065
- * @param ordinal - Zero-based position within a numbered run; see
39066
- * {@link bulletInfoForKind}.
39067
- */
39068
- function toggleParagraphBullet(paragraph, kind, ordinal = 0) {
39069
- const content = paragraph.filter((segment) => !isBulletMarkerSegment(segment));
39070
- const first = content[0];
39071
- if (!first) {
39072
- return [...paragraph];
39073
- }
39074
- const meta = paragraphMeta(paragraph[0]);
39075
- const info = bulletInfoForKind(kind, ordinal);
39076
- const rest = content.slice(1);
39077
- if (kind === 'none') {
39078
- return [{ ...first, ...meta, style: withoutListType(first.style), bulletInfo: info }, ...rest];
39079
- }
39080
- const marker = {
39081
- text: markerText(info),
39082
- style: withoutListType(first.style),
39083
- ...meta,
39084
- bulletInfo: info,
39085
- };
39086
- const body = { ...first, style: withoutListType(first.style) };
39087
- delete body.bulletInfo;
39088
- return [marker, body, ...rest];
39089
- }
39090
- function isParagraphSeparator(segment) {
39091
- return Boolean(segment.isParagraphBreak) || (segment.text === '\n' && !segment.isLineBreak);
39092
- }
39093
- /** Split a segment list into paragraphs, keeping each paragraph's terminator. */
39094
- function splitParagraphs(segments) {
39095
- const paragraphs = [
39096
- { segments: [] },
39097
- ];
39098
- for (const segment of segments) {
39099
- if (isParagraphSeparator(segment)) {
39100
- paragraphs[paragraphs.length - 1].terminator = segment;
39101
- paragraphs.push({ segments: [] });
39102
- continue;
39103
- }
39104
- paragraphs[paragraphs.length - 1].segments.push(segment);
39105
- }
39106
- return paragraphs;
39107
- }
39108
- /** The element's segments, synthesised from `text` when it carries none. */
39109
- function elementSegments(element) {
39110
- if (!hasTextProperties(element)) {
39111
- return [];
39112
- }
39113
- if (element.textSegments && element.textSegments.length > 0) {
39114
- return element.textSegments;
39115
- }
39116
- const style = { ...(element.textStyle ?? {}) };
39117
- const segments = [];
39118
- for (const [index, line] of (element.text ?? '').split('\n').entries()) {
39119
- if (index > 0) {
39120
- segments.push({ text: '\n', style: { ...style }, isParagraphBreak: true });
39121
- }
39122
- segments.push({ text: line, style: { ...style } });
39123
- }
39124
- return segments;
39125
- }
39126
- /**
39127
- * The list state an element's ribbon buttons should show: the kind of its
39128
- * first non-empty paragraph, since that is what a toggle would act on.
39129
- */
39130
- function elementBulletKind(element) {
39131
- for (const paragraph of splitParagraphs(elementSegments(element))) {
39132
- if (paragraph.segments.length > 0) {
39133
- return paragraphBulletKind(paragraph.segments);
39134
- }
39135
- }
39136
- return 'none';
39137
- }
39138
- /**
39139
- * Set every paragraph of an element to `kind`, returning the element patch
39140
- * (`textSegments` rewritten; `textStyle.listType` cleared so the element-level
39141
- * flag can no longer suppress or lie about the state). Numbered paragraphs are
39142
- * counted consecutively so the renderer shows "1. 2. 3.".
39143
- */
39144
- function setElementBullets(element, kind) {
39145
- const textStyle = withoutListType(hasTextProperties(element) ? element.textStyle : undefined);
39146
- const next = [];
39147
- let ordinal = 0;
39148
- for (const paragraph of splitParagraphs(elementSegments(element))) {
39149
- if (paragraph.segments.length > 0) {
39150
- next.push(...toggleParagraphBullet(paragraph.segments, kind, ordinal));
39151
- ordinal += 1;
39152
- }
39153
- if (paragraph.terminator) {
39154
- next.push(paragraph.terminator);
39155
- }
39156
- }
39157
- return { textSegments: next, textStyle };
39158
- }
39159
- /**
39160
- * The ribbon button behaviour: pressing Bullets (or Numbering) on an element
39161
- * already in that state turns its lists off, otherwise it applies that kind
39162
- * to every paragraph. Returns the element patch to apply through the
39163
- * binding's update-element operation.
39164
- */
39165
- function toggleElementBullets(element, kind) {
39166
- return setElementBullets(element, elementBulletKind(element) === kind ? 'none' : kind);
39167
- }
39168
-
39169
39190
  /**
39170
39191
  * notes-utils.ts: framework-agnostic pure helpers for the rich speaker-notes
39171
39192
  * editor, shared by the React, Vue, and Angular bindings.
@@ -50225,6 +50246,37 @@ function hasCopyableFormat(element) {
50225
50246
  return hasShapeProperties(element) || hasTextProperties(element);
50226
50247
  }
50227
50248
 
50249
+ /**
50250
+ * Remove marker text from editor surfaces that seed it as ordinary text.
50251
+ * Depending on the binding, the gap can be CSS (`"1.Item"`) or the parsed
50252
+ * marker's trailing space (`"1. Item"`). React instead annotates its rendered
50253
+ * marker so `readEditableText` can exclude it at the DOM boundary.
50254
+ */
50255
+ function withoutRenderedBulletPrefix(text, originalSegments, dedicatedMarker) {
50256
+ if (!dedicatedMarker) {
50257
+ return text;
50258
+ }
50259
+ const resolved = resolveParagraphBullet(dedicatedMarker);
50260
+ if (!resolved || !text.startsWith(resolved.marker)) {
50261
+ return text;
50262
+ }
50263
+ const withoutMarker = text.slice(resolved.marker.length);
50264
+ const originalContent = originalSegments
50265
+ .slice(1)
50266
+ .map((segment) => segment.text)
50267
+ .join('');
50268
+ // Empty list paragraphs do not render a marker, so marker-like text typed
50269
+ // into them is authored content and must not be stripped.
50270
+ if (originalContent.trim().length === 0) {
50271
+ return text;
50272
+ }
50273
+ const originalLeadingSpaces = originalContent.length - originalContent.trimStart().length;
50274
+ const editedLeadingSpaces = withoutMarker.length - withoutMarker.trimStart().length;
50275
+ if (editedLeadingSpaces > originalLeadingSpaces) {
50276
+ return withoutMarker.slice(1);
50277
+ }
50278
+ return withoutMarker;
50279
+ }
50228
50280
  /**
50229
50281
  * Whether an original segment is ATOMIC: its rendered text is not what is
50230
50282
  * literally stored (a field re-substitutes its live value at render, from
@@ -50274,6 +50326,34 @@ function copySegmentMetadata(from, to) {
50274
50326
  }
50275
50327
  return to;
50276
50328
  }
50329
+ /**
50330
+ * Restore paragraph-scoped metadata on the first remapped run. Core and the
50331
+ * save writer deliberately carry these values on that run only; remapping the
50332
+ * characters must not turn an authored paragraph back into a default one.
50333
+ */
50334
+ function restoreParagraphMetadata(from, segments) {
50335
+ if (segments.length === 0) {
50336
+ return segments;
50337
+ }
50338
+ const [first, ...rest] = segments;
50339
+ const restored = { ...first };
50340
+ // `remapParagraph` may itself return a donor segment. Clear its paragraph
50341
+ // fields first so an extra paragraph cannot accidentally inherit metadata
50342
+ // merely because it reused the final paragraph for run styling.
50343
+ delete restored.paragraphLevel;
50344
+ delete restored.paragraphProperties;
50345
+ delete restored.endParaRunProperties;
50346
+ if (from?.paragraphLevel !== undefined) {
50347
+ restored.paragraphLevel = from.paragraphLevel;
50348
+ }
50349
+ if (from?.paragraphProperties !== undefined) {
50350
+ restored.paragraphProperties = from.paragraphProperties;
50351
+ }
50352
+ if (from?.endParaRunProperties !== undefined) {
50353
+ restored.endParaRunProperties = from.endParaRunProperties;
50354
+ }
50355
+ return [restored, ...rest];
50356
+ }
50277
50357
  /**
50278
50358
  * Strategy:
50279
50359
  * 1. Split both original segments and new text into paragraphs by "\n".
@@ -50286,18 +50366,25 @@ function remapTextToSegments(newText, originalSegments, elementTextStyle) {
50286
50366
  if (!originalSegments || originalSegments.length === 0) {
50287
50367
  return [{ text: newText, style: fallbackStyle }];
50288
50368
  }
50289
- // Split original segments into paragraphs by paragraph-break markers.
50290
- const originalParagraphs = [[]];
50369
+ // Split original segments into paragraphs by paragraph-break markers. Keep
50370
+ // each terminator because an authored empty paragraph has no content run, so
50371
+ // core carries its paragraph metadata on the terminator itself.
50372
+ const originalParagraphs = [
50373
+ { segments: [] },
50374
+ ];
50291
50375
  for (const seg of originalSegments) {
50292
50376
  if (seg.text === '\n' || seg.isParagraphBreak) {
50293
- originalParagraphs.push([]);
50377
+ originalParagraphs[originalParagraphs.length - 1].terminator = seg;
50378
+ originalParagraphs.push({ segments: [] });
50294
50379
  }
50295
50380
  else {
50296
- originalParagraphs[originalParagraphs.length - 1].push(seg);
50381
+ originalParagraphs[originalParagraphs.length - 1].segments.push(seg);
50297
50382
  }
50298
50383
  }
50299
50384
  const newParagraphTexts = newText.split('\n');
50300
- const firstContentSeg = originalParagraphs.flat().find((s) => s.text.trim().length > 0);
50385
+ const firstContentSeg = originalParagraphs
50386
+ .flatMap((paragraph) => paragraph.segments)
50387
+ .find((s) => s.text.trim().length > 0);
50301
50388
  const baseFallbackStyle = firstContentSeg?.style
50302
50389
  ? { ...firstContentSeg.style }
50303
50390
  : fallbackStyle;
@@ -50307,6 +50394,20 @@ function remapTextToSegments(newText, originalSegments, elementTextStyle) {
50307
50394
  ? [{ text: paraNewText, style: { ...baseFallbackStyle } }]
50308
50395
  : [{ text: '', style: { ...baseFallbackStyle } }];
50309
50396
  }
50397
+ const firstSegment = paraOrigSegments[0];
50398
+ const dedicatedMarker = isBulletMarkerSegment(firstSegment) &&
50399
+ (!firstSegment.bulletInfo?.autoNumType ||
50400
+ firstSegment.bulletInfo.paragraphIndex !== undefined)
50401
+ ? firstSegment
50402
+ : undefined;
50403
+ if (dedicatedMarker) {
50404
+ const contentSegments = paraOrigSegments.slice(1);
50405
+ const contentText = withoutRenderedBulletPrefix(paraNewText, paraOrigSegments, dedicatedMarker);
50406
+ const content = contentSegments.length > 0
50407
+ ? remapParagraph(contentText, contentSegments)
50408
+ : [{ text: contentText, style: { ...dedicatedMarker.style } }];
50409
+ return [dedicatedMarker, ...content];
50410
+ }
50310
50411
  const paragraphBulletInfo = paraOrigSegments[0].bulletInfo;
50311
50412
  if (paraNewText.length === 0) {
50312
50413
  const emptyStyle = { ...paraOrigSegments[0].style };
@@ -50385,17 +50486,18 @@ function remapTextToSegments(newText, originalSegments, elementTextStyle) {
50385
50486
  return remapped;
50386
50487
  }
50387
50488
  const output = [];
50388
- const lastOrigPara = originalParagraphs[originalParagraphs.length - 1];
50489
+ const lastOrigPara = originalParagraphs[originalParagraphs.length - 1]?.segments;
50389
50490
  for (let pi = 0; pi < newParagraphTexts.length; pi++) {
50390
50491
  if (pi > 0) {
50391
- const precedingOrigPara = originalParagraphs[pi - 1] ?? [];
50492
+ const precedingOrigPara = originalParagraphs[pi - 1]?.segments ?? [];
50392
50493
  const breakStyle = precedingOrigPara[0]?.style
50393
50494
  ? { ...precedingOrigPara[0].style }
50394
50495
  : { ...baseFallbackStyle };
50395
50496
  output.push({ text: '\n', style: breakStyle, isParagraphBreak: true });
50396
50497
  }
50397
- const origPara = originalParagraphs[pi] ?? lastOrigPara ?? [];
50398
- const paraSegments = remapParagraph(newParagraphTexts[pi], origPara);
50498
+ const originalParagraph = originalParagraphs[pi];
50499
+ const origPara = originalParagraph?.segments ?? lastOrigPara ?? [];
50500
+ const paraSegments = restoreParagraphMetadata(originalParagraph?.segments[0] ?? originalParagraph?.terminator, remapParagraph(newParagraphTexts[pi], origPara));
50399
50501
  output.push(...paraSegments);
50400
50502
  }
50401
50503
  return output.length > 0 ? output : [{ text: '', style: { ...baseFallbackStyle } }];
@@ -75018,6 +75120,20 @@ function findTemplateElement(map, slideId, elementId) {
75018
75120
  function isElementIdInteractive(elementId, editTemplateMode) {
75019
75121
  return !isTemplateElementId(elementId) || editTemplateMode;
75020
75122
  }
75123
+ /**
75124
+ * Template (layout/master) elements to actually paint for `slide`, honouring
75125
+ * PowerPoint's "Hide Background Graphics" (`p:sld/@showMasterSp="0"`,
75126
+ * `slide.showMasterShapes === false`, ECMA-376 §19.3.1.38).
75127
+ *
75128
+ * `templateElementsBySlideId` is partitioned once, at load time (see
75129
+ * {@link partitionTemplateElements}); toggling the flag afterwards does not
75130
+ * re-partition it. Every render site that paints the template layer must
75131
+ * funnel the slide's entry through this before use, so flipping the toggle
75132
+ * takes effect immediately instead of requiring a full reload.
75133
+ */
75134
+ function visibleTemplateElements(slide, templateElements) {
75135
+ return slide?.showMasterShapes === false ? [] : templateElements;
75136
+ }
75021
75137
  /** Split layout/master elements out of each loaded slide while preserving order. */
75022
75138
  function partitionTemplateElements(slides) {
75023
75139
  const templateElementsBySlideId = {};
@@ -75061,7 +75177,7 @@ const DEFAULT_PREVIEW_ELEMENT_CAP = 500;
75061
75177
  */
75062
75178
  function buildPreviewElements(slide, templateElements = [], options) {
75063
75179
  const cap = options?.cap ?? DEFAULT_PREVIEW_ELEMENT_CAP;
75064
- const merged = [...templateElements, ...slide.elements];
75180
+ const merged = [...visibleTemplateElements(slide, templateElements), ...slide.elements];
75065
75181
  if (cap > 0 && merged.length > cap) {
75066
75182
  return merged.slice(0, cap);
75067
75183
  }
@@ -80147,6 +80263,13 @@ function readEditableText(root) {
80147
80263
  if (!(child instanceof HTMLElement)) {
80148
80264
  continue;
80149
80265
  }
80266
+ // A list marker is presentation chrome, not authored paragraph text.
80267
+ // React renders it inside the contenteditable so edit mode matches view
80268
+ // mode; excluding the annotated node prevents a semantic bullet from
80269
+ // being committed as literal text (for example, "1.Item").
80270
+ if (child.hasAttribute('data-pptx-bullet-marker')) {
80271
+ continue;
80272
+ }
80150
80273
  if (child.tagName === 'BR') {
80151
80274
  out += '\n';
80152
80275
  continue;
@@ -85946,7 +86069,7 @@ function createLocalStorageBackend(namespace) {
85946
86069
  /** Try IndexedDB first; fall back to localStorage on any failure. */
85947
86070
  async function resolveBackend(dbName, namespace) {
85948
86071
  try {
85949
- const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-BZTu_DJO.mjs');
86072
+ const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-CGGwWINo.mjs');
85950
86073
  const db = await openChatDb(dbName);
85951
86074
  return createIdbBackend(db);
85952
86075
  }
@@ -91174,7 +91297,15 @@ class LoadContentService {
91174
91297
  // Trust Center > "Allow external content": gates linked (non-embedded)
91175
91298
  // http(s) image URLs. Defaults to blocked when the options service is
91176
91299
  // unreachable (e.g. constructed outside DI in a unit test).
91177
- const allowExternalImages = this.optionsService?.options().trust.allowExternalContent ?? false;
91300
+ //
91301
+ // Read UNTRACKED: this runs synchronously inside the viewer's load
91302
+ // effect, before the first await, so a tracked read here made that
91303
+ // effect depend on the whole Options store. Every preference write
91304
+ // (the AutoSave switch, a View toggle, an Options dialog field) then
91305
+ // re-parsed the deck from its original bytes, which re-seeded the
91306
+ // editor and threw away unsaved edits and the undo history. The option
91307
+ // is a load-time input, exactly as in React (`[content]` deps only).
91308
+ const allowExternalImages = untracked(() => this.optionsService?.options().trust.allowExternalContent ?? false);
91178
91309
  const parsed = await newHandler.load(buffer, { allowExternalImages });
91179
91310
  if (token !== this.renderToken) {
91180
91311
  newHandler.dispose();
@@ -104524,13 +104655,21 @@ class SlideCanvasComponent {
104524
104655
  this.lastGuideCommandId = 0;
104525
104656
  this.elements = computed(() => this.slide()?.elements ?? [], /* @ts-ignore */
104526
104657
  ...(ngDevMode ? [{ debugName: "elements" }] : /* istanbul ignore next */ []));
104658
+ /**
104659
+ * `templateElements()` filtered for "Hide Background Graphics"
104660
+ * (`showMasterShapes === false`); every consumer below reads THIS instead
104661
+ * of the raw input, so toggling the flag takes effect immediately instead
104662
+ * of requiring a full reload.
104663
+ */
104664
+ this.visibleTemplateElements = computed(() => visibleTemplateElements(this.slide(), this.templateElements()), /* @ts-ignore */
104665
+ ...(ngDevMode ? [{ debugName: "visibleTemplateElements" }] : /* istanbul ignore next */ []));
104527
104666
  /**
104528
104667
  * Template elements + the slide's own elements, template first (behind). Used
104529
104668
  * for every id-based lookup (hit-testing, selection boxes, inline-edit box) so
104530
104669
  * a selected/dragged template element resolves the same as a normal one.
104531
104670
  */
104532
104671
  this.allElements = computed(() => [
104533
- ...this.templateElements(),
104672
+ ...this.visibleTemplateElements(),
104534
104673
  ...this.elements(),
104535
104674
  ], /* @ts-ignore */
104536
104675
  ...(ngDevMode ? [{ debugName: "allElements" }] : /* istanbul ignore next */ []));
@@ -104716,7 +104855,7 @@ class SlideCanvasComponent {
104716
104855
  if (ids.length !== 1) {
104717
104856
  return null;
104718
104857
  }
104719
- const all = [...this.templateElements(), ...(this.slide()?.elements ?? [])];
104858
+ const all = [...this.visibleTemplateElements(), ...(this.slide()?.elements ?? [])];
104720
104859
  const element = all.find((candidate) => candidate.id === ids[0]);
104721
104860
  return element
104722
104861
  ? { x: element.x, y: element.y, width: element.width, height: element.height }
@@ -105467,7 +105606,7 @@ class SlideCanvasComponent {
105467
105606
  // SmartArt), so template (master/layout) element commits can resolve
105468
105607
  // their owning slide; template elements are absent from slides[].elements.
105469
105608
  { provide: SLIDE_CONTEXT, useExisting: forwardRef(() => SlideCanvasComponent) },
105470
- ], viewQueries: [{ propertyName: "textEditor", first: true, predicate: ["textEditor"], descendants: true, isSignal: true }, { propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of templateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"templateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[style.left.px]=\"h.left\"\n\t\t\t\t\t[style.top.px]=\"h.top\"\n\t\t\t\t\t[style.width.px]=\"h.size\"\n\t\t\t\t\t[style.height.px]=\"h.size\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[style.left.px]=\"rh.left\"\n\t\t\t\t\t[style.top.px]=\"rh.top\"\n\t\t\t\t\t[style.width.px]=\"rh.size\"\n\t\t\t\t\t[style.height.px]=\"rh.size\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t<textarea\n\t\t\t\t\t#textEditor\n\t\t\t\t\tdata-inline-editor\n\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t></textarea>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveInkPath() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveInkPath()\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t[attr.stroke]=\"drawColor()\"\n\t\t\t\t\t\t[attr.stroke-width]=\"drawWidth()\"\n\t\t\t\t\t\t[attr.stroke-opacity]=\"drawTool() === 'highlighter' ? 0.4 : 1\"\n\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: AiFocusHighlightOverlayComponent, selector: "pptx-ai-focus-highlight-overlay", inputs: ["highlights", "elements", "activeSlideIndex"] }, { kind: "component", type: AiChangeOverlayComponent, selector: "pptx-ai-change-overlay", inputs: ["batch", "activeSlideIndex"] }, { kind: "component", type: ActiveXControlsOverlayComponent, selector: "pptx-activex-controls-overlay", inputs: ["controls", "canvasSize"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
105609
+ ], viewQueries: [{ propertyName: "textEditor", first: true, predicate: ["textEditor"], descendants: true, isSignal: true }, { propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[style.left.px]=\"h.left\"\n\t\t\t\t\t[style.top.px]=\"h.top\"\n\t\t\t\t\t[style.width.px]=\"h.size\"\n\t\t\t\t\t[style.height.px]=\"h.size\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[style.left.px]=\"rh.left\"\n\t\t\t\t\t[style.top.px]=\"rh.top\"\n\t\t\t\t\t[style.width.px]=\"rh.size\"\n\t\t\t\t\t[style.height.px]=\"rh.size\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t<textarea\n\t\t\t\t\t#textEditor\n\t\t\t\t\tdata-inline-editor\n\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t></textarea>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveInkPath() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveInkPath()\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t[attr.stroke]=\"drawColor()\"\n\t\t\t\t\t\t[attr.stroke-width]=\"drawWidth()\"\n\t\t\t\t\t\t[attr.stroke-opacity]=\"drawTool() === 'highlighter' ? 0.4 : 1\"\n\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: AiFocusHighlightOverlayComponent, selector: "pptx-ai-focus-highlight-overlay", inputs: ["highlights", "elements", "activeSlideIndex"] }, { kind: "component", type: AiChangeOverlayComponent, selector: "pptx-ai-change-overlay", inputs: ["batch", "activeSlideIndex"] }, { kind: "component", type: ActiveXControlsOverlayComponent, selector: "pptx-activex-controls-overlay", inputs: ["controls", "canvasSize"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
105471
105610
  }
105472
105611
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SlideCanvasComponent, decorators: [{
105473
105612
  type: Component,
@@ -105486,7 +105625,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
105486
105625
  AiFocusHighlightOverlayComponent,
105487
105626
  AiChangeOverlayComponent,
105488
105627
  ActiveXControlsOverlayComponent,
105489
- ], template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of templateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"templateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[style.left.px]=\"h.left\"\n\t\t\t\t\t[style.top.px]=\"h.top\"\n\t\t\t\t\t[style.width.px]=\"h.size\"\n\t\t\t\t\t[style.height.px]=\"h.size\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[style.left.px]=\"rh.left\"\n\t\t\t\t\t[style.top.px]=\"rh.top\"\n\t\t\t\t\t[style.width.px]=\"rh.size\"\n\t\t\t\t\t[style.height.px]=\"rh.size\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t<textarea\n\t\t\t\t\t#textEditor\n\t\t\t\t\tdata-inline-editor\n\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t></textarea>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveInkPath() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveInkPath()\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t[attr.stroke]=\"drawColor()\"\n\t\t\t\t\t\t[attr.stroke-width]=\"drawWidth()\"\n\t\t\t\t\t\t[attr.stroke-opacity]=\"drawTool() === 'highlighter' ? 0.4 : 1\"\n\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"] }]
105628
+ ], template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[style.left.px]=\"h.left\"\n\t\t\t\t\t[style.top.px]=\"h.top\"\n\t\t\t\t\t[style.width.px]=\"h.size\"\n\t\t\t\t\t[style.height.px]=\"h.size\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[style.left.px]=\"rh.left\"\n\t\t\t\t\t[style.top.px]=\"rh.top\"\n\t\t\t\t\t[style.width.px]=\"rh.size\"\n\t\t\t\t\t[style.height.px]=\"rh.size\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t<textarea\n\t\t\t\t\t#textEditor\n\t\t\t\t\tdata-inline-editor\n\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t></textarea>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveInkPath() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveInkPath()\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t[attr.stroke]=\"drawColor()\"\n\t\t\t\t\t\t[attr.stroke-width]=\"drawWidth()\"\n\t\t\t\t\t\t[attr.stroke-opacity]=\"drawTool() === 'highlighter' ? 0.4 : 1\"\n\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"] }]
105490
105629
  }], ctorParameters: () => [], propDecorators: { slide: [{ type: i0.Input, args: [{ isSignal: true, alias: "slide", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], rulerUnit: [{ type: i0.Input, args: [{ isSignal: true, alias: "rulerUnit", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], gridSpacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridSpacing", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], guideCommand: [{ type: i0.Input, args: [{ isSignal: true, alias: "guideCommand", required: false }] }], spellCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheck", required: false }] }], snapToGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGuides", required: false }] }], autoFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFit", required: false }] }], transparentBackground: [{ type: i0.Input, args: [{ isSignal: true, alias: "transparentBackground", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], exposeElementIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "exposeElementIds", required: false }] }], presenting: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenting", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }], editingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "editingId", required: false }] }], editTemplateMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTemplateMode", required: false }] }], templateElements: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateElements", required: false }] }], aiHighlights: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiHighlights", required: false }] }], aiActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiActive", required: false }] }], aiActiveSlideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiActiveSlideIndex", required: false }] }], aiChangeBatch: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiChangeBatch", required: false }] }], aiPickMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiPickMode", required: false }] }], drawTool: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawTool", required: false }] }], drawColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawColor", required: false }] }], drawWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawWidth", required: false }] }], elementSelect: [{ type: i0.Output, args: ["elementSelect"] }], backgroundClick: [{ type: i0.Output, args: ["backgroundClick"] }], transformStart: [{ type: i0.Output, args: ["transformStart"] }], transformUpdate: [{ type: i0.Output, args: ["transformUpdate"] }], transformEnd: [{ type: i0.Output, args: ["transformEnd"] }], adjustUpdate: [{ type: i0.Output, args: ["adjustUpdate"] }], connectorEndpointUpdate: [{ type: i0.Output, args: ["connectorEndpointUpdate"] }], contextMenu: [{ type: i0.Output, args: ["contextMenu"] }], textEditStart: [{ type: i0.Output, args: ["textEditStart"] }], textCommit: [{ type: i0.Output, args: ["textCommit"] }], textInput: [{ type: i0.Output, args: ["textInput"] }], textCancel: [{ type: i0.Output, args: ["textCancel"] }], textFormat: [{ type: i0.Output, args: ["textFormat"] }], rotateUpdate: [{ type: i0.Output, args: ["rotateUpdate"] }], marqueeSelect: [{ type: i0.Output, args: ["marqueeSelect"] }], inkStrokeComplete: [{ type: i0.Output, args: ["inkStrokeComplete"] }], eraserHit: [{ type: i0.Output, args: ["eraserHit"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], tableChange: [{ type: i0.Output, args: ["tableChange"] }], textEditor: [{ type: i0.ViewChild, args: ['textEditor', { isSignal: true }] }], stageRef: [{ type: i0.ViewChild, args: ['stage', { isSignal: true }] }], viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], onPointerMove: [{
105491
105630
  type: HostListener,
105492
105631
  args: ['document:pointermove', ['$event']]
@@ -106898,7 +107037,7 @@ class MobilePresenterViewComponent {
106898
107037
  if (!slide) {
106899
107038
  return undefined;
106900
107039
  }
106901
- const template = this.templateElements();
107040
+ const template = visibleTemplateElements(slide, this.templateElements());
106902
107041
  if (template.length === 0) {
106903
107042
  return slide;
106904
107043
  }
@@ -112137,13 +112276,25 @@ class ViewerThemeGalleryService {
112137
112276
  }
112138
112277
  applyCustomTheme(colorScheme, fontScheme, name) {
112139
112278
  const currentSlides = this.editor.slides();
112279
+ const previousColorMap = this.loader.themeColorMap() ?? {};
112140
112280
  const result = applyThemeToData({
112141
112281
  slides: [...currentSlides],
112142
112282
  theme: this.loader.theme() ?? {},
112143
- themeColorMap: this.loader.themeColorMap() ?? {},
112283
+ themeColorMap: previousColorMap,
112144
112284
  }, colorScheme, fontScheme, name);
112145
112285
  // Write slides back through the editor (records undo history).
112146
112286
  this.editor.applyReplacement(result.slides, this.translate.instant('pptx.undoAction.applyTheme', { name }));
112287
+ // Master/layout elements render as a separate per-slide layer (not part
112288
+ // of `slide.elements`), so `applyReplacement` above never touches them;
112289
+ // left alone they'd keep painting the old scheme's colours.
112290
+ const currentTemplateElements = this.editor.templateElementsBySlideId();
112291
+ if (Object.keys(currentTemplateElements).length > 0) {
112292
+ const recoloured = {};
112293
+ for (const [slideId, elements] of Object.entries(currentTemplateElements)) {
112294
+ recoloured[slideId] = reResolveElementColors(elements, previousColorMap, colorScheme);
112295
+ }
112296
+ this.editor.templateElementsBySlideId.set(recoloured);
112297
+ }
112147
112298
  // Update the loader's theme signals so the check-mark and future switches are correct.
112148
112299
  this.loader.theme.set(result.theme);
112149
112300
  this.loader.themeColorMap.set(result.themeColorMap);
@@ -114711,10 +114862,11 @@ function classicIncomingLayerSlide(isMorph, incomingAnimation, incomingSlide, te
114711
114862
  if (isMorph || incomingAnimation === 'none' || !incomingSlide) {
114712
114863
  return undefined;
114713
114864
  }
114714
- if (templateElements.length === 0) {
114865
+ const visible = visibleTemplateElements(incomingSlide, templateElements);
114866
+ if (visible.length === 0) {
114715
114867
  return incomingSlide;
114716
114868
  }
114717
- return { ...incomingSlide, elements: [...templateElements, ...incomingSlide.elements] };
114869
+ return { ...incomingSlide, elements: [...visible, ...incomingSlide.elements] };
114718
114870
  }
114719
114871
  /**
114720
114872
  * The slide the overlay paints ABOVE its ghosts, or `undefined` when a morph
@@ -114892,7 +115044,7 @@ class PresentationTransitionOverlayComponent {
114892
115044
  if (plan) {
114893
115045
  return { ...slide, elements: [...plan.outgoingElements] };
114894
115046
  }
114895
- const template = this.templateElements();
115047
+ const template = visibleTemplateElements(slide, this.templateElements());
114896
115048
  if (template.length === 0) {
114897
115049
  return slide;
114898
115050
  }
@@ -115308,11 +115460,14 @@ class PresenterSlideNavigatorComponent {
115308
115460
  ...(ngDevMode ? [{ debugName: "tileZoom" }] : /* istanbul ignore next */ []));
115309
115461
  this.tiles = computed(() => {
115310
115462
  const template = this.templateElements();
115311
- return this.slides().map((slide, index) => ({
115312
- slide: template.length > 0 ? { ...slide, elements: [...template, ...slide.elements] } : slide,
115313
- index,
115314
- key: slide.id || `slide-${String(index)}`,
115315
- }));
115463
+ return this.slides().map((slide, index) => {
115464
+ const visible = visibleTemplateElements(slide, template);
115465
+ return {
115466
+ slide: visible.length > 0 ? { ...slide, elements: [...visible, ...slide.elements] } : slide,
115467
+ index,
115468
+ key: slide.id || `slide-${String(index)}`,
115469
+ };
115470
+ });
115316
115471
  }, /* @ts-ignore */
115317
115472
  ...(ngDevMode ? [{ debugName: "tiles" }] : /* istanbul ignore next */ []));
115318
115473
  }
@@ -116723,7 +116878,7 @@ class PresenterViewComponent {
116723
116878
  if (!slide) {
116724
116879
  return undefined;
116725
116880
  }
116726
- const template = this.templateElements();
116881
+ const template = visibleTemplateElements(slide, this.templateElements());
116727
116882
  if (template.length === 0) {
116728
116883
  return slide;
116729
116884
  }
@@ -118626,6 +118781,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
118626
118781
  * {@link RibbonFontControlsComponent} and {@link RibbonParagraphControlsComponent}
118627
118782
  * mutate the selection's `textStyle` through the same code path).
118628
118783
  */
118784
+ /**
118785
+ * The live (uncommitted) plain text of the open inline-edit `<textarea
118786
+ * data-inline-editor>`, or `undefined` when none is open. The textarea is
118787
+ * UNCONTROLLED (see `slide-canvas.component.ts`): typing updates its own
118788
+ * `.value` and only publishes to collaboration broadcast on input, never the
118789
+ * model, so `element.textSegments`/`.text` can be stale relative to what is
118790
+ * on screen for the whole edit session, not just mid-keystroke.
118791
+ */
118792
+ function currentInlineEditorText() {
118793
+ if (typeof document === 'undefined') {
118794
+ return undefined;
118795
+ }
118796
+ const editor = document.querySelector(INLINE_EDITOR_SELECTOR);
118797
+ return editor ? editor.value : undefined;
118798
+ }
118629
118799
  /** The selection's text style, or null when the element carries no text props. */
118630
118800
  function textStyleOf(el) {
118631
118801
  return el && hasTextProperties(el) ? (el.textStyle ?? null) : null;
@@ -118651,12 +118821,21 @@ function transformSelectedTextCase(editor, slideIndex, el, mode) {
118651
118821
  if (!el || !hasTextProperties(el)) {
118652
118822
  return;
118653
118823
  }
118824
+ // Reconcile against the live inline-editor text first (same remap the
118825
+ // commit path uses): case-transforming a stale snapshot leaves whatever the
118826
+ // user typed since untransformed once the edit session commits. See
118827
+ // `currentInlineEditorText`.
118828
+ const liveText = currentInlineEditorText();
118829
+ const baseSegments = liveText !== undefined && el.textSegments
118830
+ ? remapTextToSegments(liveText, el.textSegments, el.textStyle)
118831
+ : el.textSegments;
118832
+ const baseText = liveText ?? el.text;
118654
118833
  const updates = {};
118655
- if (el.textSegments && el.textSegments.length > 0) {
118656
- updates.textSegments = el.textSegments.map((s) => s.isParagraphBreak || s.text === '\n' ? s : { ...s, text: transformTextCase(s.text, mode) });
118834
+ if (baseSegments && baseSegments.length > 0) {
118835
+ updates.textSegments = baseSegments.map((s) => s.isParagraphBreak || s.text === '\n' ? s : { ...s, text: transformTextCase(s.text, mode) });
118657
118836
  }
118658
- if (typeof el.text === 'string') {
118659
- updates.text = transformTextCase(el.text, mode);
118837
+ if (typeof baseText === 'string') {
118838
+ updates.text = transformTextCase(baseText, mode);
118660
118839
  }
118661
118840
  editor.updateElement(slideIndex, el.id, updates);
118662
118841
  }
@@ -122954,7 +123133,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
122954
123133
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }] } });
122955
123134
 
122956
123135
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
122957
- const PPTX_ANGULAR_VIEWER_VERSION = "3.5.0";
123136
+ const PPTX_ANGULAR_VIEWER_VERSION = "3.6.0";
122958
123137
 
122959
123138
  /**
122960
123139
  * account-page.component.ts: File > Account content.
@@ -144413,6 +144592,8 @@ class SlideBackgroundCardComponent {
144413
144592
  return Boolean(sl?.backgroundColor || sl?.backgroundImage || sl?.backgroundGradient);
144414
144593
  }, /* @ts-ignore */
144415
144594
  ...(ngDevMode ? [{ debugName: "hasBackground" }] : /* istanbul ignore next */ []));
144595
+ this.hideBackgroundGraphics = computed(() => this.slide()?.showMasterShapes === false, /* @ts-ignore */
144596
+ ...(ngDevMode ? [{ debugName: "hideBackgroundGraphics" }] : /* istanbul ignore next */ []));
144416
144597
  this.editTemplateMode = this.editor.editTemplateMode;
144417
144598
  /**
144418
144599
  * The active slide's layout/master, when it has one to edit (Master Views
@@ -144475,6 +144656,10 @@ class SlideBackgroundCardComponent {
144475
144656
  backgroundGradient: undefined,
144476
144657
  });
144477
144658
  }
144659
+ onToggleHideBackgroundGraphics(event) {
144660
+ const checked = event.target.checked;
144661
+ this.patch({ showMasterShapes: !checked });
144662
+ }
144478
144663
  patch(changes) {
144479
144664
  this.editor.updateSlide(this.slideIndex(), changes);
144480
144665
  }
@@ -144549,6 +144734,18 @@ class SlideBackgroundCardComponent {
144549
144734
  {{ 'pptx.slideBackground.clearBackground' | translate }}
144550
144735
  </button>
144551
144736
  }
144737
+
144738
+ <label class="icard__row">
144739
+ <input
144740
+ type="checkbox"
144741
+ [checked]="hideBackgroundGraphics()"
144742
+ [disabled]="!canEdit()"
144743
+ (change)="onToggleHideBackgroundGraphics($event)"
144744
+ />
144745
+ <span class="icard__label">{{
144746
+ 'pptx.slideBackground.hideBackgroundGraphics' | translate
144747
+ }}</span>
144748
+ </label>
144552
144749
  </section>
144553
144750
  }
144554
144751
  @if (editTemplateMode() && (templateRows().layout || templateRows().master)) {
@@ -144662,6 +144859,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
144662
144859
  {{ 'pptx.slideBackground.clearBackground' | translate }}
144663
144860
  </button>
144664
144861
  }
144862
+
144863
+ <label class="icard__row">
144864
+ <input
144865
+ type="checkbox"
144866
+ [checked]="hideBackgroundGraphics()"
144867
+ [disabled]="!canEdit()"
144868
+ (change)="onToggleHideBackgroundGraphics($event)"
144869
+ />
144870
+ <span class="icard__label">{{
144871
+ 'pptx.slideBackground.hideBackgroundGraphics' | translate
144872
+ }}</span>
144873
+ </label>
144665
144874
  </section>
144666
144875
  }
144667
144876
  @if (editTemplateMode() && (templateRows().layout || templateRows().master)) {
@@ -152969,9 +153178,15 @@ class PowerPointViewerComponent {
152969
153178
  this.content();
152970
153179
  this.fileIO.contentOverride.set(null);
152971
153180
  });
152972
- // Load whenever the active content (picked override, else input) changes.
153181
+ // Load whenever the active content (picked override, else input) changes,
153182
+ // and ONLY then (React: `useEffect(..., [content])`). The call itself is
153183
+ // untracked so no signal `load()` reads before its first await (it used
153184
+ // to read the Options store for Trust Center > "Allow external content")
153185
+ // can re-arm this effect: a tracked read there made every preference
153186
+ // write re-parse the deck and re-seed the editor from the original bytes.
152973
153187
  effect(() => {
152974
- void this.loader.load(this.fileIO.activeContent());
153188
+ const content = this.fileIO.activeContent();
153189
+ untracked(() => void this.loader.load(content));
152975
153190
  });
152976
153191
  // Reset to the first slide and seed the editable deck whenever a new
152977
153192
  // presentation finishes loading. Only loader.slides() may be tracked
@@ -158490,4 +158705,4 @@ function cn(...values) {
158490
158705
  */
158491
158706
 
158492
158707
  export { ColorChangedImageComponent as $, AFTER_ANIMATION_VALUES as A, AnimationPanelComponent as B, AnimationPlaybackService as C, AutosaveRecoveryDialogComponent as D, AutosaveService as E, BroadcastDialogComponent as F, CHART_EDITOR_STYLES as G, CURSOR_PALETTE as H, CanvasFitService as I, ChartAxisOptionsComponent as J, ChartAxisStyleOptionsComponent as K, ChartComboTypeOptionsComponent as L, ChartDataEditorComponent as M, ChartDataLabelOptionsComponent as N, ChartDatapointMarkerOptionsComponent as O, ChartDatapointOptionsComponent as P, ChartDisplayOptionsComponent as Q, ChartElementViewComponent as R, ChartErrorBarOptionsComponent as S, ChartMarkerOptionsComponent as T, ChartPartSelectionService as U, ChartPrimitivesComponent as V, ChartRendererComponent as W, ChartTrendlineOptionsComponent as X, ChartTypeSelectorComponent as Y, CollaborationCursorsComponent as Z, CollaborationService as _, ALIGN_OPTIONS as a, InspectorPanelComponent as a$, CommentMarkersOverlayComponent as a0, CommentsPanelComponent as a1, CommentsService as a2, ComparePanelComponent as a3, ConnectorRendererComponent as a4, ConnectorTextOverlayComponent as a5, CustomShowsComponent as a6, DEFAULT_BOUNDS as a7, DEFAULT_BROADCAST_SERVER_URL as a8, DEFAULT_CANVAS_HEIGHT as a9, ElementRendererComponent as aA, EmbeddedFontsService as aB, EncryptedFileDialogComponent as aC, EquationEditorDialogComponent as aD, EquationRendererComponent as aE, EquationTemplateGalleryComponent as aF, ExportProgressModalComponent as aG, ExportService as aH, FieldContextService as aI, FindBarComponent as aJ, FindReplaceBarComponent as aK, FollowModeBarComponent as aL, FontEmbeddingListComponent as aM, FontEmbeddingPanelComponent as aN, GALLERY_THEME_PRESETS as aO, GOOGLE_WEBFONTS_LINK_ID as aP, GRIDLINE_COLOR$1 as aQ, GoogleWebfontsService as aR, GradientPickerComponent as aS, HANDOUT_OPTIONS as aT, HeaderFooterDialogComponent as aU, HyperlinkDialogComponent as aV, ImagePropertiesPanelComponent as aW, InkDrawingService as aX, InkRendererComponent as aY, InsertSmartArtDialogComponent as aZ, InspectorPaneHeaderComponent as a_, DEFAULT_CANVAS_WIDTH as aa, DEFAULT_COLOR_SCHEME as ab, DEFAULT_FILL_COLOR$1 as ac, DEFAULT_LAYOUT as ad, DEFAULT_PALETTE$1 as ae, DEFAULT_PATTERN_FILL_PRESET as af, DEFAULT_PRINT_SETTINGS as ag, DEFAULT_SLIDE_BACKGROUND as ah, DEFAULT_STROKE_COLOR as ai, DEFAULT_STYLE as aj, DEFAULT_TABLE_ROW_HEIGHT as ak, DEFAULT_TEXT_COLOR$2 as al, DEFAULT_VIEWER_PROFILE as am, DIRECTIONAL_PRESETS as an, DIRECTION_OPTIONS as ao, DocumentPropertiesCardComponent as ap, EMBEDDED_FONTS_STYLE_ID as aq, EMPHASIS_PRESETS as ar, ENTRANCE_PRESETS as as, TEMPLATES as at, EXIT_PRESETS as au, EditorContextMenuComponent as av, EditorHistory as aw, EditorStateService as ax, EditorToolbarComponent as ay, EffectsPanelComponent as az, ANIMATION_PRESET_CATEGORIES as b, RibbonComponent as b$, IsMobileService as b0, KeepAnnotationsDialogComponent as b1, LOCALE_CATALOG as b2, LONG_PRESS_DURATION_MS as b3, LONG_PRESS_MOVE_TOLERANCE_PX as b4, LoadContentService as b5, LocalPresencePublisher as b6, MAX_ZOOM_SCALE as b7, MIN_ZOOM_SCALE as b8, MOTION_PATH_COLUMNS as b9, PasswordStrengthMeterComponent as bA, PowerPointViewerComponent as bB, PresentToolbarAutoHide as bC, PresentationAnnotationOverlayComponent as bD, PresentationAnnotationsService as bE, PresentationOverlayComponent as bF, PresentationPropertiesPanelComponent as bG, PresentationSettingsCardComponent as bH, PresentationSubtitleBarComponent as bI, PresentationToolbarComponent as bJ, PresentationTransitionOverlayComponent as bK, PresenterViewComponent as bL, PresenterWindowService as bM, PrintDialogComponent as bN, PrintService as bO, PrintSettingsPanelComponent as bP, PropertiesDialogComponent as bQ, REPEAT_MODE_OPTIONS as bR, RESIZE_HANDLES as bS, RULER_FONT_SIZE as bT, RULER_THICKNESS as bU, ReadingViewOverlayComponent as bV, RemoteSelectionOverlayComponent as bW, RibbonAnimationGalleryComponent as bX, RibbonAnimationsSectionComponent as bY, RibbonArrangeSectionComponent as bZ, RibbonColorPopoverComponent as b_, MediaPreviewComponent as ba, MediaPropertiesPanelComponent as bb, MediaRendererComponent as bc, MediaTrimTimelineComponent as bd, MobileBottomBarComponent as be, MobileMenuSheetComponent as bf, MobilePresenterViewComponent as bg, MobileSheetComponent as bh, MobileSlidesSheetComponent as bi, MobileToolbarComponent as bj, ModalDialogComponent as bk, Model3DRendererComponent as bl, NotesHandoutCardComponent as bm, NotesPanelComponent as bn, NotesToolbarComponent as bo, OleRendererComponent as bp, OutlineViewOverlayComponent as bq, POWER_POINT_VIEWER_PROVIDERS as br, PPTX_OPEN_ACCEPT as bs, PRESENTATION_OPEN_EXTENSIONS as bt, PRESENTER_CHANNEL_NAME as bu, PRESENTER_MSG_ORIGIN as bv, PRESENTER_TIMER_SEGMENT_MS as bw, PX_PER_CM as bx, PX_PER_INCH as by, PasswordProtectionDialogComponent as bz, AUDIENCE_HASH as c, TEXT_3D_TOP_BEVEL_KEYS as c$, RibbonDesignSectionComponent as c0, RibbonDrawSectionComponent as c1, RibbonDrawingGroupComponent as c2, RibbonEditingSectionComponent as c3, RibbonFileSectionComponent as c4, RibbonFontControlsComponent as c5, RibbonHomeSectionComponent as c6, RibbonHyperlinkButtonComponent as c7, RibbonInsertFieldsComponent as c8, RibbonInsertSectionComponent as c9, SettingsLanguageTabComponent as cA, ShareDialogComponent as cB, ShortcutPanelComponent as cC, ShowOptionsFieldsetComponent as cD, ShowSlidesFieldsetComponent as cE, SignatureStrippedDialogComponent as cF, SignaturesPanelComponent as cG, SignaturesService as cH, SlideBackgroundCardComponent as cI, SlideCanvasComponent as cJ, SlideDefaultInspectorComponent as cK, SlideDiffChangesComponent as cL, SlideDiffRowComponent as cM, SlideDiffThumbnailsComponent as cN, SlideSizeCardComponent as cO, SlideSorterOverlayComponent as cP, SlideThemeOverridePanelComponent as cQ, SlideTransitionCardComponent as cR, SlidesPanelComponent as cS, SmartArt3DRendererComponent as cT, SmartArt3DService as cU, SmartArtPreviewComponent as cV, SmartArtPropertiesComponent as cW, SmartArtRendererComponent as cX, StatusBarComponent as cY, TABLE_STRUCTURE_TOGGLES as cZ, TEXT_3D_BOTTOM_BEVEL_KEYS as c_, RibbonMotionPathGalleryComponent as ca, RibbonParagraphControlsComponent as cb, RibbonPrimaryRowComponent as cc, RibbonReviewSectionComponent as cd, RibbonShapeExtrasComponent as ce, RibbonSlideshowSectionComponent as cf, RibbonTransitionsSectionComponent as cg, RibbonViewSectionComponent as ch, RulerGuidesService as ci, SEQUENCE_OPTIONS as cj, SEVERITY_GROUPS as ck, SEVERITY_LABELS as cl, SHORTCUT_REFERENCE_ITEMS as cm, SLIDE_TRANSITION_KEYFRAMES as cn, DEFAULT_PALETTE as co, PALETTES$1 as cp, SMART_ART_COLOR_SCHEMES as cq, SMART_ART_STYLE_OPTIONS as cr, SUB_ITEM_LABEL as cs, SVG_WARP_PRESETS as ct, SWIPE_MAX_VERTICAL_PX as cu, SWIPE_THRESHOLD_PX as cv, SelectionPaneComponent as cw, SetUpSlideShowDialogComponent as cx, SettingsAppearanceTabComponent as cy, SettingsDialogComponent as cz, AUDIENCE_NONCE_KEY as d, animationPresetLabelKey as d$, TEXT_DIRECTION_OPTIONS$1 as d0, THEME_CATALOG as d1, TIMING_CURVE_OPTIONS as d2, TRIGGER_OPTIONS as d3, TYPE_LABELS as d4, TableCellAdvancedFillComponent as d5, TableCellFormattingComponent as d6, TableDataEditorComponent as d7, TablePropertiesComponent as d8, TableRendererComponent as d9, ViewerFileIOService as dA, ViewerFindReplaceService as dB, ViewerFormatPainterService as dC, ViewerInspectorPanelService as dD, ViewerKeyboardService as dE, ViewerMobileSheetService as dF, ViewerPresentationModeService as dG, ViewerThemeGalleryService as dH, ViewerTouchGesturesService as dI, ViewerZoomService as dJ, WEBM_MIME_CANDIDATES as dK, WriteBackScheduler as dL, ZERO_LINE_COLOR as dM, ZoomNavigationService as dN, ZoomRendererComponent as dO, ZoomTargetService as dP, addCategory as dQ, addCommentToList as dR, addGradientStopPatch as dS, addItem as dT, addSeries as dU, addSubItem as dV, advanceStep as dW, affordanceElements as dX, aiToggleVisible as dY, alignPatch as dZ, animationFor as d_, TableResizeOverlayComponent as da, TableSelectionService as db, TagsCardComponent as dc, Text3DBevelSectionComponent as dd, Text3DPanelComponent as de, TextAdvancedPanelComponent as df, ThemeEditorFieldsComponent as dg, ThemeGalleryComponent as dh, ThemeSelectorCardComponent as di, TitleBarComponent as dj, TitleBarSearchComponent as dk, TransitionDirectionPickerComponent as dl, TransitionPreviewComponent as dm, VALIGN_OPTIONS as dn, VIEWER_THEME as dp, VersionHistoryPanelComponent as dq, ViewerCanvasEditingService as dr, ViewerCollabCursorService as ds, ViewerCollaborationSessionService as dt, ViewerCompareService as du, ViewerCustomShowsService as dv, ViewerDialogsService as dw, ViewerDocumentPropertiesService as dx, ViewerExportService as dy, ViewerExtraDialogsComponent as dz, AVATAR_COLOR_SWATCHES as e, buildTreemapViewModel as e$, annotationMapToInkInserts as e0, applyAcceptedDiff as e1, applyAnimationPreset as e2, applyFindReplacements as e3, applyFormatToElement as e4, applyMove as e5, applyResize as e6, asMediaElement as e7, assignUserColor as e8, attachShowVisibilityPause as e9, buildEquationSegment as eA, buildFallbackViewModel as eB, buildFontFaceRule as eC, buildGradientFillCss as eD, buildGridlinesAndLabels as eE, buildHyperlinkPatch as eF, buildInkContainerStyle as eG, buildInkStrokes as eH, buildLegend as eI, buildMarkTooltip as eJ, buildModel3DContainerStyle as eK, buildModel3DViewModel as eL, buildOleActionModel as eM, buildOleInfoRows as eN, buildPatternFillCss as eO, buildPieViewModel as eP, buildPrintHtmlDocument as eQ, buildPropertiesPatch as eR, buildRadarViewModel as eS, buildRegionMapViewModel as eT, buildSaveSlides as eU, buildShareUrl as eV, buildSmartArtInsertElement as eW, buildSmartArtNodes as eX, buildStockViewModel as eY, buildSurfaceViewModel as eZ, buildTableViewModel as e_, attachTouchGestures as ea, axisTickValues as eb, beginNodeEdit as ec, bevelSizePatch as ed, boolFromEvent as ee, bringForward as ef, bringToFront as eg, buildBarActions as eh, buildBroadcastConfig as ei, buildBroadcastViewerUrl as ej, buildCategoryLabels as ek, buildCellParagraphs as el, buildChartViewModel as em, buildChatLogExport as en, buildChatLogMarkdown as eo, buildChromeStyle as ep, buildClearHyperlinkPatch as eq, buildClickGroups as er, buildColStyles as es, buildCollaborationConfig as et, buildComboViewModel as eu, buildCssGradientFromShapeStyle as ev, buildDuotoneFilter as ew, buildDuotoneFilterId as ex, buildEmbeddedFontStyles as ey, buildEquationElement as ez, AXIS_LABEL_COLOR as f, computeRotateHandleBox as f$, buildTrimFragment as f0, buildWaterfallViewModel as f1, buildZeroLine as f2, buildZoomContainerStyle as f3, buildZoomViewModel as f4, bulletIndentPx as f5, canAddTopLevelNode as f6, canGroupSelection as f7, canRemoveTopLevelNode as f8, canSetStrokeWidth as f9, collectUsedFontFamilies as fA, columnWidthStyle as fB, commitNodeText as fC, computeAlign as fD, computeAxisTitlePrimitives as fE, computeBarRects as fF, computeBubbleRadius as fG, computeCornerHandle as fH, computeDistribute as fI, computeDrawingViewBox as fJ, computeErrorBarPrimitives as fK, computeFocusTargets as fL, computeGridSpacingPx as fM, computeHandleBoxes as fN, computeHandoutLayout as fO, computeIsMobile as fP, computeIsTablet as fQ, computeLinePoints as fR, computeLinearRegression as fS, computePageCount as fT, computePieLayout as fU, computePieSlicePath as fV, computePieSlices as fW, computePlotLayout as fX, computeRSquared as fY, computeRadarPoints as fZ, computeResizeHandleBoxes as f_, canStartBroadcast as fa, canStartShare as fb, canUngroupSelection as fc, canUseClipboard as fd, captionDisplayText as fe, cellRunStyle as ff, cellStyleToStyleMap as fg, cellTdStyle as fh, changeCountLabel as fi, changeIcon as fj, characterSpacingPatch as fk, chartPreserveAspectRatio as fl, checkFontAvailable as fm, clampCursorPosition as fn, clampGifDimensions as fo, clampIndex as fp, clampNotesFontSize as fq, clampScale as fr, clampStep as fs, clearAllLocalViewerData as ft, clearAudienceContent as fu, cn as fv, collectAccessibilityIssues as fw, collectElementText as fx, collectSlideText as fy, collectStoredChats as fz, AccessibilityPanelComponent as g, formatAxisValue as g$, computeScatterDots as g0, computeScatterXDomain as g1, computeSelectionBoxes as g2, computeSingleSelected as g3, computeSlideIndices as g4, computeSnap as g5, computeStackedBarRects as g6, computeStackedValueRange as g7, computeTrendlinePrimitives as g8, computeValueRange as g9, disableSoftEdgePatch as gA, duplicateElementById as gB, durationOf as gC, effectsStateOf as gD, enableGlowPatch as gE, enableInnerShadowPatch as gF, enableOuterShadowPatch as gG, enableReflectionPatch as gH, enableSoftEdgePatch as gI, encodeGif as gJ, endShowMediaCleanup as gK, estimatePageCount as gL, exitPresentationFullscreen as gM, exportAiChatLogs as gN, extractPathPoints as gO, eyedropperAvailable as gP, fillColorOf$1 as gQ, findInSlides as gR, findOwningSlideIndex as gS, findSlideIndexByElementId as gT, firstVisibleIndex as gU, fitPolynomial as gV, fitZoom as gW, focusTargetChips as gX, fontMimeForFormat as gY, fontSizeOf as gZ, forgetSessionDeck as g_, convertOmmlToMathMl as ga, copyFormatFromElement as gb, countAccessibilityIssues as gc, countAnnotationStrokes as gd, createAngularAiBridge as ge, createCustomShow as gf, createSwipeDismissDrag as gg, createWebrtcBundle as gh, createWebsocketBundle as gi, cssObjectToStyleMap as gj, currentColorScheme as gk, currentLayout as gl, currentStyle as gm, defaultCssVars as gn, defaultRadius as go, defaultThemeColors as gp, deleteElementsByIds as gq, deleteVersion as gr, demoteNode as gs, deriveModel3DBlobUrl as gt, derivePresenceList as gu, describeSmartArtBounds as gv, disableGlowPatch as gw, disableInnerShadowPatch as gx, disableOuterShadowPatch as gy, disableReflectionPatch as gz, AccessibilityService as h, isElementInteractive as h$, formatBytes as h0, formatCursorLabel as h1, formatElapsed as h2, formatFileSize as h3, formatPropertyDate as h4, formatTime as h5, fpsToFrameIntervalMs as h6, generateBroadcastRoomId as h7, generateCommentId as h8, generateCustomShowId as h9, getTextBlockStyle as hA, getTextWarp as hB, getTouchDistance as hC, getWarpCategory as hD, getWarpPath as hE, gradientStateFromStyle as hF, gradientStateOf as hG, gradientStatePatch as hH, gridColumns as hI, groupIssuesBySeverity as hJ, hasAnimation as hK, hasCopyableFormat as hL, hasExistingLink as hM, hasExitedFullscreen as hN, hasGradientFill as hO, hasPressureVariation as hP, hasVisibleSlideAfter as hQ, headerLabel as hR, imageDimensions as hS, inkViewBox as hT, insertTableElementColumn as hU, insertTableElementRow as hV, interpolateWidth as hW, isAudienceTab as hX, isBold as hY, isBrowserOpenableMime as hZ, isChildNode as h_, generatePressureCircles as ha, generateTicks as hb, getClrChangeParams as hc, getContainerStyle as hd, getDuotoneFilterDef as he, getEffectSoundState as hf, getImageSrc as hg, getLocalStorageUsageSummary as hh, getOleAriaLabel as hi, getOleBadgeLabel as hj, getOleDisplayName as hk, getOleDownloadFileName as hl, getOleTypeColor as hm, getOleTypeLabel as hn, getPasswordStrength as ho, getPatternSvg as hp, getPlaceholderStyle as hq, getVersions as hr, getResolvedShapeClipPath as hs, getResolvedShapeClipPathFor as ht, getSessionTabId as hu, getShapeFillStrokeStyle as hv, getSlideBackgroundStyle as hw, getSlideTransitionAnimations as hx, getSmartArtNodeBounds as hy, getSpeechRecognitionCtor as hz, AccountPageComponent as i, overallStatus as i$, isInjectableUrl as i0, isItalic as i1, isLegacyBinaryPresentation as i2, isPpactionUrl as i3, isPresenterMessage as i4, isSigned as i5, isSupportedPresentationFile as i6, isTextElement as i7, isTwoTableFocus as i8, isUnderline as i9, moveNodeUp as iA, msToFrameDelayCs as iB, narrowToCircle as iC, narrowToPolygon as iD, narrowToRect as iE, newChartElement as iF, newEquationElement as iG, newPresetShapeElement as iH, newShapeElement as iI, newSmartArtElement as iJ, newTableElement as iK, newTextElement as iL, nextVisibleIndex as iM, nodeBold as iN, nodeEditBox as iO, nodeFillColor as iP, nodeFontColor as iQ, nodeIdFromKey as iR, nodeItalic as iS, nodeStyle as iT, normalizeFontFormat as iU, normalizeSlidesPerPage as iV, normalizeValue as iW, numFromEvent as iX, ommlToMathml as iY, ooxmlDashToCssBorderStyle as iZ, openNativeEyeDropper as i_, isUrlSafe as ia, isValidRoomId as ib, isViewportBackgroundPressTarget as ic, isZoomActivationKey as id, issueTrackKey as ie, issueTypeLabel as ig, keyToLabel as ih, lastVisibleIndex as ii, latexToMathml as ij, layoutConnectorPaints as ik, layoutNodeLabels as il, linePointsToSvgString as im, lineSpacingPatch as io, loadAudienceContent as ip, loadSessionDeck as iq, mediaFallbackFor as ir, mediaSurfaceFor as is, mergeCaptionResults as it, mergeDown as iu, mergeRight as iv, mergeSelection as iw, mergeTablesDirective as ix, moveElementBy as iy, moveNodeDown as iz, ActionSettingsPanelComponent as j, resolveTransitionDuration as j$, paletteColor as j0, parseAudienceNonce as j1, parseNodeTextarea as j2, partitionSlides as j3, patchChartData as j4, patchChartStyle as j5, patchTableData as j6, patchTextStyle as j7, patternPresetOptions as j8, pendingElementStyles as j9, removeCommentFromList as jA, removeElementAnimation as jB, removeGradientStopPatch as jC, removeNode as jD, removeTableElementRow as jE, removeSeries as jF, renderToCanvas as jG, reorderAnimationDown as jH, reorderAnimationUp as jI, replaceInSlides as jJ, replaceMatch as jK, requestPresentationFullscreen as jL, resizeElement as jM, resolveCaptionTracks as jN, resolveChartKind as jO, resolveFontVariant as jP, resolveHyperlinkHref as jQ, resolveInteractiveElementId as jR, resolveMediaSrc as jS, resolveOleType as jT, resolveParagraphBullet as jU, resolvePresenterNotes as jV, resolveProfileInitial as jW, resolveRegionCode as jX, resolveSlideAutoAdvanceMs as jY, resolvePalette as jZ, resolveThemeCatalogEntry as j_, pickColorByClickFallback as ja, pickFile as jb, pickSupportedMimeType as jc, planGifFrames as jd, planVideoSegments as je, pointsToSvgPathD as jf, presenceToCursors as jg, presentationBaseName as jh, presentationStageStyle as ji, presenterTimerProgress as jj, presetByLayout as jk, presetsForCategory as jl, pressuresToWidths as jm, prevVisibleIndex as jn, projectDrawingShapes as jo, promoteNode as jp, provideViewerTheme as jq, radarAngle as jr, radarRingPoints as js, readAsDataUrl as jt, recordWebm as ju, registerCrossSlideAudio as jv, rememberSessionDeck as jw, removeAnimation as jx, removeCategory as jy, removeTableElementColumn as jz, AdvancedChartEditorComponent as k, setTimingCurve as k$, restoreSessionDeck as k0, revealedElementStyles as k1, routeOrthogonalConnector as k2, rowStyle as k3, rulerDragToGuidePosition as k4, rulerHighlight as k5, rulerStripTicks as k6, sampleColorFromSlide as k7, sanitizeColor as k8, sanitizeSlideIndex as k9, setColorScheme as kA, setDataLabels as kB, setDataPointExplosion as kC, setDataPointFill as kD, setDataPointLabel as kE, setDataPointMarker as kF, setDelay as kG, setDirection as kH, setDuration as kI, setEffectSound as kJ, setElementPosition as kK, setGridlineStyle as kL, setLayout as kM, setLegend as kN, setNodeStyle as kO, setNodeText as kP, setRepeatCount as kQ, setRepeatMode as kR, setSequence as kS, setSeriesChartType as kT, setSeriesColor as kU, setSeriesErrorBars as kV, setSeriesMarker as kW, setSeriesName as kX, setSeriesTrendline as kY, setSeriesValue as kZ, setStyle as k_, sanitizeUserName as ka, saveViewerProfile as kb, savedPresentationFileName as kc, scanAvailableFonts as kd, searchSlides as ke, seedBroadcastFields as kf, seedHyperlinkDraft as kg, seedPropertiesDraft as kh, seedShareFields as ki, segmentFrameCount as kj, selectValue$3 as kk, sendBackward as kl, sendToBack as km, sequentialColorScale as kn, serializeWriteBack as ko, seriesColor as kp, setAfterAnimation as kq, setAfterAnimationColor as kr, setAnimationEmphasis as ks, setAnimationEntrance as kt, setAnimationExit as ku, setAxis as kv, setAxisLogScale as kw, setAxisTitleStyle as kx, setCategoryLabel as ky, setCellText as kz, AiChangeOverlayComponent as l, vermilionRadius as l$, setTitle as l0, setTrigger as l1, setTriggerShapeId as l2, shapeStylePatch$1 as l3, sheetAfterNavigate as l4, shouldBlockClickAdvance as l5, shouldUseSvgWarp as l6, showDirectionPicker as l7, showsTemplateAffordance as l8, signatureCountLabel as l9, textStylePatch as lA, themeStyle as lB, themeToCssVars as lC, thumbnailHeight as lD, thumbnailZoom as lE, toggleCommentResolvedInList as lF, toggleNodeBold as lG, toggleNodeItalic as lH, toggleSheet as lI, topLevelNodeCount as lJ, transformSelectedTextCase as lK, translationsEn as lL, updateElementById as lM, updateGlowPatch as lN, updateGradientStopPatch as lO, updateInnerShadowPatch as lP, updateOuterShadowPatch as lQ, updateReflectionPatch as lR, vAlignPatch as lS, validatePassword as lT, validatePrintSettings as lU, validateRoomId as lV, valueToY as lW, vermilionDarkColors as lX, vermilionDarkTheme as lY, vermilionLightColors as lZ, vermilionLightTheme as l_, signatureKey as la, signatureTimestamp as lb, signerName as lc, statusLabel as ld, slideNumberOf as le, slidesWithReappliedLayout as lf, smartArtNodes as lg, paletteColour as lh, snapToGridStep as li, splitCursorCell as lj, splitMergedCell as lk, statusKind as ll, statusLabel$1 as lm, storeAudienceContent as ln, stringFromEvent$5 as lo, strokeColorOf as lp, strokeToInkElement as lq, strokeWidthOf as lr, styleShadowFilter as ls, surfaceColor as lt, textAdvancedPatch as lu, textAdvancedStateFromStyle as lv, textAdvancedStateOf as lw, textColorOf as lx, textDirectionPatch as ly, textStyleOf as lz, AiChatPanelComponent as m, waypointsToPathD as m0, withManualLayouts as m1, worstStatus as m2, zoomTargetSlideIndex as m3, AiChatService as n, AiComposerComponent as o, AiFocusBarComponent as p, AiFocusHighlightOverlayComponent as q, AiHistoryMenuComponent as r, AiHistoryService as s, toChatSummary as t, AiMessageListComponent as u, AiPanelStore as v, AiProposalCardComponent as w, AiSettingsSectionComponent as x, AiToolCallCardComponent as y, AnimationAuthorPanelComponent as z };
158493
- //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-De02eZYk.mjs.map
158708
+ //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-DYmBNrLg.mjs.map