pptx-angular-viewer 2.17.1 → 2.17.3

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.
@@ -27972,6 +27972,7 @@ const translationsEn = {
27972
27972
  'pptx.inspector.lock': 'Lock',
27973
27973
  'pptx.inspector.unlock': 'Unlock',
27974
27974
  // Slide master / handout master / notes master
27975
+ 'pptx.master.backgroundColorLabel': 'Master background color',
27975
27976
  'pptx.master.collapseMasterPane': 'Collapse pane',
27976
27977
  'pptx.master.handoutBackground': 'Background',
27977
27978
  'pptx.master.handoutMasterTitle': 'Handout Master',
@@ -33945,9 +33946,9 @@ function buildRunEffectStyle(style) {
33945
33946
  * the accumulated disagreement over a line is what decides a knife-edge wrap.
33946
33947
  *
33947
33948
  * Ground truth (PowerPoint COM `TextRange.BoundWidth` over the issue #131 /
33948
- * #149 deck): summing `round(advance * 6) / 6` per character reproduced all 78
33949
- * advance-exact measured lines to under 0.001 px, while the browser's own
33950
- * measurement of the same strings ran anywhere from 1.07% narrow to 0.28% wide.
33949
+ * #149 deck): summing `round(advance * 6) / 6` reproduced all 78 advance-exact
33950
+ * measured lines to under 0.001 px, while the browser's own measurement of the
33951
+ * same strings ran anywhere from 1.07% narrow to 0.28% wide.
33951
33952
  *
33952
33953
  * That spread is the point. The first attempt at this (issue #131) applied a
33953
33954
  * flat 0.003em to every run, which is roughly the middle of the range: it
@@ -33958,19 +33959,30 @@ function buildRunEffectStyle(style) {
33958
33959
  * correction has to be derived from the actual characters.
33959
33960
  *
33960
33961
  * So: measure the run, compute the width PowerPoint would have measured, and
33961
- * emit the letter-spacing that closes the gap. Measured end to end in Chromium
33962
- * (rendered span vs COM ground truth) this leaves a mean error of 0.04 px and a
33963
- * worst case of 0.37 px, against 0.51 px / 2.06 px uncompensated.
33962
+ * emit the letter-spacing that closes the gap. Two details decide whether that
33963
+ * works or does damage, and both are documented where they are made -
33964
+ * `advancesOf` (advances come from prefix differences, never from measuring a
33965
+ * character alone) and the clamp in `resolveMetricTrackingPx`.
33966
+ *
33967
+ * Measured end to end in Chromium, rendered span against COM ground truth: mean
33968
+ * error 0.026 px, worst 0.40 px, against 0.53 px / 2.05 px uncompensated. On
33969
+ * shaped scripts the correction moves the text by 0.00% (Arabic, CJK) to 0.08%
33970
+ * (Devanagari), i.e. nothing visible.
33964
33971
  */
33965
33972
  /**
33966
33973
  * Advance-width quantisation steps per CSS px. PowerPoint snaps each glyph
33967
33974
  * advance to an integer pixel at 576 DPI = 8 steps per point = 6 steps per px.
33968
33975
  */
33969
33976
  const ADVANCE_STEPS_PER_PX = 6;
33977
+ /**
33978
+ * The most the correction can legitimately be: half a grid step. See
33979
+ * {@link resolveMetricTrackingPx} for why anything beyond this is a different
33980
+ * problem wearing a rounding error's clothes.
33981
+ */
33982
+ const MAX_TRACKING_PX_PER_CHAR = 1 / (2 * ADVANCE_STEPS_PER_PX);
33970
33983
  /** Bound the caches so a long editing session cannot grow them without limit. */
33971
33984
  const MAX_CACHE_ENTRIES = 20000;
33972
33985
  let measureContext;
33973
- let advanceCache = new Map();
33974
33986
  let trackingCache = new Map();
33975
33987
  let fontsHookInstalled = false;
33976
33988
  /**
@@ -33984,7 +33996,6 @@ function installFontLoadHook() {
33984
33996
  }
33985
33997
  fontsHookInstalled = true;
33986
33998
  document.fonts?.addEventListener?.('loadingdone', () => {
33987
- advanceCache = new Map();
33988
33999
  trackingCache = new Map();
33989
34000
  });
33990
34001
  }
@@ -34006,19 +34017,43 @@ function toCanvasFont(font) {
34006
34017
  const family = font.fontFamily || DEFAULT_FONT_FAMILY$1;
34007
34018
  return `${font.italic ? 'italic ' : ''}${font.bold ? 'bold ' : ''}${size}px ${family}`;
34008
34019
  }
34009
- function advanceOf(ctx, canvasFont, char) {
34010
- const key = `${canvasFont}\u0000${char}`;
34011
- const cached = advanceCache.get(key);
34012
- if (cached !== undefined) {
34013
- return cached;
34014
- }
34020
+ /**
34021
+ * Per-character advances measured as PREFIX DIFFERENCES, never by measuring a
34022
+ * character on its own.
34023
+ *
34024
+ * This is the difference between a model that works and one that mangles half
34025
+ * the world's scripts. A character's advance depends on its neighbours: Arabic
34026
+ * letters join, so an isolated glyph measures ~37% wider than the same letter
34027
+ * inside a word; Devanagari forms conjuncts (~66%); an emoji ZWJ sequence is
34028
+ * one glyph built from several code points (~33%); and even Latin kerns - the
34029
+ * isolated characters of "AVATAR Wave To Yak" add up 5.3% wider than the string
34030
+ * itself. Summing isolated advances would hand the grid model a difference that
34031
+ * is not a rounding error at all, and letter-spacing would then stretch the run
34032
+ * to "correct" it: visibly wrong text, and a worse wrap than the one this set
34033
+ * out to fix.
34034
+ *
34035
+ * Differencing prefixes cannot fail that way. The advances telescope, so they
34036
+ * sum to exactly the width the browser will paint, whatever the shaping did.
34037
+ * Only their DISTRIBUTION across a ligature or cluster is approximate, and the
34038
+ * grid correction stays bounded by half a step per character either way.
34039
+ */
34040
+ function advancesOf(ctx, canvasFont, chars) {
34015
34041
  ctx.font = canvasFont;
34016
- const width = ctx.measureText(char).width;
34017
- if (advanceCache.size >= MAX_CACHE_ENTRIES) {
34018
- advanceCache = new Map();
34042
+ // PowerPoint's own advances are UNKERNED unless `a:rPr/@kern` turns kerning
34043
+ // on, and this deck's ground truth confirms it: measured with kerning the
34044
+ // grid model reproduced 66 of 78 COM-measured lines, without it all 78,
34045
+ // exactly. Chrome kerns 12 of those lines by 0.17-1.55 px.
34046
+ ctx.fontKerning = 'none';
34047
+ const advances = [];
34048
+ let previous = 0;
34049
+ let prefix = '';
34050
+ for (const char of chars) {
34051
+ prefix += char;
34052
+ const width = ctx.measureText(prefix).width;
34053
+ advances.push(width - previous);
34054
+ previous = width;
34019
34055
  }
34020
- advanceCache.set(key, width);
34021
- return width;
34056
+ return advances;
34022
34057
  }
34023
34058
  /**
34024
34059
  * The letter-spacing (in CSS px) that makes `text` render at the width
@@ -34030,10 +34065,15 @@ function advanceOf(ctx, canvasFont, char) {
34030
34065
  * inline box the line breaker sees. Being wrong about that convention would
34031
34066
  * cost one unit of tracking (~0.04 px), well inside the tolerance here.
34032
34067
  *
34033
- * The result needs no sanity clamp: snapping to a grid moves a glyph by at most
34034
- * half a step, so the tracking can never exceed 1/12 px per character however
34035
- * odd the font is. That is imperceptible by construction, which is the whole
34036
- * reason this can be done with `letter-spacing` at all.
34068
+ * The result is clamped to half a grid step per character, and that bound is
34069
+ * the model's own definition rather than a magic number: snapping an advance to
34070
+ * the grid can move it by at most half a step, so a correction larger than that
34071
+ * is not describing rounding at all. It means the browser and PowerPoint
34072
+ * disagree for some other reason - kerning the run enables and PowerPoint does
34073
+ * not, a font that never loaded - and uniform letter-spacing is the wrong tool
34074
+ * for those. Clamping keeps the correction imperceptible (at most 0.083 px per
34075
+ * glyph) instead of visibly stretching the text to chase a difference it cannot
34076
+ * legitimately close.
34037
34077
  */
34038
34078
  function resolveMetricTrackingPx(text, font) {
34039
34079
  if (!text) {
@@ -34050,23 +34090,79 @@ function resolveMetricTrackingPx(text, font) {
34050
34090
  return 0;
34051
34091
  }
34052
34092
  const chars = [...text];
34053
- ctx.font = canvasFont;
34093
+ let powerPoint = 0;
34094
+ for (const advance of advancesOf(ctx, canvasFont, chars)) {
34095
+ powerPoint += Math.round(advance * ADVANCE_STEPS_PER_PX);
34096
+ }
34097
+ // ...against the width the browser will actually PAINT, which is kerned.
34098
+ ctx.fontKerning = 'auto';
34054
34099
  const natural = ctx.measureText(text).width;
34055
34100
  if (!(natural > 0)) {
34056
34101
  return 0;
34057
34102
  }
34058
- let powerPoint = 0;
34059
- for (const char of chars) {
34060
- powerPoint += Math.round(advanceOf(ctx, canvasFont, char) * ADVANCE_STEPS_PER_PX);
34061
- }
34062
34103
  powerPoint /= ADVANCE_STEPS_PER_PX;
34063
- const tracking = (powerPoint - natural) / chars.length;
34104
+ const limit = MAX_TRACKING_PX_PER_CHAR;
34105
+ const raw = (powerPoint - natural) / chars.length;
34106
+ const tracking = Math.min(limit, Math.max(-limit, raw));
34064
34107
  if (trackingCache.size >= MAX_CACHE_ENTRIES) {
34065
34108
  trackingCache = new Map();
34066
34109
  }
34067
34110
  trackingCache.set(key, tracking);
34068
34111
  return tracking;
34069
34112
  }
34113
+ /**
34114
+ * True where the browser may break a line: between whitespace and a word, and
34115
+ * after a hyphen. Deliberately conservative - a boundary we miss costs
34116
+ * accuracy, a boundary we invent costs nothing, since pieces are laid out
34117
+ * contiguously either way.
34118
+ */
34119
+ function isBreakBoundary(previous, next) {
34120
+ const previousSpace = /\s/u.test(previous);
34121
+ const nextSpace = /\s/u.test(next);
34122
+ if (previousSpace !== nextSpace) {
34123
+ return true;
34124
+ }
34125
+ return previous === '-' && next !== '-' && !nextSpace;
34126
+ }
34127
+ /**
34128
+ * Cut a run at every line-break opportunity so each piece can carry its own
34129
+ * tracking.
34130
+ *
34131
+ * One tracking for a whole run makes the RUN measure exactly, but a line is a
34132
+ * prefix of it, and the rounding error is not spread evenly through the text -
34133
+ * so a line can still come out up to ~0.95 px off, which is enough to move a
34134
+ * break (issue #149, slide 5: "operational" fitted on a line PowerPoint had
34135
+ * already closed). Give every word its own tracking and every whitespace gap
34136
+ * its own, and any line the browser assembles out of whole pieces measures
34137
+ * exactly what PowerPoint measured, because advances simply add up.
34138
+ *
34139
+ * A break INSIDE a piece (mid-word, or between CJK characters, which have no
34140
+ * spaces to cut at) falls back to that piece's average - i.e. to the run-level
34141
+ * behaviour, never worse.
34142
+ *
34143
+ * Returns a single piece when the run has no interior boundary, which keeps the
34144
+ * common case (a short label, a one-word run) at exactly one span.
34145
+ */
34146
+ function splitRunForMetrics(text, font) {
34147
+ const chars = [...text];
34148
+ if (chars.length < 2 || !getMeasureContext()) {
34149
+ return [{ text, tracking: resolveMetricTrackingPx(text, font) }];
34150
+ }
34151
+ const pieces = [];
34152
+ let current = chars[0];
34153
+ for (let i = 1; i < chars.length; i++) {
34154
+ if (isBreakBoundary(chars[i - 1], chars[i])) {
34155
+ pieces.push(current);
34156
+ current = '';
34157
+ }
34158
+ current += chars[i];
34159
+ }
34160
+ pieces.push(current);
34161
+ if (pieces.length === 1) {
34162
+ return [{ text, tracking: resolveMetricTrackingPx(text, font) }];
34163
+ }
34164
+ return pieces.map((piece) => ({ text: piece, tracking: resolveMetricTrackingPx(piece, font) }));
34165
+ }
34070
34166
  /**
34071
34167
  * {@link resolveMetricTrackingPx} as a CSS length, or `undefined` when the run
34072
34168
  * needs no correction (so callers can leave `letter-spacing` undeclared rather
@@ -34078,7 +34174,6 @@ function resolveMetricTracking(text, font) {
34078
34174
  }
34079
34175
  /** Test hook: forget every measurement (also used by the font-load listener). */
34080
34176
  function resetMetricTrackingCache() {
34081
- advanceCache = new Map();
34082
34177
  trackingCache = new Map();
34083
34178
  measureContext = undefined;
34084
34179
  }
@@ -34095,6 +34190,50 @@ function resetMetricTrackingCache() {
34095
34190
  const PX_PER_POINT = 96 / 72;
34096
34191
  /** Super/subscript glyphs render at ~65% of the run font size (matches React). */
34097
34192
  const BASELINE_FONT_SCALE = 0.65;
34193
+ /**
34194
+ * The authored `a:rPr/@spc` character spacing in CSS px (hundredths of a point).
34195
+ * The measured PowerPoint metric compensation layers on top of this, so callers
34196
+ * that re-derive a per-piece `letter-spacing` need the authored part on its own.
34197
+ */
34198
+ function authoredLetterSpacingPx(style) {
34199
+ const spc = style?.characterSpacing;
34200
+ return typeof spc === 'number' && spc !== 0 ? (spc / 100) * PX_PER_POINT : 0;
34201
+ }
34202
+ /** `letter-spacing` for a run piece: authored spacing plus its own tracking. */
34203
+ function pieceLetterSpacing(authoredPx, tracking) {
34204
+ const spacing = authoredPx + tracking;
34205
+ return spacing === 0 ? undefined : `${spacing}px`;
34206
+ }
34207
+ /**
34208
+ * Split one styled run into the per-word / per-gap runs that make a LINE
34209
+ * measure what PowerPoint measured (see `splitRunForMetrics`).
34210
+ *
34211
+ * Every binding that renders one span per run gets exact wrapping by emitting
34212
+ * these instead of the single run, so this is the one place the "which pieces,
34213
+ * what spacing" decision lives: shared's `buildParagraphs` covers Vue, Svelte
34214
+ * and Vanilla, Angular's own paragraph builder calls it directly, and React
34215
+ * splits inside its span.
34216
+ *
34217
+ * Returns a single entry (the run unchanged) when there is nothing to split,
34218
+ * which is the common case for short labels and one-word runs.
34219
+ */
34220
+ function splitStyledRun(text, style, font, authoredPx) {
34221
+ const pieces = splitRunForMetrics(text, font);
34222
+ if (pieces.length <= 1) {
34223
+ return [{ text, style }];
34224
+ }
34225
+ return pieces.map((piece) => {
34226
+ const spacing = pieceLetterSpacing(authoredPx, piece.tracking);
34227
+ const pieceStyle = { ...style };
34228
+ if (spacing === undefined) {
34229
+ delete pieceStyle.letterSpacing;
34230
+ }
34231
+ else {
34232
+ pieceStyle.letterSpacing = spacing;
34233
+ }
34234
+ return { text: piece.text, style: pieceStyle };
34235
+ });
34236
+ }
34098
34237
  /**
34099
34238
  * Combine the authored `a:rPr/@spc` character spacing with the measured
34100
34239
  * PowerPoint metric compensation into one `letter-spacing`, or leave it
@@ -34106,11 +34245,7 @@ const BASELINE_FONT_SCALE = 0.65;
34106
34245
  * (issue #149).
34107
34246
  */
34108
34247
  function resolveLetterSpacing(s, text, font) {
34109
- const authored = typeof s.characterSpacing === 'number' && s.characterSpacing !== 0
34110
- ? (s.characterSpacing / 100) * PX_PER_POINT
34111
- : 0;
34112
- const spacing = authored + resolveMetricTrackingPx(text, font);
34113
- return spacing === 0 ? undefined : `${spacing}px`;
34248
+ return pieceLetterSpacing(authoredLetterSpacingPx(s), resolveMetricTrackingPx(text, font));
34114
34249
  }
34115
34250
  /**
34116
34251
  * Layer the "extra" run properties that neither the boolean decoration set nor
@@ -34202,19 +34337,27 @@ function segmentStyleToCss(seg, fontScale = 1, context = {}) {
34202
34337
  if (deco.length > 0) {
34203
34338
  style.textDecoration = deco.join(' ');
34204
34339
  }
34205
- // The font the run will actually paint with: its own declarations where it
34206
- // made them, the body's where it did not. Bold and italic are always the
34207
- // run's own (both are declared unconditionally just above).
34208
- const runFont = {
34209
- fontFamily: style.fontFamily ?? context.blockFont?.fontFamily,
34340
+ applyExtraRunProps(style, s, context.text ?? seg.text ?? '', resolveRunFont(style, s, context.blockFont));
34341
+ return style;
34342
+ }
34343
+ /**
34344
+ * The font a run will actually paint with: its own declarations where it made
34345
+ * them, the text body's where it did not. Bold and italic are always the run's
34346
+ * own, because {@link segmentStyleToCss} declares both unconditionally.
34347
+ *
34348
+ * Exported so a caller that re-measures pieces of a run (see
34349
+ * `splitRunForMetrics`) resolves the font exactly the way the run style did,
34350
+ * rather than keeping a second copy of the fallback rules.
34351
+ */
34352
+ function resolveRunFont(style, s, blockFont) {
34353
+ return {
34354
+ fontFamily: style.fontFamily ?? blockFont?.fontFamily,
34210
34355
  fontSizePx: typeof style.fontSize === 'string'
34211
34356
  ? Number.parseFloat(style.fontSize)
34212
- : context.blockFont?.fontSizePx,
34357
+ : blockFont?.fontSizePx,
34213
34358
  bold: Boolean(s.bold),
34214
34359
  italic: Boolean(s.italic),
34215
34360
  };
34216
- applyExtraRunProps(style, s, context.text ?? seg.text ?? '', runFont);
34217
- return style;
34218
34361
  }
34219
34362
  /**
34220
34363
  * Layer the underline-style / double-strike *variant* decoration CSS
@@ -34426,7 +34569,13 @@ function buildParagraphs(element, fieldContext, segmentOverrides) {
34426
34569
  if (seg.style) {
34427
34570
  Object.assign(style, buildRunEffectStyle(seg.style));
34428
34571
  }
34429
- runs.push({ text, style });
34572
+ // Each word and each gap carries its own PowerPoint metric tracking,
34573
+ // so a line the browser assembles out of them measures exactly what
34574
+ // PowerPoint measured and breaks where PowerPoint breaks (#149).
34575
+ // Emitting them as sibling RUNS rather than nested spans is what
34576
+ // gets this to Vue/Svelte/Vanilla with no binding change: they
34577
+ // already render one span per run.
34578
+ runs.push(...splitStyledRun(text, style, resolveRunFont(style, seg.style ?? {}, blockFont), authoredLetterSpacingPx(seg.style)));
34430
34579
  }
34431
34580
  }
34432
34581
  // Suppress bullets for paragraphs with no visible text content.
@@ -34751,14 +34900,79 @@ function correspondingGroup(group, candidates) {
34751
34900
  return sameBox(group, candidate);
34752
34901
  });
34753
34902
  }
34903
+ /** Fraction of the union two boxes must share to read as the same object. */
34904
+ const CHILD_OVERLAP_RATIO = 0.5;
34905
+ /** Intersection over union of two element boxes. */
34906
+ function boxOverlapRatio(a, b) {
34907
+ const left = Math.max(a.x, b.x);
34908
+ const top = Math.max(a.y, b.y);
34909
+ const right = Math.min(a.x + a.width, b.x + b.width);
34910
+ const bottom = Math.min(a.y + a.height, b.y + b.height);
34911
+ if (right <= left || bottom <= top) {
34912
+ return 0;
34913
+ }
34914
+ const intersection = (right - left) * (bottom - top);
34915
+ const union = a.width * a.height + b.width * b.height - intersection;
34916
+ return union > 0 ? intersection / union : 0;
34917
+ }
34918
+ /** Whether two group children read as the same object, restyled or nudged. */
34919
+ function childrenPair(a, b) {
34920
+ const morphName = getElementMorphName(a);
34921
+ if (morphName !== undefined && getElementMorphName(b) === morphName) {
34922
+ return true;
34923
+ }
34924
+ if (a.name && a.name === b.name) {
34925
+ return true;
34926
+ }
34927
+ return boxOverlapRatio(a, b) >= CHILD_OVERLAP_RATIO;
34928
+ }
34929
+ /**
34930
+ * Whether two paired groups hold the SAME cast of objects, one for one.
34931
+ *
34932
+ * This is what decides between animating a group's contents individually and
34933
+ * dissolving the whole group into its counterpart, and PowerPoint draws the
34934
+ * line in the same place. Measured on the issue #131 deck by exporting the real
34935
+ * transitions to video (`CreateVideo`, 62.5fps) and fitting every frame of the
34936
+ * centre panel to a blend of the first and last:
34937
+ *
34938
+ * - hub -> topic (`!!Circle` = disc + "Select Challenge", against disc +
34939
+ * button + three paragraphs): every frame is a clean linear blend of the
34940
+ * two end states, residual < 1/255, with the arriving title AND the
34941
+ * departing wording both following the same curve. That is one object
34942
+ * dissolving into another, not four shapes appearing and one leaving:
34943
+ * unmatched shapes hold, then fade out by 23% and in from 42%, which would
34944
+ * leave the middle of the transition empty (issue #146).
34945
+ * - topic -> topic (five children against five, same boxes): also a clean
34946
+ * blend, so decomposing there is harmless - each child simply crossfades
34947
+ * into its own counterpart.
34948
+ *
34949
+ * So a group is decomposed only when its children line up; a group that gained
34950
+ * or lost content dissolves as a whole.
34951
+ */
34952
+ function childrenCorrespond(a, b) {
34953
+ if (a.length !== b.length || a.length === 0) {
34954
+ return false;
34955
+ }
34956
+ const unclaimed = b.map((child) => child);
34957
+ for (const child of a) {
34958
+ const index = unclaimed.findIndex((candidate) => childrenPair(child, candidate));
34959
+ if (index < 0) {
34960
+ return false;
34961
+ }
34962
+ unclaimed.splice(index, 1);
34963
+ }
34964
+ return true;
34965
+ }
34754
34966
  /**
34755
34967
  * The elements of `elements` that a morph should treat as individual units,
34756
34968
  * given the `counterpart` slide's elements at the same level of the tree.
34757
34969
  *
34758
34970
  * A group is replaced by its children (in document order, recursively, in
34759
- * absolute coordinates) when it holds a `!!`-named descendant AND `counterpart`
34760
- * holds a group it would pair with; everything else is passed through
34761
- * untouched. See the module comment for why both conditions are required.
34971
+ * absolute coordinates) when it holds a `!!`-named descendant, `counterpart`
34972
+ * holds a group it would pair with, AND the two groups hold the same cast of
34973
+ * objects; everything else is passed through untouched. See the module comment
34974
+ * for why the first two are required and {@link childrenCorrespond} for the
34975
+ * third.
34762
34976
  */
34763
34977
  function flattenMorphElements(elements, counterpart, offsetX = 0, offsetY = 0) {
34764
34978
  const out = [];
@@ -34767,7 +34981,7 @@ function flattenMorphElements(elements, counterpart, offsetX = 0, offsetY = 0) {
34767
34981
  if (children && containsMorphNamedDescendant(element)) {
34768
34982
  const twin = correspondingGroup(element, counterpart);
34769
34983
  const twinChildren = twin ? (groupChildren(twin) ?? []) : undefined;
34770
- if (twinChildren) {
34984
+ if (twinChildren && childrenCorrespond(children, twinChildren)) {
34771
34985
  out.push(...flattenMorphElements(children, twinChildren, offsetX + element.x, offsetY + element.y));
34772
34986
  continue;
34773
34987
  }
@@ -35081,6 +35295,20 @@ function interpolateOutline(from, to, t) {
35081
35295
  // ---------------------------------------------------------------------------
35082
35296
  /** PowerPoint's morph transition uses a specific cubic-bezier easing. */
35083
35297
  const MORPH_EASING = 'cubic-bezier(0.4, 0, 0.2, 1)';
35298
+ /**
35299
+ * The curve a matched pair DISSOLVES on, which is not the curve it travels on.
35300
+ *
35301
+ * Measured, not guessed: the issue #131 deck's hub-to-topic morph was exported
35302
+ * through PowerPoint's own `CreateVideo` and every one of the 59 frames of the
35303
+ * arriving title fitted to a blend of the first and last frame (residual under
35304
+ * 1/255, so the dissolve really is a plain linear blend). The alpha runs 0.035
35305
+ * at 7% of the duration, 0.232 at 20%, 0.477 at 34%, 0.684 at 47%, 0.888 at 68%
35306
+ * and 0.988 at 88%: an ease that leans in gently and then decelerates hard.
35307
+ * This curve tracks those samples to an RMS of 0.004 and never differs by more
35308
+ * than 0.009. {@link MORPH_EASING}, which the ghost used to fade on, sits at
35309
+ * 0.5 where PowerPoint is already at 0.73 (issue #146).
35310
+ */
35311
+ const MORPH_CROSSFADE_EASING = 'cubic-bezier(0.2, 0, 0.4, 1)';
35084
35312
  /**
35085
35313
  * When an unmatched OUTGOING shape has finished dissolving, as a percentage of
35086
35314
  * the morph's duration, and when it starts.
@@ -35630,6 +35858,122 @@ function matchMorphElementsFull(fromSlide, toSlide) {
35630
35858
  return { pairs, unmatchedFrom, unmatchedTo };
35631
35859
  }
35632
35860
 
35861
+ /** The area a shape occupies over the whole morph (start box union end box). */
35862
+ function travelledBox(from, to) {
35863
+ const boxes = to ? [from, to] : [from];
35864
+ return {
35865
+ left: Math.min(...boxes.map((element) => element.x)),
35866
+ top: Math.min(...boxes.map((element) => element.y)),
35867
+ right: Math.max(...boxes.map((element) => element.x + element.width)),
35868
+ bottom: Math.max(...boxes.map((element) => element.y + element.height)),
35869
+ };
35870
+ }
35871
+ /** Whether two travelled boxes share any area. */
35872
+ function boxesOverlap(a, b) {
35873
+ return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
35874
+ }
35875
+ /**
35876
+ * Rank every shape of both slides in a single back-to-front order.
35877
+ *
35878
+ * A matched pair is ONE object and gets ONE rank, so "is this arrival above
35879
+ * that ghost?" is a plain number comparison. The two document orders are merged
35880
+ * the way a diff merges two revisions of a list: walking the incoming slide,
35881
+ * each matched shape first flushes everything the outgoing slide drew below its
35882
+ * counterpart, so departures keep their place relative to the shapes that
35883
+ * surrounded them and arrivals keep theirs.
35884
+ *
35885
+ * Both lists must already be flattened the way the matcher flattens them (see
35886
+ * `morph-flatten`), or the ids will not line up with `pairs`.
35887
+ *
35888
+ * @param outgoing - The outgoing slide's elements, flattened, in document order.
35889
+ * @param incoming - The incoming slide's elements, flattened, in document order.
35890
+ * @param pairs - The matched pairs.
35891
+ * @returns Element id -> rank; higher is nearer the viewer.
35892
+ */
35893
+ function buildMorphMergedOrder(outgoing, incoming, pairs) {
35894
+ const partnerOf = new Map(pairs.map((pair) => [pair.toElement.id, pair.fromElement.id]));
35895
+ const outgoingIndex = new Map(outgoing.map((element, index) => [element.id, index]));
35896
+ const rank = new Map();
35897
+ let next = 0;
35898
+ let cursor = 0;
35899
+ /** Emit every outgoing shape below `limit` that has not been placed yet. */
35900
+ const flushOutgoingBelow = (limit) => {
35901
+ while (cursor < limit) {
35902
+ const element = outgoing[cursor];
35903
+ cursor += 1;
35904
+ if (!rank.has(element.id)) {
35905
+ rank.set(element.id, next);
35906
+ next += 1;
35907
+ }
35908
+ }
35909
+ };
35910
+ for (const element of incoming) {
35911
+ const partner = partnerOf.get(element.id);
35912
+ const partnerIndex = partner === undefined ? undefined : outgoingIndex.get(partner);
35913
+ if (partner === undefined || partnerIndex === undefined) {
35914
+ // An arrival holds its own place in the incoming slide's stack.
35915
+ rank.set(element.id, next);
35916
+ next += 1;
35917
+ continue;
35918
+ }
35919
+ flushOutgoingBelow(partnerIndex + 1);
35920
+ rank.set(element.id, rank.get(partner) ?? next);
35921
+ }
35922
+ flushOutgoingBelow(outgoing.length);
35923
+ return rank;
35924
+ }
35925
+ /**
35926
+ * The incoming shapes the overlay has to paint over its ghosts.
35927
+ *
35928
+ * An arriving shape is lifted when a ghost that HOLDS ITS OPACITY sits below it
35929
+ * in the merged order and covers it: on the live stage it would dissolve in
35930
+ * underneath something opaque and never be seen at all. Anything the ghosts are
35931
+ * legitimately on top of - the incoming slide's own backdrop, artwork the
35932
+ * persisting shapes are drawn over - keeps its place on the stage.
35933
+ *
35934
+ * A ghost that DISSOLVES is deliberately not counted, which is why the caller
35935
+ * passes only the holding ones. It stops hiding anything within the first
35936
+ * quarter of the morph, well before an arrival starts to appear at 42% (see
35937
+ * `MORPH_FADE_OUT_END_PERCENT` / `MORPH_FADE_IN_START_PERCENT`), so lifting for
35938
+ * it buys nothing and moves an animation the live stage should own: issue
35939
+ * #131's overview-to-topic hop dissolves the whole centre out and the arriving
35940
+ * group in, exactly that way.
35941
+ *
35942
+ * Only shapes with NO counterpart qualify. A matched pair already dissolves
35943
+ * against its own ghost, which is the whole point of the crossfade; lifting its
35944
+ * incoming half above that ghost would turn the dissolve back into a cut.
35945
+ *
35946
+ * @param outgoing - The outgoing slide's elements, flattened, in document order.
35947
+ * @param incoming - The incoming slide's elements, flattened, in document order.
35948
+ * @param pairs - The matched pairs.
35949
+ * @param holdingGhostIds - The outgoing ids the overlay paints AND keeps opaque
35950
+ * for the whole morph (a painted pair whose appearance did not change).
35951
+ * @returns The ids of the incoming elements to lift, a subset of `incoming`.
35952
+ */
35953
+ function resolveMorphOverlayArrivals(outgoing, incoming, pairs, holdingGhostIds) {
35954
+ const rank = buildMorphMergedOrder(outgoing, incoming, pairs);
35955
+ const matched = new Set(pairs.map((pair) => pair.toElement.id));
35956
+ const counterpart = new Map(pairs.map((pair) => [pair.fromElement.id, pair.toElement]));
35957
+ const ghosts = outgoing
35958
+ .filter((element) => holdingGhostIds.has(element.id))
35959
+ .map((element) => ({
35960
+ rank: rank.get(element.id) ?? 0,
35961
+ box: travelledBox(element, counterpart.get(element.id)),
35962
+ }));
35963
+ const lifted = new Set();
35964
+ for (const element of incoming) {
35965
+ if (matched.has(element.id)) {
35966
+ continue;
35967
+ }
35968
+ const mine = rank.get(element.id) ?? 0;
35969
+ const box = travelledBox(element);
35970
+ if (ghosts.some((ghost) => ghost.rank < mine && boxesOverlap(ghost.box, box))) {
35971
+ lifted.add(element.id);
35972
+ }
35973
+ }
35974
+ return lifted;
35975
+ }
35976
+
35633
35977
  // ---------------------------------------------------------------------------
35634
35978
  // Text tokenization
35635
35979
  // ---------------------------------------------------------------------------
@@ -36077,19 +36421,9 @@ function isInertMorphPair(fromElement, toElement) {
36077
36421
  (fromElement.opacity ?? 1) === (toElement.opacity ?? 1) &&
36078
36422
  !morphPairNeedsCrossfade(fromElement, toElement));
36079
36423
  }
36080
- /** The area a shape occupies over the whole morph (start box union end box). */
36081
- function travelledBox(from, to) {
36082
- const boxes = to ? [from, to] : [from];
36083
- return {
36084
- left: Math.min(...boxes.map((element) => element.x)),
36085
- top: Math.min(...boxes.map((element) => element.y)),
36086
- right: Math.max(...boxes.map((element) => element.x + element.width)),
36087
- bottom: Math.max(...boxes.map((element) => element.y + element.height)),
36088
- };
36089
- }
36090
- function boxesOverlap(a, b) {
36091
- return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
36092
- }
36424
+ // ---------------------------------------------------------------------------
36425
+ // Which outgoing shapes the overlay has to paint
36426
+ // ---------------------------------------------------------------------------
36093
36427
  /**
36094
36428
  * The outgoing shapes the transition overlay actually has to paint.
36095
36429
  *
@@ -36145,12 +36479,21 @@ function resolveMorphGhostIds(outgoingElements, pairs) {
36145
36479
  * box over `noFill` has nothing to hollow out, and pinning it means the new
36146
36480
  * wording is at full strength from frame 1 while the old dissolves off it,
36147
36481
  * which reads as the new text simply appearing rather than cross-dissolving.
36482
+ *
36483
+ * A GROUP owns no fill of its own, so the question has to be asked of its
36484
+ * children: the wheel deck's centre panel is a group around an opaque disc, and
36485
+ * fading it in while its ghost faded out turned the disc translucent for the
36486
+ * middle of every hub-to-topic morph.
36148
36487
  */
36149
36488
  function crossfadeIncomingMayFadeIn(element) {
36150
36489
  const image = element;
36151
36490
  if (image.imagePath || image.svgPath) {
36152
36491
  return false;
36153
36492
  }
36493
+ const children = element.children;
36494
+ if (children?.length) {
36495
+ return children.every((child) => crossfadeIncomingMayFadeIn(child));
36496
+ }
36154
36497
  if (!hasShapeProperties(element)) {
36155
36498
  return true;
36156
36499
  }
@@ -36245,15 +36588,19 @@ function generateMorphAnimations(pairs, durationMs, _mode = 'object', ghostIds)
36245
36588
  const crossfadesIn = !inert &&
36246
36589
  morphPairNeedsCrossfade(fromElement, toElement) &&
36247
36590
  crossfadeIncomingMayFadeIn(toElement);
36248
- // Build from/to property blocks
36591
+ // Build from/to property blocks. A half that dissolves IN keeps its opacity
36592
+ // out of this block and rides a second animation, so the journey and the
36593
+ // dissolve can follow their own measured curves (see the ghost half).
36249
36594
  const fromProps = [
36250
36595
  `\t\ttransform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${fromRot}deg)${flips};`,
36251
- `\t\topacity: ${inert ? 0 : crossfadesIn ? 0 : fromOpacity};`,
36252
36596
  ];
36253
36597
  const toProps = [
36254
36598
  `\t\ttransform: translate(0, 0) scale(1, 1) rotate(${toRot}deg)${flips};`,
36255
- `\t\topacity: ${inert ? 0 : toOpacity};`,
36256
36599
  ];
36600
+ if (!crossfadesIn) {
36601
+ fromProps.push(`\t\topacity: ${inert ? 0 : fromOpacity};`);
36602
+ toProps.push(`\t\topacity: ${inert ? 0 : toOpacity};`);
36603
+ }
36257
36604
  // Fill color interpolation
36258
36605
  const colorInterp = buildColorInterpolationProps(fromElement, toElement);
36259
36606
  if (colorInterp) {
@@ -36274,10 +36621,20 @@ ${fromProps.join('\n')}
36274
36621
  \tto {
36275
36622
  ${toProps.join('\n')}
36276
36623
  \t}
36277
- }`;
36624
+ }${crossfadesIn
36625
+ ? `
36626
+ @keyframes ${safeName}-fade {
36627
+ \tfrom {
36628
+ \t\topacity: 0;
36629
+ \t}
36630
+ \tto {
36631
+ \t\topacity: ${toOpacity};
36632
+ \t}
36633
+ }`
36634
+ : ''}`;
36278
36635
  animations.push({
36279
36636
  elementId: toElement.id,
36280
- animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
36637
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards${crossfadesIn ? `, ${safeName}-fade ${durationMs}ms ${MORPH_CROSSFADE_EASING} forwards` : ''}`,
36281
36638
  keyframes,
36282
36639
  });
36283
36640
  }
@@ -36332,22 +36689,36 @@ function generateMorphGhostAnimations(pairs, durationMs, startIndex, ghostIds) {
36332
36689
  const fromRot = fromElement.rotation ?? 0;
36333
36690
  const toRot = shortestRotationTarget(fromRot, toElement.rotation ?? 0);
36334
36691
  const flips = `${fromElement.flipHorizontal ? ' scaleX(-1)' : ''}${fromElement.flipVertical ? ' scaleY(-1)' : ''}`;
36692
+ // A dissolve and a journey are two different curves, so when the ghost does
36693
+ // both they ride two animations: the transform keeps {@link MORPH_EASING},
36694
+ // which its live counterpart also travels on (a single easing for both
36695
+ // halves is what keeps them on the same path), and the opacity gets the
36696
+ // measured {@link MORPH_CROSSFADE_EASING}.
36697
+ const opacity = fromElement.opacity ?? 1;
36335
36698
  const keyframes = `
36336
36699
  @keyframes ${safeName} {
36337
36700
  \tfrom {
36338
36701
  \t\ttransform-origin: center;
36339
- \t\ttransform: translate(0, 0) scale(1, 1) rotate(${fromRot}deg)${flips};
36340
- \t\topacity: ${fromElement.opacity ?? 1};
36702
+ \t\ttransform: translate(0, 0) scale(1, 1) rotate(${fromRot}deg)${flips};${fadesOut ? '' : `\n\t\topacity: ${opacity};`}
36341
36703
  \t}
36342
36704
  \tto {
36343
36705
  \t\ttransform-origin: center;
36344
- \t\ttransform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${toRot}deg)${flips};
36345
- \t\topacity: ${fadesOut ? 0 : (fromElement.opacity ?? 1)};
36706
+ \t\ttransform: translate(${dx}px, ${dy}px) scale(${sx}, ${sy}) rotate(${toRot}deg)${flips};${fadesOut ? '' : `\n\t\topacity: ${opacity};`}
36346
36707
  \t}
36347
- }`;
36708
+ }${fadesOut
36709
+ ? `
36710
+ @keyframes ${safeName}-fade {
36711
+ \tfrom {
36712
+ \t\topacity: ${opacity};
36713
+ \t}
36714
+ \tto {
36715
+ \t\topacity: 0;
36716
+ \t}
36717
+ }`
36718
+ : ''}`;
36348
36719
  animations.push({
36349
36720
  elementId: fromElement.id,
36350
- animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards`,
36721
+ animation: `${safeName} ${durationMs}ms ${MORPH_EASING} forwards${fadesOut ? `, ${safeName}-fade ${durationMs}ms ${MORPH_CROSSFADE_EASING} forwards` : ''}`,
36351
36722
  keyframes,
36352
36723
  });
36353
36724
  }
@@ -36576,6 +36947,21 @@ function generateFullMorphTransition(fromSlide, toSlide, durationMs, mode = 'obj
36576
36947
  return allAnimations;
36577
36948
  }
36578
36949
 
36950
+ /**
36951
+ * Keyframes for an incoming shape whose dissolve has been lifted into the
36952
+ * overlay: the copy left on the live stage holds at nothing for the whole
36953
+ * morph, so the two copies never composite with each other.
36954
+ */
36955
+ const LIFTED_HIDDEN_NAME = 'pptx-morph-lifted-hidden';
36956
+ const LIFTED_HIDDEN_KEYFRAMES = `
36957
+ @keyframes ${LIFTED_HIDDEN_NAME} {
36958
+ \tfrom {
36959
+ \t\topacity: 0;
36960
+ \t}
36961
+ \tto {
36962
+ \t\topacity: 0;
36963
+ \t}
36964
+ }`;
36579
36965
  /** Map a parsed `<p159:morph @option>` onto the engine's granularity mode. */
36580
36966
  function morphOptionToMode(option) {
36581
36967
  if (option === 'byWord') {
@@ -36657,13 +37043,45 @@ function buildMorphTransitionPlan(fromSlide, toSlide, durationMs, mode = 'object
36657
37043
  // the overlay came down). Deriving the list from the animations keeps this
36658
37044
  // decision in one place, `resolveMorphGhostIds`.
36659
37045
  const outgoingElements = flattenedOutgoing.filter((element) => outgoingAnimations.has(element.id));
37046
+ // Everything the overlay paints hides whatever the live stage is doing
37047
+ // underneath, which is wrong for a shape that ARRIVES on top of a ghost:
37048
+ // it dissolves in where nobody can see it and appears in one frame when the
37049
+ // overlay is torn down (issue #146 - the wheel's centre disc is unchanged,
37050
+ // so its opaque ghost sat over the new title, body and button for the whole
37051
+ // morph). Those few move up into the overlay, above the ghosts, and the
37052
+ // copy on the stage is held invisible so the two never composite.
37053
+ //
37054
+ // Only a ghost that KEEPS its opacity counts. One that dissolves is out of
37055
+ // the way inside the first quarter, long before an arrival begins to appear,
37056
+ // so it hides nothing worth moving an animation for.
37057
+ const flattenedIncoming = flattenMorphElements(toSlide.elements, fromSlide.elements);
37058
+ const holdingGhostIds = new Set(match.pairs
37059
+ .filter((candidate) => outgoingAnimations.has(candidate.fromElement.id) &&
37060
+ !morphPairNeedsCrossfade(candidate.fromElement, candidate.toElement))
37061
+ .map((candidate) => candidate.fromElement.id));
37062
+ const lifted = resolveMorphOverlayArrivals(flattenedOutgoing, flattenedIncoming, match.pairs, holdingGhostIds);
37063
+ const overlayIncomingAnimations = new Map();
37064
+ for (const id of lifted) {
37065
+ const animation = incomingAnimations.get(id);
37066
+ if (animation === undefined) {
37067
+ continue;
37068
+ }
37069
+ overlayIncomingAnimations.set(id, animation);
37070
+ incomingAnimations.set(id, `${LIFTED_HIDDEN_NAME} ${durationMs}ms linear forwards`);
37071
+ }
37072
+ if (overlayIncomingAnimations.size > 0) {
37073
+ keyframes.push(LIFTED_HIDDEN_KEYFRAMES);
37074
+ }
37075
+ const overlayIncomingElements = flattenedIncoming.filter((element) => overlayIncomingAnimations.has(element.id));
36660
37076
  return {
36661
37077
  keyframesCss: keyframes.join('\n'),
36662
37078
  incomingAnimations,
36663
37079
  outgoingAnimations,
36664
37080
  incomingImageAnimations,
36665
37081
  outgoingImageAnimations,
37082
+ overlayIncomingAnimations,
36666
37083
  outgoingElements,
37084
+ overlayIncomingElements,
36667
37085
  durationMs,
36668
37086
  };
36669
37087
  }
@@ -36688,6 +37106,9 @@ function cssAttributeValue(value) {
36688
37106
  * are unique to the slide being animated and need no ancestor to disambiguate.
36689
37107
  * That is what lets a binding whose incoming slide is rendered OUTSIDE the
36690
37108
  * overlay (Angular, React) still drive it from here.
37109
+ * @param which - Which half to emit: the live stage's `incoming` elements, the
37110
+ * overlay's `outgoing` ghosts, or the `lifted` copies the overlay paints over
37111
+ * those ghosts (see {@link MorphTransitionPlan.overlayIncomingElements}).
36691
37112
  * @returns Keyframes plus the scoped `animation` rules, ready to inject.
36692
37113
  */
36693
37114
  function buildMorphScopedCss(plan, scopeAttribute, which = 'incoming') {
@@ -36716,12 +37137,19 @@ function buildMorphAnimationRules(plan, scopeAttribute, which = 'incoming', only
36716
37137
  rules.push(`${prefix}[data-element-id="${cssAttributeValue(elementId)}"]${suffix} { animation: ${animation}; }`);
36717
37138
  }
36718
37139
  };
37140
+ // `lifted` is the incoming half painted in the overlay rather than on the
37141
+ // stage, so it shares the incoming img channel and differs only in which
37142
+ // container animation it carries.
36719
37143
  if (only !== 'image') {
36720
- emit(which === 'incoming' ? plan.incomingAnimations : plan.outgoingAnimations, '');
37144
+ emit(which === 'outgoing'
37145
+ ? plan.outgoingAnimations
37146
+ : which === 'lifted'
37147
+ ? plan.overlayIncomingAnimations
37148
+ : plan.incomingAnimations, '');
36721
37149
  }
36722
37150
  // The picture-crop channel targets the `<img>` the element renders, which
36723
37151
  // every binding draws inside the `data-element-id` container.
36724
- emit(which === 'incoming' ? plan.incomingImageAnimations : plan.outgoingImageAnimations, ' img');
37152
+ emit(which === 'outgoing' ? plan.outgoingImageAnimations : plan.incomingImageAnimations, ' img');
36725
37153
  return rules.join('\n');
36726
37154
  }
36727
37155
 
@@ -64394,7 +64822,7 @@ function createLocalStorageBackend(namespace) {
64394
64822
  /** Try IndexedDB first; fall back to localStorage on any failure. */
64395
64823
  async function resolveBackend(dbName, namespace) {
64396
64824
  try {
64397
- const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-hwk7tPwT.mjs');
64825
+ const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb--qaJVCPk.mjs');
64398
64826
  const db = await openChatDb(dbName);
64399
64827
  return createIdbBackend(db);
64400
64828
  }
@@ -75986,6 +76414,15 @@ class ImageRendererComponent {
75986
76414
  /** Keep the data-pptx-element marker on interaction-locked template elements. */
75987
76415
  marked = input(false, /* @ts-ignore */
75988
76416
  ...(ngDevMode ? [{ debugName: "marked" }] : /* istanbul ignore next */ []));
76417
+ /**
76418
+ * `pointer-events: none` while not interactive, mirroring React's
76419
+ * `pointer-events-none` class. {@link marked} keeps the element findable via
76420
+ * `data-pptx-element` even while locked (e.g. a template/master picture with
76421
+ * `editTemplateMode` off); this is what actually stops it from being clicked
76422
+ * or dragged.
76423
+ */
76424
+ rootPointerEvents = computed(() => (this.interactive() ? null : 'none'), /* @ts-ignore */
76425
+ ...(ngDevMode ? [{ debugName: "rootPointerEvents" }] : /* istanbul ignore next */ []));
75989
76426
  sanitizer = inject(DomSanitizer);
75990
76427
  // The clip is load-bearing, not cosmetic: a cropped picture is rendered by
75991
76428
  // scaling the source up and translating the cropped-away part out of the
@@ -76009,6 +76446,7 @@ class ImageRendererComponent {
76009
76446
  <div
76010
76447
  class="pptx-ng-element pptx-ng-image"
76011
76448
  [ngStyle]="containerStyle()"
76449
+ [style.pointer-events]="rootPointerEvents()"
76012
76450
  [attr.data-element-id]="element().id"
76013
76451
  [attr.data-pptx-element]="interactive() || marked() ? 'true' : null"
76014
76452
  >
@@ -76058,6 +76496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
76058
76496
  <div
76059
76497
  class="pptx-ng-element pptx-ng-image"
76060
76498
  [ngStyle]="containerStyle()"
76499
+ [style.pointer-events]="rootPointerEvents()"
76061
76500
  [attr.data-element-id]="element().id"
76062
76501
  [attr.data-pptx-element]="interactive() || marked() ? 'true' : null"
76063
76502
  >
@@ -76548,6 +76987,15 @@ class MediaRendererComponent {
76548
76987
  /** Keep the data-pptx-element marker on interaction-locked template elements. */
76549
76988
  marked = input(false, /* @ts-ignore */
76550
76989
  ...(ngDevMode ? [{ debugName: "marked" }] : /* istanbul ignore next */ []));
76990
+ /**
76991
+ * `pointer-events: none` while not interactive, mirroring React's
76992
+ * `pointer-events-none` class. {@link marked} keeps the element findable via
76993
+ * `data-pptx-element` even while locked (e.g. a template/master video with
76994
+ * `editTemplateMode` off); this is what actually stops it from being clicked
76995
+ * or dragged.
76996
+ */
76997
+ rootPointerEvents = computed(() => (this.interactive() ? null : 'none'), /* @ts-ignore */
76998
+ ...(ngDevMode ? [{ debugName: "rootPointerEvents" }] : /* istanbul ignore next */ []));
76551
76999
  /**
76552
77000
  * True only on the live presentation stage. When set, the media element
76553
77001
  * starts playing on its own once mounted (as PowerPoint does when a slide
@@ -76670,6 +77118,7 @@ class MediaRendererComponent {
76670
77118
  <div
76671
77119
  class="pptx-ng-element pptx-ng-media"
76672
77120
  [ngStyle]="containerStyle()"
77121
+ [style.pointer-events]="rootPointerEvents()"
76673
77122
  [attr.data-element-id]="element().id"
76674
77123
  [attr.data-pptx-element]="interactive() || marked() ? 'true' : null"
76675
77124
  >
@@ -76765,6 +77214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
76765
77214
  <div
76766
77215
  class="pptx-ng-element pptx-ng-media"
76767
77216
  [ngStyle]="containerStyle()"
77217
+ [style.pointer-events]="rootPointerEvents()"
76768
77218
  [attr.data-element-id]="element().id"
76769
77219
  [attr.data-pptx-element]="interactive() || marked() ? 'true' : null"
76770
77220
  >
@@ -78772,8 +79222,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
78772
79222
  * `sz` overrides the (already scaled) body font-size, so without it a
78773
79223
  * shrink-to-fit title painted at full size.
78774
79224
  */
78775
- function runStyleFromSegment(seg, fontScale = 1) {
78776
- const style = segmentStyleToCss(seg, fontScale);
79225
+ function runStyleFromSegment(seg, fontScale = 1, blockFont, text) {
79226
+ const style = segmentStyleToCss(seg, fontScale, { text, blockFont });
78777
79227
  const s = seg.style;
78778
79228
  if (s) {
78779
79229
  const isDoubleStrike = Boolean(s.strikethrough && s.strikeType === 'dblStrike');
@@ -78876,6 +79326,21 @@ class ElementRendererComponent {
78876
79326
  /** Whether this element's root carries `data-pptx-element="true"`. */
78877
79327
  elementMarked = computed(() => this.interactive() || this.marked(), /* @ts-ignore */
78878
79328
  ...(ngDevMode ? [{ debugName: "elementMarked" }] : /* istanbul ignore next */ []));
79329
+ /**
79330
+ * `pointer-events: none` while this render is not interactive, mirroring
79331
+ * React's `pointer-events-none` Tailwind class on the same condition. This is
79332
+ * the piece `editTemplateMode` actually depends on: {@link marked} keeps the
79333
+ * `data-pptx-element` contract attribute on a locked template (master/layout)
79334
+ * element so it stays findable as a rendered slide element, but the attribute
79335
+ * alone never stopped clicks/drags from reaching it. Without this, a
79336
+ * layout/master shape stayed fully clickable with `editTemplateMode` off:
79337
+ * nothing on its DOM node reflected the lock, only the stage's pointerdown
79338
+ * handler's id-based gate did, which kept selection/drag from acting on it
79339
+ * but left the element itself indistinguishable from an interactive one to
79340
+ * anything reading its computed style (e.g. `e2e/template-editing.spec.ts`).
79341
+ */
79342
+ rootPointerEvents = computed(() => (this.interactive() ? null : 'none'), /* @ts-ignore */
79343
+ ...(ngDevMode ? [{ debugName: "rootPointerEvents" }] : /* istanbul ignore next */ []));
78879
79344
  /**
78880
79345
  * True only on the live presentation stage; threaded to the media renderer so
78881
79346
  * a slide's media autoplays when the slide becomes active (and to group
@@ -79102,6 +79567,15 @@ class ElementRendererComponent {
79102
79567
  // run's own `sz` overrides the (already scaled) body font-size. Mirrors
79103
79568
  // shared `buildParagraphs` and React's `renderSingleSegment`.
79104
79569
  const fontScale = resolveAutoFitFontScale(el.textStyle);
79570
+ // What a run that declares no font of its own inherits from the text body,
79571
+ // used only to measure it for the PowerPoint metric tracking. Mirrors
79572
+ // shared `buildParagraphs`.
79573
+ const blockFont = {
79574
+ fontFamily: el.textStyle?.fontFamily
79575
+ ? getSubstituteFontFamily(el.textStyle.fontFamily)
79576
+ : DEFAULT_FONT_FAMILY$1,
79577
+ fontSizePx: (el.textStyle?.fontSize || DEFAULT_TEXT_FONT_SIZE) * fontScale,
79578
+ };
79105
79579
  const paragraphIndents = el.paragraphIndents;
79106
79580
  const out = [{ runs: [], bulletStyle: {}, indentPx: 0 }];
79107
79581
  let paraStarted = false;
@@ -79220,12 +79694,20 @@ class ElementRendererComponent {
79220
79694
  : rawText;
79221
79695
  if (text) {
79222
79696
  const href = resolveHyperlinkHref(seg.style?.hyperlink);
79223
- current.runs.push({
79224
- text,
79225
- style: runStyleFromSegment(seg, fontScale),
79226
- href,
79227
- tooltip: href ? seg.style?.hyperlinkTooltip : undefined,
79228
- });
79697
+ const style = runStyleFromSegment(seg, fontScale, blockFont, text);
79698
+ // One run per word (and per gap), each carrying its own PowerPoint
79699
+ // metric tracking, so a LINE measures what PowerPoint measured and
79700
+ // breaks where PowerPoint breaks (#149). Shared decides the split;
79701
+ // this builder is hand-ported from `buildParagraphs` and would
79702
+ // otherwise silently keep the old whole-run behaviour.
79703
+ for (const piece of splitStyledRun(text, style, resolveRunFont(style, seg.style ?? {}, blockFont), authoredLetterSpacingPx(seg.style))) {
79704
+ current.runs.push({
79705
+ text: piece.text,
79706
+ style: piece.style,
79707
+ href,
79708
+ tooltip: href ? seg.style?.hyperlinkTooltip : undefined,
79709
+ });
79710
+ }
79229
79711
  }
79230
79712
  }
79231
79713
  // A paragraph that already matches the body default needs no re-basing.
@@ -79271,7 +79753,7 @@ class ElementRendererComponent {
79271
79753
  }, /* @ts-ignore */
79272
79754
  ...(ngDevMode ? [{ debugName: "placeholderLabel" }] : /* istanbul ignore next */ []));
79273
79755
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ElementRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
79274
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ElementRendererComponent, isStandalone: true, selector: "pptx-element-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, obstacles: { classPropertyName: "obstacles", publicName: "obstacles", isSignal: true, isRequired: false, transformFunction: null }, canvasWidth: { classPropertyName: "canvasWidth", publicName: "canvasWidth", isSignal: true, isRequired: false, transformFunction: null }, canvasHeight: { classPropertyName: "canvasHeight", publicName: "canvasHeight", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, marked: { classPropertyName: "marked", publicName: "marked", isSignal: true, isRequired: false, transformFunction: null }, presenting: { classPropertyName: "presenting", publicName: "presenting", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, fieldContext: { classPropertyName: "fieldContext", publicName: "fieldContext", isSignal: true, isRequired: false, transformFunction: null }, slideElements: { classPropertyName: "slideElements", publicName: "slideElements", isSignal: true, isRequired: false, transformFunction: null }, editTemplateMode: { classPropertyName: "editTemplateMode", publicName: "editTemplateMode", isSignal: true, isRequired: false, transformFunction: null }, parentGroupFill: { classPropertyName: "parentGroupFill", publicName: "parentGroupFill", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellCommit: "cellCommit", tableChange: "tableChange" }, host: { classAttribute: "contents" }, ngImport: i0, template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t<svg\n\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t}\n\t\t\t\t\t</defs>\n\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t} @else if (hasText()) {\n\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t} @else if (run.href) {\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-link\"\n\t\t\t\t\t\t\t\t\t\t\t[href]=\"run.href\"\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t>{{ run.text }}</a\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t<span [ngStyle]=\"run.style\">{{ run.text }}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n", dependencies: [{ kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill"], outputs: ["cellCommit", "tableChange"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ConnectorRendererComponent, selector: "pptx-connector-renderer", inputs: ["element", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "animationState"] }, { kind: "component", type: TableRendererComponent, selector: "pptx-table-renderer", inputs: ["element", "editable"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: ChartElementViewComponent, selector: "pptx-chart-element-view", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArtRendererComponent, selector: "pptx-smart-art-renderer", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArt3DRendererComponent, selector: "pptx-smart-art-3d-renderer", inputs: ["element", "zIndex", "canEdit", "markElement"] }, { kind: "component", type: InkRendererComponent, selector: "pptx-ink-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "replay", "markElement"] }, { kind: "component", type: MediaRendererComponent, selector: "pptx-media-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "presenting", "placeholderLabel"] }, { kind: "component", type: OleRendererComponent, selector: "pptx-ole-renderer", inputs: ["element"] }, { kind: "component", type: Model3DRendererComponent, selector: "pptx-model3d-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "interactive", "markElement"] }, { kind: "component", type: ZoomRendererComponent, selector: "pptx-zoom-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "markElement"] }, { kind: "component", type: EquationRendererComponent, selector: "pptx-equation-renderer", inputs: ["equationXml", "equationNumber"] }, { kind: "component", type: ImageRendererComponent, selector: "pptx-image-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
79756
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ElementRendererComponent, isStandalone: true, selector: "pptx-element-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, obstacles: { classPropertyName: "obstacles", publicName: "obstacles", isSignal: true, isRequired: false, transformFunction: null }, canvasWidth: { classPropertyName: "canvasWidth", publicName: "canvasWidth", isSignal: true, isRequired: false, transformFunction: null }, canvasHeight: { classPropertyName: "canvasHeight", publicName: "canvasHeight", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, marked: { classPropertyName: "marked", publicName: "marked", isSignal: true, isRequired: false, transformFunction: null }, presenting: { classPropertyName: "presenting", publicName: "presenting", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, fieldContext: { classPropertyName: "fieldContext", publicName: "fieldContext", isSignal: true, isRequired: false, transformFunction: null }, slideElements: { classPropertyName: "slideElements", publicName: "slideElements", isSignal: true, isRequired: false, transformFunction: null }, editTemplateMode: { classPropertyName: "editTemplateMode", publicName: "editTemplateMode", isSignal: true, isRequired: false, transformFunction: null }, parentGroupFill: { classPropertyName: "parentGroupFill", publicName: "parentGroupFill", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellCommit: "cellCommit", tableChange: "tableChange" }, host: { classAttribute: "contents" }, ngImport: i0, template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t<svg\n\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t}\n\t\t\t\t\t</defs>\n\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t} @else if (hasText()) {\n\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t} @else if (run.href) {\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-link\"\n\t\t\t\t\t\t\t\t\t\t\t[href]=\"run.href\"\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t>{{ run.text }}</a\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t<span [ngStyle]=\"run.style\">{{ run.text }}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n", dependencies: [{ kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill"], outputs: ["cellCommit", "tableChange"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ConnectorRendererComponent, selector: "pptx-connector-renderer", inputs: ["element", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "animationState"] }, { kind: "component", type: TableRendererComponent, selector: "pptx-table-renderer", inputs: ["element", "editable"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: ChartElementViewComponent, selector: "pptx-chart-element-view", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArtRendererComponent, selector: "pptx-smart-art-renderer", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArt3DRendererComponent, selector: "pptx-smart-art-3d-renderer", inputs: ["element", "zIndex", "canEdit", "markElement"] }, { kind: "component", type: InkRendererComponent, selector: "pptx-ink-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "replay", "markElement"] }, { kind: "component", type: MediaRendererComponent, selector: "pptx-media-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "presenting", "placeholderLabel"] }, { kind: "component", type: OleRendererComponent, selector: "pptx-ole-renderer", inputs: ["element"] }, { kind: "component", type: Model3DRendererComponent, selector: "pptx-model3d-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "interactive", "markElement"] }, { kind: "component", type: ZoomRendererComponent, selector: "pptx-zoom-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "markElement"] }, { kind: "component", type: EquationRendererComponent, selector: "pptx-equation-renderer", inputs: ["equationXml", "equationNumber"] }, { kind: "component", type: ImageRendererComponent, selector: "pptx-image-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
79275
79757
  }
79276
79758
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ElementRendererComponent, decorators: [{
79277
79759
  type: Component,
@@ -79289,7 +79771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
79289
79771
  ZoomRendererComponent,
79290
79772
  EquationRendererComponent,
79291
79773
  ImageRendererComponent,
79292
- ], template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t<svg\n\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t}\n\t\t\t\t\t</defs>\n\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t} @else if (hasText()) {\n\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t} @else if (run.href) {\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-link\"\n\t\t\t\t\t\t\t\t\t\t\t[href]=\"run.href\"\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t>{{ run.text }}</a\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t<span [ngStyle]=\"run.style\">{{ run.text }}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n" }]
79774
+ ], template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t<svg\n\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t}\n\t\t\t\t\t</defs>\n\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t} @else if (hasText()) {\n\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t} @else if (run.href) {\n\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-link\"\n\t\t\t\t\t\t\t\t\t\t\t[href]=\"run.href\"\n\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t>{{ run.text }}</a\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t<span [ngStyle]=\"run.style\">{{ run.text }}</span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"element().id\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n" }]
79293
79775
  }], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], obstacles: [{ type: i0.Input, args: [{ isSignal: true, alias: "obstacles", required: false }] }], canvasWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasWidth", required: false }] }], canvasHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasHeight", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], marked: [{ type: i0.Input, args: [{ isSignal: true, alias: "marked", required: false }] }], presenting: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenting", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], fieldContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldContext", required: false }] }], slideElements: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideElements", required: false }] }], editTemplateMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTemplateMode", required: false }] }], parentGroupFill: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentGroupFill", required: false }] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], tableChange: [{ type: i0.Output, args: ["tableChange"] }] } });
79294
79776
 
79295
79777
  /**
@@ -81066,7 +81548,7 @@ class MasterViewSidebarComponent {
81066
81548
  <ng-template #backgroundEditor let-color="color">
81067
81549
  <label class="background-editor">
81068
81550
  <span>{{ 'pptx.master.notesMasterBackground' | translate }}</span>
81069
- <input type="color" aria-label="Master background color" [value]="color" (input)="backgroundChange.emit($any($event.target).value)" />
81551
+ <input type="color" [attr.aria-label]="'pptx.master.backgroundColorLabel' | translate" [value]="color" (input)="backgroundChange.emit($any($event.target).value)" />
81070
81552
  </label>
81071
81553
  </ng-template>
81072
81554
  `, isInline: true, styles: [".master-sidebar{display:flex;width:224px;min-height:0;flex-direction:column;border-right:1px solid var(--pptx-border, #33334d);background:var(--pptx-card, #1e1e2e)}header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px}header strong{color:var(--pptx-muted-foreground, #a5a5b5);font-size:11px;text-transform:uppercase}header button{border:0;background:transparent;color:inherit;font-size:20px;cursor:pointer}.tabs{display:flex;padding:0 4px;border-bottom:1px solid var(--pptx-border, #33334d)}.tabs button{flex:1;padding:6px 3px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--pptx-muted-foreground, #a5a5b5);font-size:10px;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:#f59e0b;color:#f59e0b}.body{flex:1;min-height:0;overflow:auto;padding:8px}.master-item{display:block;width:100%;margin-bottom:6px;padding:8px;border:1px solid transparent;border-radius:5px;background:transparent;color:inherit;text-align:left}.master-item.layout{width:calc(100% - 14px);margin-left:14px}.master-item[aria-pressed=true]{border-color:var(--pptx-primary, #6366f1)}section,.background-editor{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:10px;border:1px solid var(--pptx-border, #33334d);border-radius:6px}.counts{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.counts button[aria-pressed=true]{background:var(--pptx-primary, #6366f1);color:#fff}.background-editor input{width:100%;height:34px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -81122,7 +81604,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
81122
81604
  <ng-template #backgroundEditor let-color="color">
81123
81605
  <label class="background-editor">
81124
81606
  <span>{{ 'pptx.master.notesMasterBackground' | translate }}</span>
81125
- <input type="color" aria-label="Master background color" [value]="color" (input)="backgroundChange.emit($any($event.target).value)" />
81607
+ <input type="color" [attr.aria-label]="'pptx.master.backgroundColorLabel' | translate" [value]="color" (input)="backgroundChange.emit($any($event.target).value)" />
81126
81608
  </label>
81127
81609
  </ng-template>
81128
81610
  `, styles: [".master-sidebar{display:flex;width:224px;min-height:0;flex-direction:column;border-right:1px solid var(--pptx-border, #33334d);background:var(--pptx-card, #1e1e2e)}header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px}header strong{color:var(--pptx-muted-foreground, #a5a5b5);font-size:11px;text-transform:uppercase}header button{border:0;background:transparent;color:inherit;font-size:20px;cursor:pointer}.tabs{display:flex;padding:0 4px;border-bottom:1px solid var(--pptx-border, #33334d)}.tabs button{flex:1;padding:6px 3px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--pptx-muted-foreground, #a5a5b5);font-size:10px;cursor:pointer}.tabs button[aria-selected=true]{border-bottom-color:#f59e0b;color:#f59e0b}.body{flex:1;min-height:0;overflow:auto;padding:8px}.master-item{display:block;width:100%;margin-bottom:6px;padding:8px;border:1px solid transparent;border-radius:5px;background:transparent;color:inherit;text-align:left}.master-item.layout{width:calc(100% - 14px);margin-left:14px}.master-item[aria-pressed=true]{border-color:var(--pptx-primary, #6366f1)}section,.background-editor{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:10px;border:1px solid var(--pptx-border, #33334d);border-radius:6px}.counts{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}.counts button[aria-pressed=true]{background:var(--pptx-primary, #6366f1);color:#fff}.background-editor input{width:100%;height:34px}\n"] }]
@@ -89196,6 +89678,25 @@ function ensureTransitionKeyframes() {
89196
89678
 
89197
89679
  /** Safety margin (ms) added to the animation duration before firing complete. */
89198
89680
  const COMPLETE_MARGIN_MS = 50;
89681
+ /**
89682
+ * The slide the overlay paints ABOVE its ghosts, or `undefined` when a morph
89683
+ * has nothing to lift.
89684
+ *
89685
+ * A shape arriving inside a shape that persists is drawn on the live stage,
89686
+ * UNDER this overlay, so the persisting shape's opaque ghost hides it for the
89687
+ * whole transition (issue #146). `buildMorphTransitionPlan` names those few and
89688
+ * holds their stage copy invisible; this wraps them as a slide the component's
89689
+ * own `pptx-slide-canvas` can render.
89690
+ *
89691
+ * Exported and pure so it can be unit-tested: this package renders no component
89692
+ * under test (see `action-settings-panel.component.test.ts`).
89693
+ */
89694
+ function morphLiftedSlide(plan, incomingSlide) {
89695
+ if (!plan || !incomingSlide || plan.overlayIncomingElements.length === 0) {
89696
+ return undefined;
89697
+ }
89698
+ return { ...incomingSlide, elements: [...plan.overlayIncomingElements] };
89699
+ }
89199
89700
  /**
89200
89701
  * PresentationTransitionOverlayComponent: plays a PowerPoint slide transition
89201
89702
  * over the presentation stage.
@@ -89291,6 +89792,9 @@ class PresentationTransitionOverlayComponent {
89291
89792
  ? [
89292
89793
  buildMorphScopedCss(plan, '', 'incoming'),
89293
89794
  buildMorphScopedCss(plan, 'data-pptx-morph-outgoing', 'outgoing'),
89795
+ // Scoped, so it outranks the unscoped `incoming` rule that holds
89796
+ // the stage's copy of the same element invisible.
89797
+ buildMorphScopedCss(plan, 'data-pptx-morph-lifted', 'lifted'),
89294
89798
  ].join('\n')
89295
89799
  : null);
89296
89800
  });
@@ -89379,6 +89883,14 @@ class PresentationTransitionOverlayComponent {
89379
89883
  return { ...slide, elements: [...template, ...slide.elements] };
89380
89884
  }, /* @ts-ignore */
89381
89885
  ...(ngDevMode ? [{ debugName: "layerSlide" }] : /* istanbul ignore next */ []));
89886
+ /**
89887
+ * The arriving shapes the morph has to paint over its own ghosts, or
89888
+ * `undefined` when there are none (issue #146). They sit on the live stage
89889
+ * below this overlay, where the departing layer would hide them for the whole
89890
+ * transition; the plan holds that copy invisible and hands them here instead.
89891
+ */
89892
+ liftedSlide = computed(() => morphLiftedSlide(this.morphPlan(), this.incomingSlide()), /* @ts-ignore */
89893
+ ...(ngDevMode ? [{ debugName: "liftedSlide" }] : /* istanbul ignore next */ []));
89382
89894
  /** Layer container style: animation + stacking relative to the stage. */
89383
89895
  layerStyle = computed(() => {
89384
89896
  const anims = this.animations();
@@ -89451,7 +89963,7 @@ class PresentationTransitionOverlayComponent {
89451
89963
  }
89452
89964
  }
89453
89965
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PresentationTransitionOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
89454
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: PresentationTransitionOverlayComponent, isStandalone: true, selector: "pptx-presentation-transition-overlay", inputs: { outgoingSlide: { classPropertyName: "outgoingSlide", publicName: "outgoingSlide", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, transition: { classPropertyName: "transition", publicName: "transition", isSignal: true, isRequired: true, transformFunction: null }, templateElements: { classPropertyName: "templateElements", publicName: "templateElements", isSignal: true, isRequired: false, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, durationMs: { classPropertyName: "durationMs", publicName: "durationMs", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, incomingSlide: { classPropertyName: "incomingSlide", publicName: "incomingSlide", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { complete: "complete" }, host: { attributes: { "data-pptx-transition-overlay": "" } }, ngImport: i0, template: `
89966
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PresentationTransitionOverlayComponent, isStandalone: true, selector: "pptx-presentation-transition-overlay", inputs: { outgoingSlide: { classPropertyName: "outgoingSlide", publicName: "outgoingSlide", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, transition: { classPropertyName: "transition", publicName: "transition", isSignal: true, isRequired: true, transformFunction: null }, templateElements: { classPropertyName: "templateElements", publicName: "templateElements", isSignal: true, isRequired: false, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, durationMs: { classPropertyName: "durationMs", publicName: "durationMs", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, incomingSlide: { classPropertyName: "incomingSlide", publicName: "incomingSlide", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { complete: "complete" }, host: { attributes: { "data-pptx-transition-overlay": "" } }, ngImport: i0, template: `
89455
89967
  <div
89456
89968
  class="pptx-ng-transition-layer"
89457
89969
  data-pptx-transition-layer="outgoing"
@@ -89470,6 +89982,30 @@ class PresentationTransitionOverlayComponent {
89470
89982
  />
89471
89983
  </div>
89472
89984
  </div>
89985
+
89986
+ <!-- The arriving shapes that dissolve in ABOVE a departing one. They are on
89987
+ the live stage below this overlay, where the departing layer hides them
89988
+ for the whole morph, so they are painted again here. -->
89989
+ @if (liftedSlide(); as lifted) {
89990
+ <div
89991
+ class="pptx-ng-transition-layer"
89992
+ data-pptx-transition-layer="lifted"
89993
+ data-pptx-morph-lifted="true"
89994
+ [ngStyle]="{ 'z-index': '41' }"
89995
+ >
89996
+ <div [ngStyle]="slideBoxStyle()">
89997
+ <pptx-slide-canvas
89998
+ [slide]="lifted"
89999
+ [canvasSize]="canvasSize()"
90000
+ [mediaDataUrls]="mediaDataUrls()"
90001
+ [zoom]="zoom()"
90002
+ [autoFit]="false"
90003
+ [interactive]="false"
90004
+ [transparentBackground]="true"
90005
+ />
90006
+ </div>
90007
+ </div>
90008
+ }
89473
90009
  `, isInline: true, styles: [":host{display:block;position:absolute;inset:0;overflow:hidden;pointer-events:none}.pptx-ng-transition-layer{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
89474
90010
  }
89475
90011
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PresentationTransitionOverlayComponent, decorators: [{
@@ -89493,6 +90029,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
89493
90029
  />
89494
90030
  </div>
89495
90031
  </div>
90032
+
90033
+ <!-- The arriving shapes that dissolve in ABOVE a departing one. They are on
90034
+ the live stage below this overlay, where the departing layer hides them
90035
+ for the whole morph, so they are painted again here. -->
90036
+ @if (liftedSlide(); as lifted) {
90037
+ <div
90038
+ class="pptx-ng-transition-layer"
90039
+ data-pptx-transition-layer="lifted"
90040
+ data-pptx-morph-lifted="true"
90041
+ [ngStyle]="{ 'z-index': '41' }"
90042
+ >
90043
+ <div [ngStyle]="slideBoxStyle()">
90044
+ <pptx-slide-canvas
90045
+ [slide]="lifted"
90046
+ [canvasSize]="canvasSize()"
90047
+ [mediaDataUrls]="mediaDataUrls()"
90048
+ [zoom]="zoom()"
90049
+ [autoFit]="false"
90050
+ [interactive]="false"
90051
+ [transparentBackground]="true"
90052
+ />
90053
+ </div>
90054
+ </div>
90055
+ }
89496
90056
  `, styles: [":host{display:block;position:absolute;inset:0;overflow:hidden;pointer-events:none}.pptx-ng-transition-layer{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}\n"] }]
89497
90057
  }], ctorParameters: () => [], propDecorators: { outgoingSlide: [{ type: i0.Input, args: [{ isSignal: true, alias: "outgoingSlide", required: true }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], transition: [{ type: i0.Input, args: [{ isSignal: true, alias: "transition", required: true }] }], templateElements: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateElements", required: false }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], durationMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "durationMs", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], incomingSlide: [{ type: i0.Input, args: [{ isSignal: true, alias: "incomingSlide", required: false }] }], complete: [{ type: i0.Output, args: ["complete"] }] } });
89498
90058
 
@@ -89914,7 +90474,7 @@ class PresentationOverlayComponent {
89914
90474
  this.closed.emit();
89915
90475
  }
89916
90476
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PresentationOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
89917
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PresentationOverlayComponent, isStandalone: true, selector: "pptx-presentation-overlay", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, startIndex: { classPropertyName: "startIndex", publicName: "startIndex", isSignal: true, isRequired: false, transformFunction: null }, showWithAnimation: { classPropertyName: "showWithAnimation", publicName: "showWithAnimation", isSignal: true, isRequired: false, transformFunction: null }, useTimings: { classPropertyName: "useTimings", publicName: "useTimings", isSignal: true, isRequired: false, transformFunction: null }, subtitlesVisible: { classPropertyName: "subtitlesVisible", publicName: "subtitlesVisible", isSignal: true, isRequired: false, transformFunction: null }, sessionEnded: { classPropertyName: "sessionEnded", publicName: "sessionEnded", isSignal: true, isRequired: false, transformFunction: null }, endWithBlackSlide: { classPropertyName: "endWithBlackSlide", publicName: "endWithBlackSlide", isSignal: true, isRequired: false, transformFunction: null }, presenterMode: { classPropertyName: "presenterMode", publicName: "presenterMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { indexChange: "indexChange", closed: "closed", subtitlesChange: "subtitlesChange", presenterViewToggle: "presenterViewToggle", annotationsExit: "annotationsExit" }, host: { listeners: { "document:wheel": "onWheel($event)", "document:fullscreenchange": "onFullscreenChange()", "window:resize": "onWindowResize()", "document:keydown": "onKeyDown($event)" } }, providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], viewQueries: [{ propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "rootRef", first: true, predicate: ["root"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"$event.preventDefault()\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationTransitionOverlayComponent, selector: "pptx-presentation-transition-overlay", inputs: ["outgoingSlide", "canvasSize", "transition", "templateElements", "mediaDataUrls", "durationMs", "zoom", "incomingSlide"], outputs: ["complete"] }, { kind: "component", type: PresentationAnnotationOverlayComponent, selector: "pptx-presentation-annotation-overlay", inputs: ["canvasSize", "zoom"] }, { kind: "component", type: PresentationSubtitleBarComponent, selector: "pptx-presentation-subtitle-bar", inputs: ["visible"] }, { kind: "component", type: PresentationToolbarComponent, selector: "pptx-presentation-toolbar", inputs: ["currentSlideIndex", "totalSlides", "presentationStartTime", "presenterMode"], outputs: ["move", "endPresentation", "presenterViewToggle"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
90477
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PresentationOverlayComponent, isStandalone: true, selector: "pptx-presentation-overlay", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, startIndex: { classPropertyName: "startIndex", publicName: "startIndex", isSignal: true, isRequired: false, transformFunction: null }, showWithAnimation: { classPropertyName: "showWithAnimation", publicName: "showWithAnimation", isSignal: true, isRequired: false, transformFunction: null }, useTimings: { classPropertyName: "useTimings", publicName: "useTimings", isSignal: true, isRequired: false, transformFunction: null }, subtitlesVisible: { classPropertyName: "subtitlesVisible", publicName: "subtitlesVisible", isSignal: true, isRequired: false, transformFunction: null }, sessionEnded: { classPropertyName: "sessionEnded", publicName: "sessionEnded", isSignal: true, isRequired: false, transformFunction: null }, endWithBlackSlide: { classPropertyName: "endWithBlackSlide", publicName: "endWithBlackSlide", isSignal: true, isRequired: false, transformFunction: null }, presenterMode: { classPropertyName: "presenterMode", publicName: "presenterMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { indexChange: "indexChange", closed: "closed", subtitlesChange: "subtitlesChange", presenterViewToggle: "presenterViewToggle", annotationsExit: "annotationsExit" }, host: { listeners: { "document:wheel": "onWheel($event)", "document:fullscreenchange": "onFullscreenChange()", "window:resize": "onWindowResize()", "document:keydown": "onKeyDown($event)" } }, providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], viewQueries: [{ propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "rootRef", first: true, predicate: ["root"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"$event.preventDefault()\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y;overflow:hidden}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationTransitionOverlayComponent, selector: "pptx-presentation-transition-overlay", inputs: ["outgoingSlide", "canvasSize", "transition", "templateElements", "mediaDataUrls", "durationMs", "zoom", "incomingSlide"], outputs: ["complete"] }, { kind: "component", type: PresentationAnnotationOverlayComponent, selector: "pptx-presentation-annotation-overlay", inputs: ["canvasSize", "zoom"] }, { kind: "component", type: PresentationSubtitleBarComponent, selector: "pptx-presentation-subtitle-bar", inputs: ["visible"] }, { kind: "component", type: PresentationToolbarComponent, selector: "pptx-presentation-toolbar", inputs: ["currentSlideIndex", "totalSlides", "presentationStartTime", "presenterMode"], outputs: ["move", "endPresentation", "presenterViewToggle"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
89918
90478
  }
89919
90479
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PresentationOverlayComponent, decorators: [{
89920
90480
  type: Component,
@@ -89929,7 +90489,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
89929
90489
  LucideX,
89930
90490
  LucideChevronLeft,
89931
90491
  LucideChevronRight,
89932
- ], providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"$event.preventDefault()\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"] }]
90492
+ ], providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"$event.preventDefault()\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y;overflow:hidden}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"] }]
89933
90493
  }], ctorParameters: () => [], propDecorators: { slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: true }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], startIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "startIndex", required: false }] }], showWithAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWithAnimation", required: false }] }], useTimings: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTimings", required: false }] }], subtitlesVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitlesVisible", required: false }] }], sessionEnded: [{ type: i0.Input, args: [{ isSignal: true, alias: "sessionEnded", required: false }] }], endWithBlackSlide: [{ type: i0.Input, args: [{ isSignal: true, alias: "endWithBlackSlide", required: false }] }], presenterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenterMode", required: false }] }], indexChange: [{ type: i0.Output, args: ["indexChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], subtitlesChange: [{ type: i0.Output, args: ["subtitlesChange"] }], presenterViewToggle: [{ type: i0.Output, args: ["presenterViewToggle"] }], annotationsExit: [{ type: i0.Output, args: ["annotationsExit"] }], stageRef: [{ type: i0.ViewChild, args: ['stage', { isSignal: true }] }], rootRef: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], onWheel: [{
89934
90494
  type: HostListener,
89935
90495
  args: ['document:wheel', ['$event']]
@@ -96055,7 +96615,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
96055
96615
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }] } });
96056
96616
 
96057
96617
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
96058
- const PPTX_ANGULAR_VIEWER_VERSION = "2.17.0";
96618
+ const PPTX_ANGULAR_VIEWER_VERSION = "2.17.2";
96059
96619
 
96060
96620
  /**
96061
96621
  * account-page.component.ts: File > Account content.
@@ -103131,7 +103691,7 @@ function setSeriesName(element, seriesIndex, name) {
103131
103691
  if (!chartData) {
103132
103692
  return element;
103133
103693
  }
103134
- const series = chartData.series.map((s, i) => (i === seriesIndex ? { ...s, name } : s));
103694
+ const series = chartData.series.map((s, i) => i === seriesIndex ? { ...s, name } : s);
103135
103695
  return { ...element, chartData: { ...chartData, series } };
103136
103696
  }
103137
103697
  // ---------------------------------------------------------------------------
@@ -103185,7 +103745,7 @@ function setSeriesColor(element, seriesIndex, color) {
103185
103745
  return element;
103186
103746
  }
103187
103747
  const normalized = color ? normalizeHex(color) : undefined;
103188
- const series = chartData.series.map((s, i) => (i === seriesIndex ? { ...s, color: normalized } : s));
103748
+ const series = chartData.series.map((s, i) => i === seriesIndex ? { ...s, color: normalized } : s);
103189
103749
  return { ...element, chartData: { ...chartData, series } };
103190
103750
  }
103191
103751
  /** Normalise a hex colour to a `#`-prefixed form, trimming whitespace. */
@@ -113214,12 +113774,18 @@ class DocumentPropertiesCardComponent {
113214
113774
  }
113215
113775
  onCoreChange(event, key) {
113216
113776
  const value = event.target.value;
113217
- this.loader.coreProperties.update((current) => ({ ...(current ?? {}), [key]: value }));
113777
+ this.loader.coreProperties.update((current) => ({
113778
+ ...(current ?? {}),
113779
+ [key]: value,
113780
+ }));
113218
113781
  this.markDirty();
113219
113782
  }
113220
113783
  onAppChange(event, key) {
113221
113784
  const value = event.target.value;
113222
- this.loader.appProperties.update((current) => ({ ...(current ?? {}), [key]: value }));
113785
+ this.loader.appProperties.update((current) => ({
113786
+ ...(current ?? {}),
113787
+ [key]: value,
113788
+ }));
113223
113789
  this.markDirty();
113224
113790
  }
113225
113791
  onAddCustom() {
@@ -127993,4 +128559,4 @@ function cn(...values) {
127993
128559
  */
127994
128560
 
127995
128561
  export { CommentsService as $, ALIGN_OPTIONS as A, AnimationPlaybackService as B, AutosaveService as C, BroadcastDialogComponent as D, CHART_EDITOR_STYLES as E, CURSOR_PALETTE as F, CanvasFitService as G, ChartAxisOptionsComponent as H, ChartAxisStyleOptionsComponent as I, ChartComboTypeOptionsComponent as J, ChartDataEditorComponent as K, ChartDataLabelOptionsComponent as L, ChartDatapointMarkerOptionsComponent as M, ChartDatapointOptionsComponent as N, ChartDisplayOptionsComponent as O, ChartElementViewComponent as P, ChartErrorBarOptionsComponent as Q, ChartMarkerOptionsComponent as R, ChartPartSelectionService as S, ChartPrimitivesComponent as T, ChartRendererComponent as U, ChartTrendlineOptionsComponent as V, CollaborationCursorsComponent as W, CollaborationService as X, ColorChangedImageComponent as Y, CommentMarkersOverlayComponent as Z, CommentsPanelComponent as _, ANIMATION_PRESET_CATEGORIES as a, IsMobileService as a$, ComparePanelComponent as a0, ConnectorRendererComponent as a1, ConnectorTextOverlayComponent as a2, CustomShowsComponent as a3, DATA_TABLE_HEADER_H as a4, DATA_TABLE_KEY_W as a5, DATA_TABLE_PADDING as a6, DATA_TABLE_ROW_H as a7, DEFAULT_BOUNDS as a8, DEFAULT_BROADCAST_SERVER_URL as a9, EffectsPanelComponent as aA, ElementRendererComponent as aB, EmbeddedFontsService as aC, EncryptedFileDialogComponent as aD, EquationEditorDialogComponent as aE, EquationRendererComponent as aF, EquationTemplateGalleryComponent as aG, ExportProgressModalComponent as aH, ExportService as aI, FieldContextService as aJ, FindBarComponent as aK, FindReplaceBarComponent as aL, FollowModeBarComponent as aM, FontEmbeddingListComponent as aN, FontEmbeddingPanelComponent as aO, GALLERY_THEME_PRESETS as aP, GRIDLINE_COLOR as aQ, GradientPickerComponent as aR, HANDOUT_OPTIONS as aS, HeaderFooterDialogComponent as aT, HyperlinkDialogComponent as aU, ImagePropertiesPanelComponent as aV, InkDrawingService as aW, InkRendererComponent as aX, InsertSmartArtDialogComponent as aY, InspectorPaneHeaderComponent as aZ, InspectorPanelComponent as a_, DEFAULT_CANVAS_HEIGHT as aa, DEFAULT_CANVAS_WIDTH as ab, DEFAULT_COLOR_SCHEME as ac, DEFAULT_FILL_COLOR as ad, DEFAULT_LAYOUT as ae, DEFAULT_PALETTE$1 as af, DEFAULT_PATTERN_FILL_PRESET as ag, DEFAULT_PRINT_SETTINGS as ah, DEFAULT_SLIDE_BACKGROUND as ai, DEFAULT_STROKE_COLOR as aj, DEFAULT_STYLE as ak, DEFAULT_TABLE_ROW_HEIGHT as al, DEFAULT_TEXT_COLOR$1 as am, DEFAULT_VIEWER_PROFILE as an, DIRECTIONAL_PRESETS as ao, DIRECTION_OPTIONS as ap, DocumentPropertiesCardComponent as aq, EMBEDDED_FONTS_STYLE_ID as ar, EMPHASIS_PRESETS as as, ENTRANCE_PRESETS as at, TEMPLATES as au, EXIT_PRESETS as av, EditorContextMenuComponent as aw, EditorHistory as ax, EditorStateService as ay, EditorToolbarComponent as az, AUDIENCE_HASH as b, RibbonDrawingGroupComponent as b$, KeepAnnotationsDialogComponent as b0, LOCALE_CATALOG as b1, LONG_PRESS_DURATION_MS as b2, LONG_PRESS_MOVE_TOLERANCE_PX as b3, LoadContentService as b4, LocalPresencePublisher as b5, MAX_ZOOM_SCALE as b6, MIN_ZOOM_SCALE as b7, MOTION_PATH_COLUMNS as b8, MediaPreviewComponent as b9, PresentationAnnotationOverlayComponent as bA, PresentationAnnotationsService as bB, PresentationOverlayComponent as bC, PresentationPropertiesPanelComponent as bD, PresentationSettingsCardComponent as bE, PresentationSubtitleBarComponent as bF, PresentationToolbarComponent as bG, PresentationTransitionOverlayComponent as bH, PresenterViewComponent as bI, PresenterWindowService as bJ, PrintDialogComponent as bK, PrintService as bL, PrintSettingsPanelComponent as bM, PropertiesDialogComponent as bN, REPEAT_MODE_OPTIONS as bO, RESIZE_HANDLES as bP, RULER_FONT_SIZE as bQ, RULER_THICKNESS as bR, ReadingViewOverlayComponent as bS, RemoteSelectionOverlayComponent as bT, RibbonAnimationGalleryComponent as bU, RibbonAnimationsSectionComponent as bV, RibbonArrangeSectionComponent as bW, RibbonColorPopoverComponent as bX, RibbonComponent as bY, RibbonDesignSectionComponent as bZ, RibbonDrawSectionComponent as b_, MediaPropertiesPanelComponent as ba, MediaRendererComponent as bb, MediaTrimTimelineComponent as bc, MobileBottomBarComponent as bd, MobileMenuSheetComponent as be, MobilePresenterViewComponent as bf, MobileSheetComponent as bg, MobileSlidesSheetComponent as bh, MobileToolbarComponent as bi, ModalDialogComponent as bj, Model3DRendererComponent as bk, NotesHandoutCardComponent as bl, NotesPanelComponent as bm, NotesToolbarComponent as bn, OleRendererComponent as bo, OutlineViewOverlayComponent as bp, POWER_POINT_VIEWER_PROVIDERS as bq, PRESENTER_CHANNEL_NAME as br, PRESENTER_MSG_ORIGIN as bs, PRESENTER_TIMER_SEGMENT_MS as bt, PX_PER_CM as bu, PX_PER_INCH as bv, PasswordProtectionDialogComponent as bw, PasswordStrengthMeterComponent as bx, PowerPointViewerComponent as by, PresentToolbarAutoHide as bz, AUDIENCE_NONCE_KEY as c, TIMING_CURVE_OPTIONS as c$, RibbonEditingSectionComponent as c0, RibbonFileSectionComponent as c1, RibbonFontControlsComponent as c2, RibbonHomeSectionComponent as c3, RibbonHyperlinkButtonComponent as c4, RibbonInsertFieldsComponent as c5, RibbonInsertSectionComponent as c6, RibbonMotionPathGalleryComponent as c7, RibbonParagraphControlsComponent as c8, RibbonPrimaryRowComponent as c9, ShowOptionsFieldsetComponent as cA, ShowSlidesFieldsetComponent as cB, SignatureStrippedDialogComponent as cC, SignaturesPanelComponent as cD, SignaturesService as cE, SlideBackgroundCardComponent as cF, SlideCanvasComponent as cG, SlideDefaultInspectorComponent as cH, SlideDiffChangesComponent as cI, SlideDiffRowComponent as cJ, SlideDiffThumbnailsComponent as cK, SlideSizeCardComponent as cL, SlideSorterOverlayComponent as cM, SlideThemeOverridePanelComponent as cN, SlideTransitionCardComponent as cO, SlidesPanelComponent as cP, SmartArt3DRendererComponent as cQ, SmartArt3DService as cR, SmartArtPreviewComponent as cS, SmartArtPropertiesComponent as cT, SmartArtRendererComponent as cU, StatusBarComponent as cV, TABLE_STRUCTURE_TOGGLES as cW, TEXT_3D_BOTTOM_BEVEL_KEYS as cX, TEXT_3D_TOP_BEVEL_KEYS as cY, TEXT_DIRECTION_OPTIONS$1 as cZ, THEME_CATALOG as c_, RibbonReviewSectionComponent as ca, RibbonShapeExtrasComponent as cb, RibbonSlideshowSectionComponent as cc, RibbonTransitionsSectionComponent as cd, RibbonViewSectionComponent as ce, RulerGuidesService as cf, SEQUENCE_OPTIONS as cg, SEVERITY_GROUPS as ch, SEVERITY_LABELS as ci, SHORTCUT_REFERENCE_ITEMS as cj, SLIDE_TRANSITION_KEYFRAMES as ck, DEFAULT_PALETTE as cl, PALETTES$1 as cm, SMART_ART_COLOR_SCHEMES as cn, SMART_ART_STYLE_OPTIONS as co, SUB_ITEM_LABEL as cp, SVG_WARP_PRESETS as cq, SWIPE_MAX_VERTICAL_PX as cr, SWIPE_THRESHOLD_PX as cs, SelectionPaneComponent as ct, SetUpSlideShowDialogComponent as cu, SettingsAppearanceTabComponent as cv, SettingsDialogComponent as cw, SettingsLanguageTabComponent as cx, ShareDialogComponent as cy, ShortcutPanelComponent as cz, AVATAR_COLOR_SWATCHES as d, applyAnimationPreset as d$, TRIGGER_OPTIONS as d0, TYPE_LABELS as d1, TableCellAdvancedFillComponent as d2, TableCellFormattingComponent as d3, TableDataEditorComponent as d4, TablePropertiesComponent as d5, TableRendererComponent as d6, TableResizeOverlayComponent as d7, TableSelectionService as d8, TagsCardComponent as d9, ViewerInspectorPanelService as dA, ViewerKeyboardService as dB, ViewerMobileSheetService as dC, ViewerPresentationModeService as dD, ViewerThemeGalleryService as dE, ViewerTouchGesturesService as dF, ViewerZoomService as dG, WEBM_MIME_CANDIDATES as dH, WriteBackScheduler as dI, ZERO_LINE_COLOR as dJ, ZoomNavigationService as dK, ZoomRendererComponent as dL, ZoomTargetService as dM, addCategory as dN, addCommentToList as dO, addGradientStopPatch as dP, addItem as dQ, addSeries as dR, addSubItem as dS, advanceStep as dT, affordanceElements as dU, aiToggleVisible as dV, alignPatch as dW, animationFor as dX, animationPresetLabelKey as dY, annotationMapToInkInserts as dZ, applyAcceptedDiff as d_, Text3DBevelSectionComponent as da, Text3DPanelComponent as db, TextAdvancedPanelComponent as dc, ThemeEditorFieldsComponent as dd, ThemeGalleryComponent as de, ThemeSelectorCardComponent as df, TitleBarComponent as dg, TitleBarSearchComponent as dh, TransitionDirectionPickerComponent as di, TransitionPreviewComponent as dj, VALIGN_OPTIONS as dk, VIEWER_THEME as dl, VersionHistoryPanelComponent as dm, ViewerCanvasEditingService as dn, ViewerCollabCursorService as dp, ViewerCollaborationSessionService as dq, ViewerCompareService as dr, ViewerCustomShowsService as ds, ViewerDialogsService as dt, ViewerDocumentPropertiesService as du, ViewerExportService as dv, ViewerExtraDialogsComponent as dw, ViewerFileIOService as dx, ViewerFindReplaceService as dy, ViewerFormatPainterService as dz, AXIS_LABEL_COLOR as e, buildZoomViewModel as e$, applyFindReplacements as e0, applyFormatToElement as e1, applyMove as e2, applyResize as e3, applyTableStylePreset as e4, asMediaElement as e5, assignUserColor as e6, attachShowVisibilityPause as e7, attachTouchGestures as e8, axisTickValues as e9, buildFontFaceRule as eA, buildGradientFillCss as eB, buildGridlinesAndLabels as eC, buildHyperlinkPatch as eD, buildInkContainerStyle as eE, buildInkStrokes as eF, buildLegend as eG, buildModel3DContainerStyle as eH, buildModel3DViewModel as eI, buildOleActionModel as eJ, buildOleInfoRows as eK, buildPatternFillCss as eL, buildPrintHtmlDocument as eM, buildPropertiesPatch as eN, buildRegionMapViewModel as eO, buildSaveSlides as eP, buildShareUrl as eQ, buildSmartArtInsertElement as eR, buildSmartArtNodes as eS, buildStockViewModel as eT, buildSurfaceViewModel as eU, buildTableViewModel as eV, buildTreemapViewModel as eW, buildTrimFragment as eX, buildWaterfallViewModel as eY, buildZeroLine as eZ, buildZoomContainerStyle as e_, beginNodeEdit as ea, bevelSizePatch as eb, boolFromEvent as ec, bringForward as ed, bringToFront as ee, buildBarActions as ef, buildBroadcastConfig as eg, buildBroadcastViewerUrl as eh, buildCategoryLabels as ei, buildCellParagraphs as ej, buildChartViewModel as ek, buildChatLogExport as el, buildChatLogMarkdown as em, buildChromeStyle as en, buildClearHyperlinkPatch as eo, buildClickGroups as ep, buildColStyles as eq, buildCollaborationConfig as er, buildComboViewModel as es, buildCssGradientFromShapeStyle as et, buildDuotoneFilter as eu, buildDuotoneFilterId as ev, buildEmbeddedFontStyles as ew, buildEquationElement as ex, buildEquationSegment as ey, buildFallbackViewModel as ez, AccessibilityPanelComponent as f, computeTextLines as f$, bulletIndentPx as f0, canAddTopLevelNode as f1, canGroupSelection as f2, canRemoveTopLevelNode as f3, canSetStrokeWidth as f4, canStartBroadcast as f5, canStartShare as f6, canUngroupSelection as f7, canUseClipboard as f8, captionDisplayText as f9, computeBubbleRadius as fA, computeCornerHandle as fB, computeDataTablePrimitives as fC, computeDistribute as fD, computeDrawingViewBox as fE, computeErrorBarPrimitives as fF, computeFocusTargets as fG, computeHandleBoxes as fH, computeHandoutLayout as fI, computeIsMobile as fJ, computeIsTablet as fK, computeLinePoints as fL, computeLinearRegression as fM, computePageCount as fN, computePieLayout as fO, computePieSlicePath as fP, computePieSlices as fQ, computePlotLayout as fR, computeRSquared as fS, computeRadarPoints as fT, computeScatterDots as fU, computeSelectionBoxes as fV, computeSingleSelected as fW, computeSlideIndices as fX, computeSnap as fY, computeStackedBarRects as fZ, computeStackedValueRange as f_, cellRunStyle as fa, cellStyleToStyleMap as fb, cellTdStyle as fc, changeCountLabel as fd, changeIcon as fe, characterSpacingPatch as ff, checkFontAvailable as fg, clampCursorPosition as fh, clampGifDimensions as fi, clampIndex as fj, clampNotesFontSize as fk, clampScale as fl, clampStep as fm, clearAllLocalViewerData as fn, clearAudienceContent as fo, cn as fp, collectAccessibilityIssues as fq, collectElementText as fr, collectSlideText as fs, collectStoredChats as ft, collectUsedFontFamilies as fu, columnWidthStyle as fv, commitNodeText as fw, computeAlign as fx, computeAxisTitlePrimitives as fy, computeBarRects as fz, AccessibilityService as g, formatPropertyDate as g$, computeTrendlinePrimitives as g0, computeValueRange as g1, convertOmmlToMathMl as g2, copyFormatFromElement as g3, countAccessibilityIssues as g4, countAnnotationStrokes as g5, createAngularAiBridge as g6, createCustomShow as g7, createSwipeDismissDrag as g8, createWebrtcBundle as g9, enableSoftEdgePatch as gA, encodeGif as gB, endShowMediaCleanup as gC, estimatePageCount as gD, evenColumnWidths as gE, evenRowHeights as gF, exitPresentationFullscreen as gG, exportAiChatLogs as gH, extractPathPoints as gI, eyedropperAvailable as gJ, fillColorOf as gK, findInSlides as gL, findOwningSlideIndex as gM, findSlideIndexByElementId as gN, firstVisibleIndex as gO, fitPolynomial as gP, fitZoom as gQ, focusTargetChips as gR, fontMimeForFormat as gS, fontSizeOf as gT, forgetSessionDeck as gU, formatAutoNumber as gV, formatAxisValue as gW, formatBytes as gX, formatCursorLabel as gY, formatElapsed as gZ, formatFileSize as g_, createWebsocketBundle as ga, cssObjectToStyleMap as gb, currentColorScheme as gc, currentLayout as gd, currentStyle as ge, defaultCssVars as gf, defaultRadius as gg, defaultThemeColors as gh, deleteElementsByIds as gi, deleteVersion as gj, demoteNode as gk, deriveModel3DBlobUrl as gl, derivePresenceList as gm, describeSmartArtBounds as gn, disableGlowPatch as go, disableInnerShadowPatch as gp, disableOuterShadowPatch as gq, disableReflectionPatch as gr, disableSoftEdgePatch as gs, duplicateElementById as gt, durationOf as gu, effectsStateOf as gv, enableGlowPatch as gw, enableInnerShadowPatch as gx, enableOuterShadowPatch as gy, enableReflectionPatch as gz, AccountPageComponent as h, isSigned as h$, formatTime as h0, fpsToFrameIntervalMs as h1, generateBroadcastRoomId as h2, generateCommentId as h3, generateCustomShowId as h4, generatePressureCircles as h5, generateTicks as h6, getClrChangeParams as h7, getContainerStyle as h8, getDuotoneFilterDef as h9, gradientStateOf as hA, gradientStatePatch as hB, gridColumns as hC, groupElements as hD, groupIssuesBySeverity as hE, hasAnimation as hF, hasCopyableFormat as hG, hasExistingLink as hH, hasExitedFullscreen as hI, hasGradientFill as hJ, hasPressureVariation as hK, hasVisibleSlideAfter as hL, headerLabel as hM, imageDimensions as hN, inkViewBox as hO, insertTableElementColumn as hP, insertTableElementRow as hQ, interpolateWidth as hR, isAudienceTab as hS, isBold as hT, isBrowserOpenableMime as hU, isChildNode as hV, isElementInteractive as hW, isInjectableUrl as hX, isItalic as hY, isPpactionUrl as hZ, isPresenterMessage as h_, getImageSrc as ha, getLocalStorageUsageSummary as hb, getOleAriaLabel as hc, getOleBadgeLabel as hd, getOleDisplayName as he, getOleDownloadFileName as hf, getOleTypeColor as hg, getOleTypeLabel as hh, getPasswordStrength as hi, getPatternSvg as hj, getPlaceholderStyle as hk, getVersions as hl, getResolvedShapeClipPath as hm, getResolvedShapeClipPathFor as hn, getSessionTabId as ho, getShapeFillStrokeStyle as hp, getSlideBackgroundStyle as hq, getSlideTransitionAnimations as hr, getSmartArtNodeBounds as hs, getSpeechRecognitionCtor as ht, getTextBlockStyle as hu, getTextWarp as hv, getTouchDistance as hw, getWarpCategory as hx, getWarpPath as hy, gradientStateFromStyle as hz, ActionSettingsPanelComponent as i, pendingElementStyles as i$, isTextElement as i0, isTwoTableFocus as i1, isUnderline as i2, isUrlSafe as i3, isValidRoomId as i4, isViewportBackgroundPressTarget as i5, isZoomActivationKey as i6, issueTrackKey as i7, issueTypeLabel as i8, keyToLabel as i9, newTableElement as iA, newTextElement as iB, nextVisibleIndex as iC, nodeBold as iD, nodeEditBox as iE, nodeFillColor as iF, nodeFontColor as iG, nodeIdFromKey as iH, nodeItalic as iI, nodeStyle as iJ, normalizeFontFormat as iK, normalizeSlidesPerPage as iL, normalizeValue as iM, numFromEvent as iN, ommlToMathml as iO, ooxmlDashToCssBorderStyle as iP, openNativeEyeDropper as iQ, overallStatus as iR, paletteColor as iS, parseAudienceNonce as iT, parseNodeTextarea as iU, partitionSlides as iV, patchChartData as iW, patchChartStyle as iX, patchTableData as iY, patchTextStyle as iZ, patternPresetOptions as i_, lastVisibleIndex as ia, latexToMathml as ib, linePointsToSvgString as ic, lineSpacingPatch as id, loadAudienceContent as ie, loadSessionDeck as ig, mediaFallbackFor as ih, mediaSurfaceFor as ii, mergeCaptionResults as ij, mergeDown as ik, mergeRight as il, mergeSelection as im, moveElementBy as io, moveNodeDown as ip, moveNodeUp as iq, msToFrameDelayCs as ir, narrowToCircle as is, narrowToPolygon as it, narrowToRect as iu, newChartElement as iv, newEquationElement as iw, newPresetShapeElement as ix, newShapeElement as iy, newSmartArtElement as iz, AdvancedChartEditorComponent as j, sanitizeSlideIndex as j$, pickColorByClickFallback as j0, pickFile as j1, pickSupportedMimeType as j2, planGifFrames as j3, planVideoSegments as j4, pointsToSvgPathD as j5, presenceToCursors as j6, presentationStageStyle as j7, presenterTimerProgress as j8, presetByLayout as j9, replaceMatch as jA, requestPresentationFullscreen as jB, resizeElement as jC, resolveCaptionTracks as jD, resolveChartKind as jE, resolveFontVariant as jF, resolveHyperlinkHref as jG, resolveInteractiveElementId as jH, resolveMediaSrc as jI, resolveOleType as jJ, resolveParagraphBullet as jK, resolvePresenterNotes as jL, resolveProfileInitial as jM, resolveRegionCode as jN, resolveSlideAutoAdvanceMs as jO, resolvePalette as jP, resolveThemeCatalogEntry as jQ, resolveTransitionDuration as jR, restoreSessionDeck as jS, revealedElementStyles as jT, routeOrthogonalConnector as jU, rowStyle as jV, rulerDragToGuidePosition as jW, rulerHighlight as jX, rulerStripTicks as jY, sampleColorFromSlide as jZ, sanitizeColor as j_, presetsForCategory as ja, pressuresToWidths as jb, prevVisibleIndex as jc, projectDrawingShapes as jd, promoteNode as je, provideViewerTheme as jf, radarAngle as jg, radarRingPoints as jh, readAsDataUrl as ji, recordWebm as jj, redistributeColumnWidth as jk, registerCrossSlideAudio as jl, rememberSessionDeck as jm, removeAnimation as jn, removeCategory as jo, removeTableElementColumn as jp, removeCommentFromList as jq, removeElementAnimation as jr, removeGradientStopPatch as js, removeNode as jt, removeTableElementRow as ju, removeSeries as jv, renderToCanvas as jw, reorderAnimationDown as jx, reorderAnimationUp as jy, replaceInSlides as jz, AiChangeOverlayComponent as k, statusLabel as k$, sanitizeUserName as k0, saveViewerProfile as k1, scanAvailableFonts as k2, searchSlides as k3, seedBroadcastFields as k4, seedHyperlinkDraft as k5, seedPropertiesDraft as k6, seedShareFields as k7, segmentFrameCount as k8, selectValue$2 as k9, setNodeStyle as kA, setNodeText as kB, setRepeatCount as kC, setRepeatMode as kD, setSequence as kE, setSeriesChartType as kF, setSeriesColor as kG, setSeriesErrorBars as kH, setSeriesMarker as kI, setSeriesName as kJ, setSeriesTrendline as kK, setSeriesValue as kL, setStyle as kM, setTimingCurve as kN, setTitle as kO, setTrigger as kP, setTriggerShapeId as kQ, shapeStylePatch as kR, sheetAfterNavigate as kS, shouldBlockClickAdvance as kT, shouldUseSvgWarp as kU, showDirectionPicker as kV, showsTemplateAffordance as kW, signatureCountLabel as kX, signatureKey as kY, signatureTimestamp as kZ, signerName as k_, sendBackward as ka, sendToBack as kb, sequentialColorScale as kc, serializeWriteBack as kd, seriesColor as ke, setAnimationEmphasis as kf, setAnimationEntrance as kg, setAnimationExit as kh, setAxis as ki, setAxisLogScale as kj, setAxisTitleStyle as kk, setCategoryLabel as kl, setCellText as km, setColorScheme as kn, setDataLabels as ko, setDataPointExplosion as kp, setDataPointFill as kq, setDataPointLabel as kr, setDataPointMarker as ks, setDelay as kt, setDirection as ku, setDuration as kv, setElementPosition as kw, setGridlineStyle as kx, setLayout as ky, setLegend as kz, AiChatPanelComponent as l, slideNumberOf as l0, smartArtNodes as l1, paletteColour as l2, snapToGridStep as l3, splitCursorCell as l4, splitMergedCell as l5, statusKind as l6, statusLabel$1 as l7, storeAudienceContent as l8, stringFromEvent$5 as l9, updateInnerShadowPatch as lA, updateOuterShadowPatch as lB, updateReflectionPatch as lC, vAlignPatch as lD, validatePassword as lE, validatePrintSettings as lF, validateRoomId as lG, valueToY as lH, vermilionDarkColors as lI, vermilionDarkTheme as lJ, vermilionLightColors as lK, vermilionLightTheme as lL, vermilionRadius as lM, waypointsToPathD as lN, worstStatus as lO, zoomTargetSlideIndex as lP, strokeColorOf as la, strokeToInkElement as lb, strokeWidthOf as lc, styleShadowFilter as ld, textAdvancedPatch as le, textAdvancedStateFromStyle as lf, textAdvancedStateOf as lg, textColorOf as lh, textDirectionPatch as li, textStyleOf as lj, textStylePatch as lk, themeStyle as ll, themeToCssVars as lm, thumbnailHeight as ln, thumbnailZoom as lo, toggleCommentResolvedInList as lp, toggleNodeBold as lq, toggleNodeItalic as lr, toggleSheet as ls, topLevelNodeCount as lt, transformSelectedTextCase as lu, translationsEn as lv, ungroupElements as lw, updateElementById as lx, updateGlowPatch as ly, updateGradientStopPatch as lz, AiChatService as m, AiComposerComponent as n, AiFocusBarComponent as o, AiFocusHighlightOverlayComponent as p, AiHistoryMenuComponent as q, AiHistoryService as r, AiMessageListComponent as s, toChatSummary as t, AiPanelStore as u, AiProposalCardComponent as v, AiSettingsSectionComponent as w, AiToolCallCardComponent as x, AnimationAuthorPanelComponent as y, AnimationPanelComponent as z };
127996
- //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-DMmyHdPM.mjs.map
128562
+ //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-Dmq8rQWr.mjs.map