pptx-angular-viewer 1.16.1 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to this project are documented here.
4
4
  This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
5
5
  by [git-cliff](https://git-cliff.org); do not edit it by hand.
6
6
 
7
+ ## [1.17.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.17.0) - 2026-07-13
8
+
9
+ ### Bug Fixes
10
+
11
+ - **build:** Restore compatibility after dependency updates (by @ChristopherVR) ([ddbfae6](https://github.com/ChristopherVR/pptx-viewer/commit/ddbfae687669b9e6c64fd3c3b16a592623b79c10))
12
+
13
+ ### Dependencies
14
+
15
+ - **deps:** Update html2canvas-pro to 2.2.3 (by @dependabot[bot]) ([0fe015b](https://github.com/ChristopherVR/pptx-viewer/commit/0fe015b83722534f14864b2054ce6561b09386ca))
16
+ - **deps:** Update angular compiler to 22.0.6 (by @dependabot[bot]) ([3990f82](https://github.com/ChristopherVR/pptx-viewer/commit/3990f821128012438f9e72337b293fce7110d0fc))
17
+ - **deps:** Update fast-xml-parser to 5.10.0 (by @dependabot[bot]) ([6080273](https://github.com/ChristopherVR/pptx-viewer/commit/6080273f6a6f603d10d69a71d54faad1e6d9bf05))
18
+ - **deps:** Update angular vite plugin to 2.6.3 (by @dependabot[bot]) ([f3c664e](https://github.com/ChristopherVR/pptx-viewer/commit/f3c664e28425ff0059073b3119f215e981f56d00))
19
+ - **deps:** Update dompurify to 3.4.12 (by @dependabot[bot]) ([00a6ca4](https://github.com/ChristopherVR/pptx-viewer/commit/00a6ca49609d5a0e922a9e20447460b11ec690ba))
20
+ - **deps:** Update minor and patch dependencies (by @dependabot[bot]) ([5cd81fb](https://github.com/ChristopherVR/pptx-viewer/commit/5cd81fb0c8708e53990ac4858660d0b6a4b17a7a))
21
+ - **deps:** Update typescript to 7.0.2 (by @dependabot[bot]) ([0a7c1f1](https://github.com/ChristopherVR/pptx-viewer/commit/0a7c1f1f7f0ccdee9537f1e11177b6a39839d221))
22
+
23
+ ## [1.16.1](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.16.1) - 2026-07-13
24
+
7
25
  ## [1.16.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.16.0) - 2026-07-11
8
26
 
9
27
  ## [1.15.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.15.0) - 2026-07-11
@@ -3736,6 +3736,80 @@ function getWarpCssTransform(preset, adj, adj2) {
3736
3736
  return undefined;
3737
3737
  }
3738
3738
 
3739
+ /**
3740
+ * Read the first explicit DrawingML run colour nested inside an OMML tree.
3741
+ * Office Math stores formatting in `a:rPr`, not in `m:rPr`, so this colour
3742
+ * must travel with the generated MathML rather than the text shape's default
3743
+ * paragraph style.
3744
+ */
3745
+ function getOmmlMathColor(node) {
3746
+ if (!node || typeof node !== 'object') {
3747
+ return undefined;
3748
+ }
3749
+ const drawingRunProperties = node['a:rPr'];
3750
+ if (drawingRunProperties && typeof drawingRunProperties === 'object') {
3751
+ const solidFill = drawingRunProperties['a:solidFill'];
3752
+ const srgbColor = solidFill && typeof solidFill === 'object'
3753
+ ? solidFill['a:srgbClr']
3754
+ : undefined;
3755
+ const value = srgbColor?.['@_val'];
3756
+ if (typeof value === 'string' && /^[0-9a-f]{6}$/iu.test(value)) {
3757
+ return `#${value.toUpperCase()}`;
3758
+ }
3759
+ }
3760
+ for (const value of Object.values(node)) {
3761
+ if (Array.isArray(value)) {
3762
+ for (const child of value) {
3763
+ if (child && typeof child === 'object') {
3764
+ const color = getOmmlMathColor(child);
3765
+ if (color) {
3766
+ return color;
3767
+ }
3768
+ }
3769
+ }
3770
+ }
3771
+ else if (value && typeof value === 'object') {
3772
+ const color = getOmmlMathColor(value);
3773
+ if (color) {
3774
+ return color;
3775
+ }
3776
+ }
3777
+ }
3778
+ return undefined;
3779
+ }
3780
+ /** Read the first explicit DrawingML run size, stored in hundredths of a point. */
3781
+ function getOmmlMathFontSize(node) {
3782
+ if (!node || typeof node !== 'object') {
3783
+ return undefined;
3784
+ }
3785
+ const drawingRunProperties = node['a:rPr'];
3786
+ if (drawingRunProperties && typeof drawingRunProperties === 'object') {
3787
+ const size = Number(drawingRunProperties['@_sz']);
3788
+ if (Number.isFinite(size) && size > 0) {
3789
+ return size / 100;
3790
+ }
3791
+ }
3792
+ for (const value of Object.values(node)) {
3793
+ if (Array.isArray(value)) {
3794
+ for (const child of value) {
3795
+ if (child && typeof child === 'object') {
3796
+ const size = getOmmlMathFontSize(child);
3797
+ if (size) {
3798
+ return size;
3799
+ }
3800
+ }
3801
+ }
3802
+ }
3803
+ else if (value && typeof value === 'object') {
3804
+ const size = getOmmlMathFontSize(value);
3805
+ if (size) {
3806
+ return size;
3807
+ }
3808
+ }
3809
+ }
3810
+ return undefined;
3811
+ }
3812
+
3739
3813
  /**
3740
3814
  * omml-to-mathml.ts — pure OMML → MathML conversion.
3741
3815
  *
@@ -4250,7 +4324,11 @@ function convertOmmlToMathMl(ommlNode) {
4250
4324
  if (inner.length === 0) {
4251
4325
  return '';
4252
4326
  }
4253
- return `<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">${inner}</math>`;
4327
+ const color = getOmmlMathColor(ommlNode);
4328
+ const colorAttribute = color ? ` mathcolor="${color}"` : '';
4329
+ const fontSize = getOmmlMathFontSize(ommlNode);
4330
+ const sizeAttribute = fontSize ? ` mathsize="${fontSize}pt"` : '';
4331
+ return `<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"${colorAttribute}${sizeAttribute}>${inner}</math>`;
4254
4332
  }
4255
4333
  /**
4256
4334
  * Convenience alias used by the Vue viewer: `ommlToMathml(omml)`.
@@ -16722,6 +16800,37 @@ function mergeAdditiveSelection(baseSelectionIds, hitIds) {
16722
16800
  return Array.from(new Set([...(baseSelectionIds ?? []), ...hitIds]));
16723
16801
  }
16724
16802
 
16803
+ /** Union of all selected element boxes, or null for an empty selection. */
16804
+ function selectionBounds(boxes) {
16805
+ if (boxes.length === 0) {
16806
+ return null;
16807
+ }
16808
+ const minX = Math.min(...boxes.map((box) => box.x));
16809
+ const minY = Math.min(...boxes.map((box) => box.y));
16810
+ const maxX = Math.max(...boxes.map((box) => box.x + box.width));
16811
+ const maxY = Math.max(...boxes.map((box) => box.y + box.height));
16812
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY, rotation: 0 };
16813
+ }
16814
+ /** Move all boxes by the same slide-space delta. */
16815
+ function moveSelection(boxes, dx, dy) {
16816
+ return boxes.map((box) => ({ ...box, x: box.x + dx, y: box.y + dy }));
16817
+ }
16818
+ /**
16819
+ * Scale boxes from one selection boundary into another. Each element keeps its
16820
+ * relative position and size within the collective selection.
16821
+ */
16822
+ function resizeSelection(boxes, from, to) {
16823
+ const scaleX = from.width === 0 ? 1 : to.width / from.width;
16824
+ const scaleY = from.height === 0 ? 1 : to.height / from.height;
16825
+ return boxes.map((box) => ({
16826
+ ...box,
16827
+ x: to.x + (box.x - from.x) * scaleX,
16828
+ y: to.y + (box.y - from.y) * scaleY,
16829
+ width: Math.max(1, box.width * scaleX),
16830
+ height: Math.max(1, box.height * scaleY),
16831
+ }));
16832
+ }
16833
+
16725
16834
  /** Map a number to a CSS pixel string. */
16726
16835
  function px(n) {
16727
16836
  return `${n}px`;
@@ -20459,7 +20568,14 @@ function sanitizeMarkupOrEmpty(markup, config) {
20459
20568
  * @returns The sanitised markup, or the raw input when no DOM is available.
20460
20569
  */
20461
20570
  function sanitizeMathMl(markup) {
20462
- return sanitizeMarkupOrRaw(markup, { USE_PROFILES: { mathMl: true, svg: true } });
20571
+ const sanitized = sanitizeMarkupOrRaw(markup, { USE_PROFILES: { mathMl: true, svg: true } });
20572
+ // DOMPurify's HTML parser can retain MathML descendants while dropping the
20573
+ // outer namespace-bearing <math> node. Restore that generated, constant
20574
+ // wrapper so browsers keep the fragment in the MathML rendering context.
20575
+ if (/<math(?:\s|>)/iu.test(markup) && !/<math(?:\s|>)/iu.test(sanitized) && sanitized) {
20576
+ return `<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">${sanitized}</math>`;
20577
+ }
20578
+ return sanitized;
20463
20579
  }
20464
20580
 
20465
20581
  /**
@@ -29437,6 +29553,23 @@ function buildFontFaceRule(variant) {
29437
29553
  '}',
29438
29554
  ].join('\n');
29439
29555
  }
29556
+ /** Build a safe `@font-face` stylesheet for host-provided font sources. */
29557
+ function buildUserFontFaceStyles(fonts) {
29558
+ const rules = [];
29559
+ for (const font of fonts ?? []) {
29560
+ const family = typeof font.family === 'string' ? font.family.trim() : '';
29561
+ const src = typeof font.src === 'string' ? font.src.trim() : '';
29562
+ const isRemoteUrl = /^https?:\/\/[^"\\\n\r{};]+$/iu.test(src);
29563
+ if (!family || FONT_NAME_UNSAFE_CHARS.test(family) || !(isInjectableUrl(src) || isRemoteUrl)) {
29564
+ continue;
29565
+ }
29566
+ const format = normalizeFontFormat(font.format);
29567
+ const weight = typeof font.weight === 'number' || typeof font.weight === 'string' ? font.weight : '400';
29568
+ const style = font.style === 'italic' ? 'italic' : 'normal';
29569
+ rules.push(buildFontFaceRule({ name: family, url: src, format, weight: String(weight), style }));
29570
+ }
29571
+ return rules.join('\n\n');
29572
+ }
29440
29573
  /**
29441
29574
  * Resolve a list of embedded fonts into the injectable `@font-face` stylesheet,
29442
29575
  * the distinct substitution-resolved family strings, and any object URLs minted
@@ -32593,6 +32726,60 @@ function createTouchGestureRecognizer(config) {
32593
32726
  };
32594
32727
  }
32595
32728
 
32729
+ /**
32730
+ * Build the stable presentation-control state shared by every UI binding.
32731
+ * Empty presentations disable both directions and use the same 0 / 0 label.
32732
+ */
32733
+ function buildPresentationTouchControlState(currentSlideIndex, totalSlides) {
32734
+ if (totalSlides <= 0) {
32735
+ return {
32736
+ previousDisabled: true,
32737
+ nextDisabled: true,
32738
+ counterLabel: '0 / 0',
32739
+ };
32740
+ }
32741
+ return {
32742
+ previousDisabled: currentSlideIndex <= 0,
32743
+ nextDisabled: currentSlideIndex >= totalSlides - 1,
32744
+ counterLabel: `${currentSlideIndex + 1} / ${totalSlides}`,
32745
+ };
32746
+ }
32747
+
32748
+ /** Framework-neutral downward drag recognizer for mobile bottom sheets. */
32749
+ function createSheetDismissGesture(onOffset, onDismiss, threshold = 120) {
32750
+ let startY = null;
32751
+ const finish = (event, allowDismiss) => {
32752
+ if (startY === null) {
32753
+ return;
32754
+ }
32755
+ const delta = Math.max(0, event.clientY - startY);
32756
+ startY = null;
32757
+ event.currentTarget?.releasePointerCapture?.(event.pointerId);
32758
+ onOffset(0, false);
32759
+ if (allowDismiss && delta > threshold) {
32760
+ onDismiss();
32761
+ }
32762
+ };
32763
+ return {
32764
+ pointerDown(event) {
32765
+ startY = event.clientY;
32766
+ event.currentTarget?.setPointerCapture?.(event.pointerId);
32767
+ onOffset(0, true);
32768
+ },
32769
+ pointerMove(event) {
32770
+ if (startY !== null) {
32771
+ onOffset(Math.max(0, event.clientY - startY), true);
32772
+ }
32773
+ },
32774
+ pointerUp(event) {
32775
+ finish(event, true);
32776
+ },
32777
+ cancel(event) {
32778
+ finish(event, false);
32779
+ },
32780
+ };
32781
+ }
32782
+
32596
32783
  /**
32597
32784
  * insert-chart.ts - framework-agnostic factory for a sensible DEFAULT new
32598
32785
  * chart element, the single source of truth every binding (React, Vue,
@@ -33299,6 +33486,39 @@ function deserializeElementClipboard(text) {
33299
33486
  };
33300
33487
  }
33301
33488
 
33489
+ /** Immutably replace one slide's inherited element list. */
33490
+ function setTemplateElements(map, slideId, elements) {
33491
+ return { ...map, [slideId]: elements };
33492
+ }
33493
+ /** Find an inherited element on one slide. */
33494
+ function findTemplateElement(map, slideId, elementId) {
33495
+ return slideId ? map[slideId]?.find((element) => element.id === elementId) : undefined;
33496
+ }
33497
+ /** Gate layout/master hits unless template editing is enabled. */
33498
+ function isElementIdInteractive(elementId, editTemplateMode) {
33499
+ return !isTemplateElementId(elementId) || editTemplateMode;
33500
+ }
33501
+ /** Split layout/master elements out of each loaded slide while preserving order. */
33502
+ function partitionTemplateElements(slides) {
33503
+ const templateElementsBySlideId = {};
33504
+ const nextSlides = slides.map((slide) => {
33505
+ const template = slide.elements.filter(isTemplateElement);
33506
+ if (template.length === 0) {
33507
+ return slide;
33508
+ }
33509
+ templateElementsBySlideId[slide.id] = template;
33510
+ return { ...slide, elements: slide.elements.filter((element) => !isTemplateElement(element)) };
33511
+ });
33512
+ return { slides: nextSlides, templateElementsBySlideId };
33513
+ }
33514
+ /** Merge editable layout/master elements behind slide-owned elements for save/export. */
33515
+ function buildSaveSlides$1(slides, templateElementsBySlideId) {
33516
+ return slides.map((slide) => {
33517
+ const template = templateElementsBySlideId[slide.id];
33518
+ return template?.length ? { ...slide, elements: [...template, ...slide.elements] } : slide;
33519
+ });
33520
+ }
33521
+
33302
33522
  /**
33303
33523
  * shape-preset-catalog.ts: the Insert > Shape picker catalogue shared by every
33304
33524
  * binding's toolbar/inspector.
@@ -39621,7 +39841,7 @@ const translationsEn = {
39621
39841
  'pptx.collaboration.status.connecting': 'Connecting...',
39622
39842
  'pptx.collaboration.status.disconnected': 'Disconnected',
39623
39843
  'pptx.collaboration.status.error': 'Connection error',
39624
- 'pptx.collaboration.statusAriaLabel': 'Collaboration: {{status}}. {{count}} user(s) connected.',
39844
+ 'pptx.collaboration.statusAriaLabel': 'Collaboration: {{status}}',
39625
39845
  'pptx.collaboration.userCount': '{{count}} user(s)',
39626
39846
  'pptx.collaboration.youLabel': '{{name}} (you)',
39627
39847
  'pptx.collaboration.usersConnected': '{{count}} user(s) connected',
@@ -53255,6 +53475,7 @@ class SmartArtPropertiesComponent {
53255
53475
  @for (layout of layoutTypes; track layout) {
53256
53476
  <button
53257
53477
  type="button"
53478
+ [attr.data-testid]="'smartart-layout-' + layout"
53258
53479
  class="pptx-sa-props__layout"
53259
53480
  [class.is-active]="activeLayout() === layout"
53260
53481
  [disabled]="!canEdit()"
@@ -53272,6 +53493,8 @@ class SmartArtPropertiesComponent {
53272
53493
  <span class="pptx-sa-props__label">{{ 'pptx.smartart.colorScheme' | translate }}</span>
53273
53494
  <select
53274
53495
  class="pptx-sa-props__select"
53496
+ data-testid="smartart-color-scheme"
53497
+ [attr.aria-label]="'pptx.smartart.colorScheme' | translate"
53275
53498
  [disabled]="!canEdit()"
53276
53499
  [value]="activeColorScheme()"
53277
53500
  (change)="onColorScheme($event)"
@@ -53335,11 +53558,13 @@ class SmartArtPropertiesComponent {
53335
53558
  <span class="pptx-sa-props__bullet">{{ isChild(node) ? '•' : i + 1 }}</span>
53336
53559
  <input
53337
53560
  type="text"
53561
+ data-testid="smartart-node-text"
53562
+ [attr.aria-label]="node.text"
53338
53563
  class="pptx-sa-props__node-input"
53339
53564
  [disabled]="!canEdit()"
53340
53565
  [value]="node.text"
53341
53566
  [attr.placeholder]="'pptx.smartArt.nodePlaceholder' | translate"
53342
- (change)="onNodeText($event, node.id)"
53567
+ (input)="onNodeText($event, node.id)"
53343
53568
  (keydown)="onNodeKeydown($event, node.id)"
53344
53569
  />
53345
53570
  <div class="pptx-sa-props__node-actions">
@@ -53481,6 +53706,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
53481
53706
  @for (layout of layoutTypes; track layout) {
53482
53707
  <button
53483
53708
  type="button"
53709
+ [attr.data-testid]="'smartart-layout-' + layout"
53484
53710
  class="pptx-sa-props__layout"
53485
53711
  [class.is-active]="activeLayout() === layout"
53486
53712
  [disabled]="!canEdit()"
@@ -53498,6 +53724,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
53498
53724
  <span class="pptx-sa-props__label">{{ 'pptx.smartart.colorScheme' | translate }}</span>
53499
53725
  <select
53500
53726
  class="pptx-sa-props__select"
53727
+ data-testid="smartart-color-scheme"
53728
+ [attr.aria-label]="'pptx.smartart.colorScheme' | translate"
53501
53729
  [disabled]="!canEdit()"
53502
53730
  [value]="activeColorScheme()"
53503
53731
  (change)="onColorScheme($event)"
@@ -53561,11 +53789,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
53561
53789
  <span class="pptx-sa-props__bullet">{{ isChild(node) ? '•' : i + 1 }}</span>
53562
53790
  <input
53563
53791
  type="text"
53792
+ data-testid="smartart-node-text"
53793
+ [attr.aria-label]="node.text"
53564
53794
  class="pptx-sa-props__node-input"
53565
53795
  [disabled]="!canEdit()"
53566
53796
  [value]="node.text"
53567
53797
  [attr.placeholder]="'pptx.smartArt.nodePlaceholder' | translate"
53568
- (change)="onNodeText($event, node.id)"
53798
+ (input)="onNodeText($event, node.id)"
53569
53799
  (keydown)="onNodeKeydown($event, node.id)"
53570
53800
  />
53571
53801
  <div class="pptx-sa-props__node-actions">
@@ -56137,10 +56367,7 @@ class InspectorPanelComponent {
56137
56367
  mid-edit: the caret stays put and the on-screen keyboard does not dismiss.
56138
56368
  All commits happen on (change) (blur), reading event.target.value.
56139
56369
  -->
56140
- <aside
56141
- [class]="inspectorClass()"
56142
- [attr.aria-label]="'pptx.inspector.elementProperties' | translate"
56143
- >
56370
+ <aside [class]="inspectorClass()" [attr.aria-label]="'pptx.inspector.properties' | translate">
56144
56371
  <!-- ── Transform: Position & Size ─────────────────────────────────── -->
56145
56372
  <section class="pptx-ng-inspector__section">
56146
56373
  <h3 class="pptx-ng-inspector__heading">{{ 'pptx.inspector.transform' | translate }}</h3>
@@ -56515,10 +56742,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
56515
56742
  mid-edit: the caret stays put and the on-screen keyboard does not dismiss.
56516
56743
  All commits happen on (change) (blur), reading event.target.value.
56517
56744
  -->
56518
- <aside
56519
- [class]="inspectorClass()"
56520
- [attr.aria-label]="'pptx.inspector.elementProperties' | translate"
56521
- >
56745
+ <aside [class]="inspectorClass()" [attr.aria-label]="'pptx.inspector.properties' | translate">
56522
56746
  <!-- ── Transform: Position & Size ─────────────────────────────────── -->
56523
56747
  <section class="pptx-ng-inspector__section">
56524
56748
  <h3 class="pptx-ng-inspector__heading">{{ 'pptx.inspector.transform' | translate }}</h3>
@@ -56995,6 +57219,7 @@ class MobileBottomBarComponent {
56995
57219
  {
56996
57220
  key: 'notes',
56997
57221
  labelKey: 'pptx.notes.title',
57222
+ ariaLabelKey: 'pptx.statusBar.toggleNotes',
56998
57223
  // Note / document-text icon
56999
57224
  svgPath: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M8 13h8 M8 17h5',
57000
57225
  disabled: noSlides,
@@ -57013,7 +57238,7 @@ class MobileBottomBarComponent {
57013
57238
  class="pptx-ng-mbar-btn"
57014
57239
  [class.is-active]="action.active"
57015
57240
  [attr.aria-pressed]="action.active ? true : null"
57016
- [attr.aria-label]="action.labelKey | translate"
57241
+ [attr.aria-label]="action.ariaLabelKey ?? action.labelKey | translate"
57017
57242
  [disabled]="action.disabled"
57018
57243
  (click)="action.emit()"
57019
57244
  >
@@ -57054,7 +57279,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
57054
57279
  class="pptx-ng-mbar-btn"
57055
57280
  [class.is-active]="action.active"
57056
57281
  [attr.aria-pressed]="action.active ? true : null"
57057
- [attr.aria-label]="action.labelKey | translate"
57282
+ [attr.aria-label]="action.ariaLabelKey ?? action.labelKey | translate"
57058
57283
  [disabled]="action.disabled"
57059
57284
  (click)="action.emit()"
57060
57285
  >
@@ -57505,7 +57730,6 @@ class MobileMenuSheetComponent {
57505
57730
  [class.is-active]="row.active"
57506
57731
  [class.is-danger]="row.danger"
57507
57732
  [disabled]="row.disabled"
57508
- role="menuitem"
57509
57733
  [attr.aria-label]="row.labelKey | translate"
57510
57734
  (click)="onRowClick(row)"
57511
57735
  >
@@ -57558,7 +57782,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
57558
57782
  [class.is-active]="row.active"
57559
57783
  [class.is-danger]="row.danger"
57560
57784
  [disabled]="row.disabled"
57561
- role="menuitem"
57562
57785
  [attr.aria-label]="row.labelKey | translate"
57563
57786
  (click)="onRowClick(row)"
57564
57787
  >
@@ -68720,8 +68943,12 @@ class PresentationTransitionOverlayComponent {
68720
68943
  }
68721
68944
  }
68722
68945
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PresentationTransitionOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
68723
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.6", type: PresentationTransitionOverlayComponent, isStandalone: true, selector: "pptx-presentation-transition-overlay", inputs: { outgoingSlide: { classPropertyName: "outgoingSlide", publicName: "outgoingSlide", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, transition: { classPropertyName: "transition", publicName: "transition", isSignal: true, isRequired: true, transformFunction: null }, templateElements: { classPropertyName: "templateElements", publicName: "templateElements", isSignal: true, isRequired: false, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, durationMs: { classPropertyName: "durationMs", publicName: "durationMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { complete: "complete" }, ngImport: i0, template: `
68724
- <div class="pptx-ng-transition-layer" [ngStyle]="layerStyle()">
68946
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.6", type: PresentationTransitionOverlayComponent, isStandalone: true, selector: "pptx-presentation-transition-overlay", inputs: { outgoingSlide: { classPropertyName: "outgoingSlide", publicName: "outgoingSlide", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, transition: { classPropertyName: "transition", publicName: "transition", isSignal: true, isRequired: true, transformFunction: null }, templateElements: { classPropertyName: "templateElements", publicName: "templateElements", isSignal: true, isRequired: false, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, durationMs: { classPropertyName: "durationMs", publicName: "durationMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { complete: "complete" }, host: { attributes: { "data-pptx-transition-overlay": "" } }, ngImport: i0, template: `
68947
+ <div
68948
+ class="pptx-ng-transition-layer"
68949
+ data-pptx-transition-layer="outgoing"
68950
+ [ngStyle]="layerStyle()"
68951
+ >
68725
68952
  <div [ngStyle]="slideBoxStyle()">
68726
68953
  <pptx-slide-canvas
68727
68954
  [slide]="layerSlide()"
@@ -68736,8 +68963,12 @@ class PresentationTransitionOverlayComponent {
68736
68963
  }
68737
68964
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: PresentationTransitionOverlayComponent, decorators: [{
68738
68965
  type: Component,
68739
- args: [{ selector: 'pptx-presentation-transition-overlay', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgStyle, SlideCanvasComponent], template: `
68740
- <div class="pptx-ng-transition-layer" [ngStyle]="layerStyle()">
68966
+ args: [{ selector: 'pptx-presentation-transition-overlay', host: { 'data-pptx-transition-overlay': '' }, standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgStyle, SlideCanvasComponent], template: `
68967
+ <div
68968
+ class="pptx-ng-transition-layer"
68969
+ data-pptx-transition-layer="outgoing"
68970
+ [ngStyle]="layerStyle()"
68971
+ >
68741
68972
  <div [ngStyle]="slideBoxStyle()">
68742
68973
  <pptx-slide-canvas
68743
68974
  [slide]="layerSlide()"
@@ -73066,6 +73297,7 @@ class RibbonFileSectionComponent {
73066
73297
  class="pptx-rb-pill"
73067
73298
  [disabled]="slideCount() === 0"
73068
73299
  (click)="save.emit()"
73300
+ [attr.aria-label]="'pptx.file.saveAsPptx' | translate"
73069
73301
  [title]="'pptx.ribbon.saveAsPptx' | translate"
73070
73302
  >
73071
73303
  {{ 'pptx.toolbar.save' | translate }}
@@ -73171,6 +73403,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
73171
73403
  class="pptx-rb-pill"
73172
73404
  [disabled]="slideCount() === 0"
73173
73405
  (click)="save.emit()"
73406
+ [attr.aria-label]="'pptx.file.saveAsPptx' | translate"
73174
73407
  [title]="'pptx.ribbon.saveAsPptx' | translate"
73175
73408
  >
73176
73409
  {{ 'pptx.toolbar.save' | translate }}
@@ -76880,7 +77113,7 @@ class RibbonComponent {
76880
77113
  />
76881
77114
 
76882
77115
  <!-- ── Tab bar ───────────────────────────────────────────────────── -->
76883
- <div class="flex items-center border-b border-border/60 px-1">
77116
+ <div role="tablist" class="flex items-center border-b border-border/60 px-1">
76884
77117
  <!-- Scrollable tab strip: on narrow widths the tabs scroll instead of
76885
77118
  clipping (mirrors React's max-md:overflow-x-auto scrollbar-none),
76886
77119
  while the Record/Share actions and collapse toggle stay pinned. -->
@@ -76888,6 +77121,8 @@ class RibbonComponent {
76888
77121
  @for (t of tabs; track t.id) {
76889
77122
  <button
76890
77123
  type="button"
77124
+ role="tab"
77125
+ [attr.aria-selected]="activeTab() === t.id"
76891
77126
  (click)="activeTab.set(t.id)"
76892
77127
  class="relative whitespace-nowrap px-3.5 py-2 text-[12px] font-medium transition-colors"
76893
77128
  [ngClass]="
@@ -76915,29 +77150,39 @@ class RibbonComponent {
76915
77150
  <span>{{ 'pptx.titleBar.record' | translate }}</span>
76916
77151
  </button>
76917
77152
  }
76918
- <button
76919
- type="button"
76920
- class="relative inline-flex items-center gap-1 whitespace-nowrap rounded-sm px-2.5 py-1 text-[11px] font-medium text-white transition-colors"
76921
- [ngClass]="
76922
- collabConnected()
76923
- ? 'bg-green-600 hover:bg-green-500'
76924
- : 'bg-primary hover:bg-primary/90'
76925
- "
76926
- [title]="
77153
+ <div
77154
+ role="status"
77155
+ [attr.aria-label]="
76927
77156
  collabConnected()
76928
- ? ('pptx.toolbar.sharingUsers' | translate: { count: connectedCount() })
76929
- : ('pptx.toolbar.share' | translate)
77157
+ ? ('pptx.collaboration.statusAriaLabel'
77158
+ | translate: { status: 'pptx.collaboration.status.connected' | translate })
77159
+ : null
76930
77160
  "
76931
- [attr.aria-label]="'pptx.toolbar.share' | translate"
76932
- (click)="share.emit()"
76933
77161
  >
76934
- <svg lucideShare2 class="h-3.5 w-3.5"></svg>
76935
- <span>{{
76936
- collabConnected()
76937
- ? ('pptx.toolbar.sharingCount' | translate: { count: connectedCount() })
76938
- : ('pptx.toolbar.share' | translate)
76939
- }}</span>
76940
- </button>
77162
+ <button
77163
+ type="button"
77164
+ class="relative inline-flex items-center gap-1 whitespace-nowrap rounded-sm px-2.5 py-1 text-[11px] font-medium text-white transition-colors"
77165
+ [ngClass]="
77166
+ collabConnected()
77167
+ ? 'bg-green-600 hover:bg-green-500'
77168
+ : 'bg-primary hover:bg-primary/90'
77169
+ "
77170
+ [title]="
77171
+ collabConnected()
77172
+ ? ('pptx.toolbar.sharingUsers' | translate: { count: connectedCount() })
77173
+ : ('pptx.toolbar.share' | translate)
77174
+ "
77175
+ [attr.aria-label]="'pptx.toolbar.share' | translate"
77176
+ (click)="share.emit()"
77177
+ >
77178
+ <svg lucideShare2 class="h-3.5 w-3.5"></svg>
77179
+ <span>{{
77180
+ collabConnected()
77181
+ ? ('pptx.toolbar.sharingCount' | translate: { count: connectedCount() })
77182
+ : ('pptx.toolbar.share' | translate)
77183
+ }}</span>
77184
+ </button>
77185
+ </div>
76941
77186
  </div>
76942
77187
 
76943
77188
  <button
@@ -77186,7 +77431,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
77186
77431
  />
77187
77432
 
77188
77433
  <!-- ── Tab bar ───────────────────────────────────────────────────── -->
77189
- <div class="flex items-center border-b border-border/60 px-1">
77434
+ <div role="tablist" class="flex items-center border-b border-border/60 px-1">
77190
77435
  <!-- Scrollable tab strip: on narrow widths the tabs scroll instead of
77191
77436
  clipping (mirrors React's max-md:overflow-x-auto scrollbar-none),
77192
77437
  while the Record/Share actions and collapse toggle stay pinned. -->
@@ -77194,6 +77439,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
77194
77439
  @for (t of tabs; track t.id) {
77195
77440
  <button
77196
77441
  type="button"
77442
+ role="tab"
77443
+ [attr.aria-selected]="activeTab() === t.id"
77197
77444
  (click)="activeTab.set(t.id)"
77198
77445
  class="relative whitespace-nowrap px-3.5 py-2 text-[12px] font-medium transition-colors"
77199
77446
  [ngClass]="
@@ -77221,29 +77468,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
77221
77468
  <span>{{ 'pptx.titleBar.record' | translate }}</span>
77222
77469
  </button>
77223
77470
  }
77224
- <button
77225
- type="button"
77226
- class="relative inline-flex items-center gap-1 whitespace-nowrap rounded-sm px-2.5 py-1 text-[11px] font-medium text-white transition-colors"
77227
- [ngClass]="
77228
- collabConnected()
77229
- ? 'bg-green-600 hover:bg-green-500'
77230
- : 'bg-primary hover:bg-primary/90'
77231
- "
77232
- [title]="
77471
+ <div
77472
+ role="status"
77473
+ [attr.aria-label]="
77233
77474
  collabConnected()
77234
- ? ('pptx.toolbar.sharingUsers' | translate: { count: connectedCount() })
77235
- : ('pptx.toolbar.share' | translate)
77475
+ ? ('pptx.collaboration.statusAriaLabel'
77476
+ | translate: { status: 'pptx.collaboration.status.connected' | translate })
77477
+ : null
77236
77478
  "
77237
- [attr.aria-label]="'pptx.toolbar.share' | translate"
77238
- (click)="share.emit()"
77239
77479
  >
77240
- <svg lucideShare2 class="h-3.5 w-3.5"></svg>
77241
- <span>{{
77242
- collabConnected()
77243
- ? ('pptx.toolbar.sharingCount' | translate: { count: connectedCount() })
77244
- : ('pptx.toolbar.share' | translate)
77245
- }}</span>
77246
- </button>
77480
+ <button
77481
+ type="button"
77482
+ class="relative inline-flex items-center gap-1 whitespace-nowrap rounded-sm px-2.5 py-1 text-[11px] font-medium text-white transition-colors"
77483
+ [ngClass]="
77484
+ collabConnected()
77485
+ ? 'bg-green-600 hover:bg-green-500'
77486
+ : 'bg-primary hover:bg-primary/90'
77487
+ "
77488
+ [title]="
77489
+ collabConnected()
77490
+ ? ('pptx.toolbar.sharingUsers' | translate: { count: connectedCount() })
77491
+ : ('pptx.toolbar.share' | translate)
77492
+ "
77493
+ [attr.aria-label]="'pptx.toolbar.share' | translate"
77494
+ (click)="share.emit()"
77495
+ >
77496
+ <svg lucideShare2 class="h-3.5 w-3.5"></svg>
77497
+ <span>{{
77498
+ collabConnected()
77499
+ ? ('pptx.toolbar.sharingCount' | translate: { count: connectedCount() })
77500
+ : ('pptx.toolbar.share' | translate)
77501
+ }}</span>
77502
+ </button>
77503
+ </div>
77247
77504
  </div>
77248
77505
 
77249
77506
  <button
@@ -85035,9 +85292,9 @@ class ViewerInspectorPanelService {
85035
85292
  case 'selection':
85036
85293
  return 'pptx.selectionPane.title';
85037
85294
  case 'element':
85038
- return 'pptx.viewer.elementProperties';
85295
+ return 'pptx.inspector.properties';
85039
85296
  case 'slide':
85040
- return 'pptx.viewer.slideProperties';
85297
+ return 'pptx.inspector.properties';
85041
85298
  default:
85042
85299
  return '';
85043
85300
  }
@@ -86705,6 +86962,7 @@ class PowerPointViewerComponent {
86705
86962
  -->
86706
86963
  @if (inspectorPanel.visibleInspectorKind(); as kind) {
86707
86964
  <aside
86965
+ data-pptx-inspector
86708
86966
  class="pptx-ng-inspector-host"
86709
86967
  [attr.aria-label]="inspectorPanel.inspectorLabel() | translate"
86710
86968
  [style.transform]="
@@ -87382,6 +87640,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
87382
87640
  -->
87383
87641
  @if (inspectorPanel.visibleInspectorKind(); as kind) {
87384
87642
  <aside
87643
+ data-pptx-inspector
87385
87644
  class="pptx-ng-inspector-host"
87386
87645
  [attr.aria-label]="inspectorPanel.inspectorLabel() | translate"
87387
87646
  [style.transform]="