pptx-angular-viewer 1.28.1 → 1.29.0

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.
@@ -5,7 +5,7 @@ import { TranslatePipe, TranslateService, translate } from '@ngx-translate/core'
5
5
  import { guideEmuToPx, getShapeClipPath, getAdjustmentAwareShapeClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, hasShapeProperties, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, isImageLikeElement, hasTextProperties, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$2, THEME_COLOR_SCHEME_KEYS, getLinkedTextBoxSegments, svgPathToPolygons, deobfuscateFont, detectFontFormat, getSubstituteFontFamily, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, formatCommentTimestamp as formatCommentTimestamp$1, PptxHandler, EncryptedFileError, parseSignatureXml, cloneSlide as cloneSlide$1, cloneTemplateElementsBySlideId as cloneTemplateElementsBySlideId$1, cloneElement as cloneElement$1, SvgExporter, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, parseDataUrlToBytes, isZoomElement, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, chartDataChangeType, getOleObjectTypeLabel, addSmartArtNodeAsChild, removeSmartArtNode, promoteSmartArtNode, demoteSmartArtNode, reorderSmartArtNode, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, THEME_PRESETS, applyThemeToData, getAnimationPresetInfo } from 'pptx-viewer-core';
6
6
  export { SWITCHABLE_LAYOUT_TYPES, addSmartArtNode, addSmartArtNodeAsChild, chartDataAddCategory, chartDataAddSeries, chartDataChangeType, chartDataRemoveCategory, chartDataRemoveSeries, chartDataUpdatePoint, demoteSmartArtNode, promoteSmartArtNode, removeSmartArtNode, reorderSmartArtNode, switchSmartArtLayout, updateSmartArtNodeText } from 'pptx-viewer-core';
7
7
  import DOMPurify from 'dompurify';
8
- import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucideChevronRight, LucidePenTool, LucideHighlighter, LucideEraser, LucideMousePointer2, LucideChevronLeft, LucidePlay, LucideSparkles, LucidePanelRight, LucideMoveRight, LucidePencil, LucideType, LucideMinus, LucideSpline, LucideArrowLeft, LucideDownload, LucideFilePlus2, LucideFolderOpen, LucideHome, LucideInfo, LucidePrinter, LucideSave, LucideSettings, LucideShare2, LucideUpload, LucideUserRound, LucideAArrowUp, LucideAArrowDown, LucideRemoveFormatting, LucideList, LucideListOrdered, LucideListIndentDecrease, LucideListIndentIncrease, LucideTextAlignJustify, LucidePlus, LucideImage, LucideVideo, LucideDatabase, LucideLayers, LucidePanelLeft, LucideMessageSquare, LucideEllipsis, LucideEye, LucideEyeOff, LucideSettings2, LucideStickyNote, LucideMonitor, LucideColumns2, LucidePresentation, LucideCheck, LucideUndo, LucideRedo, LucideSearch } from '@lucide/angular';
8
+ import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucideChevronRight, LucidePenTool, LucideHighlighter, LucideEraser, LucideMousePointer2, LucideChevronLeft, LucidePlay, LucideSparkles, LucidePanelRight, LucideMoveRight, LucidePencil, LucideType, LucideMinus, LucideSpline, LucideArrowLeft, LucideDownload, LucideFilePlus2, LucideFolderOpen, LucideHome, LucideInfo, LucidePrinter, LucideSave, LucideSettings, LucideShare2, LucideUpload, LucideUserRound, LucideAArrowUp, LucideAArrowDown, LucideRemoveFormatting, LucideList, LucideListOrdered, LucideListIndentDecrease, LucideListIndentIncrease, LucideTextAlignJustify, LucidePlus, LucideClipboardPaste, LucideFolderPlus, LucideLayoutGrid, LucidePaintbrush, LucideRotateCcw, LucideScissors, LucideImage, LucideVideo, LucideDatabase, LucideLayers, LucidePanelLeft, LucideMessageSquare, LucideEllipsis, LucideEye, LucideEyeOff, LucideSettings2, LucideStickyNote, LucideMonitor, LucideColumns2, LucidePresentation, LucideCheck, LucideUndo, LucideRedo, LucideSearch } from '@lucide/angular';
9
9
  import { jsPDF } from 'jspdf';
10
10
  import { DomSanitizer } from '@angular/platform-browser';
11
11
  import JSZip from 'jszip';
@@ -96,6 +96,16 @@ const COLOR_KEY_TO_CSS = {
96
96
  input: 'input',
97
97
  ring: 'ring',
98
98
  };
99
+ /**
100
+ * Derived component tokens: CSS custom properties consumed by the binding
101
+ * chrome (inspector accents and separators) that are sourced from the base
102
+ * `ViewerThemeColors` rather than being standalone theme inputs. Emitting
103
+ * them here lets `var(--pptx-inspector-*)` lookups resolve in every binding.
104
+ */
105
+ const DERIVED_COLOR_TOKENS = [
106
+ { source: 'primary', cssSuffix: 'inspector-active' },
107
+ { source: 'border', cssSuffix: 'inspector-border' },
108
+ ];
99
109
  /**
100
110
  * Convert a `ViewerTheme` into a flat `Record<string, string>` of CSS
101
111
  * custom properties (including the `--` prefix) ready to be spread onto
@@ -125,6 +135,16 @@ function themeToCssVars(theme, omitDefaults = false) {
125
135
  // @theme :root declaration, which cannot see vars set on a child element.
126
136
  vars[`--color-${cssSuffix}`] = value;
127
137
  }
138
+ for (const { source, cssSuffix } of DERIVED_COLOR_TOKENS) {
139
+ const value = colors[source];
140
+ if (value === undefined) {
141
+ continue;
142
+ }
143
+ if (omitDefaults && value === defaultThemeColors[source]) {
144
+ continue;
145
+ }
146
+ vars[`--pptx-${cssSuffix}`] = value;
147
+ }
128
148
  }
129
149
  // ── Radius ───────────────────────────────────────────────────────
130
150
  if (theme.radius !== undefined) {
@@ -155,6 +175,9 @@ function defaultCssVars() {
155
175
  for (const [key, cssSuffix] of Object.entries(COLOR_KEY_TO_CSS)) {
156
176
  vars[`--pptx-${cssSuffix}`] = defaultThemeColors[key];
157
177
  }
178
+ for (const { source, cssSuffix } of DERIVED_COLOR_TOKENS) {
179
+ vars[`--pptx-${cssSuffix}`] = defaultThemeColors[source];
180
+ }
158
181
  vars['--pptx-radius'] = defaultRadius;
159
182
  return vars;
160
183
  }
@@ -4628,6 +4651,70 @@ function tokenize(latex) {
4628
4651
  }
4629
4652
  return tokens;
4630
4653
  }
4654
+ // ── Sibling merging ──────────────────────────────────────────────────────────
4655
+ /**
4656
+ * True when merging the sibling nodes into one tag-keyed object keeps their
4657
+ * visual order. fast-xml-parser's collapsed shape stores same-tag siblings as
4658
+ * an array under one key and distinct tags under separate keys, so a walker
4659
+ * iterating `Object.keys` re-emits the sequence grouped by tag in
4660
+ * first-appearance order. That equals the original order only while each
4661
+ * tag's occurrences are contiguous (e.g. `r r sSup` survives, `sSup r sSup`
4662
+ * does not: the runs would migrate to the end, turning a^2+b^2 into a2b2+).
4663
+ */
4664
+ function mergesLosslessly(nodes) {
4665
+ const seen = new Set();
4666
+ let previous = '';
4667
+ for (const node of nodes) {
4668
+ for (const key of Object.keys(node)) {
4669
+ if (node[key] === undefined) {
4670
+ continue;
4671
+ }
4672
+ if (key !== previous && seen.has(key)) {
4673
+ return false;
4674
+ }
4675
+ seen.add(key);
4676
+ previous = key;
4677
+ }
4678
+ }
4679
+ return true;
4680
+ }
4681
+ /**
4682
+ * Merge parsed sibling nodes into a single OMML container object.
4683
+ *
4684
+ * When tags interleave (`m:sSup`, `m:r`, `m:sSup`, ... for a^2+b^2=c^2), the
4685
+ * collapsed tag-keyed shape cannot represent the sibling order, so each node
4686
+ * is wrapped in its own `m:box`: the standard OMML invisible grouping element
4687
+ * (ECMA-376 §22.1.2.13). Every sibling then shares the single `m:box` key and
4688
+ * their array preserves the exact order through MathML rendering, the reverse
4689
+ * LaTeX conversion, and OOXML serialization on save. Grouped-by-tag sequences
4690
+ * keep the compact merged shape.
4691
+ */
4692
+ function mergeSiblings(nodes) {
4693
+ if (!mergesLosslessly(nodes)) {
4694
+ return { 'm:box': nodes.map((node) => ({ 'm:e': node })) };
4695
+ }
4696
+ const result = {};
4697
+ for (const node of nodes) {
4698
+ for (const key of Object.keys(node)) {
4699
+ if (node[key] === undefined) {
4700
+ continue;
4701
+ }
4702
+ if (result[key]) {
4703
+ const existing = result[key];
4704
+ if (Array.isArray(existing)) {
4705
+ existing.push(node[key]);
4706
+ }
4707
+ else {
4708
+ result[key] = [existing, node[key]];
4709
+ }
4710
+ }
4711
+ else {
4712
+ result[key] = node[key];
4713
+ }
4714
+ }
4715
+ }
4716
+ return result;
4717
+ }
4631
4718
  /** Try to parse trailing ^ and _ to wrap the base in superscript/subscript. */
4632
4719
  function tryParseScripts(ctx, base) {
4633
4720
  let hasSup = false;
@@ -4818,26 +4905,10 @@ class LatexParser {
4818
4905
  'm:nary': nodes[0]['m:nary'],
4819
4906
  'm:d': nodes[0]['m:d'],
4820
4907
  'm:func': nodes[0]['m:func'],
4908
+ 'm:box': nodes[0]['m:box'],
4821
4909
  };
4822
4910
  }
4823
- const result = {};
4824
- for (const n of nodes) {
4825
- for (const key of Object.keys(n)) {
4826
- if (result[key]) {
4827
- const existing = result[key];
4828
- if (Array.isArray(existing)) {
4829
- existing.push(n[key]);
4830
- }
4831
- else {
4832
- result[key] = [existing, n[key]];
4833
- }
4834
- }
4835
- else {
4836
- result[key] = n[key];
4837
- }
4838
- }
4839
- }
4840
- return result;
4911
+ return mergeSiblings(nodes);
4841
4912
  }
4842
4913
  makeRun(text, normal = false) {
4843
4914
  const run = { 'm:t': text };
@@ -4993,23 +5064,7 @@ function convertLatexToOmml(latex) {
4993
5064
  if (nodes.length === 0) {
4994
5065
  return {};
4995
5066
  }
4996
- const oMath = {};
4997
- for (const node of nodes) {
4998
- for (const key of Object.keys(node)) {
4999
- if (oMath[key]) {
5000
- const existing = oMath[key];
5001
- if (Array.isArray(existing)) {
5002
- existing.push(node[key]);
5003
- }
5004
- else {
5005
- oMath[key] = [existing, node[key]];
5006
- }
5007
- }
5008
- else {
5009
- oMath[key] = node[key];
5010
- }
5011
- }
5012
- }
5067
+ const oMath = mergeSiblings(nodes);
5013
5068
  return {
5014
5069
  'm:oMathPara': {
5015
5070
  'm:oMath': oMath,
@@ -5175,6 +5230,14 @@ function ommlElementToLatex(tag, node) {
5175
5230
  const body = ommlChildrenToLatex(childNode(node, 'm:e'));
5176
5231
  return `${fName}{${body}}`;
5177
5232
  }
5233
+ case 'm:box':
5234
+ case 'm:borderBox': {
5235
+ // Transparent grouping containers: emit the boxed content in place
5236
+ // (mergeSiblings emits per-sibling boxes to preserve ordering).
5237
+ return ensureArr(node['m:e'])
5238
+ .map((e) => ommlChildrenToLatex(e))
5239
+ .join('');
5240
+ }
5178
5241
  case 'm:oMath':
5179
5242
  return ommlChildrenToLatex(node);
5180
5243
  default:
@@ -5203,6 +5266,78 @@ function convertOmmlToLatex(omml) {
5203
5266
  return ommlChildrenToLatex(oMath);
5204
5267
  }
5205
5268
 
5269
+ /**
5270
+ * equation-templates: the shared catalogue of pre-built equation templates
5271
+ * shown in every binding's equation editor dialog (React's
5272
+ * `EquationEditorDialog` is the reference implementation). Each entry pairs a
5273
+ * LaTeX source with an i18n key (plus an English fallback label) so the
5274
+ * gallery tiles render identically across React, Vue, Angular, Svelte, and
5275
+ * Vanilla.
5276
+ */
5277
+ /** Pre-defined equation templates covering common mathematical formulas. */
5278
+ const EQUATION_TEMPLATES = [
5279
+ {
5280
+ label: 'Fraction',
5281
+ latex: '\\frac{a}{b}',
5282
+ i18nKey: 'pptx.equation.template.fraction',
5283
+ },
5284
+ {
5285
+ label: 'Quadratic',
5286
+ latex: 'x=\\frac{-b\\pm\\sqrt{b^{2}-4ac}}{2a}',
5287
+ i18nKey: 'pptx.equation.template.quadratic',
5288
+ },
5289
+ {
5290
+ label: 'Pythagorean',
5291
+ latex: 'a^{2}+b^{2}=c^{2}',
5292
+ i18nKey: 'pptx.equation.template.pythagorean',
5293
+ },
5294
+ {
5295
+ label: 'Sum',
5296
+ latex: '\\sum_{i=1}^{n}{a_{i}}',
5297
+ i18nKey: 'pptx.equation.template.sum',
5298
+ },
5299
+ {
5300
+ label: 'Integral',
5301
+ latex: '\\int_{a}^{b}{f(x)}dx',
5302
+ i18nKey: 'pptx.equation.template.integral',
5303
+ },
5304
+ {
5305
+ label: 'Square Root',
5306
+ latex: '\\sqrt{x^{2}+y^{2}}',
5307
+ i18nKey: 'pptx.equation.template.squareRoot',
5308
+ },
5309
+ {
5310
+ label: 'Limit',
5311
+ latex: '\\lim_{x\\to\\infty}{f(x)}',
5312
+ i18nKey: 'pptx.equation.template.limit',
5313
+ },
5314
+ {
5315
+ label: "Euler's",
5316
+ latex: 'e^{i\\pi}+1=0',
5317
+ i18nKey: 'pptx.equation.template.euler',
5318
+ },
5319
+ {
5320
+ label: 'Matrix 2x2',
5321
+ latex: '\\left[a,b;c,d\\right]',
5322
+ i18nKey: 'pptx.equation.template.matrix',
5323
+ },
5324
+ {
5325
+ label: 'Binomial',
5326
+ latex: '\\left(a+b\\right)^{n}',
5327
+ i18nKey: 'pptx.equation.template.binomial',
5328
+ },
5329
+ {
5330
+ label: 'Derivative',
5331
+ latex: '\\frac{dy}{dx}',
5332
+ i18nKey: 'pptx.equation.template.derivative',
5333
+ },
5334
+ {
5335
+ label: 'Trig Identity',
5336
+ latex: '\\sin^{2}\\theta+\\cos^{2}\\theta=1',
5337
+ i18nKey: 'pptx.equation.template.trigIdentity',
5338
+ },
5339
+ ];
5340
+
5206
5341
  /**
5207
5342
  * Framework-agnostic chart helpers, a focused Vue port of the React package's
5208
5343
  * `viewer/utils/chart-helpers.ts`, `chart-layout.ts`, and
@@ -69786,7 +69921,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
69786
69921
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }] } });
69787
69922
 
69788
69923
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
69789
- const PPTX_ANGULAR_VIEWER_VERSION = "1.28.0";
69924
+ const PPTX_ANGULAR_VIEWER_VERSION = "1.28.1";
69790
69925
 
69791
69926
  /**
69792
69927
  * account-page.component.ts: File > Account content.
@@ -70317,7 +70452,8 @@ class RibbonFontControlsComponent {
70317
70452
  return this.curStyle()?.fontFamily ?? 'Segoe UI';
70318
70453
  }
70319
70454
  curFontSize() {
70320
- return Math.round(this.curStyle()?.fontSize ?? 18);
70455
+ // Mirror React's HomeSection default (24) shown when nothing is selected.
70456
+ return Math.round(this.curStyle()?.fontSize ?? 24);
70321
70457
  }
70322
70458
  /** Current font colour of the selection (for the swatch + active-state ring). */
70323
70459
  curColor() {
@@ -70486,16 +70622,33 @@ class RibbonFontControlsComponent {
70486
70622
  S
70487
70623
  </button>
70488
70624
  </div>
70489
- <!-- Text Shadow toggle -->
70625
+ <!-- Text Shadow toggle (icon-only "S" shadow glyph, React TextSection parity). -->
70490
70626
  <button
70491
70627
  type="button"
70492
70628
  class="pptx-rb-gb"
70493
70629
  [disabled]="!isText()"
70494
70630
  [ngClass]="curStyle()?.textShadowColor ? 'bg-accent' : ''"
70495
70631
  [title]="'pptx.textEffects.shadow' | translate"
70632
+ [attr.aria-label]="'pptx.textEffects.shadow' | translate"
70496
70633
  (click)="toggleShadow()"
70497
70634
  >
70498
- Shadow
70635
+ <svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
70636
+ <text x="6" y="17" font-size="16" font-weight="bold" fill="currentColor" stroke="none">
70637
+ S
70638
+ </text>
70639
+ <text
70640
+ x="7.5"
70641
+ y="18.5"
70642
+ font-size="16"
70643
+ font-weight="bold"
70644
+ fill="none"
70645
+ stroke="currentColor"
70646
+ stroke-width="0.5"
70647
+ opacity="0.4"
70648
+ >
70649
+ S
70650
+ </text>
70651
+ </svg>
70499
70652
  </button>
70500
70653
  <!-- Character Spacing -->
70501
70654
  <select
@@ -70666,16 +70819,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
70666
70819
  S
70667
70820
  </button>
70668
70821
  </div>
70669
- <!-- Text Shadow toggle -->
70822
+ <!-- Text Shadow toggle (icon-only "S" shadow glyph, React TextSection parity). -->
70670
70823
  <button
70671
70824
  type="button"
70672
70825
  class="pptx-rb-gb"
70673
70826
  [disabled]="!isText()"
70674
70827
  [ngClass]="curStyle()?.textShadowColor ? 'bg-accent' : ''"
70675
70828
  [title]="'pptx.textEffects.shadow' | translate"
70829
+ [attr.aria-label]="'pptx.textEffects.shadow' | translate"
70676
70830
  (click)="toggleShadow()"
70677
70831
  >
70678
- Shadow
70832
+ <svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
70833
+ <text x="6" y="17" font-size="16" font-weight="bold" fill="currentColor" stroke="none">
70834
+ S
70835
+ </text>
70836
+ <text
70837
+ x="7.5"
70838
+ y="18.5"
70839
+ font-size="16"
70840
+ font-weight="bold"
70841
+ fill="none"
70842
+ stroke="currentColor"
70843
+ stroke-width="0.5"
70844
+ opacity="0.4"
70845
+ >
70846
+ S
70847
+ </text>
70848
+ </svg>
70679
70849
  </button>
70680
70850
  <!-- Character Spacing -->
70681
70851
  <select
@@ -71195,31 +71365,35 @@ class RibbonHomeSectionComponent {
71195
71365
  <!-- Clipboard -->
71196
71366
  <div class="flex flex-col items-center gap-0.5">
71197
71367
  <div class="pptx-rb-grp">
71368
+ <!-- Icon-only clipboard buttons with title tooltips, matching React's HomeSection. -->
71198
71369
  <button
71199
71370
  type="button"
71200
71371
  class="pptx-rb-gb"
71201
71372
  [title]="'pptx.arrange.paste' | translate"
71373
+ [attr.aria-label]="'pptx.arrange.paste' | translate"
71202
71374
  (click)="paste()"
71203
71375
  >
71204
- {{ 'pptx.arrange.paste' | translate }}
71376
+ <svg lucideClipboardPaste class="h-4 w-4"></svg>
71205
71377
  </button>
71206
71378
  <button
71207
71379
  type="button"
71208
71380
  class="pptx-rb-gb"
71209
71381
  [title]="'pptx.arrange.cut' | translate"
71382
+ [attr.aria-label]="'pptx.arrange.cut' | translate"
71210
71383
  [disabled]="!hasSel()"
71211
71384
  (click)="cut()"
71212
71385
  >
71213
- {{ 'pptx.arrange.cut' | translate }}
71386
+ <svg lucideScissors class="h-4 w-4"></svg>
71214
71387
  </button>
71215
71388
  <button
71216
71389
  type="button"
71217
71390
  class="pptx-rb-gb"
71218
71391
  [title]="'pptx.arrange.copy' | translate"
71392
+ [attr.aria-label]="'pptx.arrange.copy' | translate"
71219
71393
  [disabled]="!hasSel()"
71220
71394
  (click)="copy()"
71221
71395
  >
71222
- {{ 'pptx.arrange.copy' | translate }}
71396
+ <svg lucideCopy class="h-4 w-4"></svg>
71223
71397
  </button>
71224
71398
  <button
71225
71399
  type="button"
@@ -71229,9 +71403,10 @@ class RibbonHomeSectionComponent {
71229
71403
  [ngClass]="formatPainterActive() ? 'bg-primary text-primary-foreground' : ''"
71230
71404
  [disabled]="!canActivateFormatPainter() && !formatPainterActive()"
71231
71405
  [title]="'pptx.arrange.formatPainter' | translate"
71406
+ [attr.aria-label]="'pptx.arrange.formatPainter' | translate"
71232
71407
  (click)="toggleFormatPainter.emit()"
71233
71408
  >
71234
- {{ 'pptx.ribbon.painter' | translate }}
71409
+ <svg lucidePaintbrush class="h-4 w-4"></svg>
71235
71410
  </button>
71236
71411
  </div>
71237
71412
  <span class="text-[9px] leading-none text-muted-foreground">
@@ -71242,44 +71417,39 @@ class RibbonHomeSectionComponent {
71242
71417
  <!-- Slides -->
71243
71418
  <div class="flex flex-col items-center gap-0.5">
71244
71419
  <div class="pptx-rb-grp">
71420
+ <!-- New Slide (React SlidesGroup parity: New Slide / Layout / Reset /
71421
+ Section, no Duplicate button). -->
71245
71422
  <button
71246
71423
  type="button"
71247
- class="pptx-rb-gb gap-1.5"
71248
- [title]="'pptx.ribbon.newSlide' | translate"
71424
+ class="pptx-rb-gb gap-1.5 whitespace-nowrap"
71425
+ [title]="'pptx.home.newSlide' | translate"
71249
71426
  (click)="editor.addSlide(slideIndex())"
71250
71427
  >
71251
- <svg lucidePlus class="h-4 w-4"></svg> {{ 'pptx.ribbon.slide' | translate }}
71252
- </button>
71253
- <button
71254
- type="button"
71255
- class="pptx-rb-gl"
71256
- [title]="'pptx.ribbon.duplicateSlide' | translate"
71257
- (click)="editor.duplicateSlide(slideIndex())"
71258
- >
71259
- {{ 'pptx.arrange.duplicate' | translate }}
71428
+ <svg lucidePlus class="h-4 w-4"></svg> {{ 'pptx.home.newSlide' | translate }}
71260
71429
  </button>
71261
71430
  <button
71262
71431
  type="button"
71263
- class="pptx-rb-gb"
71432
+ class="pptx-rb-gb whitespace-nowrap"
71264
71433
  [title]="'pptx.master.layout' | translate"
71265
71434
  (click)="applyLayout.emit('blank')"
71266
71435
  >
71267
- {{ 'pptx.master.layout' | translate }}
71436
+ <svg lucideLayoutGrid class="h-4 w-4"></svg> {{ 'pptx.master.layout' | translate }}
71268
71437
  </button>
71269
71438
  <button
71270
71439
  type="button"
71271
- class="pptx-rb-gb"
71440
+ class="pptx-rb-gb whitespace-nowrap"
71272
71441
  [title]="'pptx.sections.resetSlideTitle' | translate"
71273
71442
  (click)="resetSlide.emit()"
71274
71443
  >
71275
- {{ 'pptx.sections.resetSlideTitle' | translate }}
71444
+ <svg lucideRotateCcw class="h-4 w-4"></svg> {{ 'pptx.animations.reset' | translate }}
71276
71445
  </button>
71277
71446
  <button
71278
71447
  type="button"
71279
- class="pptx-rb-gb"
71280
- [title]="'pptx.sections.sectionButtonLabel' | translate"
71448
+ class="pptx-rb-gl whitespace-nowrap"
71449
+ [title]="'pptx.sections.addSection' | translate"
71281
71450
  (click)="editor.addSection(slideIndex())"
71282
71451
  >
71452
+ <svg lucideFolderPlus class="h-4 w-4"></svg>
71283
71453
  {{ 'pptx.sections.sectionButtonLabel' | translate }}
71284
71454
  </button>
71285
71455
  </div>
@@ -71324,7 +71494,7 @@ class RibbonHomeSectionComponent {
71324
71494
  {{ 'pptx.shortcuts.group.editing' | translate }}
71325
71495
  </span>
71326
71496
  </div>
71327
- `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: RibbonFontControlsComponent, selector: "pptx-ribbon-font-controls", inputs: ["slideIndex", "selectedElement"] }, { kind: "component", type: RibbonParagraphControlsComponent, selector: "pptx-ribbon-paragraph-controls", inputs: ["slideIndex", "selectedElement"] }, { kind: "component", type: RibbonEditingSectionComponent, selector: "pptx-ribbon-editing-section", outputs: ["toggleFindReplace", "selectAll"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
71497
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: LucideClipboardPaste, selector: "svg[lucideClipboardPaste]" }, { kind: "component", type: LucideCopy, selector: "svg[lucideCopy]" }, { kind: "component", type: LucideFolderPlus, selector: "svg[lucideFolderPlus]" }, { kind: "component", type: LucideLayoutGrid, selector: "svg[lucideLayoutGrid]" }, { kind: "component", type: LucidePaintbrush, selector: "svg[lucidePaintbrush]" }, { kind: "component", type: LucideRotateCcw, selector: "svg[lucideRotateCcw]" }, { kind: "component", type: LucideScissors, selector: "svg[lucideScissors]" }, { kind: "component", type: RibbonFontControlsComponent, selector: "pptx-ribbon-font-controls", inputs: ["slideIndex", "selectedElement"] }, { kind: "component", type: RibbonParagraphControlsComponent, selector: "pptx-ribbon-paragraph-controls", inputs: ["slideIndex", "selectedElement"] }, { kind: "component", type: RibbonEditingSectionComponent, selector: "pptx-ribbon-editing-section", outputs: ["toggleFindReplace", "selectAll"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
71328
71498
  }
71329
71499
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: RibbonHomeSectionComponent, decorators: [{
71330
71500
  type: Component,
@@ -71337,6 +71507,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
71337
71507
  NgClass,
71338
71508
  TranslatePipe,
71339
71509
  LucidePlus,
71510
+ LucideClipboardPaste,
71511
+ LucideCopy,
71512
+ LucideFolderPlus,
71513
+ LucideLayoutGrid,
71514
+ LucidePaintbrush,
71515
+ LucideRotateCcw,
71516
+ LucideScissors,
71340
71517
  RibbonFontControlsComponent,
71341
71518
  RibbonParagraphControlsComponent,
71342
71519
  RibbonEditingSectionComponent,
@@ -71345,31 +71522,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
71345
71522
  <!-- Clipboard -->
71346
71523
  <div class="flex flex-col items-center gap-0.5">
71347
71524
  <div class="pptx-rb-grp">
71525
+ <!-- Icon-only clipboard buttons with title tooltips, matching React's HomeSection. -->
71348
71526
  <button
71349
71527
  type="button"
71350
71528
  class="pptx-rb-gb"
71351
71529
  [title]="'pptx.arrange.paste' | translate"
71530
+ [attr.aria-label]="'pptx.arrange.paste' | translate"
71352
71531
  (click)="paste()"
71353
71532
  >
71354
- {{ 'pptx.arrange.paste' | translate }}
71533
+ <svg lucideClipboardPaste class="h-4 w-4"></svg>
71355
71534
  </button>
71356
71535
  <button
71357
71536
  type="button"
71358
71537
  class="pptx-rb-gb"
71359
71538
  [title]="'pptx.arrange.cut' | translate"
71539
+ [attr.aria-label]="'pptx.arrange.cut' | translate"
71360
71540
  [disabled]="!hasSel()"
71361
71541
  (click)="cut()"
71362
71542
  >
71363
- {{ 'pptx.arrange.cut' | translate }}
71543
+ <svg lucideScissors class="h-4 w-4"></svg>
71364
71544
  </button>
71365
71545
  <button
71366
71546
  type="button"
71367
71547
  class="pptx-rb-gb"
71368
71548
  [title]="'pptx.arrange.copy' | translate"
71549
+ [attr.aria-label]="'pptx.arrange.copy' | translate"
71369
71550
  [disabled]="!hasSel()"
71370
71551
  (click)="copy()"
71371
71552
  >
71372
- {{ 'pptx.arrange.copy' | translate }}
71553
+ <svg lucideCopy class="h-4 w-4"></svg>
71373
71554
  </button>
71374
71555
  <button
71375
71556
  type="button"
@@ -71379,9 +71560,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
71379
71560
  [ngClass]="formatPainterActive() ? 'bg-primary text-primary-foreground' : ''"
71380
71561
  [disabled]="!canActivateFormatPainter() && !formatPainterActive()"
71381
71562
  [title]="'pptx.arrange.formatPainter' | translate"
71563
+ [attr.aria-label]="'pptx.arrange.formatPainter' | translate"
71382
71564
  (click)="toggleFormatPainter.emit()"
71383
71565
  >
71384
- {{ 'pptx.ribbon.painter' | translate }}
71566
+ <svg lucidePaintbrush class="h-4 w-4"></svg>
71385
71567
  </button>
71386
71568
  </div>
71387
71569
  <span class="text-[9px] leading-none text-muted-foreground">
@@ -71392,44 +71574,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
71392
71574
  <!-- Slides -->
71393
71575
  <div class="flex flex-col items-center gap-0.5">
71394
71576
  <div class="pptx-rb-grp">
71577
+ <!-- New Slide (React SlidesGroup parity: New Slide / Layout / Reset /
71578
+ Section, no Duplicate button). -->
71395
71579
  <button
71396
71580
  type="button"
71397
- class="pptx-rb-gb gap-1.5"
71398
- [title]="'pptx.ribbon.newSlide' | translate"
71581
+ class="pptx-rb-gb gap-1.5 whitespace-nowrap"
71582
+ [title]="'pptx.home.newSlide' | translate"
71399
71583
  (click)="editor.addSlide(slideIndex())"
71400
71584
  >
71401
- <svg lucidePlus class="h-4 w-4"></svg> {{ 'pptx.ribbon.slide' | translate }}
71402
- </button>
71403
- <button
71404
- type="button"
71405
- class="pptx-rb-gl"
71406
- [title]="'pptx.ribbon.duplicateSlide' | translate"
71407
- (click)="editor.duplicateSlide(slideIndex())"
71408
- >
71409
- {{ 'pptx.arrange.duplicate' | translate }}
71585
+ <svg lucidePlus class="h-4 w-4"></svg> {{ 'pptx.home.newSlide' | translate }}
71410
71586
  </button>
71411
71587
  <button
71412
71588
  type="button"
71413
- class="pptx-rb-gb"
71589
+ class="pptx-rb-gb whitespace-nowrap"
71414
71590
  [title]="'pptx.master.layout' | translate"
71415
71591
  (click)="applyLayout.emit('blank')"
71416
71592
  >
71417
- {{ 'pptx.master.layout' | translate }}
71593
+ <svg lucideLayoutGrid class="h-4 w-4"></svg> {{ 'pptx.master.layout' | translate }}
71418
71594
  </button>
71419
71595
  <button
71420
71596
  type="button"
71421
- class="pptx-rb-gb"
71597
+ class="pptx-rb-gb whitespace-nowrap"
71422
71598
  [title]="'pptx.sections.resetSlideTitle' | translate"
71423
71599
  (click)="resetSlide.emit()"
71424
71600
  >
71425
- {{ 'pptx.sections.resetSlideTitle' | translate }}
71601
+ <svg lucideRotateCcw class="h-4 w-4"></svg> {{ 'pptx.animations.reset' | translate }}
71426
71602
  </button>
71427
71603
  <button
71428
71604
  type="button"
71429
- class="pptx-rb-gb"
71430
- [title]="'pptx.sections.sectionButtonLabel' | translate"
71605
+ class="pptx-rb-gl whitespace-nowrap"
71606
+ [title]="'pptx.sections.addSection' | translate"
71431
71607
  (click)="editor.addSection(slideIndex())"
71432
71608
  >
71609
+ <svg lucideFolderPlus class="h-4 w-4"></svg>
71433
71610
  {{ 'pptx.sections.sectionButtonLabel' | translate }}
71434
71611
  </button>
71435
71612
  </div>
@@ -72773,8 +72950,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
72773
72950
  * LEFT : slides-pane toggle
72774
72951
  * RIGHT : Comments (with count), Present split-button + dropdown
72775
72952
  * (From Beginning / Presenter View / Broadcast), +Show (custom
72776
- * shows), Inspector toggle, overflow "..." menu (exports / print /
72777
- * properties / accessibility / save).
72953
+ * shows), Inspector toggle, Settings cog, overflow "..." menu
72954
+ * (exports / print / properties / accessibility / save).
72778
72955
  *
72779
72956
  * Undo/Redo/Find and Save moved up to the title bar; Record and Share moved to
72780
72957
  * the ribbon tab row (both mirroring React). Slide navigation and zoom live in
@@ -72820,6 +72997,8 @@ class RibbonPrimaryRowComponent {
72820
72997
  broadcast = output();
72821
72998
  openCustomShows = output();
72822
72999
  toggleInspector = output();
73000
+ /** Emitted when the user clicks the Settings cog (opens the Settings dialog). */
73001
+ openSettings = output();
72823
73002
  exportPng = output();
72824
73003
  exportPdf = output();
72825
73004
  exportGif = output();
@@ -72835,6 +73014,28 @@ class RibbonPrimaryRowComponent {
72835
73014
  toolbar = toolbarVisibility(this.hiddenActions);
72836
73015
  overflowItems = computed(() => visibleOverflowItems(this.hiddenActions()), /* @ts-ignore */
72837
73016
  ...(ngDevMode ? [{ debugName: "overflowItems" }] : /* istanbul ignore next */ []));
73017
+ presentRoot = viewChild('presentRoot', /* @ts-ignore */
73018
+ ...(ngDevMode ? [{ debugName: "presentRoot" }] : /* istanbul ignore next */ []));
73019
+ overflowRoot = viewChild('overflowRoot', /* @ts-ignore */
73020
+ ...(ngDevMode ? [{ debugName: "overflowRoot" }] : /* istanbul ignore next */ []));
73021
+ /** Escape dismisses any open dropdown (Present options / overflow). */
73022
+ onDocumentEscape() {
73023
+ this.presentMenuOpen.set(false);
73024
+ this.overflowOpen.set(false);
73025
+ }
73026
+ /** A pointerdown outside a dropdown's trigger + panel dismisses it. */
73027
+ onDocumentPointerDown(event) {
73028
+ const target = event.target;
73029
+ if (!(target instanceof Node)) {
73030
+ return;
73031
+ }
73032
+ if (this.presentMenuOpen() && !this.presentRoot()?.nativeElement.contains(target)) {
73033
+ this.presentMenuOpen.set(false);
73034
+ }
73035
+ if (this.overflowOpen() && !this.overflowRoot()?.nativeElement.contains(target)) {
73036
+ this.overflowOpen.set(false);
73037
+ }
73038
+ }
72838
73039
  onOverflow(key) {
72839
73040
  this.overflowOpen.set(false);
72840
73041
  switch (key) {
@@ -72867,7 +73068,7 @@ class RibbonPrimaryRowComponent {
72867
73068
  }
72868
73069
  }
72869
73070
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: RibbonPrimaryRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
72870
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: RibbonPrimaryRowComponent, isStandalone: true, selector: "pptx-ribbon-primary-row", inputs: { slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, sidebarCollapsed: { classPropertyName: "sidebarCollapsed", publicName: "sidebarCollapsed", isSignal: true, isRequired: false, transformFunction: null }, inspectorOpen: { classPropertyName: "inspectorOpen", publicName: "inspectorOpen", isSignal: true, isRequired: false, transformFunction: null }, commentsOpen: { classPropertyName: "commentsOpen", publicName: "commentsOpen", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggleSidebar: "toggleSidebar", toggleComments: "toggleComments", present: "present", presenter: "presenter", broadcast: "broadcast", openCustomShows: "openCustomShows", toggleInspector: "toggleInspector", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", print: "print", info: "info", a11y: "a11y", save: "save" }, ngImport: i0, template: `
73071
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: RibbonPrimaryRowComponent, isStandalone: true, selector: "pptx-ribbon-primary-row", inputs: { slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, sidebarCollapsed: { classPropertyName: "sidebarCollapsed", publicName: "sidebarCollapsed", isSignal: true, isRequired: false, transformFunction: null }, inspectorOpen: { classPropertyName: "inspectorOpen", publicName: "inspectorOpen", isSignal: true, isRequired: false, transformFunction: null }, commentsOpen: { classPropertyName: "commentsOpen", publicName: "commentsOpen", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggleSidebar: "toggleSidebar", toggleComments: "toggleComments", present: "present", presenter: "presenter", broadcast: "broadcast", openCustomShows: "openCustomShows", toggleInspector: "toggleInspector", openSettings: "openSettings", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", print: "print", info: "info", a11y: "a11y", save: "save" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()", "document:pointerdown": "onDocumentPointerDown($event)" } }, viewQueries: [{ propertyName: "presentRoot", first: true, predicate: ["presentRoot"], descendants: true, isSignal: true }, { propertyName: "overflowRoot", first: true, predicate: ["overflowRoot"], descendants: true, isSignal: true }], ngImport: i0, template: `
72871
73072
  <div class="flex items-center gap-0.5 px-1.5 py-0.5">
72872
73073
  <!-- Left: slides pane toggle (undo/redo/find moved to the title bar) -->
72873
73074
  <button
@@ -72903,7 +73104,7 @@ class RibbonPrimaryRowComponent {
72903
73104
  </button>
72904
73105
 
72905
73106
  <!-- Present split-button + dropdown -->
72906
- <div class="relative inline-flex items-center">
73107
+ <div class="relative inline-flex items-center" #presentRoot>
72907
73108
  <button
72908
73109
  type="button"
72909
73110
  class="pptx-rb-pill rounded-r-none"
@@ -72978,8 +73179,19 @@ class RibbonPrimaryRowComponent {
72978
73179
  <svg lucidePanelRight class="h-4 w-4"></svg>
72979
73180
  </button>
72980
73181
 
73182
+ <!-- Settings (mirrors React: between the panel toggle and the overflow "...") -->
73183
+ <button
73184
+ type="button"
73185
+ class="pptx-rb-icon text-muted-foreground"
73186
+ [title]="'pptx.toolbar.settingsShortcuts' | translate"
73187
+ [attr.aria-label]="'pptx.toolbar.settings' | translate"
73188
+ (click)="openSettings.emit()"
73189
+ >
73190
+ <svg lucideSettings class="h-3.5 w-3.5"></svg>
73191
+ </button>
73192
+
72981
73193
  <!-- Overflow menu -->
72982
- <div class="relative inline-flex items-center">
73194
+ <div class="relative inline-flex items-center" #overflowRoot>
72983
73195
  <button
72984
73196
  type="button"
72985
73197
  class="pptx-rb-icon text-muted-foreground"
@@ -73012,7 +73224,7 @@ class RibbonPrimaryRowComponent {
73012
73224
  }
73013
73225
  </div>
73014
73226
  </div>
73015
- `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LucidePanelLeft, selector: "svg[lucidePanelLeft], svg[lucideSidebar]" }, { kind: "component", type: LucidePanelRight, selector: "svg[lucidePanelRight]" }, { kind: "component", type: LucideMessageSquare, selector: "svg[lucideMessageSquare]" }, { kind: "component", type: LucidePlay, selector: "svg[lucidePlay]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: LucideEllipsis, selector: "svg[lucideEllipsis], svg[lucideMoreHorizontal]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
73227
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LucidePanelLeft, selector: "svg[lucidePanelLeft], svg[lucideSidebar]" }, { kind: "component", type: LucidePanelRight, selector: "svg[lucidePanelRight]" }, { kind: "component", type: LucideMessageSquare, selector: "svg[lucideMessageSquare]" }, { kind: "component", type: LucidePlay, selector: "svg[lucidePlay]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: LucideEllipsis, selector: "svg[lucideEllipsis], svg[lucideMoreHorizontal]" }, { kind: "component", type: LucideSettings, selector: "svg[lucideSettings]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
73016
73228
  }
73017
73229
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: RibbonPrimaryRowComponent, decorators: [{
73018
73230
  type: Component,
@@ -73030,6 +73242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
73030
73242
  LucideChevronDown,
73031
73243
  LucidePlus,
73032
73244
  LucideEllipsis,
73245
+ LucideSettings,
73033
73246
  ],
73034
73247
  template: `
73035
73248
  <div class="flex items-center gap-0.5 px-1.5 py-0.5">
@@ -73067,7 +73280,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
73067
73280
  </button>
73068
73281
 
73069
73282
  <!-- Present split-button + dropdown -->
73070
- <div class="relative inline-flex items-center">
73283
+ <div class="relative inline-flex items-center" #presentRoot>
73071
73284
  <button
73072
73285
  type="button"
73073
73286
  class="pptx-rb-pill rounded-r-none"
@@ -73142,8 +73355,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
73142
73355
  <svg lucidePanelRight class="h-4 w-4"></svg>
73143
73356
  </button>
73144
73357
 
73358
+ <!-- Settings (mirrors React: between the panel toggle and the overflow "...") -->
73359
+ <button
73360
+ type="button"
73361
+ class="pptx-rb-icon text-muted-foreground"
73362
+ [title]="'pptx.toolbar.settingsShortcuts' | translate"
73363
+ [attr.aria-label]="'pptx.toolbar.settings' | translate"
73364
+ (click)="openSettings.emit()"
73365
+ >
73366
+ <svg lucideSettings class="h-3.5 w-3.5"></svg>
73367
+ </button>
73368
+
73145
73369
  <!-- Overflow menu -->
73146
- <div class="relative inline-flex items-center">
73370
+ <div class="relative inline-flex items-center" #overflowRoot>
73147
73371
  <button
73148
73372
  type="button"
73149
73373
  class="pptx-rb-icon text-muted-foreground"
@@ -73178,7 +73402,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
73178
73402
  </div>
73179
73403
  `,
73180
73404
  }]
73181
- }], propDecorators: { slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], inspectorOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "inspectorOpen", required: false }] }], commentsOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentsOpen", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], toggleSidebar: [{ type: i0.Output, args: ["toggleSidebar"] }], toggleComments: [{ type: i0.Output, args: ["toggleComments"] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], exportPng: [{ type: i0.Output, args: ["exportPng"] }], exportPdf: [{ type: i0.Output, args: ["exportPdf"] }], exportGif: [{ type: i0.Output, args: ["exportGif"] }], exportVideo: [{ type: i0.Output, args: ["exportVideo"] }], print: [{ type: i0.Output, args: ["print"] }], info: [{ type: i0.Output, args: ["info"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], save: [{ type: i0.Output, args: ["save"] }] } });
73405
+ }], propDecorators: { slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], inspectorOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "inspectorOpen", required: false }] }], commentsOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentsOpen", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], toggleSidebar: [{ type: i0.Output, args: ["toggleSidebar"] }], toggleComments: [{ type: i0.Output, args: ["toggleComments"] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], openSettings: [{ type: i0.Output, args: ["openSettings"] }], exportPng: [{ type: i0.Output, args: ["exportPng"] }], exportPdf: [{ type: i0.Output, args: ["exportPdf"] }], exportGif: [{ type: i0.Output, args: ["exportGif"] }], exportVideo: [{ type: i0.Output, args: ["exportVideo"] }], print: [{ type: i0.Output, args: ["print"] }], info: [{ type: i0.Output, args: ["info"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], save: [{ type: i0.Output, args: ["save"] }], presentRoot: [{ type: i0.ViewChild, args: ['presentRoot', { isSignal: true }] }], overflowRoot: [{ type: i0.ViewChild, args: ['overflowRoot', { isSignal: true }] }], onDocumentEscape: [{
73406
+ type: HostListener,
73407
+ args: ['document:keydown.escape']
73408
+ }], onDocumentPointerDown: [{
73409
+ type: HostListener,
73410
+ args: ['document:pointerdown', ['$event']]
73411
+ }] } });
73182
73412
 
73183
73413
  /**
73184
73414
  * ribbon-tab-list.component.ts: the ribbon's tab strip row, split out of
@@ -73612,6 +73842,7 @@ class RibbonComponent {
73612
73842
  (broadcast)="broadcast.emit()"
73613
73843
  (openCustomShows)="openCustomShows.emit()"
73614
73844
  (toggleInspector)="toggleInspector.emit()"
73845
+ (openSettings)="requestSettings()"
73615
73846
  (exportPng)="exportPng.emit()"
73616
73847
  (exportPdf)="exportPdf.emit()"
73617
73848
  (exportGif)="exportGif.emit()"
@@ -73733,7 +73964,7 @@ class RibbonComponent {
73733
73964
  />
73734
73965
  </div>
73735
73966
  </div>
73736
- `, isInline: true, dependencies: [{ kind: "component", type: RibbonPrimaryRowComponent, selector: "pptx-ribbon-primary-row", inputs: ["slideCount", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "hiddenActions"], outputs: ["toggleSidebar", "toggleComments", "present", "presenter", "broadcast", "openCustomShows", "toggleInspector", "exportPng", "exportPdf", "exportGif", "exportVideo", "print", "info", "a11y", "save"] }, { kind: "component", type: RibbonTabListComponent, selector: "pptx-ribbon-tab-list", inputs: ["activeTab", "canEdit", "collabConnected", "connectedCount", "ribbonExpanded", "hiddenActions"], outputs: ["selectTab", "record", "share", "toggleRibbonExpanded"] }, { kind: "component", type: RibbonContentComponent, selector: "pptx-ribbon-content", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "hiddenActions", "accountAuth"], outputs: ["selectTab", "find", "share", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "signatures", "info", "print", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "openSmartArtDialog", "openEquationDialog", "openPassword", "openFontEmbedding", "openVersionHistory", "openSettings"] }, { kind: "component", type: RibbonContentSecondaryComponent, selector: "pptx-ribbon-content-secondary", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "spellCheckEnabled", "showSubtitles", "hiddenActions"], outputs: ["present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "broadcast", "info", "print", "comments", "a11y", "link", "openSorter", "openMasterView", "toggleNotes", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSetUpSlideShow", "openCompare", "openShortcuts", "openSettings"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
73967
+ `, isInline: true, dependencies: [{ kind: "component", type: RibbonPrimaryRowComponent, selector: "pptx-ribbon-primary-row", inputs: ["slideCount", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "hiddenActions"], outputs: ["toggleSidebar", "toggleComments", "present", "presenter", "broadcast", "openCustomShows", "toggleInspector", "openSettings", "exportPng", "exportPdf", "exportGif", "exportVideo", "print", "info", "a11y", "save"] }, { kind: "component", type: RibbonTabListComponent, selector: "pptx-ribbon-tab-list", inputs: ["activeTab", "canEdit", "collabConnected", "connectedCount", "ribbonExpanded", "hiddenActions"], outputs: ["selectTab", "record", "share", "toggleRibbonExpanded"] }, { kind: "component", type: RibbonContentComponent, selector: "pptx-ribbon-content", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "hiddenActions", "accountAuth"], outputs: ["selectTab", "find", "share", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "signatures", "info", "print", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "openSmartArtDialog", "openEquationDialog", "openPassword", "openFontEmbedding", "openVersionHistory", "openSettings"] }, { kind: "component", type: RibbonContentSecondaryComponent, selector: "pptx-ribbon-content-secondary", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "spellCheckEnabled", "showSubtitles", "hiddenActions"], outputs: ["present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "broadcast", "info", "print", "comments", "a11y", "link", "openSorter", "openMasterView", "toggleNotes", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSetUpSlideShow", "openCompare", "openShortcuts", "openSettings"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
73737
73968
  }
73738
73969
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: RibbonComponent, decorators: [{
73739
73970
  type: Component,
@@ -73768,6 +73999,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
73768
73999
  (broadcast)="broadcast.emit()"
73769
74000
  (openCustomShows)="openCustomShows.emit()"
73770
74001
  (toggleInspector)="toggleInspector.emit()"
74002
+ (openSettings)="requestSettings()"
73771
74003
  (exportPng)="exportPng.emit()"
73772
74004
  (exportPdf)="exportPdf.emit()"
73773
74005
  (exportGif)="exportGif.emit()"
@@ -86445,7 +86677,8 @@ class SlideSizeCardComponent {
86445
86677
  <h3 class="icard__heading">{{ 'pptx.slideSize.title' | translate }}</h3>
86446
86678
  <div class="icard__grid2">
86447
86679
  <label class="icard__row">
86448
- <span class="icard__label">{{ 'pptx.slideSize.width' | translate }}</span>
86680
+ <!-- Compact "W"/"H" labels, matching React's SlideSizeCard. -->
86681
+ <span class="icard__label">W</span>
86449
86682
  <input
86450
86683
  type="number"
86451
86684
  class="icard__input icard__input--number"
@@ -86456,7 +86689,7 @@ class SlideSizeCardComponent {
86456
86689
  />
86457
86690
  </label>
86458
86691
  <label class="icard__row">
86459
- <span class="icard__label">{{ 'pptx.slideSize.height' | translate }}</span>
86692
+ <span class="icard__label">H</span>
86460
86693
  <input
86461
86694
  type="number"
86462
86695
  class="icard__input icard__input--number"
@@ -86477,7 +86710,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
86477
86710
  <h3 class="icard__heading">{{ 'pptx.slideSize.title' | translate }}</h3>
86478
86711
  <div class="icard__grid2">
86479
86712
  <label class="icard__row">
86480
- <span class="icard__label">{{ 'pptx.slideSize.width' | translate }}</span>
86713
+ <!-- Compact "W"/"H" labels, matching React's SlideSizeCard. -->
86714
+ <span class="icard__label">W</span>
86481
86715
  <input
86482
86716
  type="number"
86483
86717
  class="icard__input icard__input--number"
@@ -86488,7 +86722,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
86488
86722
  />
86489
86723
  </label>
86490
86724
  <label class="icard__row">
86491
- <span class="icard__label">{{ 'pptx.slideSize.height' | translate }}</span>
86725
+ <span class="icard__label">H</span>
86492
86726
  <input
86493
86727
  type="number"
86494
86728
  class="icard__input icard__input--number"
@@ -86568,7 +86802,7 @@ class SlideThemeOverridePanelComponent {
86568
86802
  <div class="override">
86569
86803
  <label class="toggle">
86570
86804
  <input type="checkbox" [checked]="active()" (change)="toggle($event)" />
86571
- <span>Use slide color override</span>
86805
+ <span>{{ 'pptx.themeOverride.enableOverride' | translate }}</span>
86572
86806
  </label>
86573
86807
  @if (active()) {
86574
86808
  @for (alias of aliases; track alias) {
@@ -86584,15 +86818,15 @@ class SlideThemeOverridePanelComponent {
86584
86818
  }
86585
86819
  }
86586
86820
  </div>
86587
- `, isInline: true, styles: [".override{display:grid;gap:6px;margin-top:8px;padding-top:8px;border-top:1px solid var(--pptx-inspector-border, #444);font-size:11px}.toggle{display:flex;align-items:center;gap:7px}.mapping{display:grid;grid-template-columns:90px 16px 1fr;align-items:center;gap:6px}.mapping span{overflow:hidden;text-overflow:ellipsis;color:var(--pptx-inspector-muted, #aaa)}i{width:14px;height:14px;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px}select{box-sizing:border-box;min-width:0;width:100%;padding:3px 5px;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:var(--pptx-inspector-input-bg, #2d2d2d);color:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
86821
+ `, isInline: true, styles: [".override{display:grid;gap:6px;margin-top:8px;padding-top:8px;border-top:1px solid var(--pptx-inspector-border, #444);font-size:11px}.toggle{display:flex;align-items:center;gap:7px}.mapping{display:grid;grid-template-columns:90px 16px 1fr;align-items:center;gap:6px}.mapping span{overflow:hidden;text-overflow:ellipsis;color:var(--pptx-inspector-muted, #aaa)}i{width:14px;height:14px;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px}select{box-sizing:border-box;min-width:0;width:100%;padding:3px 5px;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:var(--pptx-inspector-input-bg, #2d2d2d);color:inherit}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
86588
86822
  }
86589
86823
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SlideThemeOverridePanelComponent, decorators: [{
86590
86824
  type: Component,
86591
- args: [{ selector: 'pptx-slide-theme-override-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
86825
+ args: [{ selector: 'pptx-slide-theme-override-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: `
86592
86826
  <div class="override">
86593
86827
  <label class="toggle">
86594
86828
  <input type="checkbox" [checked]="active()" (change)="toggle($event)" />
86595
- <span>Use slide color override</span>
86829
+ <span>{{ 'pptx.themeOverride.enableOverride' | translate }}</span>
86596
86830
  </label>
86597
86831
  @if (active()) {
86598
86832
  @for (alias of aliases; track alias) {
@@ -87972,9 +88206,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
87972
88206
  args: ['document:keydown', ['$event']]
87973
88207
  }] } });
87974
88208
 
87975
- /** Pixel width of each thumbnail clipping box inside the panel. */
87976
- const THUMB_W$1 = 150;
87977
- const THUMB_CARD_CHROME_HEIGHT = 31;
88209
+ /** Pixel width of each thumbnail clipping box inside the panel. Slightly
88210
+ * narrower than the panel so the slide-number column fits to its left
88211
+ * (React SlideItem lays the number beside, not below, the preview). */
88212
+ const THUMB_W$1 = 132;
88213
+ const THUMB_CARD_CHROME_HEIGHT = 12;
87978
88214
  /**
87979
88215
  * SlidesPanelComponent: vertical slide-strip for the editor sidebar.
87980
88216
  *
@@ -88110,7 +88346,7 @@ class SlidesPanelComponent {
88110
88346
  return this.editor.sections().findIndex((section) => section.id === sectionId);
88111
88347
  }
88112
88348
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SlidesPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
88113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: SlidesPanelComponent, isStandalone: true, selector: "pptx-slides-panel", inputs: { canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"pptx-ng-spanel\">\n\t<!-- Scrollable slide list -->\n\t<div\n\t\t#scrollViewport\n\t\tclass=\"pptx-ng-spanel-scroll\"\n\t\trole=\"listbox\"\n\t\t[attr.aria-label]=\"'pptx.sections.slides' | translate\"\n\t\t(scroll)=\"onScroll()\"\n\t>\n\t\t<div\n\t\t\tclass=\"pptx-ng-spanel-space\"\n\t\t\t[attr.data-virtualized]=\"shouldVirtualize() ? 'true' : null\"\n\t\t\t[style.height.px]=\"shouldVirtualize() ? virtualRange().totalHeight : null\"\n\t\t>\n\t\t\t<div\n\t\t\t\tclass=\"pptx-ng-spanel-window\"\n\t\t\t\t[class.is-virtualized]=\"shouldVirtualize()\"\n\t\t\t\t[style.top.px]=\"shouldVirtualize() ? virtualRange().offsetY : null\"\n\t\t\t>\n\t\t\t\t@for (item of renderedSlides(); track item.slide.id) {\n\t\t\t\t\t@let slide = item.slide;\n\t\t\t\t\t@let i = item.index;\n\t\t\t\t\t@if (item.sectionStart) {\n\t\t\t\t\t\t<header class=\"pptx-ng-section-header\" [attr.data-section-id]=\"item.section?.id\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-section-toggle\"\n\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!item.section?.collapsed\"\n\t\t\t\t\t\t\t\t(click)=\"item.section && editor.sectionOps.toggle(item.section.id)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span>{{ item.section?.collapsed ? '\u25B8' : '\u25BE' }}</span>\n\t\t\t\t\t\t\t\t<strong>{{\n\t\t\t\t\t\t\t\t\titem.section?.name ?? ('pptx.slides.ungroupedSlides' | translate)\n\t\t\t\t\t\t\t\t}}</strong>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t@if (item.section) {\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-section-actions\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"onRenameSection(item.section.id, item.section.name)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u270E\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === 0\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'up')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2191\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === editor.sections().length - 1\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'down')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2193\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.delete(item.section.id)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u00D7\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</header>\n\t\t\t\t\t}\n\t\t\t\t\t@if (!item.section?.collapsed) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-card\"\n\t\t\t\t\t\t\t[class.is-active]=\"i === activeIndex()\"\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t[attr.aria-selected]=\"i === activeIndex()\"\n\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.notes.slideN' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<!-- Thumbnail (clickable to select) -->\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-thumb-btn\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slidesPanel.goToSlide' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t\t(click)=\"select.emit(i)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<!-- Clipping wrapper: neutralises the 1rem auto margin from SlideCanvas -->\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-spanel-clip\" [ngStyle]=\"clipStyle()\">\n\t\t\t\t\t\t\t\t\t<pptx-slide-canvas\n\t\t\t\t\t\t\t\t\t\t[slide]=\"slide\"\n\t\t\t\t\t\t\t\t\t\t[templateElements]=\"editor.templateElementsBySlideId()[slide.id] ?? []\"\n\t\t\t\t\t\t\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t\t\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t\t\t\t\t\t[zoom]=\"thumbZoom()\"\n\t\t\t\t\t\t\t\t\t\t[editable]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[autoFit]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[interactive]=\"false\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t<!-- Slide number badge -->\n\t\t\t\t\t\t\t<span class=\"pptx-ng-spanel-num\" aria-hidden=\"true\">{{ i + 1 }}</span>\n\n\t\t\t\t\t\t\t<!-- Per-card action toolbar (visible on hover / focus-within) -->\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-actions\"\n\t\t\t\t\t\t\t\trole=\"toolbar\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slideMenu.slideActions' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.ribbon.duplicateSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.duplicate' | translate\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDuplicate(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideCopy class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.slidesPanel.deleteSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.delete' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"editor.slides().length <= 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDelete(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideTrash2 class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === 0\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveUp(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowUp class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === editor.slides().length - 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveDown(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowDown class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer: add new slide -->\n\t<footer class=\"pptx-ng-spanel-footer\">\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-spanel-add\"\n\t\t\t[attr.aria-label]=\"'pptx.sections.addSlide' | translate\"\n\t\t\t(click)=\"onAddSlide()\"\n\t\t>\n\t\t\t<svg lucidePlus class=\"h-3.5 w-3.5\"></svg> {{ 'pptx.sections.addSlide' | translate }}\n\t\t</button>\n\t</footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;overflow:hidden}.pptx-ng-spanel{display:flex;flex-direction:column;height:100%;background:#1e1e1e;color:#e5e5e5;border-right:1px solid rgba(255,255,255,.08);overflow:hidden}.pptx-ng-spanel-scroll{flex:1;overflow-y:auto;padding:.5rem .375rem}.pptx-ng-spanel-space{position:relative}.pptx-ng-spanel-window{display:flex;flex-direction:column;gap:.375rem}.pptx-ng-spanel-window.is-virtualized{position:absolute;inset-inline:0}.pptx-ng-section-header{display:flex;align-items:center;gap:.2rem;min-height:1.75rem;color:#ffffff94}.pptx-ng-section-toggle{display:flex;align-items:center;gap:.35rem;min-width:0;flex:1;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left}.pptx-ng-section-toggle strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem}.pptx-ng-section-actions{display:flex}.pptx-ng-section-actions button{width:1.25rem;height:1.25rem;padding:0;border:0;border-radius:.2rem;background:transparent;color:inherit;cursor:pointer}.pptx-ng-section-actions button:hover:not(:disabled){background:#3b82f659;color:#fff}.pptx-ng-section-actions button:disabled{opacity:.3}.pptx-ng-spanel-card{position:relative;border-radius:.375rem;border:2px solid transparent;background:transparent;transition:border-color .15s,background .15s}.pptx-ng-spanel-card:hover,.pptx-ng-spanel-card:focus-within{background:#ffffff0d;border-color:#ffffff26}.pptx-ng-spanel-card.is-active{border-color:#3b82f6;background:#3b82f61a}.pptx-ng-spanel-thumb-btn{display:block;width:100%;padding:.375rem .375rem 0;border:none;background:transparent;cursor:pointer;color:inherit;line-height:0}.pptx-ng-spanel-thumb-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:.25rem}.pptx-ng-spanel-clip{overflow:hidden;border-radius:2px}.pptx-ng-spanel-clip ::ng-deep .pptx-ng-canvas-wrapper{margin:0!important}.pptx-ng-spanel-num{display:block;text-align:center;font-size:.625rem;line-height:1.6;color:#ffffff73;-webkit-user-select:none;user-select:none;padding-bottom:.25rem}.pptx-ng-spanel-actions{position:absolute;top:.25rem;right:.25rem;display:flex;flex-direction:column;gap:.125rem;opacity:0;pointer-events:none;transition:opacity .12s}.pptx-ng-spanel-card:hover .pptx-ng-spanel-actions,.pptx-ng-spanel-card:focus-within .pptx-ng-spanel-actions{opacity:1;pointer-events:auto}.pptx-ng-spanel-action{display:flex;align-items:center;justify-content:center;width:1.375rem;height:1.375rem;padding:0;border:none;border-radius:.25rem;background:#1e1e1ed9;color:#e5e5e5;font-size:.6875rem;cursor:pointer;transition:background .12s;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.pptx-ng-spanel-action:hover:not([disabled]){background:#3b82f6bf}.pptx-ng-spanel-action[disabled]{opacity:.3;cursor:not-allowed}.pptx-ng-spanel-footer{flex-shrink:0;padding:.5rem .375rem;border-top:1px solid rgba(255,255,255,.08)}.pptx-ng-spanel-add{display:block;width:100%;padding:.4375rem 0;border:1px dashed rgba(255,255,255,.2);border-radius:.375rem;background:transparent;color:#fff9;font-size:.75rem;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.pptx-ng-spanel-add:hover{background:#3b82f626;border-color:#3b82f6;color:#e5e5e5}\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", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: LucideCopy, selector: "svg[lucideCopy]" }, { kind: "component", type: LucideTrash2, selector: "svg[lucideTrash2]" }, { kind: "component", type: LucideArrowUp, selector: "svg[lucideArrowUp]" }, { kind: "component", type: LucideArrowDown, selector: "svg[lucideArrowDown]" }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
88349
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: SlidesPanelComponent, isStandalone: true, selector: "pptx-slides-panel", inputs: { canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"pptx-ng-spanel\">\n\t<!-- Scrollable slide list -->\n\t<div\n\t\t#scrollViewport\n\t\tclass=\"pptx-ng-spanel-scroll\"\n\t\trole=\"listbox\"\n\t\t[attr.aria-label]=\"'pptx.sections.slides' | translate\"\n\t\t(scroll)=\"onScroll()\"\n\t>\n\t\t<div\n\t\t\tclass=\"pptx-ng-spanel-space\"\n\t\t\t[attr.data-virtualized]=\"shouldVirtualize() ? 'true' : null\"\n\t\t\t[style.height.px]=\"shouldVirtualize() ? virtualRange().totalHeight : null\"\n\t\t>\n\t\t\t<div\n\t\t\t\tclass=\"pptx-ng-spanel-window\"\n\t\t\t\t[class.is-virtualized]=\"shouldVirtualize()\"\n\t\t\t\t[style.top.px]=\"shouldVirtualize() ? virtualRange().offsetY : null\"\n\t\t\t>\n\t\t\t\t@for (item of renderedSlides(); track item.slide.id) {\n\t\t\t\t\t@let slide = item.slide;\n\t\t\t\t\t@let i = item.index;\n\t\t\t\t\t@if (item.sectionStart) {\n\t\t\t\t\t\t<header class=\"pptx-ng-section-header\" [attr.data-section-id]=\"item.section?.id\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-section-toggle\"\n\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!item.section?.collapsed\"\n\t\t\t\t\t\t\t\t(click)=\"item.section && editor.sectionOps.toggle(item.section.id)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span>{{ item.section?.collapsed ? '\u25B8' : '\u25BE' }}</span>\n\t\t\t\t\t\t\t\t<strong>{{\n\t\t\t\t\t\t\t\t\titem.section?.name ?? ('pptx.slides.ungroupedSlides' | translate)\n\t\t\t\t\t\t\t\t}}</strong>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t@if (item.section) {\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-section-actions\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"onRenameSection(item.section.id, item.section.name)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u270E\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === 0\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'up')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2191\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === editor.sections().length - 1\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'down')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2193\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.delete(item.section.id)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u00D7\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</header>\n\t\t\t\t\t}\n\t\t\t\t\t@if (!item.section?.collapsed) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-card\"\n\t\t\t\t\t\t\t[class.is-active]=\"i === activeIndex()\"\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t[attr.aria-selected]=\"i === activeIndex()\"\n\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.notes.slideN' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<!-- Thumbnail (clickable to select). Slide number sits to the LEFT\n\t\t\t\t\t\t\t of the preview (React SlideItem parity), not below it. -->\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-thumb-btn\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slidesPanel.goToSlide' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t\t(click)=\"select.emit(i)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<!-- Slide number badge (left column) -->\n\t\t\t\t\t\t\t\t<span class=\"pptx-ng-spanel-num\" aria-hidden=\"true\">{{ i + 1 }}</span>\n\n\t\t\t\t\t\t\t\t<!-- Clipping wrapper: neutralises the 1rem auto margin from SlideCanvas -->\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-spanel-clip\" [ngStyle]=\"clipStyle()\">\n\t\t\t\t\t\t\t\t\t<pptx-slide-canvas\n\t\t\t\t\t\t\t\t\t\t[slide]=\"slide\"\n\t\t\t\t\t\t\t\t\t\t[templateElements]=\"editor.templateElementsBySlideId()[slide.id] ?? []\"\n\t\t\t\t\t\t\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t\t\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t\t\t\t\t\t[zoom]=\"thumbZoom()\"\n\t\t\t\t\t\t\t\t\t\t[editable]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[autoFit]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[interactive]=\"false\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t<!-- Per-card action toolbar (visible on hover / focus-within) -->\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-actions\"\n\t\t\t\t\t\t\t\trole=\"toolbar\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slideMenu.slideActions' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.ribbon.duplicateSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.duplicate' | translate\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDuplicate(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideCopy class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.slidesPanel.deleteSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.delete' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"editor.slides().length <= 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDelete(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideTrash2 class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === 0\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveUp(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowUp class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === editor.slides().length - 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveDown(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowDown class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer: add new slide -->\n\t<footer class=\"pptx-ng-spanel-footer\">\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-spanel-add\"\n\t\t\t[attr.aria-label]=\"'pptx.sections.addSlide' | translate\"\n\t\t\t(click)=\"onAddSlide()\"\n\t\t>\n\t\t\t<svg lucidePlus class=\"h-3.5 w-3.5\"></svg> {{ 'pptx.sections.addSlide' | translate }}\n\t\t</button>\n\t</footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;overflow:hidden}.pptx-ng-spanel{display:flex;flex-direction:column;height:100%;background:var(--pptx-secondary, #1e1e1e);color:var(--pptx-foreground, #e5e5e5);border-right:1px solid var(--pptx-border, rgba(255, 255, 255, .08));overflow:hidden}.pptx-ng-spanel-scroll{flex:1;overflow-y:auto;padding:.5rem .375rem}.pptx-ng-spanel-space{position:relative}.pptx-ng-spanel-window{display:flex;flex-direction:column;gap:.375rem}.pptx-ng-spanel-window.is-virtualized{position:absolute;inset-inline:0}.pptx-ng-section-header{display:flex;align-items:center;gap:.2rem;min-height:1.75rem;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .58))}.pptx-ng-section-toggle{display:flex;align-items:center;gap:.35rem;min-width:0;flex:1;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left}.pptx-ng-section-toggle strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem}.pptx-ng-section-actions{display:flex}.pptx-ng-section-actions button{width:1.25rem;height:1.25rem;padding:0;border:0;border-radius:.2rem;background:transparent;color:inherit;cursor:pointer}.pptx-ng-section-actions button:hover:not(:disabled){background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 35%,transparent);color:var(--pptx-foreground, #fff)}.pptx-ng-section-actions button:disabled{opacity:.3}.pptx-ng-spanel-card{position:relative;border-radius:.375rem;border:2px solid transparent;background:transparent;transition:border-color .15s,background .15s}.pptx-ng-spanel-card:hover,.pptx-ng-spanel-card:focus-within{background:color-mix(in srgb,var(--pptx-foreground, #fff) 5%,transparent);border-color:color-mix(in srgb,var(--pptx-foreground, #fff) 15%,transparent)}.pptx-ng-spanel-card.is-active{border-color:var(--pptx-primary, #3b82f6);background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 10%,transparent)}.pptx-ng-spanel-thumb-btn{display:flex;align-items:center;gap:.25rem;width:100%;padding:.375rem;border:none;background:transparent;cursor:pointer;color:inherit;line-height:0}.pptx-ng-spanel-thumb-btn:focus-visible{outline:2px solid var(--pptx-ring, #3b82f6);outline-offset:2px;border-radius:.25rem}.pptx-ng-spanel-clip{overflow:hidden;border-radius:2px}.pptx-ng-spanel-clip ::ng-deep .pptx-ng-canvas-wrapper{margin:0!important}.pptx-ng-spanel-num{flex:0 0 auto;width:1.1rem;text-align:right;font-size:.625rem;line-height:1;font-variant-numeric:tabular-nums;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .45));-webkit-user-select:none;user-select:none}.pptx-ng-spanel-card.is-active .pptx-ng-spanel-num{color:var(--pptx-primary, #3b82f6);font-weight:500}.pptx-ng-spanel-actions{position:absolute;top:.25rem;right:.25rem;display:flex;flex-direction:column;gap:.125rem;opacity:0;pointer-events:none;transition:opacity .12s}.pptx-ng-spanel-card:hover .pptx-ng-spanel-actions,.pptx-ng-spanel-card:focus-within .pptx-ng-spanel-actions{opacity:1;pointer-events:auto}.pptx-ng-spanel-action{display:flex;align-items:center;justify-content:center;width:1.375rem;height:1.375rem;padding:0;border:none;border-radius:.25rem;background:color-mix(in srgb,var(--pptx-popover, #1e1e1e) 85%,transparent);color:var(--pptx-popover-foreground, #e5e5e5);font-size:.6875rem;cursor:pointer;transition:background .12s;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.pptx-ng-spanel-action:hover:not([disabled]){background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 75%,transparent);color:var(--pptx-primary-foreground, #fff)}.pptx-ng-spanel-action[disabled]{opacity:.3;cursor:not-allowed}.pptx-ng-spanel-footer{flex-shrink:0;padding:.5rem .375rem;border-top:1px solid var(--pptx-border, rgba(255, 255, 255, .08))}.pptx-ng-spanel-add{display:flex;align-items:center;justify-content:center;gap:.25rem;width:100%;padding:.25rem .5rem;border:none;border-radius:.25rem;background:transparent;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .6));font-size:.6875rem;cursor:pointer;transition:background .15s,color .15s}.pptx-ng-spanel-add:hover{background:color-mix(in srgb,var(--pptx-foreground, #fff) 8%,transparent);color:var(--pptx-foreground, #e5e5e5)}\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", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: LucideCopy, selector: "svg[lucideCopy]" }, { kind: "component", type: LucideTrash2, selector: "svg[lucideTrash2]" }, { kind: "component", type: LucideArrowUp, selector: "svg[lucideArrowUp]" }, { kind: "component", type: LucideArrowDown, selector: "svg[lucideArrowDown]" }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
88114
88350
  }
88115
88351
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: SlidesPanelComponent, decorators: [{
88116
88352
  type: Component,
@@ -88123,7 +88359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
88123
88359
  LucideArrowUp,
88124
88360
  LucideArrowDown,
88125
88361
  LucidePlus,
88126
- ], template: "<div class=\"pptx-ng-spanel\">\n\t<!-- Scrollable slide list -->\n\t<div\n\t\t#scrollViewport\n\t\tclass=\"pptx-ng-spanel-scroll\"\n\t\trole=\"listbox\"\n\t\t[attr.aria-label]=\"'pptx.sections.slides' | translate\"\n\t\t(scroll)=\"onScroll()\"\n\t>\n\t\t<div\n\t\t\tclass=\"pptx-ng-spanel-space\"\n\t\t\t[attr.data-virtualized]=\"shouldVirtualize() ? 'true' : null\"\n\t\t\t[style.height.px]=\"shouldVirtualize() ? virtualRange().totalHeight : null\"\n\t\t>\n\t\t\t<div\n\t\t\t\tclass=\"pptx-ng-spanel-window\"\n\t\t\t\t[class.is-virtualized]=\"shouldVirtualize()\"\n\t\t\t\t[style.top.px]=\"shouldVirtualize() ? virtualRange().offsetY : null\"\n\t\t\t>\n\t\t\t\t@for (item of renderedSlides(); track item.slide.id) {\n\t\t\t\t\t@let slide = item.slide;\n\t\t\t\t\t@let i = item.index;\n\t\t\t\t\t@if (item.sectionStart) {\n\t\t\t\t\t\t<header class=\"pptx-ng-section-header\" [attr.data-section-id]=\"item.section?.id\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-section-toggle\"\n\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!item.section?.collapsed\"\n\t\t\t\t\t\t\t\t(click)=\"item.section && editor.sectionOps.toggle(item.section.id)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span>{{ item.section?.collapsed ? '\u25B8' : '\u25BE' }}</span>\n\t\t\t\t\t\t\t\t<strong>{{\n\t\t\t\t\t\t\t\t\titem.section?.name ?? ('pptx.slides.ungroupedSlides' | translate)\n\t\t\t\t\t\t\t\t}}</strong>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t@if (item.section) {\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-section-actions\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"onRenameSection(item.section.id, item.section.name)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u270E\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === 0\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'up')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2191\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === editor.sections().length - 1\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'down')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2193\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.delete(item.section.id)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u00D7\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</header>\n\t\t\t\t\t}\n\t\t\t\t\t@if (!item.section?.collapsed) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-card\"\n\t\t\t\t\t\t\t[class.is-active]=\"i === activeIndex()\"\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t[attr.aria-selected]=\"i === activeIndex()\"\n\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.notes.slideN' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<!-- Thumbnail (clickable to select) -->\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-thumb-btn\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slidesPanel.goToSlide' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t\t(click)=\"select.emit(i)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<!-- Clipping wrapper: neutralises the 1rem auto margin from SlideCanvas -->\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-spanel-clip\" [ngStyle]=\"clipStyle()\">\n\t\t\t\t\t\t\t\t\t<pptx-slide-canvas\n\t\t\t\t\t\t\t\t\t\t[slide]=\"slide\"\n\t\t\t\t\t\t\t\t\t\t[templateElements]=\"editor.templateElementsBySlideId()[slide.id] ?? []\"\n\t\t\t\t\t\t\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t\t\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t\t\t\t\t\t[zoom]=\"thumbZoom()\"\n\t\t\t\t\t\t\t\t\t\t[editable]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[autoFit]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[interactive]=\"false\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t<!-- Slide number badge -->\n\t\t\t\t\t\t\t<span class=\"pptx-ng-spanel-num\" aria-hidden=\"true\">{{ i + 1 }}</span>\n\n\t\t\t\t\t\t\t<!-- Per-card action toolbar (visible on hover / focus-within) -->\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-actions\"\n\t\t\t\t\t\t\t\trole=\"toolbar\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slideMenu.slideActions' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.ribbon.duplicateSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.duplicate' | translate\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDuplicate(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideCopy class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.slidesPanel.deleteSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.delete' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"editor.slides().length <= 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDelete(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideTrash2 class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === 0\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveUp(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowUp class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === editor.slides().length - 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveDown(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowDown class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer: add new slide -->\n\t<footer class=\"pptx-ng-spanel-footer\">\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-spanel-add\"\n\t\t\t[attr.aria-label]=\"'pptx.sections.addSlide' | translate\"\n\t\t\t(click)=\"onAddSlide()\"\n\t\t>\n\t\t\t<svg lucidePlus class=\"h-3.5 w-3.5\"></svg> {{ 'pptx.sections.addSlide' | translate }}\n\t\t</button>\n\t</footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;overflow:hidden}.pptx-ng-spanel{display:flex;flex-direction:column;height:100%;background:#1e1e1e;color:#e5e5e5;border-right:1px solid rgba(255,255,255,.08);overflow:hidden}.pptx-ng-spanel-scroll{flex:1;overflow-y:auto;padding:.5rem .375rem}.pptx-ng-spanel-space{position:relative}.pptx-ng-spanel-window{display:flex;flex-direction:column;gap:.375rem}.pptx-ng-spanel-window.is-virtualized{position:absolute;inset-inline:0}.pptx-ng-section-header{display:flex;align-items:center;gap:.2rem;min-height:1.75rem;color:#ffffff94}.pptx-ng-section-toggle{display:flex;align-items:center;gap:.35rem;min-width:0;flex:1;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left}.pptx-ng-section-toggle strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem}.pptx-ng-section-actions{display:flex}.pptx-ng-section-actions button{width:1.25rem;height:1.25rem;padding:0;border:0;border-radius:.2rem;background:transparent;color:inherit;cursor:pointer}.pptx-ng-section-actions button:hover:not(:disabled){background:#3b82f659;color:#fff}.pptx-ng-section-actions button:disabled{opacity:.3}.pptx-ng-spanel-card{position:relative;border-radius:.375rem;border:2px solid transparent;background:transparent;transition:border-color .15s,background .15s}.pptx-ng-spanel-card:hover,.pptx-ng-spanel-card:focus-within{background:#ffffff0d;border-color:#ffffff26}.pptx-ng-spanel-card.is-active{border-color:#3b82f6;background:#3b82f61a}.pptx-ng-spanel-thumb-btn{display:block;width:100%;padding:.375rem .375rem 0;border:none;background:transparent;cursor:pointer;color:inherit;line-height:0}.pptx-ng-spanel-thumb-btn:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;border-radius:.25rem}.pptx-ng-spanel-clip{overflow:hidden;border-radius:2px}.pptx-ng-spanel-clip ::ng-deep .pptx-ng-canvas-wrapper{margin:0!important}.pptx-ng-spanel-num{display:block;text-align:center;font-size:.625rem;line-height:1.6;color:#ffffff73;-webkit-user-select:none;user-select:none;padding-bottom:.25rem}.pptx-ng-spanel-actions{position:absolute;top:.25rem;right:.25rem;display:flex;flex-direction:column;gap:.125rem;opacity:0;pointer-events:none;transition:opacity .12s}.pptx-ng-spanel-card:hover .pptx-ng-spanel-actions,.pptx-ng-spanel-card:focus-within .pptx-ng-spanel-actions{opacity:1;pointer-events:auto}.pptx-ng-spanel-action{display:flex;align-items:center;justify-content:center;width:1.375rem;height:1.375rem;padding:0;border:none;border-radius:.25rem;background:#1e1e1ed9;color:#e5e5e5;font-size:.6875rem;cursor:pointer;transition:background .12s;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.pptx-ng-spanel-action:hover:not([disabled]){background:#3b82f6bf}.pptx-ng-spanel-action[disabled]{opacity:.3;cursor:not-allowed}.pptx-ng-spanel-footer{flex-shrink:0;padding:.5rem .375rem;border-top:1px solid rgba(255,255,255,.08)}.pptx-ng-spanel-add{display:block;width:100%;padding:.4375rem 0;border:1px dashed rgba(255,255,255,.2);border-radius:.375rem;background:transparent;color:#fff9;font-size:.75rem;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.pptx-ng-spanel-add:hover{background:#3b82f626;border-color:#3b82f6;color:#e5e5e5}\n"] }]
88362
+ ], template: "<div class=\"pptx-ng-spanel\">\n\t<!-- Scrollable slide list -->\n\t<div\n\t\t#scrollViewport\n\t\tclass=\"pptx-ng-spanel-scroll\"\n\t\trole=\"listbox\"\n\t\t[attr.aria-label]=\"'pptx.sections.slides' | translate\"\n\t\t(scroll)=\"onScroll()\"\n\t>\n\t\t<div\n\t\t\tclass=\"pptx-ng-spanel-space\"\n\t\t\t[attr.data-virtualized]=\"shouldVirtualize() ? 'true' : null\"\n\t\t\t[style.height.px]=\"shouldVirtualize() ? virtualRange().totalHeight : null\"\n\t\t>\n\t\t\t<div\n\t\t\t\tclass=\"pptx-ng-spanel-window\"\n\t\t\t\t[class.is-virtualized]=\"shouldVirtualize()\"\n\t\t\t\t[style.top.px]=\"shouldVirtualize() ? virtualRange().offsetY : null\"\n\t\t\t>\n\t\t\t\t@for (item of renderedSlides(); track item.slide.id) {\n\t\t\t\t\t@let slide = item.slide;\n\t\t\t\t\t@let i = item.index;\n\t\t\t\t\t@if (item.sectionStart) {\n\t\t\t\t\t\t<header class=\"pptx-ng-section-header\" [attr.data-section-id]=\"item.section?.id\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-section-toggle\"\n\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!item.section?.collapsed\"\n\t\t\t\t\t\t\t\t(click)=\"item.section && editor.sectionOps.toggle(item.section.id)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span>{{ item.section?.collapsed ? '\u25B8' : '\u25BE' }}</span>\n\t\t\t\t\t\t\t\t<strong>{{\n\t\t\t\t\t\t\t\t\titem.section?.name ?? ('pptx.slides.ungroupedSlides' | translate)\n\t\t\t\t\t\t\t\t}}</strong>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t@if (item.section) {\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-section-actions\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"onRenameSection(item.section.id, item.section.name)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u270E\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === 0\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'up')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2191\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t[disabled]=\"sectionIndex(item.section.id) === editor.sections().length - 1\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.move(item.section.id, 'down')\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u2193\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t\t(click)=\"editor.sectionOps.delete(item.section.id)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\u00D7\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</header>\n\t\t\t\t\t}\n\t\t\t\t\t@if (!item.section?.collapsed) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-card\"\n\t\t\t\t\t\t\t[class.is-active]=\"i === activeIndex()\"\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t[attr.aria-selected]=\"i === activeIndex()\"\n\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.notes.slideN' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<!-- Thumbnail (clickable to select). Slide number sits to the LEFT\n\t\t\t\t\t\t\t of the preview (React SlideItem parity), not below it. -->\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-thumb-btn\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slidesPanel.goToSlide' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t\t(click)=\"select.emit(i)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<!-- Slide number badge (left column) -->\n\t\t\t\t\t\t\t\t<span class=\"pptx-ng-spanel-num\" aria-hidden=\"true\">{{ i + 1 }}</span>\n\n\t\t\t\t\t\t\t\t<!-- Clipping wrapper: neutralises the 1rem auto margin from SlideCanvas -->\n\t\t\t\t\t\t\t\t<div class=\"pptx-ng-spanel-clip\" [ngStyle]=\"clipStyle()\">\n\t\t\t\t\t\t\t\t\t<pptx-slide-canvas\n\t\t\t\t\t\t\t\t\t\t[slide]=\"slide\"\n\t\t\t\t\t\t\t\t\t\t[templateElements]=\"editor.templateElementsBySlideId()[slide.id] ?? []\"\n\t\t\t\t\t\t\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t\t\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t\t\t\t\t\t[zoom]=\"thumbZoom()\"\n\t\t\t\t\t\t\t\t\t\t[editable]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[autoFit]=\"false\"\n\t\t\t\t\t\t\t\t\t\t[interactive]=\"false\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t<!-- Per-card action toolbar (visible on hover / focus-within) -->\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-actions\"\n\t\t\t\t\t\t\t\trole=\"toolbar\"\n\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.slideMenu.slideActions' | translate: { n: i + 1 }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.ribbon.duplicateSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.duplicate' | translate\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDuplicate(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideCopy class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.slidesPanel.deleteSlide' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.arrange.delete' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"editor.slides().length <= 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onDelete(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideTrash2 class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveUp' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === 0\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveUp(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowUp class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-spanel-action\"\n\t\t\t\t\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\t\t\t\t\t[title]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.sections.moveDown' | translate\"\n\t\t\t\t\t\t\t\t\t[disabled]=\"i === editor.slides().length - 1\"\n\t\t\t\t\t\t\t\t\t(click)=\"onMoveDown(i)\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<svg lucideArrowDown class=\"h-3.5 w-3.5\"></svg>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n\n\t<!-- Footer: add new slide -->\n\t<footer class=\"pptx-ng-spanel-footer\">\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-spanel-add\"\n\t\t\t[attr.aria-label]=\"'pptx.sections.addSlide' | translate\"\n\t\t\t(click)=\"onAddSlide()\"\n\t\t>\n\t\t\t<svg lucidePlus class=\"h-3.5 w-3.5\"></svg> {{ 'pptx.sections.addSlide' | translate }}\n\t\t</button>\n\t</footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:100%;overflow:hidden}.pptx-ng-spanel{display:flex;flex-direction:column;height:100%;background:var(--pptx-secondary, #1e1e1e);color:var(--pptx-foreground, #e5e5e5);border-right:1px solid var(--pptx-border, rgba(255, 255, 255, .08));overflow:hidden}.pptx-ng-spanel-scroll{flex:1;overflow-y:auto;padding:.5rem .375rem}.pptx-ng-spanel-space{position:relative}.pptx-ng-spanel-window{display:flex;flex-direction:column;gap:.375rem}.pptx-ng-spanel-window.is-virtualized{position:absolute;inset-inline:0}.pptx-ng-section-header{display:flex;align-items:center;gap:.2rem;min-height:1.75rem;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .58))}.pptx-ng-section-toggle{display:flex;align-items:center;gap:.35rem;min-width:0;flex:1;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left}.pptx-ng-section-toggle strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7rem}.pptx-ng-section-actions{display:flex}.pptx-ng-section-actions button{width:1.25rem;height:1.25rem;padding:0;border:0;border-radius:.2rem;background:transparent;color:inherit;cursor:pointer}.pptx-ng-section-actions button:hover:not(:disabled){background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 35%,transparent);color:var(--pptx-foreground, #fff)}.pptx-ng-section-actions button:disabled{opacity:.3}.pptx-ng-spanel-card{position:relative;border-radius:.375rem;border:2px solid transparent;background:transparent;transition:border-color .15s,background .15s}.pptx-ng-spanel-card:hover,.pptx-ng-spanel-card:focus-within{background:color-mix(in srgb,var(--pptx-foreground, #fff) 5%,transparent);border-color:color-mix(in srgb,var(--pptx-foreground, #fff) 15%,transparent)}.pptx-ng-spanel-card.is-active{border-color:var(--pptx-primary, #3b82f6);background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 10%,transparent)}.pptx-ng-spanel-thumb-btn{display:flex;align-items:center;gap:.25rem;width:100%;padding:.375rem;border:none;background:transparent;cursor:pointer;color:inherit;line-height:0}.pptx-ng-spanel-thumb-btn:focus-visible{outline:2px solid var(--pptx-ring, #3b82f6);outline-offset:2px;border-radius:.25rem}.pptx-ng-spanel-clip{overflow:hidden;border-radius:2px}.pptx-ng-spanel-clip ::ng-deep .pptx-ng-canvas-wrapper{margin:0!important}.pptx-ng-spanel-num{flex:0 0 auto;width:1.1rem;text-align:right;font-size:.625rem;line-height:1;font-variant-numeric:tabular-nums;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .45));-webkit-user-select:none;user-select:none}.pptx-ng-spanel-card.is-active .pptx-ng-spanel-num{color:var(--pptx-primary, #3b82f6);font-weight:500}.pptx-ng-spanel-actions{position:absolute;top:.25rem;right:.25rem;display:flex;flex-direction:column;gap:.125rem;opacity:0;pointer-events:none;transition:opacity .12s}.pptx-ng-spanel-card:hover .pptx-ng-spanel-actions,.pptx-ng-spanel-card:focus-within .pptx-ng-spanel-actions{opacity:1;pointer-events:auto}.pptx-ng-spanel-action{display:flex;align-items:center;justify-content:center;width:1.375rem;height:1.375rem;padding:0;border:none;border-radius:.25rem;background:color-mix(in srgb,var(--pptx-popover, #1e1e1e) 85%,transparent);color:var(--pptx-popover-foreground, #e5e5e5);font-size:.6875rem;cursor:pointer;transition:background .12s;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.pptx-ng-spanel-action:hover:not([disabled]){background:color-mix(in srgb,var(--pptx-primary, #3b82f6) 75%,transparent);color:var(--pptx-primary-foreground, #fff)}.pptx-ng-spanel-action[disabled]{opacity:.3;cursor:not-allowed}.pptx-ng-spanel-footer{flex-shrink:0;padding:.5rem .375rem;border-top:1px solid var(--pptx-border, rgba(255, 255, 255, .08))}.pptx-ng-spanel-add{display:flex;align-items:center;justify-content:center;gap:.25rem;width:100%;padding:.25rem .5rem;border:none;border-radius:.25rem;background:transparent;color:var(--pptx-muted-foreground, rgba(255, 255, 255, .6));font-size:.6875rem;cursor:pointer;transition:background .15s,color .15s}.pptx-ng-spanel-add:hover{background:color-mix(in srgb,var(--pptx-foreground, #fff) 8%,transparent);color:var(--pptx-foreground, #e5e5e5)}\n"] }]
88127
88363
  }], ctorParameters: () => [], propDecorators: { canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], scrollViewport: [{ type: i0.ViewChild, args: ['scrollViewport', { isSignal: true }] }] } });
88128
88364
 
88129
88365
  class StatusBarComponent {
@@ -91005,21 +91241,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
91005
91241
  * LaTeX -> MathML conversion and the template catalogue are unit testable in
91006
91242
  * isolation.
91007
91243
  */
91008
- /** Pre-defined equation templates covering common mathematical formulas. */
91009
- const TEMPLATES = [
91010
- { label: 'Fraction', latex: '\\frac{a}{b}' },
91011
- { label: 'Quadratic', latex: 'x=\\frac{-b\\pm\\sqrt{b^{2}-4ac}}{2a}' },
91012
- { label: 'Pythagorean', latex: 'a^{2}+b^{2}=c^{2}' },
91013
- { label: 'Sum', latex: '\\sum_{i=1}^{n}{a_{i}}' },
91014
- { label: 'Integral', latex: '\\int_{a}^{b}{f(x)}dx' },
91015
- { label: 'Square Root', latex: '\\sqrt{x^{2}+y^{2}}' },
91016
- { label: 'Limit', latex: '\\lim_{x\\to\\infty}{f(x)}' },
91017
- { label: "Euler's", latex: 'e^{i\\pi}+1=0' },
91018
- { label: 'Matrix 2x2', latex: '\\left[a,b;c,d\\right]' },
91019
- { label: 'Binomial', latex: '\\left(a+b\\right)^{n}' },
91020
- { label: 'Derivative', latex: '\\frac{dy}{dx}' },
91021
- { label: 'Trig Identity', latex: '\\sin^{2}\\theta+\\cos^{2}\\theta=1' },
91022
- ];
91244
+ /**
91245
+ * Pre-defined equation templates covering common mathematical formulas
91246
+ * (the shared catalogue every binding's equation dialog renders).
91247
+ */
91248
+ const TEMPLATES = EQUATION_TEMPLATES;
91023
91249
  /** Convert a LaTeX string to a MathML markup string, empty on any failure. */
91024
91250
  function latexToMathml(latex) {
91025
91251
  if (!latex.trim()) {
@@ -91045,25 +91271,6 @@ function latexToMathml(latex) {
91045
91271
  * MathML preview each (computed once), highlighting the one matching the
91046
91272
  * current LaTeX and emitting `select` when a template is clicked.
91047
91273
  */
91048
- /**
91049
- * Maps each built-in template's English label to its shared i18n key (the same
91050
- * keys the React equation editor uses), so the gallery renders localized labels
91051
- * without changing the framework-agnostic TEMPLATES list.
91052
- */
91053
- const TEMPLATE_I18N_KEYS = {
91054
- Fraction: 'pptx.equation.template.fraction',
91055
- Quadratic: 'pptx.equation.template.quadratic',
91056
- Pythagorean: 'pptx.equation.template.pythagorean',
91057
- Sum: 'pptx.equation.template.sum',
91058
- Integral: 'pptx.equation.template.integral',
91059
- 'Square Root': 'pptx.equation.template.squareRoot',
91060
- Limit: 'pptx.equation.template.limit',
91061
- "Euler's": 'pptx.equation.template.euler',
91062
- 'Matrix 2x2': 'pptx.equation.template.matrix',
91063
- Binomial: 'pptx.equation.template.binomial',
91064
- Derivative: 'pptx.equation.template.derivative',
91065
- 'Trig Identity': 'pptx.equation.template.trigIdentity',
91066
- };
91067
91274
  class EquationTemplateGalleryComponent {
91068
91275
  /** Current LaTeX source (drives the active-template highlight). */
91069
91276
  activeLatex = input('', /* @ts-ignore */
@@ -91075,7 +91282,6 @@ class EquationTemplateGalleryComponent {
91075
91282
  templates = TEMPLATES.map((tmpl) => ({
91076
91283
  ...tmpl,
91077
91284
  mathml: this.sanitizer.bypassSecurityTrustHtml(latexToMathml(tmpl.latex)),
91078
- i18nKey: TEMPLATE_I18N_KEYS[tmpl.label] ?? tmpl.label,
91079
91285
  }));
91080
91286
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: EquationTemplateGalleryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
91081
91287
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: EquationTemplateGalleryComponent, isStandalone: true, selector: "pptx-equation-template-gallery", inputs: { activeLatex: { classPropertyName: "activeLatex", publicName: "activeLatex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, ngImport: i0, template: `