pptx-angular-viewer 4.5.0 → 4.6.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.
@@ -1,6 +1,6 @@
1
1
  import { NgStyle, NgTemplateOutlet, NgClass } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { InjectionToken, input, output, inject, computed, ChangeDetectionStrategy, Component, signal, Injectable, DestroyRef, viewChild, effect, Injector, untracked, ElementRef, HostListener, afterNextRender, Renderer2, ViewEncapsulation, CUSTOM_ELEMENTS_SCHEMA, Directive, forwardRef, linkedSignal } from '@angular/core';
3
+ import { InjectionToken, input, output, inject, computed, ChangeDetectionStrategy, Component, signal, Injectable, DestroyRef, viewChild, effect, Injector, afterNextRender, untracked, ElementRef, HostListener, Renderer2, ViewEncapsulation, CUSTOM_ELEMENTS_SCHEMA, Directive, forwardRef, linkedSignal } from '@angular/core';
4
4
  import { TranslateService, TranslatePipe, translate } from '@ngx-translate/core';
5
5
  import { THEME_PRESETS, guideEmuToPx, evaluateCustomGeometryPathData, getShapeClipPath, getAdjustmentAwareClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, evaluateCustomGeometryPaths, customGeometryPathsToSvgSubpaths, evaluatePresetShape, hasShapeProperties, ooxmlGradientAngleToCssDegrees, getShapeType, isImageLikeElement as isImageLikeElement$1, getElementTextContent, getRoundRectRadiusPx as getRoundRectRadiusPx$1, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, getSubstituteFontFamily, parsePanoseString, hasTextProperties, evaluateGuides, deobfuscateFont, detectFontFormat, stripXmlOrderSuffix, orderedXmlKey, parseDataUrlToBytes, sampleFirstPixelColorFromBytes, flattenChartUserShapes, chartDataChangeType, isParetoChartData, resolveDisplayedChartTypeName, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, resolveThemeColorRef, rebuildTableStructureInRawXml, updateCellTextInRawXml, deepCloneData, cloneTemplateElementsBySlideId, cloneSlide, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$1, EMU_PER_PX as EMU_PER_PX$2, DEFAULT_POWERPOINT_TABLE_STYLE_ID, DEFAULT_SCHEME_COLOR_MAP as DEFAULT_SCHEME_COLOR_MAP$1, formatAutoNumberMarker, createAutoNumberSequence, nextAutoNumber, breakAutoNumberRun, ELEMENT_PARAGRAPH_GEOMETRY_KEYS, getLinkedTextBoxSegments, deriveSlideTitle, svgPathToPolygons, THEME_COLOR_SCHEME_KEYS, createBuiltinVariables, resolveCoordinate, getPresetConnectionSites, getConnectorPathGeometry, resolveCustomGeometryToken, resolveCustomGeometryGuideContext, lookupPresetShape, normalizeStShapeType, PptxHandler, styleStroke, strokeFor, fitFontSize, nodeTextStyle, truncate, nodeOpacity, nodeStroke, nodeFill, styleShadow, buildTree, treeWidth, treeDepth, gearPoints, flattenNodes, interpretSmartArtLayout, addSmartArtNode, removeSmartArtNode, demoteSmartArtNode, promoteSmartArtNode, reorderSmartArtNode, createEditorId, makeStoreAwareId, reassignDescendantIds, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, createImageElement, THEME_COLOR_PALETTE_COLUMNS, hexToRgbChannels as hexToRgbChannels$2, rgbToHsl as rgbToHsl$1, renameSlideMaster, deleteSlideMaster, duplicateSlideMaster, insertSlideMaster, renameLayout, deleteLayout, duplicateLayout, insertLayout, detectFileFormat, cloneElement, duplicateElement, resolveModifyVerifierAlgorithmName, verifyModifyPassword, TABLE_STYLE_PART_SEQUENCE, serializePptxToJson, PPTX_JSON_MIME_TYPE, PptxMarkdownConverter, ThemePresets, formatCommentTimestamp as formatCommentTimestamp$1, EncryptedFileError, decodeXmlEntities, parseSignatureXml, groupElements, ungroupElements, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, isZoomElement, SvgExporter, applyThemeToData, reResolveElementColors, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointMarker, setChartDataPointExplosion, getOleSheetGrid, getOleDocumentParagraphs, getOleNestedDeckDetail, applyOleSheetCellEdit, applyOleDocumentParagraphEdit, applyOleNestedDeckElementTextEdit, replaceOleFile, getOleObjectTypeLabel, addSmartArtNodeAsChild, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, normalizeTableStyleGuid, createTableStyleEntry, addTableStyleToMap, deleteTableStyleFromMap, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, TRANSITION_VALID_DIRECTIONS, TRANSITION_PATTERN_OPTIONS, TRANSITION_THRUBLK_TYPES } from 'pptx-viewer-core';
6
6
  import { parse } from 'opentype.js';
@@ -42719,6 +42719,41 @@ class PresentationAnimationController {
42719
42719
  }
42720
42720
  }
42721
42721
 
42722
+ /**
42723
+ * Find the editing canvas's DOM node for a slide element.
42724
+ *
42725
+ * Every binding marks a rendered element with `data-element-id`, but Angular,
42726
+ * Svelte and Vanilla leave that marker on the slides-pane thumbnails too, and
42727
+ * the thumbnail rail sits AHEAD of the main canvas in their DOM. A bare
42728
+ * `document.querySelector('[data-element-id="..."]')` therefore returned the
42729
+ * thumbnail's copy: the ribbon's animation Preview played on a 150px
42730
+ * thumbnail, and the Paste Options toolbar anchored itself to one. The main
42731
+ * canvas is the `[data-pptx-viewport]` subtree in all five bindings, so that
42732
+ * copy wins; anywhere else is only a fallback for hosts without one.
42733
+ *
42734
+ * @module render/canvas-element-node
42735
+ */
42736
+ function idSelector(elementId) {
42737
+ const escaped = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'
42738
+ ? CSS.escape(elementId)
42739
+ : elementId.replace(/["\\]/gu, '\\$&');
42740
+ return `[data-element-id="${escaped}"]`;
42741
+ }
42742
+ /**
42743
+ * The main-canvas node for `elementId`, else (unless `canvasOnly`) the first
42744
+ * node anywhere, else null. Pass `canvasOnly` when a thumbnail copy would be
42745
+ * actively wrong, e.g. anchoring on-canvas chrome to a node that has not
42746
+ * rendered on the canvas yet.
42747
+ */
42748
+ function findCanvasElementNode(root, elementId, options = {}) {
42749
+ const selector = idSelector(elementId);
42750
+ const onCanvas = root.querySelector(`[data-pptx-viewport] ${selector}`);
42751
+ if (onCanvas || options.canvasOnly) {
42752
+ return onCanvas;
42753
+ }
42754
+ return root.querySelector(selector);
42755
+ }
42756
+
42722
42757
  /** Slide size assumed when the stage cannot be measured (detached documents). */
42723
42758
  const FALLBACK_SLIDE_WIDTH$2 = 1280;
42724
42759
  const FALLBACK_SLIDE_HEIGHT$2 = 720;
@@ -42766,7 +42801,8 @@ function playAnimationRibbonPreview(doc, animation) {
42766
42801
  if (!animation) {
42767
42802
  return;
42768
42803
  }
42769
- const target = doc.querySelector(`[data-element-id="${CSS.escape(animation.elementId)}"]`);
42804
+ // The canvas copy, not a slides-pane thumbnail's (see canvas-element-node).
42805
+ const target = findCanvasElementNode(doc, animation.elementId);
42770
42806
  if (!target) {
42771
42807
  return;
42772
42808
  }
@@ -55765,6 +55801,7 @@ const translationsEn = {
55765
55801
  'pptx.options.screenTipStyle.off': "Don't show ScreenTips",
55766
55802
  'pptx.options.general.personalize': 'Personalize your copy of the viewer',
55767
55803
  'pptx.options.general.userName': 'User name',
55804
+ 'pptx.options.lockedByHost': 'This setting is managed by your organization',
55768
55805
  'pptx.options.general.userInitials': 'Initials',
55769
55806
  'pptx.options.general.appearance': 'Viewer theme',
55770
55807
  'pptx.options.general.fonts': 'Fonts',
@@ -93394,6 +93431,107 @@ function mapInlineTextFormatKey(input) {
93394
93431
  }
93395
93432
  }
93396
93433
 
93434
+ /**
93435
+ * Classify the element a key press came from, for {@link ./editor-keymap}.
93436
+ *
93437
+ * Split out of `editor-keymap.ts` (file-size limit) and kept together because
93438
+ * both predicates answer the same question for every binding: "is this key
93439
+ * press aimed at the editor, or at some other control that owns it?"
93440
+ *
93441
+ * @module render/editor-key-target
93442
+ */
93443
+ const FORM_FIELD_TAGS = /^(?:INPUT|TEXTAREA|SELECT)$/u;
93444
+ function asElement$1(target) {
93445
+ const element = target;
93446
+ if (!element || typeof element.tagName !== 'string') {
93447
+ return null;
93448
+ }
93449
+ return element;
93450
+ }
93451
+ /**
93452
+ * True when a key press is the user typing into a field rather than driving the
93453
+ * editor. Kept here so every binding classifies the same targets: a binding that
93454
+ * forgot `<select>` would swallow the arrow keys of its own dropdowns.
93455
+ */
93456
+ function isEditorTextInputTarget(target) {
93457
+ const element = asElement$1(target);
93458
+ if (!element) {
93459
+ return false;
93460
+ }
93461
+ return FORM_FIELD_TAGS.test(element.tagName) || element.isContentEditable === true;
93462
+ }
93463
+ /** The slide canvas: Tab there cycles the selection, PowerPoint-style. */
93464
+ const CANVAS_SELECTOR = '[data-pptx-viewport]';
93465
+ /**
93466
+ * Keyboard-navigable chrome: native controls, ARIA widgets and the containers
93467
+ * that own their own Tab order (dialogs, menus, toolbars, tab lists).
93468
+ */
93469
+ const CONTROL_SELECTOR = [
93470
+ 'button',
93471
+ 'a[href]',
93472
+ 'summary',
93473
+ '[aria-modal="true"]',
93474
+ ...[
93475
+ 'button',
93476
+ 'checkbox',
93477
+ 'combobox',
93478
+ 'dialog',
93479
+ 'alertdialog',
93480
+ 'grid',
93481
+ 'gridcell',
93482
+ 'link',
93483
+ 'listbox',
93484
+ 'menu',
93485
+ 'menubar',
93486
+ 'menuitem',
93487
+ 'menuitemcheckbox',
93488
+ 'menuitemradio',
93489
+ 'option',
93490
+ 'radio',
93491
+ 'slider',
93492
+ 'spinbutton',
93493
+ 'switch',
93494
+ 'tab',
93495
+ 'tablist',
93496
+ 'toolbar',
93497
+ 'tree',
93498
+ 'treeitem',
93499
+ ].map((role) => `[role="${role}"]`),
93500
+ ].join(',');
93501
+ /**
93502
+ * True when a key press came from a focusable chrome control (a ribbon button,
93503
+ * a File-backstage row, a dialog field, a web-component control) rather than
93504
+ * from the slide canvas or the page itself.
93505
+ *
93506
+ * Tab on such a target is the browser's focus navigation and must not be
93507
+ * claimed: when the keymap mapped a bare Tab to selection cycling for every
93508
+ * non-text target, it `preventDefault()`ed Tab on every button in every
93509
+ * binding, so keyboard users could no longer move through the ribbon, the
93510
+ * File backstage or any dialog.
93511
+ */
93512
+ function isEditorControlTarget(target) {
93513
+ const element = asElement$1(target);
93514
+ if (!element) {
93515
+ return false;
93516
+ }
93517
+ const tag = element.tagName.toUpperCase();
93518
+ if (tag === 'BODY' || tag === 'HTML') {
93519
+ return false;
93520
+ }
93521
+ if (typeof element.closest !== 'function') {
93522
+ return false;
93523
+ }
93524
+ if (element.closest(CANVAS_SELECTOR)) {
93525
+ return false;
93526
+ }
93527
+ // A custom element (`pptx-ui-select`, `pptx-ui-search`, ...) hides its real
93528
+ // control in a shadow root, so the event is retargeted to the host.
93529
+ if (tag.includes('-')) {
93530
+ return true;
93531
+ }
93532
+ return Boolean(element.closest(CONTROL_SELECTOR));
93533
+ }
93534
+
93397
93535
  /**
93398
93536
  * The editor keymap: one source of truth for "what does this key do".
93399
93537
  *
@@ -93441,23 +93579,13 @@ const GUARD_DEFAULTS$1 = {
93441
93579
  isEditingText: false,
93442
93580
  isDrawing: false,
93443
93581
  isTextInputTarget: false,
93582
+ isControlTarget: false,
93444
93583
  };
93445
93584
  // ---------------------------------------------------------------------------
93446
93585
  // Target inspection
93447
93586
  // ---------------------------------------------------------------------------
93448
- const FORM_FIELD_TAGS = /^(?:INPUT|TEXTAREA|SELECT)$/u;
93449
- /**
93450
- * True when a key press is the user typing into a field rather than driving the
93451
- * editor. Kept here so every binding classifies the same targets: a binding that
93452
- * forgot `<select>` would swallow the arrow keys of its own dropdowns.
93453
- */
93454
- function isEditorTextInputTarget(target) {
93455
- const element = target;
93456
- if (!element || typeof element.tagName !== 'string') {
93457
- return false;
93458
- }
93459
- return FORM_FIELD_TAGS.test(element.tagName) || element.isContentEditable === true;
93460
- }
93587
+ // `isEditorTextInputTarget` / `isEditorControlTarget` live in
93588
+ // `./editor-key-target` and are re-exported above.
93461
93589
  /** Map an arrow key to a nudge delta in slide pixels, or `null` for other keys. */
93462
93590
  function editorNudgeDelta(key, large) {
93463
93591
  const step = large ? NUDGE_LARGE : NUDGE_SMALL;
@@ -93478,7 +93606,7 @@ function editorNudgeDelta(key, large) {
93478
93606
  // Mapping
93479
93607
  // ---------------------------------------------------------------------------
93480
93608
  /** Nothing matched; hoisted so the common path allocates no object. */
93481
- const NO_ACTION$1 = { action: null };
93609
+ const NO_ACTION$2 = { action: null };
93482
93610
  /**
93483
93611
  * Resolve one key press to an editor command.
93484
93612
  *
@@ -93504,7 +93632,7 @@ function mapEditorKey(input, guard = {}) {
93504
93632
  const state = { ...GUARD_DEFAULTS$1, ...guard };
93505
93633
  const { key } = input;
93506
93634
  if (state.isPresenting || !state.canEdit) {
93507
- return NO_ACTION$1;
93635
+ return NO_ACTION$2;
93508
93636
  }
93509
93637
  // Escape is handled even while inline-editing: it is the way out.
93510
93638
  if (key === 'Escape') {
@@ -93532,7 +93660,7 @@ function mapEditorKey(input, guard = {}) {
93532
93660
  // a foreign input/textarea/select. It shares plain Paste's `canPaste`
93533
93661
  // guard so a host with nothing internal to offer leaves it to the browser.
93534
93662
  if (mod && alt && key.toLowerCase() === 'v' && !state.isTextInputTarget) {
93535
- return state.canPaste === false ? NO_ACTION$1 : { action: 'pasteSpecial' };
93663
+ return state.canPaste === false ? NO_ACTION$2 : { action: 'pasteSpecial' };
93536
93664
  }
93537
93665
  // Alignment, font-size stepping, format painter, hyperlink and clear-format
93538
93666
  // are PowerPoint text commands: their main use is a caret or a text range
@@ -93547,11 +93675,11 @@ function mapEditorKey(input, guard = {}) {
93547
93675
  const liveFormat = resolveLiveFormatChord(key, Boolean(input.shiftKey));
93548
93676
  if (liveFormat) {
93549
93677
  const targetsOurText = state.isEditingText || (state.hasSelection && !state.isTextInputTarget);
93550
- return !state.isDrawing && targetsOurText ? liveFormat : NO_ACTION$1;
93678
+ return !state.isDrawing && targetsOurText ? liveFormat : NO_ACTION$2;
93551
93679
  }
93552
93680
  }
93553
93681
  if (state.isEditingText || state.isDrawing || state.isTextInputTarget) {
93554
- return NO_ACTION$1;
93682
+ return NO_ACTION$2;
93555
93683
  }
93556
93684
  // "?" is Shift+/ on most layouts, so it cannot be gated on `!shiftKey`.
93557
93685
  if (key === '?' && !mod && !alt) {
@@ -93571,15 +93699,16 @@ function mapEditorKey(input, guard = {}) {
93571
93699
  }
93572
93700
  // Tab cycles the selection through the slide's elements when nothing is
93573
93701
  // being typed into; Ctrl+Tab / Cmd+Tab are the browser/OS's own tab
93574
- // switchers and must be left alone.
93575
- if (key === 'Tab' && !mod && !alt) {
93702
+ // switchers and must be left alone. Tab on a chrome control (a ribbon
93703
+ // button, a File backstage row, a dialog field) is focus navigation.
93704
+ if (key === 'Tab' && !mod && !alt && !state.isControlTarget) {
93576
93705
  return { action: input.shiftKey ? 'cycleSelectionPrev' : 'cycleSelectionNext' };
93577
93706
  }
93578
93707
  if (mod && !alt) {
93579
93708
  const chord = resolveChord(key, Boolean(input.shiftKey), state.hasSelection);
93580
93709
  if (chord) {
93581
93710
  if (chord.action === 'paste' && state.canPaste === false) {
93582
- return NO_ACTION$1;
93711
+ return NO_ACTION$2;
93583
93712
  }
93584
93713
  return chord;
93585
93714
  }
@@ -93589,7 +93718,7 @@ function mapEditorKey(input, guard = {}) {
93589
93718
  if (delta) {
93590
93719
  return { action: 'nudge', dx: delta.dx, dy: delta.dy };
93591
93720
  }
93592
- return NO_ACTION$1;
93721
+ return NO_ACTION$2;
93593
93722
  }
93594
93723
  // With nothing selected the horizontal arrows page through the deck, which
93595
93724
  // is what a viewer-first user expects when no element has the keyboard.
@@ -93599,7 +93728,7 @@ function mapEditorKey(input, guard = {}) {
93599
93728
  if (key === 'ArrowRight') {
93600
93729
  return { action: 'nextSlide' };
93601
93730
  }
93602
- return NO_ACTION$1;
93731
+ return NO_ACTION$2;
93603
93732
  }
93604
93733
 
93605
93734
  /**
@@ -93709,7 +93838,7 @@ const GUARD_DEFAULTS = {
93709
93838
  isTextInputTarget: false,
93710
93839
  };
93711
93840
  /** Nothing matched; hoisted so the common path allocates no object. */
93712
- const NO_ACTION = { action: null };
93841
+ const NO_ACTION$1 = { action: null };
93713
93842
  // ---------------------------------------------------------------------------
93714
93843
  // Mapping
93715
93844
  // ---------------------------------------------------------------------------
@@ -93735,21 +93864,21 @@ function mapSlideSorterKey(input, guard = {}) {
93735
93864
  return { action: state.hasMultiSelection ? 'collapseSelection' : 'close' };
93736
93865
  }
93737
93866
  if (state.isTextInputTarget) {
93738
- return NO_ACTION;
93867
+ return NO_ACTION$1;
93739
93868
  }
93740
93869
  if (key === 'Delete' || key === 'Backspace') {
93741
- return state.canEdit ? { action: 'delete' } : NO_ACTION;
93870
+ return state.canEdit ? { action: 'delete' } : NO_ACTION$1;
93742
93871
  }
93743
93872
  if (!(input.ctrlKey || input.metaKey) || input.altKey) {
93744
- return NO_ACTION;
93873
+ return NO_ACTION$1;
93745
93874
  }
93746
93875
  switch (key.toLowerCase()) {
93747
93876
  case 'c':
93748
93877
  return { action: 'copy' };
93749
93878
  case 'v':
93750
- return state.canEdit ? { action: 'paste' } : NO_ACTION;
93879
+ return state.canEdit ? { action: 'paste' } : NO_ACTION$1;
93751
93880
  case 'd':
93752
- return state.canEdit ? { action: 'duplicate' } : NO_ACTION;
93881
+ return state.canEdit ? { action: 'duplicate' } : NO_ACTION$1;
93753
93882
  case 'a':
93754
93883
  return { action: 'selectAll' };
93755
93884
  // The zoom pair is spelled differently by layout and by browser: the key
@@ -93766,7 +93895,7 @@ function mapSlideSorterKey(input, guard = {}) {
93766
93895
  case 'subtract':
93767
93896
  return { action: 'zoomOut' };
93768
93897
  default:
93769
- return NO_ACTION;
93898
+ return NO_ACTION$1;
93770
93899
  }
93771
93900
  }
93772
93901
 
@@ -105576,6 +105705,102 @@ function playFeedbackSound(options) {
105576
105705
  }
105577
105706
  }
105578
105707
 
105708
+ /** Split `<group>.<key>`, rejecting ids that do not name a primitive option. */
105709
+ function parseOptionsSettingId(id) {
105710
+ const dot = id.indexOf('.');
105711
+ if (dot <= 0) {
105712
+ return null;
105713
+ }
105714
+ const group = id.slice(0, dot);
105715
+ const key = id.slice(dot + 1);
105716
+ const defaults = DEFAULT_VIEWER_OPTIONS[group];
105717
+ if (!defaults || !(key in defaults) || Array.isArray(defaults[key])) {
105718
+ return null;
105719
+ }
105720
+ return { group, key };
105721
+ }
105722
+ function entriesOf(values) {
105723
+ return Object.entries(values ?? {}).filter((entry) => entry[1] !== undefined);
105724
+ }
105725
+ /** Write each `<group>.<key>` value into `target` when its type matches the model. */
105726
+ function writeValues(target, values) {
105727
+ for (const [id, value] of entriesOf(values)) {
105728
+ const parsed = parseOptionsSettingId(id);
105729
+ if (!parsed) {
105730
+ continue;
105731
+ }
105732
+ const record = target[parsed.group];
105733
+ if (typeof record[parsed.key] === typeof value) {
105734
+ record[parsed.key] = value;
105735
+ }
105736
+ }
105737
+ }
105738
+ /** `options` with every locked value forced in (a new object; input untouched). */
105739
+ function applyLockedOptions(options, locked) {
105740
+ if (entriesOf(locked).length === 0) {
105741
+ return options;
105742
+ }
105743
+ const next = cloneOptions(options);
105744
+ writeValues(next, locked);
105745
+ return next;
105746
+ }
105747
+ /** The built-in defaults with the host's defaults layered on top. */
105748
+ function buildOptionsBaseline(defaults) {
105749
+ const baseline = cloneOptions(DEFAULT_VIEWER_OPTIONS);
105750
+ writeValues(baseline, defaults);
105751
+ return baseline;
105752
+ }
105753
+ /** True when `<group>.<key>` is locked. */
105754
+ function isOptionLocked(locked, group, key) {
105755
+ return Object.hasOwn(locked ?? {}, `${group}.${key}`);
105756
+ }
105757
+ /**
105758
+ * The sparse diff of `options` against `baseline`, minus locked settings, for
105759
+ * persistence: neither a host default nor a host lock is ever saved as the
105760
+ * user's own choice.
105761
+ */
105762
+ function diffOptionsAgainstBaseline(options, baseline, locked) {
105763
+ const diff = {};
105764
+ for (const group of Object.keys(baseline)) {
105765
+ const base = baseline[group];
105766
+ const current = options[group];
105767
+ for (const key of Object.keys(base)) {
105768
+ if (isOptionLocked(locked, group, key)) {
105769
+ continue;
105770
+ }
105771
+ const changed = Array.isArray(base[key])
105772
+ ? JSON.stringify(base[key]) !== JSON.stringify(current[key])
105773
+ : base[key] !== current[key];
105774
+ if (changed) {
105775
+ (diff[group] ??= {})[key] = current[key];
105776
+ }
105777
+ }
105778
+ }
105779
+ return diff;
105780
+ }
105781
+ /**
105782
+ * Move every setting that still sits at the OLD baseline (and that the user
105783
+ * never saved) onto the NEW baseline, so changing a host default updates
105784
+ * users who have not touched that setting and leaves the rest alone.
105785
+ */
105786
+ function rebaseOptions(options, previousBaseline, nextBaseline, userSaved) {
105787
+ const next = cloneOptions(options);
105788
+ for (const group of Object.keys(nextBaseline)) {
105789
+ const before = previousBaseline[group];
105790
+ const after = nextBaseline[group];
105791
+ const target = next[group];
105792
+ for (const key of Object.keys(after)) {
105793
+ if (Array.isArray(after[key]) || userSaved.has(`${group}.${key}`)) {
105794
+ continue;
105795
+ }
105796
+ if (target[key] === before[key]) {
105797
+ target[key] = after[key];
105798
+ }
105799
+ }
105800
+ }
105801
+ return next;
105802
+ }
105803
+
105579
105804
  function toggle(group, key, labelKey, extra) {
105580
105805
  return { kind: 'toggle', group, key, labelKey, ...extra };
105581
105806
  }
@@ -105968,16 +106193,26 @@ function getViewerOptionsTab(id) {
105968
106193
  function createViewerOptionsStore(init) {
105969
106194
  const persist = init?.persist !== false;
105970
106195
  const seeded = mergeViewerOptions(init?.initial);
106196
+ const stored = persist ? readStoredViewerPrefs().options : undefined;
106197
+ // Settings the user saved before this session: host defaults never
106198
+ // override those (see `setConstraints`).
106199
+ const userSaved = new Set(savedSettingIds(stored));
105971
106200
  // Backed by the shared selectively-subscribable runtime rather than a private
105972
106201
  // listener Set, so consumers can subscribe to one option instead of to "the
105973
106202
  // options" and a multi-field write can land as a single notification.
105974
- const store = createViewerStore(persist ? overlayStored(seeded, readStoredViewerPrefs().options) : seeded);
106203
+ const store = createViewerStore(persist ? overlayStored(seeded, stored) : seeded);
105975
106204
  const options = () => store.getState();
105976
- function commit(next) {
106205
+ let constraints = {};
106206
+ let baseline = buildOptionsBaseline(undefined);
106207
+ function commit(raw) {
106208
+ const next = applyLockedOptions(raw, constraints.locked);
105977
106209
  // Persist before notifying, so a subscriber that reads storage during its
105978
- // callback sees the value it was just told about.
106210
+ // callback sees the value it was just told about. Neither a host default
106211
+ // nor a host lock is persisted as the user's own choice.
105979
106212
  if (persist) {
105980
- writeStoredViewerPrefs({ options: diffViewerOptions(next) });
106213
+ writeStoredViewerPrefs({
106214
+ options: diffOptionsAgainstBaseline(next, baseline, constraints.locked),
106215
+ });
105981
106216
  }
105982
106217
  store.setState(next);
105983
106218
  }
@@ -105985,8 +106220,10 @@ function createViewerOptionsStore(init) {
105985
106220
  getOptions: options,
105986
106221
  setOptions: (next) => commit(cloneOptions(next)),
105987
106222
  setValue: (group, key, value) => {
105988
- const defaults = DEFAULT_VIEWER_OPTIONS[group];
105989
- if (!(key in defaults) || typeof defaults[key] !== typeof value) {
106223
+ const defaults = baseline[group];
106224
+ if (!(key in defaults) ||
106225
+ typeof defaults[key] !== typeof value ||
106226
+ isOptionLocked(constraints.locked, group, key)) {
105990
106227
  return;
105991
106228
  }
105992
106229
  const next = cloneOptions(options());
@@ -106022,19 +106259,32 @@ function createViewerOptionsStore(init) {
106022
106259
  },
106023
106260
  reset: (group) => {
106024
106261
  if (!group) {
106025
- commit(cloneOptions(DEFAULT_VIEWER_OPTIONS));
106262
+ commit(cloneOptions(baseline));
106026
106263
  return;
106027
106264
  }
106028
106265
  const next = cloneOptions(options());
106029
- const defaults = cloneOptions(DEFAULT_VIEWER_OPTIONS);
106266
+ const defaults = cloneOptions(baseline);
106030
106267
  next[group] = defaults[group];
106031
106268
  commit(next);
106032
106269
  },
106033
106270
  subscribe: (listener) => store.subscribe(() => listener(store.getState())),
106034
106271
  subscribeSelector: (selector, listener, isEqual) => store.subscribeSelector(selector, listener, isEqual),
106035
106272
  batch: (write) => store.batch(write),
106273
+ setConstraints: (next) => {
106274
+ const previousBaseline = baseline;
106275
+ constraints = { locked: { ...next.locked }, defaults: { ...next.defaults } };
106276
+ baseline = buildOptionsBaseline(constraints.defaults);
106277
+ commit(rebaseOptions(options(), previousBaseline, baseline, userSaved));
106278
+ },
106279
+ isLocked: (group, key) => isOptionLocked(constraints.locked, group, key),
106036
106280
  };
106037
106281
  }
106282
+ function savedSettingIds(stored) {
106283
+ if (!stored) {
106284
+ return [];
106285
+ }
106286
+ return Object.entries(stored).flatMap(([group, values]) => values && typeof values === 'object' ? Object.keys(values).map((key) => `${group}.${key}`) : []);
106287
+ }
106038
106288
  function overlayStored(base, stored) {
106039
106289
  if (!stored) {
106040
106290
  return base;
@@ -106052,6 +106302,723 @@ function overlayStored(base, stored) {
106052
106302
  return merged;
106053
106303
  }
106054
106304
 
106305
+ /**
106306
+ * Runtime catalogues of every id the customisation model accepts.
106307
+ *
106308
+ * The union types in `customization-types.ts` catch typos at compile time;
106309
+ * these arrays are the same sets as values, for hosts that build a settings
106310
+ * screen of their own, for the docs reference (which is generated from them,
106311
+ * see `customization-reference.ts`), and for the test that fails when an id is
106312
+ * left undocumented. Each literal list carries a compile-time exhaustiveness
106313
+ * check against its union, so a new command id cannot be forgotten here.
106314
+ *
106315
+ * @module render/customization/customization-catalog
106316
+ */
106317
+ function exhaustive() {
106318
+ return (list) => list;
106319
+ }
106320
+ const RIBBON_TAB_IDS = TOOLBAR_TABS.map((tab) => tab.id);
106321
+ const TOOLBAR_BUTTON_IDS = exhaustive()([
106322
+ 'share',
106323
+ 'broadcast',
106324
+ 'export',
106325
+ 'undo',
106326
+ 'redo',
106327
+ 'record',
106328
+ 'notes',
106329
+ 'fullscreen',
106330
+ 'zoom',
106331
+ 'navigation',
106332
+ ]);
106333
+ const OPTIONS_PAGE_IDS = [
106334
+ ...VIEWER_OPTIONS_TABS.map((tab) => tab.id),
106335
+ 'ai',
106336
+ ];
106337
+ const OPTIONS_SECTION_IDS = VIEWER_OPTIONS_TABS.flatMap((tab) => tab.sections.map((section) => `${tab.id}.${section.id}`));
106338
+ function primitiveSettingIds() {
106339
+ const ids = [];
106340
+ for (const group of Object.keys(DEFAULT_VIEWER_OPTIONS)) {
106341
+ const values = DEFAULT_VIEWER_OPTIONS[group];
106342
+ for (const [key, value] of Object.entries(values)) {
106343
+ if (!Array.isArray(value)) {
106344
+ ids.push(`${group}.${key}`);
106345
+ }
106346
+ }
106347
+ }
106348
+ return ids;
106349
+ }
106350
+ const OPTIONS_SETTING_IDS = primitiveSettingIds();
106351
+ const BACKSTAGE_PAGE_IDS = BACKSTAGE_NAV.map((item) => item.id);
106352
+ const BACKSTAGE_CARD_IDS = Object.keys(BACKSTAGE_CARDS);
106353
+ const ELEMENT_CONTEXT_MENU_COMMAND_IDS = exhaustive()([
106354
+ 'copy',
106355
+ 'cut',
106356
+ 'paste',
106357
+ 'duplicate',
106358
+ 'edit-text',
106359
+ 'bring-forward',
106360
+ 'send-backward',
106361
+ 'bring-front',
106362
+ 'send-back',
106363
+ 'ai-ask',
106364
+ 'ai-fix',
106365
+ 'comment',
106366
+ 'hyperlink',
106367
+ 'table-insert-row-above',
106368
+ 'table-insert-row-below',
106369
+ 'table-delete-row',
106370
+ 'table-insert-col-left',
106371
+ 'table-insert-col-right',
106372
+ 'table-delete-col',
106373
+ 'table-merge-selected',
106374
+ 'table-merge-right',
106375
+ 'table-merge-down',
106376
+ 'table-split',
106377
+ 'group',
106378
+ 'ungroup',
106379
+ 'save-as-picture',
106380
+ 'edit-alt-text',
106381
+ 'size-and-position',
106382
+ 'format-shape',
106383
+ 'delete',
106384
+ ]);
106385
+ const CANVAS_CONTEXT_MENU_COMMAND_IDS = exhaustive()([
106386
+ 'paste',
106387
+ 'layout',
106388
+ 'reset-slide',
106389
+ 'format-background',
106390
+ 'grid-and-guides',
106391
+ 'ruler',
106392
+ ]);
106393
+ const EDITOR_SHORTCUT_ACTION_IDS = exhaustive()([
106394
+ 'undo',
106395
+ 'redo',
106396
+ 'copy',
106397
+ 'cut',
106398
+ 'paste',
106399
+ 'duplicate',
106400
+ 'delete',
106401
+ 'selectAll',
106402
+ 'group',
106403
+ 'ungroup',
106404
+ 'nudge',
106405
+ 'prevSlide',
106406
+ 'nextSlide',
106407
+ 'escape',
106408
+ 'find',
106409
+ 'findReplace',
106410
+ 'toggleShortcuts',
106411
+ 'alignLeft',
106412
+ 'alignCenter',
106413
+ 'alignRight',
106414
+ 'alignJustify',
106415
+ 'increaseFontSize',
106416
+ 'decreaseFontSize',
106417
+ 'copyFormat',
106418
+ 'pasteFormat',
106419
+ 'newSlide',
106420
+ 'hyperlink',
106421
+ 'clearFormatting',
106422
+ 'cycleSelectionNext',
106423
+ 'cycleSelectionPrev',
106424
+ 'pasteSpecial',
106425
+ ]);
106426
+ const VIEWER_PANEL_IDS = exhaustive()([
106427
+ 'statusBar',
106428
+ 'slidesPane',
106429
+ 'inspector',
106430
+ 'notes',
106431
+ 'quickAccessToolbar',
106432
+ 'titleBar',
106433
+ ]);
106434
+ const VIEWER_FEATURE_IDS = exhaustive()([
106435
+ 'ai',
106436
+ 'collaboration',
106437
+ 'comments',
106438
+ 'presentMode',
106439
+ ]);
106440
+ const VIEWER_DIALOG_IDS = exhaustive()([
106441
+ 'options',
106442
+ 'share',
106443
+ 'broadcast',
106444
+ 'print',
106445
+ 'export',
106446
+ ]);
106447
+ const VIEWER_EXPORT_FORMAT_IDS = exhaustive()([
106448
+ 'pdf',
106449
+ 'png',
106450
+ 'video',
106451
+ 'gif',
106452
+ 'json',
106453
+ 'copyImage',
106454
+ ]);
106455
+
106456
+ /**
106457
+ * Merge `patch` over `base`, one level deep: each section object (`ribbon`,
106458
+ * `options`, `backstage`, `contextMenu`, `keyboard`) merges field by field,
106459
+ * and within a section a list or record in `patch` REPLACES the one in
106460
+ * `base`. Top-level lists (`hiddenPanels`, `disabledFeatures`, ...) replace
106461
+ * too. A field explicitly set to `undefined` in `patch` clears it.
106462
+ */
106463
+ function mergeCustomization(base, patch) {
106464
+ const next = { ...base };
106465
+ for (const key of Object.keys(patch)) {
106466
+ const value = patch[key];
106467
+ const current = base[key];
106468
+ if (value !== undefined &&
106469
+ !Array.isArray(value) &&
106470
+ typeof value === 'object' &&
106471
+ current !== undefined &&
106472
+ !Array.isArray(current) &&
106473
+ typeof current === 'object') {
106474
+ next[key] = { ...current, ...value };
106475
+ }
106476
+ else {
106477
+ next[key] = value;
106478
+ }
106479
+ }
106480
+ return next;
106481
+ }
106482
+ /** `list` with `value` added (once) or removed. */
106483
+ function toggleInList(list, value, present) {
106484
+ const current = list ?? [];
106485
+ const has = current.includes(value);
106486
+ if (present === has) {
106487
+ return [...current];
106488
+ }
106489
+ return present ? [...current, value] : current.filter((entry) => entry !== value);
106490
+ }
106491
+ /** `record` with `key` set to `value`, or removed when `value` is undefined. */
106492
+ function withRecordEntry(record, key, value) {
106493
+ const next = { ...record };
106494
+ if (value === undefined) {
106495
+ delete next[key];
106496
+ }
106497
+ else {
106498
+ next[key] = value;
106499
+ }
106500
+ return next;
106501
+ }
106502
+
106503
+ /**
106504
+ * Editor keyboard-shortcut customisation: turning shortcuts off and remapping
106505
+ * them onto other chords, layered over the shared `mapEditorKey` so every
106506
+ * binding keeps a single call site.
106507
+ *
106508
+ * @module render/customization/customization-keymap
106509
+ */
106510
+ /**
106511
+ * Commands a remap cannot move: `nudge` carries a direction and distance per
106512
+ * arrow key, and `escape` must stay the way out of every mode.
106513
+ */
106514
+ const NOT_REMAPPABLE = new Set(['nudge', 'escape']);
106515
+ /** Commands the built-in keymap only fires with a selection. */
106516
+ const SELECTION_GATED = new Set([
106517
+ 'copy',
106518
+ 'cut',
106519
+ 'duplicate',
106520
+ 'delete',
106521
+ 'group',
106522
+ 'ungroup',
106523
+ ]);
106524
+ /**
106525
+ * Parse `Mod+Shift+D` (case-insensitive modifiers, `+` separated; the last
106526
+ * segment is the `KeyboardEvent.key`). Returns `null` for an empty chord.
106527
+ * A literal plus key is written `Mod+Plus`.
106528
+ */
106529
+ function parseShortcutChord(chord) {
106530
+ const parts = chord
106531
+ .split('+')
106532
+ .map((part) => part.trim())
106533
+ .filter((part) => part.length > 0);
106534
+ const rawKey = parts.pop();
106535
+ if (!rawKey) {
106536
+ return null;
106537
+ }
106538
+ const parsed = {
106539
+ key: rawKey.toLowerCase() === 'plus' ? '+' : rawKey,
106540
+ mod: false,
106541
+ ctrl: false,
106542
+ meta: false,
106543
+ alt: false,
106544
+ shift: false,
106545
+ };
106546
+ for (const part of parts) {
106547
+ switch (part.toLowerCase()) {
106548
+ case 'mod':
106549
+ case 'cmdorctrl':
106550
+ parsed.mod = true;
106551
+ break;
106552
+ case 'ctrl':
106553
+ case 'control':
106554
+ parsed.ctrl = true;
106555
+ break;
106556
+ case 'meta':
106557
+ case 'cmd':
106558
+ parsed.meta = true;
106559
+ break;
106560
+ case 'alt':
106561
+ case 'option':
106562
+ parsed.alt = true;
106563
+ break;
106564
+ case 'shift':
106565
+ parsed.shift = true;
106566
+ break;
106567
+ default:
106568
+ return null;
106569
+ }
106570
+ }
106571
+ return parsed;
106572
+ }
106573
+ /** True when a key press is `chord`. Letter keys compare case-insensitively. */
106574
+ function matchesShortcutChord(input, chord) {
106575
+ const ctrl = Boolean(input.ctrlKey);
106576
+ const meta = Boolean(input.metaKey);
106577
+ if (chord.mod) {
106578
+ if (!(ctrl || meta) || (chord.ctrl && !ctrl) || (chord.meta && !meta)) {
106579
+ return false;
106580
+ }
106581
+ }
106582
+ else if (ctrl !== chord.ctrl || meta !== chord.meta) {
106583
+ return false;
106584
+ }
106585
+ if (Boolean(input.altKey) !== chord.alt) {
106586
+ return false;
106587
+ }
106588
+ // A shifted symbol ("?") is typed WITH Shift, so Shift is implied there.
106589
+ const shiftImplied = chord.key.length === 1 && !/[a-z0-9]/iu.test(chord.key);
106590
+ if (!shiftImplied && Boolean(input.shiftKey) !== chord.shift) {
106591
+ return false;
106592
+ }
106593
+ return input.key.toLowerCase() === chord.key.toLowerCase();
106594
+ }
106595
+ /** Normalise the keyboard slice of a customisation. */
106596
+ function resolveKeyboardCustomization(keyboard) {
106597
+ const remap = new Map();
106598
+ for (const [action, value] of Object.entries(keyboard?.remap ?? {})) {
106599
+ if (value === undefined || NOT_REMAPPABLE.has(action)) {
106600
+ continue;
106601
+ }
106602
+ const chords = (typeof value === 'string' ? [value] : value)
106603
+ .map(parseShortcutChord)
106604
+ .filter((chord) => chord !== null);
106605
+ remap.set(action, chords);
106606
+ }
106607
+ return {
106608
+ disableAll: keyboard?.disableAll === true,
106609
+ disabled: new Set(keyboard?.disabled ?? []),
106610
+ remap,
106611
+ };
106612
+ }
106613
+ const NO_ACTION = { action: null };
106614
+ function remappedAction(input, guard, keyboard) {
106615
+ for (const [action, chords] of keyboard.remap) {
106616
+ if (keyboard.disabled.has(action) || !chords.some((c) => matchesShortcutChord(input, c))) {
106617
+ continue;
106618
+ }
106619
+ if (SELECTION_GATED.has(action) && !guard.hasSelection) {
106620
+ return null;
106621
+ }
106622
+ return action;
106623
+ }
106624
+ return null;
106625
+ }
106626
+ /**
106627
+ * `mapEditorKey` with the host's keyboard customisation applied: disabled
106628
+ * commands never fire, remapped commands answer to their new chord(s) instead
106629
+ * of the built-in one, and `disableAll` silences the editor keymap entirely.
106630
+ * The built-in mode and typing gates still apply to remapped chords.
106631
+ */
106632
+ function mapCustomizedEditorKey(input, guard = {}, keyboard) {
106633
+ if (!keyboard) {
106634
+ return mapEditorKey(input, guard);
106635
+ }
106636
+ if (keyboard.disableAll) {
106637
+ return NO_ACTION;
106638
+ }
106639
+ const blocked = guard.isPresenting === true ||
106640
+ guard.canEdit === false ||
106641
+ guard.isEditingText === true ||
106642
+ guard.isDrawing === true ||
106643
+ guard.isTextInputTarget === true;
106644
+ if (!blocked && keyboard.remap.size > 0) {
106645
+ const action = remappedAction(input, guard, keyboard);
106646
+ if (action) {
106647
+ return { action };
106648
+ }
106649
+ }
106650
+ const result = mapEditorKey(input, guard);
106651
+ if (result.action &&
106652
+ (keyboard.disabled.has(result.action) || keyboard.remap.has(result.action))) {
106653
+ return NO_ACTION;
106654
+ }
106655
+ return result;
106656
+ }
106657
+
106658
+ /** Which toolbar button, File page and card each dialog owns. */
106659
+ const DIALOG_ENTRY_POINTS = {
106660
+ options: { actions: [], pages: ['options'], cards: [] },
106661
+ share: { actions: ['share'], pages: ['share'], cards: ['share'] },
106662
+ broadcast: { actions: ['broadcast'], pages: [], cards: [] },
106663
+ print: { actions: [], pages: ['print'], cards: ['print'] },
106664
+ export: { actions: ['export'], pages: ['export'], cards: [...VIEWER_EXPORT_FORMAT_IDS] },
106665
+ };
106666
+ function addAll(target, values) {
106667
+ for (const value of values ?? []) {
106668
+ target.add(value);
106669
+ }
106670
+ }
106671
+ function resolveDialogs(customization) {
106672
+ const dialogs = new Set(customization.hiddenDialogs ?? []);
106673
+ const features = new Set(customization.disabledFeatures ?? []);
106674
+ if (features.has('collaboration')) {
106675
+ dialogs.add('share');
106676
+ dialogs.add('broadcast');
106677
+ }
106678
+ const formats = new Set(customization.hiddenExportFormats ?? []);
106679
+ if (VIEWER_EXPORT_FORMAT_IDS.every((id) => formats.has(id))) {
106680
+ dialogs.add('export');
106681
+ }
106682
+ return dialogs;
106683
+ }
106684
+ /** Normalise `customization` (undefined means "customise nothing"). */
106685
+ function resolveCustomization(customization) {
106686
+ const c = customization ?? {};
106687
+ const hiddenActions = new Set();
106688
+ addAll(hiddenActions, c.ribbon?.hiddenTabs);
106689
+ addAll(hiddenActions, c.ribbon?.hiddenButtons);
106690
+ const pages = new Set(c.backstage?.hiddenPages ?? []);
106691
+ const cards = new Set(c.backstage?.hiddenCards ?? []);
106692
+ addAll(cards, c.hiddenExportFormats);
106693
+ const dialogs = resolveDialogs(c);
106694
+ for (const dialog of dialogs) {
106695
+ const entry = DIALOG_ENTRY_POINTS[dialog];
106696
+ addAll(hiddenActions, entry.actions);
106697
+ addAll(pages, entry.pages);
106698
+ addAll(cards, entry.cards);
106699
+ }
106700
+ const features = new Set(c.disabledFeatures ?? []);
106701
+ const elementCommands = new Set(c.contextMenu?.hiddenElementCommands);
106702
+ const optionsPages = new Set(c.options?.hiddenPages ?? []);
106703
+ if (features.has('ai')) {
106704
+ elementCommands.add('ai-ask');
106705
+ elementCommands.add('ai-fix');
106706
+ optionsPages.add('ai');
106707
+ }
106708
+ if (features.has('comments')) {
106709
+ elementCommands.add('comment');
106710
+ }
106711
+ if (features.has('presentMode')) {
106712
+ hiddenActions.add('slideShow');
106713
+ }
106714
+ return {
106715
+ hiddenActions,
106716
+ hiddenOptionsPages: optionsPages,
106717
+ hiddenOptionsSections: new Set(c.options?.hiddenSections ?? []),
106718
+ hiddenSettings: new Set(c.options?.hiddenSettings ?? []),
106719
+ lockedSettings: { ...c.options?.locked },
106720
+ defaultSettings: { ...c.options?.defaults },
106721
+ hiddenBackstagePages: pages,
106722
+ hiddenBackstageCards: cards,
106723
+ hiddenElementCommands: elementCommands,
106724
+ hiddenCanvasCommands: new Set(c.contextMenu?.hiddenCanvasCommands ?? []),
106725
+ elementMenuEnabled: c.contextMenu?.disableElementMenu !== true,
106726
+ canvasMenuEnabled: c.contextMenu?.disableCanvasMenu !== true,
106727
+ hiddenPanels: new Set(c.hiddenPanels ?? []),
106728
+ disabledFeatures: features,
106729
+ hiddenDialogs: dialogs,
106730
+ keyboard: resolveKeyboardCustomization(c.keyboard),
106731
+ };
106732
+ }
106733
+ /** The resolution of "no customisation", shared so it is allocated once. */
106734
+ const EMPTY_RESOLVED_CUSTOMIZATION = resolveCustomization(undefined);
106735
+ /**
106736
+ * The `hiddenActions` list a binding threads through its existing ribbon and
106737
+ * toolbar gates: the legacy `hiddenActions` prop unioned with the ribbon,
106738
+ * dialog and feature rules above. Returns `undefined` when nothing is hidden,
106739
+ * which is what those gates treat as "show everything".
106740
+ */
106741
+ function resolveEffectiveHiddenActions(resolved, legacyHiddenActions) {
106742
+ if (resolved.hiddenActions.size === 0 && !legacyHiddenActions?.length) {
106743
+ return legacyHiddenActions ? [...legacyHiddenActions] : undefined;
106744
+ }
106745
+ const merged = new Set(legacyHiddenActions ?? []);
106746
+ addAll(merged, [...resolved.hiddenActions]);
106747
+ return [...merged];
106748
+ }
106749
+ /** True unless the host removed this chrome region. */
106750
+ function isPanelVisible(resolved, panel) {
106751
+ return !resolved.hiddenPanels.has(panel);
106752
+ }
106753
+ /** True unless the host switched this feature area off. */
106754
+ function isFeatureEnabled(resolved, feature) {
106755
+ return !resolved.disabledFeatures.has(feature);
106756
+ }
106757
+ /** True unless the host removed this dialog (directly, or via a feature). */
106758
+ function isDialogAvailable(resolved, dialog) {
106759
+ return !resolved.hiddenDialogs.has(dialog);
106760
+ }
106761
+
106762
+ function stateOf(customization) {
106763
+ return { customization, resolved: resolveCustomization(customization) };
106764
+ }
106765
+ /** Create the store for one viewer instance, seeded with `initial`. */
106766
+ function createCustomizationController(initial) {
106767
+ const store = createViewerStore(stateOf({ ...initial }));
106768
+ const current = () => store.getState().customization;
106769
+ const set = (next) => store.setState(stateOf(next));
106770
+ const update = (patch) => set(mergeCustomization(current(), patch));
106771
+ const ribbon = (edit) => {
106772
+ const next = { ...current().ribbon };
106773
+ edit(next);
106774
+ update({ ribbon: next });
106775
+ };
106776
+ const options = (edit) => {
106777
+ const next = { ...current().options };
106778
+ edit(next);
106779
+ update({ options: next });
106780
+ };
106781
+ const backstage = (edit) => {
106782
+ const next = { ...current().backstage };
106783
+ edit(next);
106784
+ update({ backstage: next });
106785
+ };
106786
+ const menus = (edit) => {
106787
+ const next = { ...current().contextMenu };
106788
+ edit(next);
106789
+ update({ contextMenu: next });
106790
+ };
106791
+ const keys = (edit) => {
106792
+ const next = { ...current().keyboard };
106793
+ edit(next);
106794
+ update({ keyboard: next });
106795
+ };
106796
+ const api = {
106797
+ getCustomization: current,
106798
+ setCustomization: (next) => set({ ...next }),
106799
+ updateCustomization: update,
106800
+ resetCustomization: () => set({}),
106801
+ hideRibbonTab: (tab) => ribbon((r) => (r.hiddenTabs = toggleInList(r.hiddenTabs, tab, true))),
106802
+ showRibbonTab: (tab) => ribbon((r) => (r.hiddenTabs = toggleInList(r.hiddenTabs, tab, false))),
106803
+ hideToolbarButton: (b) => ribbon((r) => (r.hiddenButtons = toggleInList(r.hiddenButtons, b, true))),
106804
+ showToolbarButton: (b) => ribbon((r) => (r.hiddenButtons = toggleInList(r.hiddenButtons, b, false))),
106805
+ hideOptionsPage: (p) => options((o) => (o.hiddenPages = toggleInList(o.hiddenPages, p, true))),
106806
+ showOptionsPage: (p) => options((o) => (o.hiddenPages = toggleInList(o.hiddenPages, p, false))),
106807
+ hideOptionsSection: (s) => options((o) => (o.hiddenSections = toggleInList(o.hiddenSections, s, true))),
106808
+ showOptionsSection: (s) => options((o) => (o.hiddenSections = toggleInList(o.hiddenSections, s, false))),
106809
+ hideSetting: (s) => options((o) => (o.hiddenSettings = toggleInList(o.hiddenSettings, s, true))),
106810
+ showSetting: (s) => options((o) => (o.hiddenSettings = toggleInList(o.hiddenSettings, s, false))),
106811
+ lockSetting: (s, value, hidden) => options((o) => {
106812
+ o.locked = withRecordEntry(o.locked, s, value);
106813
+ if (hidden !== undefined) {
106814
+ o.hiddenSettings = toggleInList(o.hiddenSettings, s, hidden);
106815
+ }
106816
+ }),
106817
+ unlockSetting: (s) => options((o) => (o.locked = withRecordEntry(o.locked, s, undefined))),
106818
+ setSettingDefault: (s, value) => options((o) => (o.defaults = withRecordEntry(o.defaults, s, value))),
106819
+ hideBackstagePage: (p) => backstage((b) => (b.hiddenPages = toggleInList(b.hiddenPages, p, true))),
106820
+ showBackstagePage: (p) => backstage((b) => (b.hiddenPages = toggleInList(b.hiddenPages, p, false))),
106821
+ hideBackstageCard: (c) => backstage((b) => (b.hiddenCards = toggleInList(b.hiddenCards, c, true))),
106822
+ showBackstageCard: (c) => backstage((b) => (b.hiddenCards = toggleInList(b.hiddenCards, c, false))),
106823
+ hideContextMenuCommand: (c) => menus((m) => (m.hiddenElementCommands = toggleInList(m.hiddenElementCommands, c, true))),
106824
+ showContextMenuCommand: (c) => menus((m) => (m.hiddenElementCommands = toggleInList(m.hiddenElementCommands, c, false))),
106825
+ hideCanvasContextMenuCommand: (c) => menus((m) => (m.hiddenCanvasCommands = toggleInList(m.hiddenCanvasCommands, c, true))),
106826
+ showCanvasContextMenuCommand: (c) => menus((m) => (m.hiddenCanvasCommands = toggleInList(m.hiddenCanvasCommands, c, false))),
106827
+ disableShortcut: (a) => keys((k) => (k.disabled = toggleInList(k.disabled, a, true))),
106828
+ enableShortcut: (a) => keys((k) => (k.disabled = toggleInList(k.disabled, a, false))),
106829
+ remapShortcut: (a, chords) => keys((k) => (k.remap = withRecordEntry(k.remap, a, chords))),
106830
+ setPanelVisible: (panel, visible) => update({ hiddenPanels: toggleInList(current().hiddenPanels, panel, !visible) }),
106831
+ setFeatureEnabled: (feature, enabled) => update({ disabledFeatures: toggleInList(current().disabledFeatures, feature, !enabled) }),
106832
+ setDialogAvailable: (dialog, available) => update({ hiddenDialogs: toggleInList(current().hiddenDialogs, dialog, !available) }),
106833
+ };
106834
+ return {
106835
+ api,
106836
+ getResolved: () => store.getState().resolved,
106837
+ subscribe: (listener) => store.subscribe(listener),
106838
+ };
106839
+ }
106840
+
106841
+ /** The `<group>.<key>` id of a schema control. */
106842
+ function optionsSettingIdOf(control) {
106843
+ return `${control.group}.${control.key}`;
106844
+ }
106845
+ /** True unless the host hid this Options page. */
106846
+ function isOptionsPageVisible(resolved, page) {
106847
+ return !resolved.hiddenOptionsPages.has(page);
106848
+ }
106849
+ /** True when the host locked this setting to a fixed value. */
106850
+ function isSettingLocked(resolved, id) {
106851
+ return Object.hasOwn(resolved.lockedSettings, id);
106852
+ }
106853
+ /** True unless the host hid this setting. */
106854
+ function isSettingVisible(resolved, id) {
106855
+ return !resolved.hiddenSettings.has(id);
106856
+ }
106857
+ function customizeSection(tabId, section, resolved) {
106858
+ if (resolved.hiddenOptionsSections.has(`${tabId}.${section.id}`)) {
106859
+ return null;
106860
+ }
106861
+ const controls = section.controls
106862
+ .filter((control) => isSettingVisible(resolved, optionsSettingIdOf(control)))
106863
+ .map((control) => isSettingLocked(resolved, optionsSettingIdOf(control))
106864
+ ? { ...control, readOnly: true }
106865
+ : control);
106866
+ // A section that lost every control and has no bespoke block is an empty
106867
+ // heading; drop it. One that was empty to begin with keeps its shape.
106868
+ if (controls.length === 0 && section.controls.length > 0 && !section.special) {
106869
+ return null;
106870
+ }
106871
+ return { ...section, controls };
106872
+ }
106873
+ /**
106874
+ * The File > Options tabs to render: hidden pages, sections and settings
106875
+ * removed, locked settings marked `readOnly`. A page that loses every section
106876
+ * (and has no bespoke pane) is removed too. Returns the input unchanged when
106877
+ * nothing about Options is customised, so a memoised render stays stable.
106878
+ */
106879
+ function customizeOptionsTabs(tabs, resolved) {
106880
+ if (resolved.hiddenOptionsPages.size === 0 &&
106881
+ resolved.hiddenOptionsSections.size === 0 &&
106882
+ resolved.hiddenSettings.size === 0 &&
106883
+ Object.keys(resolved.lockedSettings).length === 0) {
106884
+ return tabs;
106885
+ }
106886
+ const result = [];
106887
+ for (const tab of tabs) {
106888
+ if (!isOptionsPageVisible(resolved, tab.id)) {
106889
+ continue;
106890
+ }
106891
+ const sections = tab.sections
106892
+ .map((section) => customizeSection(tab.id, section, resolved))
106893
+ .filter((section) => section !== null);
106894
+ if (sections.length === 0 && tab.sections.length > 0 && !tab.custom) {
106895
+ continue;
106896
+ }
106897
+ result.push({ ...tab, sections });
106898
+ }
106899
+ return result;
106900
+ }
106901
+ /**
106902
+ * Drop hidden entries from a menu and repair its separators: a group that
106903
+ * lost its first entry hands the rule to its next survivor, and the menu never
106904
+ * starts with a rule.
106905
+ */
106906
+ function filterMenuEntries(entries, hidden) {
106907
+ const result = [];
106908
+ let pendingSeparator = false;
106909
+ for (const entry of entries) {
106910
+ if (hidden.has(entry.id)) {
106911
+ pendingSeparator ||= entry.separatorBefore === true;
106912
+ continue;
106913
+ }
106914
+ const separatorBefore = result.length > 0 && (entry.separatorBefore === true || pendingSeparator);
106915
+ pendingSeparator = false;
106916
+ result.push(separatorBefore === (entry.separatorBefore === true) ? entry : { ...entry, separatorBefore });
106917
+ }
106918
+ return result;
106919
+ }
106920
+ /** The element context menu after the host's customisation (empty when disabled). */
106921
+ function customizeContextMenuEntries(entries, resolved) {
106922
+ if (!resolved.elementMenuEnabled) {
106923
+ return [];
106924
+ }
106925
+ return filterMenuEntries(entries, resolved.hiddenElementCommands);
106926
+ }
106927
+ /** The empty-canvas context menu after the host's customisation (empty when disabled). */
106928
+ function customizeCanvasContextMenuEntries(entries, resolved) {
106929
+ if (!resolved.canvasMenuEnabled) {
106930
+ return [];
106931
+ }
106932
+ return filterMenuEntries(entries, resolved.hiddenCanvasCommands);
106933
+ }
106934
+ /** True unless the host hid this File tab page. */
106935
+ function isBackstagePageVisible(resolved, page) {
106936
+ return !resolved.hiddenBackstagePages.has(page);
106937
+ }
106938
+ /** Filter any `{ id: BackstagePage }` list (the nav rail) down to visible pages. */
106939
+ function customizeBackstageNav(items, resolved) {
106940
+ return items.filter((item) => isBackstagePageVisible(resolved, item.id));
106941
+ }
106942
+ /** Filter a page's action cards down to the ones the host kept. */
106943
+ function customizeBackstageCards(cards, resolved) {
106944
+ return cards.filter((card) => !resolved.hiddenBackstageCards.has(card.id));
106945
+ }
106946
+
106947
+ const TOOLBAR_BUTTON_DESCRIPTIONS = {
106948
+ share: 'Share / collaboration button in the tab row and mobile toolbar.',
106949
+ broadcast: 'Broadcast (present online) button.',
106950
+ export: 'Export button and the File > Export page.',
106951
+ undo: 'Undo button in the quick-access strip.',
106952
+ redo: 'Redo button in the quick-access strip.',
106953
+ record: 'Record button and the Record ribbon tab.',
106954
+ notes: 'Notes toggle in the status bar.',
106955
+ fullscreen: 'Full-screen toggle.',
106956
+ zoom: 'The zoom cluster (zoom in, zoom out, fit).',
106957
+ navigation: 'The previous / next slide cluster.',
106958
+ };
106959
+ const VIEWER_PANEL_DESCRIPTIONS = {
106960
+ statusBar: 'The status bar under the canvas (slide counter, zoom, view buttons).',
106961
+ slidesPane: 'The slide thumbnail rail on the left.',
106962
+ inspector: 'The format / properties inspector on the right.',
106963
+ notes: 'The speaker-notes panel under the canvas.',
106964
+ quickAccessToolbar: 'The quick-access strip in the title bar (save, undo, redo, ...).',
106965
+ titleBar: 'The title bar above the ribbon (file name, quick access, account).',
106966
+ };
106967
+ const VIEWER_FEATURE_DESCRIPTIONS = {
106968
+ ai: 'The AI assistant: toolbar toggle, chat panel, AI context-menu entries, AI Options page.',
106969
+ collaboration: 'Real-time collaboration: Share and Broadcast buttons, dialogs and File pages.',
106970
+ comments: 'Commenting: the Add Comment context-menu entry.',
106971
+ presentMode: 'Slide-show entry points: the Slide Show ribbon tab.',
106972
+ };
106973
+ const VIEWER_DIALOG_DESCRIPTIONS = {
106974
+ options: 'File > Options (the Settings dialog) and the File tab entry that opens it.',
106975
+ share: 'The Share dialog, its toolbar button, File > Share page and card.',
106976
+ broadcast: 'The Broadcast dialog and its button.',
106977
+ print: 'The Print dialog, File > Print page and card.',
106978
+ export: 'File > Export page, its cards and the Export button.',
106979
+ };
106980
+ const VIEWER_EXPORT_FORMAT_DESCRIPTIONS = {
106981
+ pdf: 'Export to PDF.',
106982
+ png: 'Export the current slide as PNG.',
106983
+ video: 'Export the deck as a video.',
106984
+ gif: 'Export the deck as an animated GIF.',
106985
+ json: 'Export the parsed deck as JSON.',
106986
+ copyImage: 'Copy the current slide to the clipboard as an image.',
106987
+ };
106988
+ const EDITOR_SHORTCUT_DESCRIPTIONS = {
106989
+ undo: 'Undo (Ctrl/Cmd+Z).',
106990
+ redo: 'Redo (Ctrl/Cmd+Y, Ctrl/Cmd+Shift+Z).',
106991
+ copy: 'Copy the selection (Ctrl/Cmd+C).',
106992
+ cut: 'Cut the selection (Ctrl/Cmd+X).',
106993
+ paste: 'Paste (Ctrl/Cmd+V).',
106994
+ duplicate: 'Duplicate the selection (Ctrl/Cmd+D).',
106995
+ delete: 'Delete the selection (Delete, Backspace).',
106996
+ selectAll: 'Select every element on the slide (Ctrl/Cmd+A).',
106997
+ group: 'Group the selection (Ctrl/Cmd+G).',
106998
+ ungroup: 'Ungroup (Ctrl/Cmd+Shift+G).',
106999
+ nudge: 'Move the selection with the arrow keys (disable only; not remappable).',
107000
+ prevSlide: 'Previous slide (ArrowLeft with nothing selected).',
107001
+ nextSlide: 'Next slide (ArrowRight with nothing selected).',
107002
+ escape: 'Escape: leave the current mode (disable only; not remappable).',
107003
+ find: 'Find (Ctrl/Cmd+F).',
107004
+ findReplace: 'Find and replace (Ctrl/Cmd+H).',
107005
+ toggleShortcuts: 'Keyboard-shortcut reference (?, Ctrl/Cmd+/).',
107006
+ alignLeft: 'Align text left (Ctrl/Cmd+L).',
107007
+ alignCenter: 'Center text (Ctrl/Cmd+E).',
107008
+ alignRight: 'Align text right (Ctrl/Cmd+R).',
107009
+ alignJustify: 'Justify text (Ctrl/Cmd+J).',
107010
+ increaseFontSize: 'Increase font size (Ctrl/Cmd+Shift+>).',
107011
+ decreaseFontSize: 'Decrease font size (Ctrl/Cmd+Shift+<).',
107012
+ copyFormat: 'Copy formatting (Ctrl/Cmd+Shift+C).',
107013
+ pasteFormat: 'Paste formatting (Ctrl/Cmd+Shift+V).',
107014
+ newSlide: 'New slide (Ctrl/Cmd+M).',
107015
+ hyperlink: 'Insert or edit a hyperlink (Ctrl/Cmd+K).',
107016
+ clearFormatting: 'Clear character formatting (Ctrl/Cmd+Space).',
107017
+ cycleSelectionNext: 'Select the next element (Tab).',
107018
+ cycleSelectionPrev: 'Select the previous element (Shift+Tab).',
107019
+ pasteSpecial: 'Paste Special (Ctrl/Cmd+Alt+V).',
107020
+ };
107021
+
106055
107022
  function rect(x, y, width, height, rx) {
106056
107023
  return {
106057
107024
  tag: 'rect',
@@ -108869,7 +109836,7 @@ function resetThreeRendererHostForTests() {
108869
109836
  }
108870
109837
 
108871
109838
  const loaders = {
108872
- chart: async () => (await import('./pptx-angular-viewer-chart-3d-view-scene-cJkRFjnr.mjs')).mountChart3DView,
109839
+ chart: async () => (await import('./pptx-angular-viewer-chart-3d-view-scene-BvVx5_I3.mjs')).mountChart3DView,
108873
109840
  smartart: async () => (await import('./pptx-angular-viewer-view-scene-C5oUG9yl.mjs')).mountSmartArt3DView,
108874
109841
  };
108875
109842
  /** Resolve the scene factory for a spec kind. */
@@ -116270,7 +117237,7 @@ function createLocalStorageBackend(namespace) {
116270
117237
  /** Try IndexedDB first; fall back to localStorage on any failure. */
116271
117238
  async function resolveBackend(dbName, namespace) {
116272
117239
  try {
116273
- const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-DbiE0pR5.mjs');
117240
+ const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-NpaCpp0C.mjs');
116274
117241
  const db = await openChatDb(dbName);
116275
117242
  return createIdbBackend(db);
116276
117243
  }
@@ -120887,6 +121854,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
120887
121854
  args: [{ selector: 'pptx-custom-shows', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe, LucideX], template: "@if (open()) {\n\t<!-- Backdrop -->\n\t<div class=\"pptx-ng-cs-backdrop\" aria-hidden=\"true\" (click)=\"close.emit()\"></div>\n\n\t<!-- Dialog -->\n\t<div class=\"pptx-ng-cs-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"pptx-cs-title\">\n\t\t<header class=\"pptx-ng-cs-header\">\n\t\t\t<h2 id=\"pptx-cs-title\" class=\"pptx-ng-cs-title\">\n\t\t\t\t{{ 'pptx.customShows.title' | translate }}\n\t\t\t</h2>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"pptx-ng-cs-close\"\n\t\t\t\t[attr.aria-label]=\"'pptx.customShows.closeDialog' | translate\"\n\t\t\t\t(click)=\"close.emit()\"\n\t\t\t>\n\t\t\t\t<svg lucideX class=\"h-4 w-4\"></svg>\n\t\t\t</button>\n\t\t</header>\n\n\t\t<div class=\"pptx-ng-cs-body\">\n\t\t\t<!-- Existing shows list -->\n\t\t\t<section class=\"pptx-ng-cs-section\">\n\t\t\t\t<h3 class=\"pptx-ng-cs-section-title\">\n\t\t\t\t\t{{ 'pptx.customShows.savedShows' | translate }}\n\t\t\t\t\t@if (customShows().length > 0) {\n\t\t\t\t\t\t<span class=\"pptx-ng-cs-badge\">{{ customShows().length }}</span>\n\t\t\t\t\t}\n\t\t\t\t</h3>\n\n\t\t\t\t@if (customShows().length > 0) {\n\t\t\t\t\t<ul class=\"pptx-ng-cs-show-list\">\n\t\t\t\t\t\t@for (show of customShows(); track show.id) {\n\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-show-row\"\n\t\t\t\t\t\t\t\t[class.pptx-ng-cs-show-row--active]=\"show.id === activeCustomShowId()\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<!-- Edit mode for this show -->\n\t\t\t\t\t\t\t\t@if (editingShowId() === show.id) {\n\t\t\t\t\t\t\t\t\t<div class=\"pptx-ng-cs-edit-row\">\n\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-input\"\n\t\t\t\t\t\t\t\t\t\t\t[value]=\"editDraftName()\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'pptx.customShows.editNameLabel' | translate\"\n\t\t\t\t\t\t\t\t\t\t\t(input)=\"onEditNameInput($event)\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-btn pptx-ng-cs-btn--primary\"\n\t\t\t\t\t\t\t\t\t\t\t[disabled]=\"!canSaveEdit()\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"saveEdit(show.id)\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ 'pptx.customShows.save' | translate }}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button type=\"button\" class=\"pptx-ng-cs-btn\" (click)=\"editingShowId.set(null)\">\n\t\t\t\t\t\t\t\t\t\t\t{{ 'pptx.customShows.cancel' | translate }}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<!-- Slide picker for edit -->\n\t\t\t\t\t\t\t\t\t<div class=\"pptx-ng-cs-slide-picker\">\n\t\t\t\t\t\t\t\t\t\t@for (slide of slides(); track slide.id; let i = $index) {\n\t\t\t\t\t\t\t\t\t\t\t<label class=\"pptx-ng-cs-slide-option\">\n\t\t\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t[checked]=\"editDraftSlideIds().includes(slide.id)\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t(change)=\"toggleEditSlide(slide.id)\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>{{ slideLabel(slide, i) }}</span>\n\t\t\t\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t<div class=\"pptx-ng-cs-show-info\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-cs-show-name\">{{ show.name }}</span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-cs-show-meta\">\n\t\t\t\t\t\t\t\t\t\t\t{{\n\t\t\t\t\t\t\t\t\t\t\t\t'pptx.customShows.slideCount' | translate: { count: show.slideIds.length }\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div class=\"pptx-ng-cs-show-actions\">\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-btn\"\n\t\t\t\t\t\t\t\t\t\t\t[class.pptx-ng-cs-btn--active]=\"show.id === activeCustomShowId()\"\n\t\t\t\t\t\t\t\t\t\t\t[title]=\"\n\t\t\t\t\t\t\t\t\t\t\t\t(show.id === activeCustomShowId()\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'pptx.customShows.unsetActive'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'pptx.customShows.setActive'\n\t\t\t\t\t\t\t\t\t\t\t\t) | translate\n\t\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"onToggleActive(show.id)\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{\n\t\t\t\t\t\t\t\t\t\t\t\t(show.id === activeCustomShowId()\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'pptx.customShows.active'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'pptx.customShows.setActiveShort'\n\t\t\t\t\t\t\t\t\t\t\t\t) | translate\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-btn\"\n\t\t\t\t\t\t\t\t\t\t\t[title]=\"'pptx.customShows.editShow' | translate\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"startEdit(show)\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ 'pptx.customShows.edit' | translate }}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-cs-btn pptx-ng-cs-btn--danger\"\n\t\t\t\t\t\t\t\t\t\t\t[title]=\"'pptx.customShows.deleteShow' | translate\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"remove.emit(show.id)\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ 'pptx.customShows.delete' | translate }}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t}\n\t\t\t\t\t</ul>\n\t\t\t\t} @else {\n\t\t\t\t\t<p class=\"pptx-ng-cs-empty\">{{ 'pptx.customShows.empty' | translate }}</p>\n\t\t\t\t}\n\t\t\t</section>\n\n\t\t\t<!-- Create new show form -->\n\t\t\t<section class=\"pptx-ng-cs-section\">\n\t\t\t\t<h3 class=\"pptx-ng-cs-section-title\">{{ 'pptx.customShows.createNew' | translate }}</h3>\n\t\t\t\t<div class=\"pptx-ng-cs-create-form\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"pptx-ng-cs-input\"\n\t\t\t\t\t\t[placeholder]=\"'pptx.customShows.namePlaceholder' | translate\"\n\t\t\t\t\t\t[value]=\"draftName()\"\n\t\t\t\t\t\t[attr.aria-label]=\"'pptx.customShows.newNameLabel' | translate\"\n\t\t\t\t\t\t(input)=\"onDraftNameInput($event)\"\n\t\t\t\t\t/>\n\n\t\t\t\t\t@if (slides().length > 0) {\n\t\t\t\t\t\t<div class=\"pptx-ng-cs-slide-picker\">\n\t\t\t\t\t\t\t@for (slide of slides(); track slide.id; let i = $index) {\n\t\t\t\t\t\t\t\t<label class=\"pptx-ng-cs-slide-option\">\n\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t[checked]=\"draftSlideIds().includes(slide.id)\"\n\t\t\t\t\t\t\t\t\t\t(change)=\"toggleDraftSlide(slide.id)\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t<span>{{ slideLabel(slide, i) }}</span>\n\t\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"pptx-ng-cs-btn pptx-ng-cs-btn--primary\"\n\t\t\t\t\t\t[disabled]=\"!canCreate()\"\n\t\t\t\t\t\t(click)=\"submitCreate()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{{ 'pptx.customShows.create' | translate }}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t</div>\n\n\t\t<footer class=\"pptx-ng-cs-footer\">\n\t\t\t<button type=\"button\" class=\"pptx-ng-cs-btn\" (click)=\"close.emit()\">\n\t\t\t\t{{ 'pptx.customShows.close' | translate }}\n\t\t\t</button>\n\t\t</footer>\n\t</div>\n}\n", styles: [":host{display:contents}.pptx-ng-cs-backdrop{position:fixed;inset:0;background:#00000080;z-index:200}.pptx-ng-cs-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:201;width:min(540px,94vw);max-height:80vh;display:flex;flex-direction:column;background:var(--pptx-card, #111827);color:var(--pptx-foreground, #f3f4f6);border:1px solid var(--pptx-border, #374151);border-radius:12px;box-shadow:0 20px 60px #0009;font-family:system-ui,sans-serif}.pptx-ng-cs-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--pptx-border, #374151);flex-shrink:0}.pptx-ng-cs-title{margin:0;font-size:15px;font-weight:600}.pptx-ng-cs-close{background:transparent;border:none;color:var(--pptx-muted-foreground, #9ca3af);cursor:pointer;font-size:16px;padding:2px 6px;border-radius:4px}.pptx-ng-cs-close:hover{background:var(--pptx-accent, #1f2937);color:var(--pptx-foreground, #f3f4f6)}.pptx-ng-cs-body{flex:1 1 auto;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:20px;min-height:0}.pptx-ng-cs-section{display:flex;flex-direction:column;gap:10px}.pptx-ng-cs-section-title{margin:0;font-size:13px;font-weight:600;color:var(--pptx-muted-foreground, #9ca3af);text-transform:uppercase;letter-spacing:.05em;display:flex;align-items:center;gap:6px}.pptx-ng-cs-badge{background:var(--pptx-primary, #6366f1);color:#fff;border-radius:10px;padding:1px 7px;font-size:11px;font-weight:700}.pptx-ng-cs-show-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.pptx-ng-cs-show-row{padding:10px 12px;border:1px solid var(--pptx-border, #374151);border-radius:8px;display:flex;flex-direction:column;gap:8px}.pptx-ng-cs-show-row--active{border-color:var(--pptx-primary, #6366f1);background:color-mix(in srgb,var(--pptx-primary, #6366f1) 10%,transparent)}.pptx-ng-cs-show-info{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.pptx-ng-cs-show-name{font-size:13px;font-weight:600}.pptx-ng-cs-show-meta{font-size:11px;color:var(--pptx-muted-foreground, #9ca3af)}.pptx-ng-cs-show-actions{display:flex;gap:6px;flex-wrap:wrap}.pptx-ng-cs-edit-row{display:flex;gap:6px;align-items:center;flex-wrap:wrap}.pptx-ng-cs-input{flex:1 1 auto;min-width:120px;padding:6px 10px;border-radius:6px;border:1px solid var(--pptx-border, #374151);background:var(--pptx-background, #030712);color:inherit;font:inherit;font-size:13px}.pptx-ng-cs-slide-picker{display:flex;flex-direction:column;gap:4px;max-height:160px;overflow-y:auto;padding:6px 8px;border:1px solid var(--pptx-border, #374151);border-radius:6px;background:var(--pptx-background, #030712)}.pptx-ng-cs-slide-option{display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer;padding:2px 0}.pptx-ng-cs-empty{font-size:13px;color:var(--pptx-muted-foreground, #9ca3af);margin:0}.pptx-ng-cs-create-form{display:flex;flex-direction:column;gap:10px}.pptx-ng-cs-btn{font-size:12px;padding:5px 12px;border-radius:6px;border:1px solid var(--pptx-border, #374151);background:transparent;color:inherit;cursor:pointer;white-space:nowrap}.pptx-ng-cs-btn:hover{background:var(--pptx-accent, #1f2937)}.pptx-ng-cs-btn--primary{background:var(--pptx-primary, #6366f1);border-color:var(--pptx-primary, #6366f1);color:#fff;align-self:flex-start}.pptx-ng-cs-btn--primary:hover:not(:disabled){opacity:.9}.pptx-ng-cs-btn--primary:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-cs-btn--danger{color:#f87171;border-color:#f87171}.pptx-ng-cs-btn--danger:hover{background:#f871711a}.pptx-ng-cs-btn--active{background:color-mix(in srgb,var(--pptx-primary, #6366f1) 20%,transparent);border-color:var(--pptx-primary, #6366f1);color:var(--pptx-primary, #6366f1)}.pptx-ng-cs-btn:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-cs-footer{display:flex;justify-content:flex-end;padding:12px 20px;border-top:1px solid var(--pptx-border, #374151);flex-shrink:0}\n"] }]
120888
121855
  }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: false }] }], customShows: [{ type: i0.Input, args: [{ isSignal: true, alias: "customShows", required: false }] }], activeCustomShowId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeCustomShowId", required: false }] }], create: [{ type: i0.Output, args: ["create"] }], remove: [{ type: i0.Output, args: ["remove"] }], update: [{ type: i0.Output, args: ["update"] }], setActive: [{ type: i0.Output, args: ["setActive"] }], close: [{ type: i0.Output, args: ["close"] }] } });
120889
121856
 
121857
+ /**
121858
+ * Viewport clamping for the Angular right-click menus.
121859
+ *
121860
+ * Both `EditorContextMenuComponent` and `SlideCanvasContextMenuComponent`
121861
+ * were placed at the raw cursor position, so a right-click near the bottom or
121862
+ * right edge of the window painted part of the menu off-screen, where its
121863
+ * lower commands could not be clicked. Svelte and Vanilla already clamped
121864
+ * through the shared `clampFlyoutPosition`; this wires the same decision to
121865
+ * Angular signals.
121866
+ */
121867
+ /**
121868
+ * Must be called from an injection context (a component field initializer):
121869
+ * the menu is measured once after its first render.
121870
+ */
121871
+ function clampedMenuPosition(host, x, y) {
121872
+ const size = signal({ width: 0, height: 0 }, /* @ts-ignore */
121873
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
121874
+ afterNextRender(() => {
121875
+ const menu = host.nativeElement.querySelector('[role="menu"]') ?? host.nativeElement;
121876
+ const rect = menu.getBoundingClientRect();
121877
+ size.set({ width: rect.width, height: rect.height });
121878
+ });
121879
+ const position = computed(() => clampFlyoutPosition({
121880
+ x: x(),
121881
+ y: y(),
121882
+ width: size().width,
121883
+ height: size().height,
121884
+ viewportWidth: typeof window === 'undefined' ? 0 : window.innerWidth,
121885
+ viewportHeight: typeof window === 'undefined' ? 0 : window.innerHeight,
121886
+ }), /* @ts-ignore */
121887
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
121888
+ return {
121889
+ left: computed(() => position().left),
121890
+ top: computed(() => position().top),
121891
+ };
121892
+ }
121893
+
120890
121894
  /**
120891
121895
  * editor-context-menu-context.ts: what the canvas menu is being opened ON.
120892
121896
  *
@@ -123056,6 +124060,106 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
123056
124060
  type: Injectable
123057
124061
  }] });
123058
124062
 
124063
+ /**
124064
+ * viewer-customization.service.ts: the per-viewer owner of the shared UI
124065
+ * customisation model (`ViewerCustomization`, see docs/guide/customization.md).
124066
+ *
124067
+ * Wraps ONE `createCustomizationController` per viewer instance behind an
124068
+ * Angular signal, so every render site (ribbon gates, File > Options, the File
124069
+ * tab, both right-click menus, the editor keymap, the chrome regions) reads the
124070
+ * same `ResolvedCustomization` reactively. It also pushes the resolved locks and
124071
+ * host defaults into the viewer's File > Options store on every change.
124072
+ *
124073
+ * No decision logic lives here: the helpers below only forward to the shared
124074
+ * pure functions, so Angular cannot drift from the other four bindings.
124075
+ *
124076
+ * Provided per viewer through `POWER_POINT_VIEWER_PROVIDERS`. Deep components
124077
+ * inject it optionally (see {@link injectResolvedCustomization}) so they keep
124078
+ * working when mounted outside a viewer, e.g. in unit tests.
124079
+ */
124080
+ /** `inject()` that tolerates a plain `new` outside an injection context. */
124081
+ function tryInject(token) {
124082
+ try {
124083
+ return inject(token, { optional: true });
124084
+ }
124085
+ catch {
124086
+ return null;
124087
+ }
124088
+ }
124089
+ class ViewerCustomizationService {
124090
+ constructor() {
124091
+ this.destroyRef = tryInject(DestroyRef);
124092
+ this.viewerOptions = tryInject(ViewerOptionsService);
124093
+ this.controller = createCustomizationController();
124094
+ /** The imperative helpers every binding's public handle exposes. */
124095
+ this.api = this.controller.api;
124096
+ this._resolved = signal(this.controller.getResolved(), /* @ts-ignore */
124097
+ ...(ngDevMode ? [{ debugName: "_resolved" }] : /* istanbul ignore next */ []));
124098
+ /** The normalised customisation the render sites read. */
124099
+ this.resolved = this._resolved.asReadonly();
124100
+ this.applyConstraints();
124101
+ const unsubscribe = this.controller.subscribe(() => {
124102
+ this._resolved.set(this.controller.getResolved());
124103
+ this.applyConstraints();
124104
+ });
124105
+ this.destroyRef?.onDestroy(unsubscribe);
124106
+ }
124107
+ /**
124108
+ * Follow the host's `customization` input: each new object identity
124109
+ * REPLACES the customisation (including any imperative edits). The initial
124110
+ * `undefined` is not applied, so edits made before the first change
124111
+ * detection survive. Must be called from an injection context.
124112
+ */
124113
+ bindInput(source) {
124114
+ let last;
124115
+ return effect(() => {
124116
+ const next = source();
124117
+ if (next === last) {
124118
+ return;
124119
+ }
124120
+ last = next;
124121
+ untracked(() => this.api.setCustomization(next ?? {}));
124122
+ });
124123
+ }
124124
+ /** The legacy `hiddenActions` list unioned with the customisation. */
124125
+ effectiveHiddenActions(legacy) {
124126
+ return resolveEffectiveHiddenActions(this.resolved(), legacy) ?? [];
124127
+ }
124128
+ panelVisible(panel) {
124129
+ return isPanelVisible(this.resolved(), panel);
124130
+ }
124131
+ featureEnabled(feature) {
124132
+ return isFeatureEnabled(this.resolved(), feature);
124133
+ }
124134
+ dialogAvailable(dialog) {
124135
+ return isDialogAvailable(this.resolved(), dialog);
124136
+ }
124137
+ /** The Quick Access options, switched off when the host hid the strip. */
124138
+ quickAccess(options) {
124139
+ return this.panelVisible('quickAccessToolbar') ? options : { ...options, visible: false };
124140
+ }
124141
+ applyConstraints() {
124142
+ const resolved = this.controller.getResolved();
124143
+ this.viewerOptions?.store.setConstraints({
124144
+ locked: resolved.lockedSettings,
124145
+ defaults: resolved.defaultSettings,
124146
+ });
124147
+ }
124148
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ViewerCustomizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
124149
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ViewerCustomizationService }); }
124150
+ }
124151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ViewerCustomizationService, decorators: [{
124152
+ type: Injectable
124153
+ }], ctorParameters: () => [] });
124154
+ const EMPTY_RESOLVED = signal(EMPTY_RESOLVED_CUSTOMIZATION).asReadonly();
124155
+ /**
124156
+ * The viewer's resolved customisation, or the empty one when the component is
124157
+ * mounted outside a viewer. Call from an injection context.
124158
+ */
124159
+ function injectResolvedCustomization() {
124160
+ return inject(ViewerCustomizationService, { optional: true })?.resolved ?? EMPTY_RESOLVED;
124161
+ }
124162
+
123059
124163
  /**
123060
124164
  * swipe-dismiss.ts: Reusable pointer-drag-to-dismiss gesture for a docked
123061
124165
  * sheet/panel that lives in normal document flow (not a fixed overlay), so a
@@ -123332,19 +124436,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
123332
124436
  * the host is mounted before the listener fires, so `!host.contains(target)`
123333
124437
  * is always correct without any extra first-event guard).
123334
124438
  *
123335
- * Usage:
123336
- * ```html
123337
- * @if (canEdit() && contextMenu(); as m) {
123338
- * <pptx-editor-context-menu
123339
- * [x]="m.x"
123340
- * [y]="m.y"
123341
- * [slideIndex]="activeSlideIndex()"
123342
- * (editHyperlink)="docProperties.showHyperlink.set(true)"
123343
- * (addComment)="openCommentsPanel()"
123344
- * (closed)="contextMenu.set(null)"
123345
- * />
123346
- * }
123347
- * ```
124439
+ * The host's UI customisation (hidden commands, a disabled menu) is applied
124440
+ * through the shared `customizeContextMenuEntries`; an emptied menu renders
124441
+ * nothing. See `PowerPointViewerComponent`'s template for the usage.
123348
124442
  */
123349
124443
  class EditorContextMenuComponent {
123350
124444
  constructor() {
@@ -123390,7 +124484,9 @@ class EditorContextMenuComponent {
123390
124484
  this.editor = inject(EditorStateService);
123391
124485
  this.tableSelection = inject(TableSelectionService, { optional: true });
123392
124486
  this.host = inject(ElementRef);
124487
+ this.position = clampedMenuPosition(this.host, this.x, this.y);
123393
124488
  this.inspectorPanel = inject(ViewerInspectorPanelService);
124489
+ this.customization = injectResolvedCustomization();
123394
124490
  /**
123395
124491
  * The table element + cell selection the menu should act on, or null when the
123396
124492
  * current selection is not a single table with a selected cell. Drives the
@@ -123430,7 +124526,7 @@ class EditorContextMenuComponent {
123430
124526
  /** The menu, as the shared command list builds it for this right-click. */
123431
124527
  this.entries = computed(() => {
123432
124528
  const table = this.tableCtx();
123433
- return buildContextMenuEntries({
124529
+ const built = buildContextMenuEntries({
123434
124530
  elementType: this.selectedElement()?.type ?? null,
123435
124531
  table: table ? tableMenuContext(table.element, table.sel) : null,
123436
124532
  hasMultiSelection: this.editor.selectedIds().length >= 2,
@@ -123438,6 +124534,7 @@ class EditorContextMenuComponent {
123438
124534
  aiEnabled: this.showAiActions(),
123439
124535
  hasClipboard: this.editor.hasClipboard(),
123440
124536
  });
124537
+ return customizeContextMenuEntries(built, this.customization());
123441
124538
  }, /* @ts-ignore */
123442
124539
  ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
123443
124540
  /** Editor operations behind each command id (see the dispatch module). */
@@ -123523,33 +124620,36 @@ class EditorContextMenuComponent {
123523
124620
  }
123524
124621
  }
123525
124622
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: EditorContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
123526
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: EditorContextMenuComponent, isStandalone: true, selector: "pptx-editor-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: true, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: true, transformFunction: null }, slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: true, transformFunction: null }, showAiActions: { classPropertyName: "showAiActions", publicName: "showAiActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", askAi: "askAi", fixAi: "fixAi", editHyperlink: "editHyperlink", addComment: "addComment", editText: "editText", saveAsPicture: "saveAsPicture" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:pointerdown": "onDocumentPointerDown($event)" }, properties: { "style.--pptx-ctx-x": "x() + \"px\"", "style.--pptx-ctx-y": "y() + \"px\"" } }, ngImport: i0, template: `
124623
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: EditorContextMenuComponent, isStandalone: true, selector: "pptx-editor-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: true, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: true, transformFunction: null }, slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: true, transformFunction: null }, showAiActions: { classPropertyName: "showAiActions", publicName: "showAiActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", askAi: "askAi", fixAi: "fixAi", editHyperlink: "editHyperlink", addComment: "addComment", editText: "editText", saveAsPicture: "saveAsPicture" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:pointerdown": "onDocumentPointerDown($event)" }, properties: { "style.--pptx-ctx-x": "position.left() + \"px\"", "style.--pptx-ctx-y": "position.top() + \"px\"" } }, ngImport: i0, template: `
123527
124624
  <!-- data-pptx-context-menu is the neutral cross-binding hook for "this is
123528
124625
  the canvas context menu", alongside the role. -->
123529
- <ul
123530
- class="pptx-ctx__menu"
123531
- data-pptx-context-menu="true"
123532
- role="menu"
123533
- [attr.aria-label]="'pptx.contextMenu.ariaLabel' | translate"
123534
- >
123535
- @for (entry of entries(); track entry.id) {
123536
- @if (entry.separatorBefore) {
123537
- <li role="separator" class="pptx-ctx__divider"></li>
124626
+ <!-- An empty menu (host customisation removed every entry) renders nothing. -->
124627
+ @if (entries().length > 0) {
124628
+ <ul
124629
+ class="pptx-ctx__menu"
124630
+ data-pptx-context-menu="true"
124631
+ role="menu"
124632
+ [attr.aria-label]="'pptx.contextMenu.ariaLabel' | translate"
124633
+ >
124634
+ @for (entry of entries(); track entry.id) {
124635
+ @if (entry.separatorBefore) {
124636
+ <li role="separator" class="pptx-ctx__divider"></li>
124637
+ }
124638
+ <li role="none">
124639
+ <button
124640
+ type="button"
124641
+ class="pptx-ctx__item"
124642
+ [class.pptx-ctx__item--danger]="!!entry.danger"
124643
+ role="menuitem"
124644
+ [disabled]="!!entry.disabled"
124645
+ (click)="run(entry.id)"
124646
+ >
124647
+ {{ entry.labelKey | translate }}
124648
+ </button>
124649
+ </li>
123538
124650
  }
123539
- <li role="none">
123540
- <button
123541
- type="button"
123542
- class="pptx-ctx__item"
123543
- [class.pptx-ctx__item--danger]="!!entry.danger"
123544
- role="menuitem"
123545
- [disabled]="!!entry.disabled"
123546
- (click)="run(entry.id)"
123547
- >
123548
- {{ entry.labelKey | translate }}
123549
- </button>
123550
- </li>
123551
- }
123552
- </ul>
124651
+ </ul>
124652
+ }
123553
124653
  `, isInline: true, styles: [":host{position:fixed;left:var(--pptx-ctx-x, 0px);top:var(--pptx-ctx-y, 0px);z-index:9000;display:block}.pptx-ctx__menu{list-style:none;margin:0;padding:4px 0;min-width:160px;background:var(--pptx-ctx-bg, #252526);color:var(--pptx-ctx-fg, #e0e0e0);border:1px solid var(--pptx-ctx-border, #454545);border-radius:4px;box-shadow:0 4px 12px #0006,0 1px 3px #0000004d;font-size:13px;-webkit-user-select:none;user-select:none}.pptx-ctx__item{display:block;width:100%;padding:5px 14px;background:transparent;border:none;color:inherit;text-align:left;cursor:pointer;font-size:inherit;white-space:nowrap}.pptx-ctx__item:hover:not(:disabled){background:var(--pptx-ctx-hover, #094771);color:var(--pptx-ctx-hover-fg, #ffffff)}.pptx-ctx__item:disabled{opacity:.4;pointer-events:none;cursor:default}.pptx-ctx__item--danger{color:var(--pptx-ctx-danger, #f47c7c)}.pptx-ctx__item--danger:hover:not(:disabled){background:var(--pptx-ctx-danger-hover, #4a1a1a);color:var(--pptx-ctx-danger-fg, #ffaaaa)}.pptx-ctx__divider{height:1px;background:var(--pptx-ctx-divider, #454545);margin:3px 0}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
123554
124654
  }
123555
124655
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: EditorContextMenuComponent, decorators: [{
@@ -123557,33 +124657,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
123557
124657
  args: [{ selector: 'pptx-editor-context-menu', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
123558
124658
  <!-- data-pptx-context-menu is the neutral cross-binding hook for "this is
123559
124659
  the canvas context menu", alongside the role. -->
123560
- <ul
123561
- class="pptx-ctx__menu"
123562
- data-pptx-context-menu="true"
123563
- role="menu"
123564
- [attr.aria-label]="'pptx.contextMenu.ariaLabel' | translate"
123565
- >
123566
- @for (entry of entries(); track entry.id) {
123567
- @if (entry.separatorBefore) {
123568
- <li role="separator" class="pptx-ctx__divider"></li>
124660
+ <!-- An empty menu (host customisation removed every entry) renders nothing. -->
124661
+ @if (entries().length > 0) {
124662
+ <ul
124663
+ class="pptx-ctx__menu"
124664
+ data-pptx-context-menu="true"
124665
+ role="menu"
124666
+ [attr.aria-label]="'pptx.contextMenu.ariaLabel' | translate"
124667
+ >
124668
+ @for (entry of entries(); track entry.id) {
124669
+ @if (entry.separatorBefore) {
124670
+ <li role="separator" class="pptx-ctx__divider"></li>
124671
+ }
124672
+ <li role="none">
124673
+ <button
124674
+ type="button"
124675
+ class="pptx-ctx__item"
124676
+ [class.pptx-ctx__item--danger]="!!entry.danger"
124677
+ role="menuitem"
124678
+ [disabled]="!!entry.disabled"
124679
+ (click)="run(entry.id)"
124680
+ >
124681
+ {{ entry.labelKey | translate }}
124682
+ </button>
124683
+ </li>
123569
124684
  }
123570
- <li role="none">
123571
- <button
123572
- type="button"
123573
- class="pptx-ctx__item"
123574
- [class.pptx-ctx__item--danger]="!!entry.danger"
123575
- role="menuitem"
123576
- [disabled]="!!entry.disabled"
123577
- (click)="run(entry.id)"
123578
- >
123579
- {{ entry.labelKey | translate }}
123580
- </button>
123581
- </li>
123582
- }
123583
- </ul>
124685
+ </ul>
124686
+ }
123584
124687
  `, host: {
123585
- '[style.--pptx-ctx-x]': 'x() + "px"',
123586
- '[style.--pptx-ctx-y]': 'y() + "px"',
124688
+ '[style.--pptx-ctx-x]': 'position.left() + "px"',
124689
+ '[style.--pptx-ctx-y]': 'position.top() + "px"',
123587
124690
  }, styles: [":host{position:fixed;left:var(--pptx-ctx-x, 0px);top:var(--pptx-ctx-y, 0px);z-index:9000;display:block}.pptx-ctx__menu{list-style:none;margin:0;padding:4px 0;min-width:160px;background:var(--pptx-ctx-bg, #252526);color:var(--pptx-ctx-fg, #e0e0e0);border:1px solid var(--pptx-ctx-border, #454545);border-radius:4px;box-shadow:0 4px 12px #0006,0 1px 3px #0000004d;font-size:13px;-webkit-user-select:none;user-select:none}.pptx-ctx__item{display:block;width:100%;padding:5px 14px;background:transparent;border:none;color:inherit;text-align:left;cursor:pointer;font-size:inherit;white-space:nowrap}.pptx-ctx__item:hover:not(:disabled){background:var(--pptx-ctx-hover, #094771);color:var(--pptx-ctx-hover-fg, #ffffff)}.pptx-ctx__item:disabled{opacity:.4;pointer-events:none;cursor:default}.pptx-ctx__item--danger{color:var(--pptx-ctx-danger, #f47c7c)}.pptx-ctx__item--danger:hover:not(:disabled){background:var(--pptx-ctx-danger-hover, #4a1a1a);color:var(--pptx-ctx-danger-fg, #ffaaaa)}.pptx-ctx__divider{height:1px;background:var(--pptx-ctx-divider, #454545);margin:3px 0}\n"] }]
123588
124691
  }], propDecorators: { x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: true }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: true }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: true }] }], showAiActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAiActions", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], askAi: [{ type: i0.Output, args: ["askAi"] }], fixAi: [{ type: i0.Output, args: ["fixAi"] }], editHyperlink: [{ type: i0.Output, args: ["editHyperlink"] }], addComment: [{ type: i0.Output, args: ["addComment"] }], editText: [{ type: i0.Output, args: ["editText"] }], saveAsPicture: [{ type: i0.Output, args: ["saveAsPicture"] }], onEscape: [{
123589
124692
  type: HostListener,
@@ -129827,6 +130930,7 @@ class ChartRendererComponent {
129827
130930
  [attr.font-size]="lbl.fontSize"
129828
130931
  [attr.fill]="lbl.fill"
129829
130932
  [attr.dominant-baseline]="lbl.dominantBaseline ?? 'auto'"
130933
+ [attr.transform]="lbl.transform ?? null"
129830
130934
  >
129831
130935
  {{ lbl.text }}
129832
130936
  </text>
@@ -129883,6 +130987,7 @@ class ChartRendererComponent {
129883
130987
  [attr.font-size]="lbl.fontSize"
129884
130988
  [attr.fill]="lbl.fill"
129885
130989
  [attr.dominant-baseline]="lbl.dominantBaseline ?? 'auto'"
130990
+ [attr.transform]="lbl.transform ?? null"
129886
130991
  >
129887
130992
  {{ lbl.text }}
129888
130993
  </text>
@@ -129902,6 +131007,8 @@ class ChartRendererComponent {
129902
131007
  [attr.fill]="dl.fill"
129903
131008
  [attr.font-weight]="dl.fontWeight ?? 'normal'"
129904
131009
  [attr.dominant-baseline]="dl.dominantBaseline ?? 'auto'"
131010
+ [attr.opacity]="dl.opacity ?? 1"
131011
+ [attr.transform]="dl.transform ?? null"
129905
131012
  >
129906
131013
  {{ dl.text }}
129907
131014
  </text>
@@ -130044,6 +131151,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
130044
131151
  [attr.font-size]="lbl.fontSize"
130045
131152
  [attr.fill]="lbl.fill"
130046
131153
  [attr.dominant-baseline]="lbl.dominantBaseline ?? 'auto'"
131154
+ [attr.transform]="lbl.transform ?? null"
130047
131155
  >
130048
131156
  {{ lbl.text }}
130049
131157
  </text>
@@ -130100,6 +131208,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
130100
131208
  [attr.font-size]="lbl.fontSize"
130101
131209
  [attr.fill]="lbl.fill"
130102
131210
  [attr.dominant-baseline]="lbl.dominantBaseline ?? 'auto'"
131211
+ [attr.transform]="lbl.transform ?? null"
130103
131212
  >
130104
131213
  {{ lbl.text }}
130105
131214
  </text>
@@ -130119,6 +131228,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
130119
131228
  [attr.fill]="dl.fill"
130120
131229
  [attr.font-weight]="dl.fontWeight ?? 'normal'"
130121
131230
  [attr.dominant-baseline]="dl.dominantBaseline ?? 'auto'"
131231
+ [attr.opacity]="dl.opacity ?? 1"
131232
+ [attr.transform]="dl.transform ?? null"
130122
131233
  >
130123
131234
  {{ dl.text }}
130124
131235
  </text>
@@ -139919,7 +141030,11 @@ class MobileMenuSheetComponent {
139919
141030
  /** Open the print dialog. */
139920
141031
  this.print = output();
139921
141032
  // ── Derived row list ──────────────────────────────────────────────────────
139922
- this.rows = computed(() => buildMobileMenuRows({
141033
+ /** Host UI customisation (optional: absent outside a viewer). */
141034
+ this.customization = inject(ViewerCustomizationService, { optional: true });
141035
+ this.rows = computed(() => this.allRows().filter((row) => row.key !== 'print' || this.customization?.dialogAvailable('print') !== false), /* @ts-ignore */
141036
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
141037
+ this.allRows = computed(() => buildMobileMenuRows({
139923
141038
  slideCount: this.slideCount(),
139924
141039
  exporting: this.exporting(),
139925
141040
  showNotes: this.showNotes(),
@@ -139939,7 +141054,7 @@ class MobileMenuSheetComponent {
139939
141054
  savePptx: () => this.savePptx.emit(),
139940
141055
  print: () => this.print.emit(),
139941
141056
  }), /* @ts-ignore */
139942
- ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
141057
+ ...(ngDevMode ? [{ debugName: "allRows" }] : /* istanbul ignore next */ []));
139943
141058
  }
139944
141059
  /**
139945
141060
  * Emit the row's action and close the sheet so the user returns to the
@@ -141791,7 +142906,7 @@ class PasteOptionsToolbarComponent {
141791
142906
  });
141792
142907
  }
141793
142908
  measure(id) {
141794
- const node = document.querySelector(`[data-element-id="${id}"]`);
142909
+ const node = findCanvasElementNode(document, id, { canvasOnly: true });
141795
142910
  if (!node) {
141796
142911
  this.rect.set(null);
141797
142912
  return;
@@ -142370,6 +143485,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
142370
143485
  class PrintService {
142371
143486
  constructor() {
142372
143487
  this.translate = inject(TranslateService);
143488
+ this.customization = inject(ViewerCustomizationService, { optional: true });
142373
143489
  /** Whether the print dialog is currently open. */
142374
143490
  this.isDialogOpen = signal(false, /* @ts-ignore */
142375
143491
  ...(ngDevMode ? [{ debugName: "isDialogOpen" }] : /* istanbul ignore next */ []));
@@ -142377,9 +143493,11 @@ class PrintService {
142377
143493
  this.settings = signal({ ...DEFAULT_PRINT_SETTINGS }, /* @ts-ignore */
142378
143494
  ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
142379
143495
  }
142380
- /** Open the print dialog. */
143496
+ /** Open the print dialog (a no-op when the host removed the `print` dialog). */
142381
143497
  openDialog() {
142382
- this.isDialogOpen.set(true);
143498
+ if (this.customization?.dialogAvailable('print') !== false) {
143499
+ this.isDialogOpen.set(true);
143500
+ }
142383
143501
  }
142384
143502
  /** Close the print dialog. */
142385
143503
  closeDialog() {
@@ -145424,6 +146542,7 @@ class ViewerKeyboardService {
145424
146542
  this.presentationMode = inject(ViewerPresentationModeService);
145425
146543
  this.docProperties = inject(ViewerDocumentPropertiesService);
145426
146544
  this.canvasEditing = inject(ViewerCanvasEditingService, { optional: true });
146545
+ this.customization = inject(ViewerCustomizationService, { optional: true });
145427
146546
  this.host = null;
145428
146547
  }
145429
146548
  /** Wire the host accessors (called once from the component constructor). */
@@ -145440,7 +146559,10 @@ class ViewerKeyboardService {
145440
146559
  // this runs ahead of (and unguarded by) the canEdit/text-input gates
145441
146560
  // `mapEditorKey` applies below. `event.preventDefault()` only on a match:
145442
146561
  // otherwise the browser reloads the page on a bare F5.
145443
- const showAction = mapSlideShowStartKey(event, { isPresenting: host.presenting() });
146562
+ const resolved = this.customization?.resolved() ?? EMPTY_RESOLVED_CUSTOMIZATION;
146563
+ const showAction = isFeatureEnabled(resolved, 'presentMode')
146564
+ ? mapSlideShowStartKey(event, { isPresenting: host.presenting() })
146565
+ : null;
145444
146566
  if (showAction !== null) {
145445
146567
  event.preventDefault();
145446
146568
  if (showAction === 'fromBeginning') {
@@ -145451,7 +146573,7 @@ class ViewerKeyboardService {
145451
146573
  }
145452
146574
  return;
145453
146575
  }
145454
- const { action, dx, dy } = mapEditorKey(event, {
146576
+ const guard = {
145455
146577
  canEdit: host.canEdit(),
145456
146578
  canPaste: this.editor.hasClipboard(),
145457
146579
  isPresenting: host.presenting(),
@@ -145459,7 +146581,9 @@ class ViewerKeyboardService {
145459
146581
  isDrawing: host.isDrawing?.() ?? false,
145460
146582
  isEditingText: host.isEditingText?.() ?? false,
145461
146583
  isTextInputTarget: isEditorTextInputTarget(event.target),
145462
- });
146584
+ isControlTarget: isEditorControlTarget(event.target),
146585
+ };
146586
+ const { action, dx, dy } = mapCustomizedEditorKey(event, guard, resolved.keyboard);
145463
146587
  if (action === null) {
145464
146588
  return;
145465
146589
  }
@@ -146040,6 +147164,7 @@ const POWER_POINT_VIEWER_PROVIDERS = [
146040
147164
  ViewerKeyboardService,
146041
147165
  ViewerMobileSheetService,
146042
147166
  ViewerOptionsService,
147167
+ ViewerCustomizationService,
146043
147168
  ViewerPresentationModeService,
146044
147169
  ViewerThemeGalleryService,
146045
147170
  ViewerTouchGesturesService,
@@ -157568,6 +158693,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
157568
158693
  */
157569
158694
  class RibbonContentSecondaryComponent {
157570
158695
  constructor() {
158696
+ /** Host UI customisation (optional: absent outside a viewer). */
158697
+ this.customization = inject(ViewerCustomizationService, { optional: true });
157571
158698
  this.activeTab = input.required(/* @ts-ignore */
157572
158699
  ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
157573
158700
  this.slideIndex = input(0, /* @ts-ignore */
@@ -157759,9 +158886,11 @@ class RibbonContentSecondaryComponent {
157759
158886
  />
157760
158887
  }
157761
158888
  @case ('help') {
157762
- <button type="button" class="pptx-rb-pill" (click)="openSettings.emit()">
157763
- {{ 'pptx.settings.title' | translate }}
157764
- </button>
158889
+ @if (customization?.dialogAvailable('options') !== false) {
158890
+ <button type="button" class="pptx-rb-pill" (click)="openSettings.emit()">
158891
+ {{ 'pptx.settings.title' | translate }}
158892
+ </button>
158893
+ }
157765
158894
  <button type="button" class="pptx-rb-pill" (click)="openShortcuts.emit()">
157766
158895
  {{ 'pptx.settings.keyboardShortcuts' | translate }}
157767
158896
  </button>
@@ -157887,9 +159016,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
157887
159016
  />
157888
159017
  }
157889
159018
  @case ('help') {
157890
- <button type="button" class="pptx-rb-pill" (click)="openSettings.emit()">
157891
- {{ 'pptx.settings.title' | translate }}
157892
- </button>
159019
+ @if (customization?.dialogAvailable('options') !== false) {
159020
+ <button type="button" class="pptx-rb-pill" (click)="openSettings.emit()">
159021
+ {{ 'pptx.settings.title' | translate }}
159022
+ </button>
159023
+ }
157893
159024
  <button type="button" class="pptx-rb-pill" (click)="openShortcuts.emit()">
157894
159025
  {{ 'pptx.settings.keyboardShortcuts' | translate }}
157895
159026
  </button>
@@ -158986,7 +160117,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
158986
160117
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }] } });
158987
160118
 
158988
160119
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
158989
- const PPTX_ANGULAR_VIEWER_VERSION = "4.4.0";
160120
+ const PPTX_ANGULAR_VIEWER_VERSION = "4.5.0";
158990
160121
 
158991
160122
  /**
158992
160123
  * account-page.component.ts: File > Account content.
@@ -159242,16 +160373,30 @@ class RibbonFileSectionComponent {
159242
160373
  ? (key, params) => this.translate?.instant(key, params) ?? key
159243
160374
  : undefined;
159244
160375
  this.templates = BACKSTAGE_TEMPLATES;
159245
- this.mainNav = computed(() => visibleMainNav(this.hiddenActions()), /* @ts-ignore */
160376
+ this.customization = injectResolvedCustomization();
160377
+ this.mainNav = computed(() => customizeBackstageNav(visibleMainNav(this.hiddenActions()), this.customization()), /* @ts-ignore */
159246
160378
  ...(ngDevMode ? [{ debugName: "mainNav" }] : /* istanbul ignore next */ []));
159247
- this.footerNav = BACKSTAGE_NAV.filter((item) => item.group);
160379
+ this.footerNav = computed(() => customizeBackstageNav(BACKSTAGE_NAV.filter((item) => item.group), this.customization()), /* @ts-ignore */
160380
+ ...(ngDevMode ? [{ debugName: "footerNav" }] : /* istanbul ignore next */ []));
160381
+ /** The page the user picked; see {@link currentPage} for the one shown. */
159248
160382
  this.page = signal('home', /* @ts-ignore */
159249
160383
  ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
160384
+ /** The picked page, or 'home' (else the first visible page) when the host hid it. */
160385
+ this.currentPage = computed(() => {
160386
+ const visible = [...this.mainNav(), ...this.footerNav()].map((item) => item.id);
160387
+ const picked = this.page();
160388
+ if (visible.includes(picked)) {
160389
+ return picked;
160390
+ }
160391
+ return visible.includes('home') ? 'home' : (visible[0] ?? 'home');
160392
+ }, /* @ts-ignore */
160393
+ ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
159250
160394
  this.query = signal('', /* @ts-ignore */
159251
160395
  ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
159252
160396
  this.recent = signal([], /* @ts-ignore */
159253
160397
  ...(ngDevMode ? [{ debugName: "recent" }] : /* istanbul ignore next */ []));
159254
- this.titleKey = computed(() => BACKSTAGE_NAV.find((item) => item.id === this.page())?.labelKey ?? 'pptx.backstage.nav.home', /* @ts-ignore */
160398
+ this.titleKey = computed(() => BACKSTAGE_NAV.find((item) => item.id === this.currentPage())?.labelKey ??
160399
+ 'pptx.backstage.nav.home', /* @ts-ignore */
159255
160400
  ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
159256
160401
  this.visibleRecent = computed(() => {
159257
160402
  const q = this.query().trim().toLowerCase();
@@ -159261,7 +160406,7 @@ class RibbonFileSectionComponent {
159261
160406
  }, /* @ts-ignore */
159262
160407
  ...(ngDevMode ? [{ debugName: "visibleRecent" }] : /* istanbul ignore next */ []));
159263
160408
  this.size = formatBackstageSize;
159264
- this.actions = computed(() => this.pageActions(this.page()), /* @ts-ignore */
160409
+ this.actions = computed(() => this.pageActions(this.currentPage()), /* @ts-ignore */
159265
160410
  ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
159266
160411
  void (async () => this.recent.set(await listBackstageRecentFiles(this.t, this.recentPresentationsCount())))();
159267
160412
  }
@@ -159321,7 +160466,7 @@ class RibbonFileSectionComponent {
159321
160466
  print: this.print,
159322
160467
  share: this.share,
159323
160468
  };
159324
- return backstageCardsFor(page)
160469
+ return customizeBackstageCards(backstageCardsFor(page), this.customization())
159325
160470
  .filter((card) => card.id !== 'saveAsPptm' || this.hasMacros())
159326
160471
  .map((card) => ({
159327
160472
  titleKey: card.titleKey,
@@ -159331,11 +160476,11 @@ class RibbonFileSectionComponent {
159331
160476
  }));
159332
160477
  }
159333
160478
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RibbonFileSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
159334
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RibbonFileSectionComponent, isStandalone: true, selector: "pptx-ribbon-file-section", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, exporting: { classPropertyName: "exporting", publicName: "exporting", isSignal: true, isRequired: false, transformFunction: null }, hasMacros: { classPropertyName: "hasMacros", publicName: "hasMacros", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, recentPresentationsCount: { classPropertyName: "recentPresentationsCount", publicName: "recentPresentationsCount", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", createPresentation: "createPresentation", openFile: "openFile", openRecentFile: "openRecentFile", save: "save", savePpsx: "savePpsx", savePptm: "savePptm", savePpt: "savePpt", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", exportJson: "exportJson", copySlideAsImage: "copySlideAsImage", print: "print", info: "info", signatures: "signatures", replace: "replace", openPassword: "openPassword", openFontEmbedding: "openFontEmbedding", openVersionHistory: "openVersionHistory", share: "share", options: "options" }, host: { classAttribute: "contents" }, ngImport: i0, template: "<div\n\tclass=\"bs\"\n\trole=\"dialog\"\n\taria-modal=\"true\"\n\t[attr.aria-label]=\"'pptx.backstage.title' | translate\"\n>\n\t<aside>\n\t\t<div class=\"back-row\">\n\t\t\t<button\n\t\t\t\tclass=\"back\"\n\t\t\t\ttype=\"button\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.back' | translate\"\n\t\t\t\t(click)=\"close.emit()\"\n\t\t\t>\n\t\t\t\t<pptx-backstage-nav-icon page=\"back\" />\n\t\t\t</button>\n\t\t</div>\n\t\t<nav>\n\t\t\t@for (item of mainNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"page() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"page() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<i></i>\n\t\t\t@for (item of footerNav; track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"page() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"page() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</nav>\n\t</aside>\n\t<main>\n\t\t<h1>{{ (page() === 'home' ? 'pptx.backstage.greeting' : titleKey()) | translate }}</h1>\n\t\t@if (page() === 'home' || page() === 'new') {\n\t\t\t<h2>{{ 'pptx.backstage.newHeading' | translate }}</h2>\n\t\t\t<div class=\"templates\">\n\t\t\t\t@for (template of templates; track template.id) {\n\t\t\t\t\t<button type=\"button\" (click)=\"create(template.id)\">\n\t\t\t\t\t\t<b [style.background]=\"template.preview\"></b\n\t\t\t\t\t\t><strong>{{ template.nameKey | translate }}</strong\n\t\t\t\t\t\t><small>{{ template.descriptionKey | translate }}</small>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (page() === 'home' || page() === 'open') {\n\t\t\t<pptx-ui-search\n\t\t\t\tdata-pptx-search-surface\n\t\t\t\tclass=\"search\"\n\t\t\t\tstyle=\"display: block; width: min(540px, 100%); margin-top: 32px\"\n\t\t\t\tdata-pptx-search-input\n\t\t\t\t[attr.placeholder]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[value]=\"query()\"\n\t\t\t\t(input)=\"query.set($any($event.target).value)\"\n\t\t\t/>\n\t\t\t@if (page() === 'open') {\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(openFile)\">\n\t\t\t\t\t{{ 'pptx.backstage.browseDevice' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<h2>{{ 'pptx.backstage.recentHeading' | translate }}</h2>\n\t\t\t<div class=\"recent\">\n\t\t\t\t<header>\n\t\t\t\t\t<span>{{ 'pptx.backstage.columnName' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnModified' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnSize' | translate }}</span>\n\t\t\t\t</header>\n\t\t\t\t@for (file of visibleRecent(); track file.key) {\n\t\t\t\t\t<button type=\"button\" (click)=\"openRecent(file.key)\">\n\t\t\t\t\t\t<span class=\"name\"\n\t\t\t\t\t\t\t><b>P</b\n\t\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t\t><strong>{{ file.name }}</strong\n\t\t\t\t\t\t\t\t><small>{{ file.location }}</small></span\n\t\t\t\t\t\t\t></span\n\t\t\t\t\t\t><span>{{ date(file.timestamp) }}</span\n\t\t\t\t\t\t><span>{{ size(file.size) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t} @empty {\n\t\t\t\t\t<p>{{ 'pptx.backstage.noRecent' | translate }}</p>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (actions().length) {\n\t\t\t<div class=\"actions\">\n\t\t\t\t@for (action of actions(); track action.titleKey) {\n\t\t\t\t\t<button type=\"button\" (click)=\"run(action.event)\">\n\t\t\t\t\t\t<b aria-hidden=\"true\">{{ action.icon }}</b\n\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t><strong>{{ action.titleKey | translate }}</strong\n\t\t\t\t\t\t\t><small>{{ action.bodyKey | translate }}</small></span\n\t\t\t\t\t\t>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (page() === 'account') {\n\t\t\t<pptx-account-page [accountAuth]=\"accountAuth()\" />\n\t\t}\n\t\t@if (page() === 'options') {\n\t\t\t<section class=\"card\">\n\t\t\t\t<b class=\"avatar\">\u2699</b>\n\t\t\t\t<h2>{{ 'pptx.backstage.optionsTitle' | translate }}</h2>\n\t\t\t\t<p>{{ 'pptx.backstage.optionsBody' | translate }}</p>\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(options)\">\n\t\t\t\t\t{{ 'pptx.backstage.openOptions' | translate }}\n\t\t\t\t</button>\n\t\t\t</section>\n\t\t}\n\t\t<footer>\n\t\t\t{{ fileName() || ('pptx.backstage.untitled' | translate) }} \u00B7\n\t\t\t{{ 'pptx.backstage.savedToBrowser' | translate }}\n\t\t</footer>\n\t</main>\n</div>\n", styles: [":host{font-family:Aptos,Segoe UI,sans-serif}.bs{position:fixed;inset:0;z-index:200;display:flex;background:var(--pptx-background, #fafafa);color:var(--pptx-foreground, #242424)}.bs aside{display:flex;width:148px;flex:none;flex-direction:column;border-right:1px solid var(--pptx-border, #d7d7d7);background:var(--pptx-secondary, #f5eee9)}.back-row{display:flex;height:40px;flex:none;border-bottom:1px solid var(--pptx-border, #ddd)}.back{width:100%;height:40px;border:0;background:none;color:inherit;font-size:22px}.back:hover,nav button:not(.active):hover,.recent>button:hover{background:var(--pptx-accent, #eadfd8)}nav{display:flex;min-height:0;flex:1;flex-direction:column;overflow-y:auto;padding:0 0 8px}nav i{flex:1}nav button{display:flex;min-height:40px;flex:none;align-items:center;gap:12px;padding:0 16px;border:0;border-left:2px solid transparent;background:none;color:inherit;font-size:12px;text-align:left}nav button span{display:grid;width:17px;flex:none;place-items:center;font-size:16px}nav button.active{border-left-color:var(--pptx-primary, #c43e1c);background:var(--pptx-card, #fff);color:var(--pptx-primary, #c43e1c)}main{min-width:0;flex:1;overflow:auto;padding:20px clamp(32px,4vw,72px)}h1{margin:0;font-size:24px;font-weight:600}h2{margin:28px 0 18px;font-size:17px}.templates{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:24px}.templates button{border:0;background:none;color:inherit;text-align:left}.templates button>b{display:block;aspect-ratio:16/9;border:1px solid var(--pptx-border, #ccc);box-shadow:0 1px 2px #0002;transition:.15s}.templates button:hover>b{transform:translateY(-2px);border-color:var(--pptx-primary, #c43e1c);box-shadow:0 7px 18px #0002}.templates strong,.templates small{display:block;overflow:hidden;margin-top:8px;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.templates small{margin-top:2px;color:var(--pptx-muted-foreground, #777);font-size:10px}.primary{margin-top:16px;padding:10px 20px;border:0;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-weight:600}.recent{border-top:1px solid var(--pptx-border, #ddd)}.recent header,.recent>button{display:grid;grid-template-columns:1fr 120px 90px;align-items:center;padding:10px 12px}.recent header{color:var(--pptx-muted-foreground, #666);font-size:11px;font-weight:600}.recent>button{width:100%;border:0;border-top:1px solid var(--pptx-border, #e5e5e5);background:none;color:inherit;font-size:11px;text-align:left}.name{display:flex;min-width:0;align-items:center;gap:12px}.name>b{display:grid;width:32px;height:32px;place-items:center;background:var(--pptx-primary, #d24726);color:var(--pptx-primary-foreground, #fff)}.name strong,.name small{display:block;overflow:hidden;font-size:13px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}.name small,.recent p{color:var(--pptx-muted-foreground, #666);font-size:11px}.recent p{text-align:center}.actions{display:grid;max-width:900px;grid-template-columns:1fr 1fr;gap:20px;margin-top:32px}.actions button{display:flex;min-height:112px;gap:16px;padding:20px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424);text-align:left}.actions button:hover{border-color:var(--pptx-primary, #c43e1c);box-shadow:0 5px 15px #0002}.actions button>b{display:grid;width:40px;height:40px;flex:none;place-items:center;background:var(--pptx-accent, #fbe9e3);color:var(--pptx-primary, #c43e1c)}.actions strong,.actions small{display:block;font-size:15px}.actions small{margin-top:7px;color:var(--pptx-muted-foreground, #666);font-size:12px;line-height:1.5}.card{max-width:760px;margin-top:32px;padding:28px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424)}.avatar{display:grid;width:56px;height:56px;place-items:center;border-radius:50%;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-size:20px}.card p,footer{color:var(--pptx-muted-foreground, #666)}.card p{line-height:1.6}footer{margin-top:48px;font-size:11px}@media(max-width:640px),(pointer:coarse){.bs{flex-direction:column}.bs aside{width:100%;flex-direction:row;align-items:center;overflow-x:auto;border-right:0;border-bottom:1px solid var(--pptx-border, #d7d7d7)}.back-row{width:48px;height:48px;border-bottom:0;border-right:1px solid var(--pptx-border, #ddd)}.back{width:48px;height:48px}nav{flex-direction:row;align-items:center;overflow-y:visible;padding:0}nav i{display:none}nav button{flex-shrink:0;white-space:nowrap;border-left:0;border-bottom:2px solid transparent;padding:0 12px}nav button.active{border-left-color:transparent;border-bottom-color:var(--pptx-primary, #c43e1c)}main{padding:16px}.actions{grid-template-columns:1fr}.recent header,.recent>button{grid-template-columns:1fr 90px}.recent header span:last-child,.recent>button>span:last-child{display:none}}\n"], dependencies: [{ kind: "component", type: BackstageNavIconComponent, selector: "pptx-backstage-nav-icon", inputs: ["page"] }, { kind: "component", type: AccountPageComponent, selector: "pptx-account-page", inputs: ["accountAuth"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
160479
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RibbonFileSectionComponent, isStandalone: true, selector: "pptx-ribbon-file-section", inputs: { fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, exporting: { classPropertyName: "exporting", publicName: "exporting", isSignal: true, isRequired: false, transformFunction: null }, hasMacros: { classPropertyName: "hasMacros", publicName: "hasMacros", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, recentPresentationsCount: { classPropertyName: "recentPresentationsCount", publicName: "recentPresentationsCount", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { close: "close", createPresentation: "createPresentation", openFile: "openFile", openRecentFile: "openRecentFile", save: "save", savePpsx: "savePpsx", savePptm: "savePptm", savePpt: "savePpt", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", exportJson: "exportJson", copySlideAsImage: "copySlideAsImage", print: "print", info: "info", signatures: "signatures", replace: "replace", openPassword: "openPassword", openFontEmbedding: "openFontEmbedding", openVersionHistory: "openVersionHistory", share: "share", options: "options" }, host: { classAttribute: "contents" }, ngImport: i0, template: "<div\n\tclass=\"bs\"\n\trole=\"dialog\"\n\taria-modal=\"true\"\n\t[attr.aria-label]=\"'pptx.backstage.title' | translate\"\n>\n\t<aside>\n\t\t<div class=\"back-row\">\n\t\t\t<button\n\t\t\t\tclass=\"back\"\n\t\t\t\ttype=\"button\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.back' | translate\"\n\t\t\t\t(click)=\"close.emit()\"\n\t\t\t>\n\t\t\t\t<pptx-backstage-nav-icon page=\"back\" />\n\t\t\t</button>\n\t\t</div>\n\t\t<nav>\n\t\t\t@for (item of mainNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"currentPage() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"currentPage() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<i></i>\n\t\t\t@for (item of footerNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"currentPage() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"currentPage() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</nav>\n\t</aside>\n\t<main>\n\t\t<h1>{{ (currentPage() === 'home' ? 'pptx.backstage.greeting' : titleKey()) | translate }}</h1>\n\t\t@if (currentPage() === 'home' || currentPage() === 'new') {\n\t\t\t<h2>{{ 'pptx.backstage.newHeading' | translate }}</h2>\n\t\t\t<div class=\"templates\">\n\t\t\t\t@for (template of templates; track template.id) {\n\t\t\t\t\t<button type=\"button\" (click)=\"create(template.id)\">\n\t\t\t\t\t\t<b [style.background]=\"template.preview\"></b\n\t\t\t\t\t\t><strong>{{ template.nameKey | translate }}</strong\n\t\t\t\t\t\t><small>{{ template.descriptionKey | translate }}</small>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (currentPage() === 'home' || currentPage() === 'open') {\n\t\t\t<pptx-ui-search\n\t\t\t\tdata-pptx-search-surface\n\t\t\t\tclass=\"search\"\n\t\t\t\tstyle=\"display: block; width: min(540px, 100%); margin-top: 32px\"\n\t\t\t\tdata-pptx-search-input\n\t\t\t\t[attr.placeholder]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[value]=\"query()\"\n\t\t\t\t(input)=\"query.set($any($event.target).value)\"\n\t\t\t/>\n\t\t\t@if (currentPage() === 'open') {\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(openFile)\">\n\t\t\t\t\t{{ 'pptx.backstage.browseDevice' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<h2>{{ 'pptx.backstage.recentHeading' | translate }}</h2>\n\t\t\t<div class=\"recent\">\n\t\t\t\t<header>\n\t\t\t\t\t<span>{{ 'pptx.backstage.columnName' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnModified' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnSize' | translate }}</span>\n\t\t\t\t</header>\n\t\t\t\t@for (file of visibleRecent(); track file.key) {\n\t\t\t\t\t<button type=\"button\" (click)=\"openRecent(file.key)\">\n\t\t\t\t\t\t<span class=\"name\"\n\t\t\t\t\t\t\t><b>P</b\n\t\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t\t><strong>{{ file.name }}</strong\n\t\t\t\t\t\t\t\t><small>{{ file.location }}</small></span\n\t\t\t\t\t\t\t></span\n\t\t\t\t\t\t><span>{{ date(file.timestamp) }}</span\n\t\t\t\t\t\t><span>{{ size(file.size) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t} @empty {\n\t\t\t\t\t<p>{{ 'pptx.backstage.noRecent' | translate }}</p>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (actions().length) {\n\t\t\t<div class=\"actions\">\n\t\t\t\t@for (action of actions(); track action.titleKey) {\n\t\t\t\t\t<button type=\"button\" (click)=\"run(action.event)\">\n\t\t\t\t\t\t<b aria-hidden=\"true\">{{ action.icon }}</b\n\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t><strong>{{ action.titleKey | translate }}</strong\n\t\t\t\t\t\t\t><small>{{ action.bodyKey | translate }}</small></span\n\t\t\t\t\t\t>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (currentPage() === 'account') {\n\t\t\t<pptx-account-page [accountAuth]=\"accountAuth()\" />\n\t\t}\n\t\t@if (currentPage() === 'options') {\n\t\t\t<section class=\"card\">\n\t\t\t\t<b class=\"avatar\">\u2699</b>\n\t\t\t\t<h2>{{ 'pptx.backstage.optionsTitle' | translate }}</h2>\n\t\t\t\t<p>{{ 'pptx.backstage.optionsBody' | translate }}</p>\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(options)\">\n\t\t\t\t\t{{ 'pptx.backstage.openOptions' | translate }}\n\t\t\t\t</button>\n\t\t\t</section>\n\t\t}\n\t\t<footer>\n\t\t\t{{ fileName() || ('pptx.backstage.untitled' | translate) }} \u00B7\n\t\t\t{{ 'pptx.backstage.savedToBrowser' | translate }}\n\t\t</footer>\n\t</main>\n</div>\n", styles: [":host{font-family:Aptos,Segoe UI,sans-serif}.bs{position:fixed;inset:0;z-index:200;display:flex;background:var(--pptx-background, #fafafa);color:var(--pptx-foreground, #242424)}.bs aside{display:flex;width:148px;flex:none;flex-direction:column;border-right:1px solid var(--pptx-border, #d7d7d7);background:var(--pptx-secondary, #f5eee9)}.back-row{display:flex;height:40px;flex:none;border-bottom:1px solid var(--pptx-border, #ddd)}.back{width:100%;height:40px;border:0;background:none;color:inherit;font-size:22px}.back:hover,nav button:not(.active):hover,.recent>button:hover{background:var(--pptx-accent, #eadfd8)}nav{display:flex;min-height:0;flex:1;flex-direction:column;overflow-y:auto;padding:0 0 8px}nav i{flex:1}nav button{display:flex;min-height:40px;flex:none;align-items:center;gap:12px;padding:0 16px;border:0;border-left:2px solid transparent;background:none;color:inherit;font-size:12px;text-align:left}nav button span{display:grid;width:17px;flex:none;place-items:center;font-size:16px}nav button.active{border-left-color:var(--pptx-primary, #c43e1c);background:var(--pptx-card, #fff);color:var(--pptx-primary, #c43e1c)}main{min-width:0;flex:1;overflow:auto;padding:20px clamp(32px,4vw,72px)}h1{margin:0;font-size:24px;font-weight:600}h2{margin:28px 0 18px;font-size:17px}.templates{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:24px}.templates button{border:0;background:none;color:inherit;text-align:left}.templates button>b{display:block;aspect-ratio:16/9;border:1px solid var(--pptx-border, #ccc);box-shadow:0 1px 2px #0002;transition:.15s}.templates button:hover>b{transform:translateY(-2px);border-color:var(--pptx-primary, #c43e1c);box-shadow:0 7px 18px #0002}.templates strong,.templates small{display:block;overflow:hidden;margin-top:8px;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.templates small{margin-top:2px;color:var(--pptx-muted-foreground, #777);font-size:10px}.primary{margin-top:16px;padding:10px 20px;border:0;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-weight:600}.recent{border-top:1px solid var(--pptx-border, #ddd)}.recent header,.recent>button{display:grid;grid-template-columns:1fr 120px 90px;align-items:center;padding:10px 12px}.recent header{color:var(--pptx-muted-foreground, #666);font-size:11px;font-weight:600}.recent>button{width:100%;border:0;border-top:1px solid var(--pptx-border, #e5e5e5);background:none;color:inherit;font-size:11px;text-align:left}.name{display:flex;min-width:0;align-items:center;gap:12px}.name>b{display:grid;width:32px;height:32px;place-items:center;background:var(--pptx-primary, #d24726);color:var(--pptx-primary-foreground, #fff)}.name strong,.name small{display:block;overflow:hidden;font-size:13px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}.name small,.recent p{color:var(--pptx-muted-foreground, #666);font-size:11px}.recent p{text-align:center}.actions{display:grid;max-width:900px;grid-template-columns:1fr 1fr;gap:20px;margin-top:32px}.actions button{display:flex;min-height:112px;gap:16px;padding:20px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424);text-align:left}.actions button:hover{border-color:var(--pptx-primary, #c43e1c);box-shadow:0 5px 15px #0002}.actions button>b{display:grid;width:40px;height:40px;flex:none;place-items:center;background:var(--pptx-accent, #fbe9e3);color:var(--pptx-primary, #c43e1c)}.actions strong,.actions small{display:block;font-size:15px}.actions small{margin-top:7px;color:var(--pptx-muted-foreground, #666);font-size:12px;line-height:1.5}.card{max-width:760px;margin-top:32px;padding:28px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424)}.avatar{display:grid;width:56px;height:56px;place-items:center;border-radius:50%;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-size:20px}.card p,footer{color:var(--pptx-muted-foreground, #666)}.card p{line-height:1.6}footer{margin-top:48px;font-size:11px}@media(max-width:640px),(pointer:coarse){.bs{flex-direction:column}.bs aside{width:100%;flex-direction:row;align-items:center;overflow-x:auto;border-right:0;border-bottom:1px solid var(--pptx-border, #d7d7d7)}.back-row{width:48px;height:48px;border-bottom:0;border-right:1px solid var(--pptx-border, #ddd)}.back{width:48px;height:48px}nav{flex-direction:row;align-items:center;overflow-y:visible;padding:0}nav i{display:none}nav button{flex-shrink:0;white-space:nowrap;border-left:0;border-bottom:2px solid transparent;padding:0 12px}nav button.active{border-left-color:transparent;border-bottom-color:var(--pptx-primary, #c43e1c)}main{padding:16px}.actions{grid-template-columns:1fr}.recent header,.recent>button{grid-template-columns:1fr 90px}.recent header span:last-child,.recent>button>span:last-child{display:none}}\n"], dependencies: [{ kind: "component", type: BackstageNavIconComponent, selector: "pptx-backstage-nav-icon", inputs: ["page"] }, { kind: "component", type: AccountPageComponent, selector: "pptx-account-page", inputs: ["accountAuth"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
159335
160480
  }
159336
160481
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RibbonFileSectionComponent, decorators: [{
159337
160482
  type: Component,
159338
- args: [{ selector: 'pptx-ribbon-file-section', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'contents' }, imports: [BackstageNavIconComponent, AccountPageComponent, TranslatePipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div\n\tclass=\"bs\"\n\trole=\"dialog\"\n\taria-modal=\"true\"\n\t[attr.aria-label]=\"'pptx.backstage.title' | translate\"\n>\n\t<aside>\n\t\t<div class=\"back-row\">\n\t\t\t<button\n\t\t\t\tclass=\"back\"\n\t\t\t\ttype=\"button\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.back' | translate\"\n\t\t\t\t(click)=\"close.emit()\"\n\t\t\t>\n\t\t\t\t<pptx-backstage-nav-icon page=\"back\" />\n\t\t\t</button>\n\t\t</div>\n\t\t<nav>\n\t\t\t@for (item of mainNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"page() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"page() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<i></i>\n\t\t\t@for (item of footerNav; track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"page() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"page() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</nav>\n\t</aside>\n\t<main>\n\t\t<h1>{{ (page() === 'home' ? 'pptx.backstage.greeting' : titleKey()) | translate }}</h1>\n\t\t@if (page() === 'home' || page() === 'new') {\n\t\t\t<h2>{{ 'pptx.backstage.newHeading' | translate }}</h2>\n\t\t\t<div class=\"templates\">\n\t\t\t\t@for (template of templates; track template.id) {\n\t\t\t\t\t<button type=\"button\" (click)=\"create(template.id)\">\n\t\t\t\t\t\t<b [style.background]=\"template.preview\"></b\n\t\t\t\t\t\t><strong>{{ template.nameKey | translate }}</strong\n\t\t\t\t\t\t><small>{{ template.descriptionKey | translate }}</small>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (page() === 'home' || page() === 'open') {\n\t\t\t<pptx-ui-search\n\t\t\t\tdata-pptx-search-surface\n\t\t\t\tclass=\"search\"\n\t\t\t\tstyle=\"display: block; width: min(540px, 100%); margin-top: 32px\"\n\t\t\t\tdata-pptx-search-input\n\t\t\t\t[attr.placeholder]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[value]=\"query()\"\n\t\t\t\t(input)=\"query.set($any($event.target).value)\"\n\t\t\t/>\n\t\t\t@if (page() === 'open') {\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(openFile)\">\n\t\t\t\t\t{{ 'pptx.backstage.browseDevice' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<h2>{{ 'pptx.backstage.recentHeading' | translate }}</h2>\n\t\t\t<div class=\"recent\">\n\t\t\t\t<header>\n\t\t\t\t\t<span>{{ 'pptx.backstage.columnName' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnModified' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnSize' | translate }}</span>\n\t\t\t\t</header>\n\t\t\t\t@for (file of visibleRecent(); track file.key) {\n\t\t\t\t\t<button type=\"button\" (click)=\"openRecent(file.key)\">\n\t\t\t\t\t\t<span class=\"name\"\n\t\t\t\t\t\t\t><b>P</b\n\t\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t\t><strong>{{ file.name }}</strong\n\t\t\t\t\t\t\t\t><small>{{ file.location }}</small></span\n\t\t\t\t\t\t\t></span\n\t\t\t\t\t\t><span>{{ date(file.timestamp) }}</span\n\t\t\t\t\t\t><span>{{ size(file.size) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t} @empty {\n\t\t\t\t\t<p>{{ 'pptx.backstage.noRecent' | translate }}</p>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (actions().length) {\n\t\t\t<div class=\"actions\">\n\t\t\t\t@for (action of actions(); track action.titleKey) {\n\t\t\t\t\t<button type=\"button\" (click)=\"run(action.event)\">\n\t\t\t\t\t\t<b aria-hidden=\"true\">{{ action.icon }}</b\n\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t><strong>{{ action.titleKey | translate }}</strong\n\t\t\t\t\t\t\t><small>{{ action.bodyKey | translate }}</small></span\n\t\t\t\t\t\t>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (page() === 'account') {\n\t\t\t<pptx-account-page [accountAuth]=\"accountAuth()\" />\n\t\t}\n\t\t@if (page() === 'options') {\n\t\t\t<section class=\"card\">\n\t\t\t\t<b class=\"avatar\">\u2699</b>\n\t\t\t\t<h2>{{ 'pptx.backstage.optionsTitle' | translate }}</h2>\n\t\t\t\t<p>{{ 'pptx.backstage.optionsBody' | translate }}</p>\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(options)\">\n\t\t\t\t\t{{ 'pptx.backstage.openOptions' | translate }}\n\t\t\t\t</button>\n\t\t\t</section>\n\t\t}\n\t\t<footer>\n\t\t\t{{ fileName() || ('pptx.backstage.untitled' | translate) }} \u00B7\n\t\t\t{{ 'pptx.backstage.savedToBrowser' | translate }}\n\t\t</footer>\n\t</main>\n</div>\n", styles: [":host{font-family:Aptos,Segoe UI,sans-serif}.bs{position:fixed;inset:0;z-index:200;display:flex;background:var(--pptx-background, #fafafa);color:var(--pptx-foreground, #242424)}.bs aside{display:flex;width:148px;flex:none;flex-direction:column;border-right:1px solid var(--pptx-border, #d7d7d7);background:var(--pptx-secondary, #f5eee9)}.back-row{display:flex;height:40px;flex:none;border-bottom:1px solid var(--pptx-border, #ddd)}.back{width:100%;height:40px;border:0;background:none;color:inherit;font-size:22px}.back:hover,nav button:not(.active):hover,.recent>button:hover{background:var(--pptx-accent, #eadfd8)}nav{display:flex;min-height:0;flex:1;flex-direction:column;overflow-y:auto;padding:0 0 8px}nav i{flex:1}nav button{display:flex;min-height:40px;flex:none;align-items:center;gap:12px;padding:0 16px;border:0;border-left:2px solid transparent;background:none;color:inherit;font-size:12px;text-align:left}nav button span{display:grid;width:17px;flex:none;place-items:center;font-size:16px}nav button.active{border-left-color:var(--pptx-primary, #c43e1c);background:var(--pptx-card, #fff);color:var(--pptx-primary, #c43e1c)}main{min-width:0;flex:1;overflow:auto;padding:20px clamp(32px,4vw,72px)}h1{margin:0;font-size:24px;font-weight:600}h2{margin:28px 0 18px;font-size:17px}.templates{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:24px}.templates button{border:0;background:none;color:inherit;text-align:left}.templates button>b{display:block;aspect-ratio:16/9;border:1px solid var(--pptx-border, #ccc);box-shadow:0 1px 2px #0002;transition:.15s}.templates button:hover>b{transform:translateY(-2px);border-color:var(--pptx-primary, #c43e1c);box-shadow:0 7px 18px #0002}.templates strong,.templates small{display:block;overflow:hidden;margin-top:8px;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.templates small{margin-top:2px;color:var(--pptx-muted-foreground, #777);font-size:10px}.primary{margin-top:16px;padding:10px 20px;border:0;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-weight:600}.recent{border-top:1px solid var(--pptx-border, #ddd)}.recent header,.recent>button{display:grid;grid-template-columns:1fr 120px 90px;align-items:center;padding:10px 12px}.recent header{color:var(--pptx-muted-foreground, #666);font-size:11px;font-weight:600}.recent>button{width:100%;border:0;border-top:1px solid var(--pptx-border, #e5e5e5);background:none;color:inherit;font-size:11px;text-align:left}.name{display:flex;min-width:0;align-items:center;gap:12px}.name>b{display:grid;width:32px;height:32px;place-items:center;background:var(--pptx-primary, #d24726);color:var(--pptx-primary-foreground, #fff)}.name strong,.name small{display:block;overflow:hidden;font-size:13px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}.name small,.recent p{color:var(--pptx-muted-foreground, #666);font-size:11px}.recent p{text-align:center}.actions{display:grid;max-width:900px;grid-template-columns:1fr 1fr;gap:20px;margin-top:32px}.actions button{display:flex;min-height:112px;gap:16px;padding:20px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424);text-align:left}.actions button:hover{border-color:var(--pptx-primary, #c43e1c);box-shadow:0 5px 15px #0002}.actions button>b{display:grid;width:40px;height:40px;flex:none;place-items:center;background:var(--pptx-accent, #fbe9e3);color:var(--pptx-primary, #c43e1c)}.actions strong,.actions small{display:block;font-size:15px}.actions small{margin-top:7px;color:var(--pptx-muted-foreground, #666);font-size:12px;line-height:1.5}.card{max-width:760px;margin-top:32px;padding:28px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424)}.avatar{display:grid;width:56px;height:56px;place-items:center;border-radius:50%;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-size:20px}.card p,footer{color:var(--pptx-muted-foreground, #666)}.card p{line-height:1.6}footer{margin-top:48px;font-size:11px}@media(max-width:640px),(pointer:coarse){.bs{flex-direction:column}.bs aside{width:100%;flex-direction:row;align-items:center;overflow-x:auto;border-right:0;border-bottom:1px solid var(--pptx-border, #d7d7d7)}.back-row{width:48px;height:48px;border-bottom:0;border-right:1px solid var(--pptx-border, #ddd)}.back{width:48px;height:48px}nav{flex-direction:row;align-items:center;overflow-y:visible;padding:0}nav i{display:none}nav button{flex-shrink:0;white-space:nowrap;border-left:0;border-bottom:2px solid transparent;padding:0 12px}nav button.active{border-left-color:transparent;border-bottom-color:var(--pptx-primary, #c43e1c)}main{padding:16px}.actions{grid-template-columns:1fr}.recent header,.recent>button{grid-template-columns:1fr 90px}.recent header span:last-child,.recent>button>span:last-child{display:none}}\n"] }]
160483
+ args: [{ selector: 'pptx-ribbon-file-section', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'contents' }, imports: [BackstageNavIconComponent, AccountPageComponent, TranslatePipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div\n\tclass=\"bs\"\n\trole=\"dialog\"\n\taria-modal=\"true\"\n\t[attr.aria-label]=\"'pptx.backstage.title' | translate\"\n>\n\t<aside>\n\t\t<div class=\"back-row\">\n\t\t\t<button\n\t\t\t\tclass=\"back\"\n\t\t\t\ttype=\"button\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.back' | translate\"\n\t\t\t\t(click)=\"close.emit()\"\n\t\t\t>\n\t\t\t\t<pptx-backstage-nav-icon page=\"back\" />\n\t\t\t</button>\n\t\t</div>\n\t\t<nav>\n\t\t\t@for (item of mainNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"currentPage() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"currentPage() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<i></i>\n\t\t\t@for (item of footerNav(); track item.id) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdata-pptx-backstage-nav-item\n\t\t\t\t\t[class.active]=\"currentPage() === item.id\"\n\t\t\t\t\t[attr.aria-current]=\"currentPage() === item.id ? 'page' : null\"\n\t\t\t\t\t(click)=\"selectPage(item.id)\"\n\t\t\t\t>\n\t\t\t\t\t<span><pptx-backstage-nav-icon [page]=\"item.id\" /></span>{{ item.labelKey | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</nav>\n\t</aside>\n\t<main>\n\t\t<h1>{{ (currentPage() === 'home' ? 'pptx.backstage.greeting' : titleKey()) | translate }}</h1>\n\t\t@if (currentPage() === 'home' || currentPage() === 'new') {\n\t\t\t<h2>{{ 'pptx.backstage.newHeading' | translate }}</h2>\n\t\t\t<div class=\"templates\">\n\t\t\t\t@for (template of templates; track template.id) {\n\t\t\t\t\t<button type=\"button\" (click)=\"create(template.id)\">\n\t\t\t\t\t\t<b [style.background]=\"template.preview\"></b\n\t\t\t\t\t\t><strong>{{ template.nameKey | translate }}</strong\n\t\t\t\t\t\t><small>{{ template.descriptionKey | translate }}</small>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (currentPage() === 'home' || currentPage() === 'open') {\n\t\t\t<pptx-ui-search\n\t\t\t\tdata-pptx-search-surface\n\t\t\t\tclass=\"search\"\n\t\t\t\tstyle=\"display: block; width: min(540px, 100%); margin-top: 32px\"\n\t\t\t\tdata-pptx-search-input\n\t\t\t\t[attr.placeholder]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[attr.aria-label]=\"'pptx.backstage.searchPlaceholder' | translate\"\n\t\t\t\t[value]=\"query()\"\n\t\t\t\t(input)=\"query.set($any($event.target).value)\"\n\t\t\t/>\n\t\t\t@if (currentPage() === 'open') {\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(openFile)\">\n\t\t\t\t\t{{ 'pptx.backstage.browseDevice' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<h2>{{ 'pptx.backstage.recentHeading' | translate }}</h2>\n\t\t\t<div class=\"recent\">\n\t\t\t\t<header>\n\t\t\t\t\t<span>{{ 'pptx.backstage.columnName' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnModified' | translate }}</span\n\t\t\t\t\t><span>{{ 'pptx.backstage.columnSize' | translate }}</span>\n\t\t\t\t</header>\n\t\t\t\t@for (file of visibleRecent(); track file.key) {\n\t\t\t\t\t<button type=\"button\" (click)=\"openRecent(file.key)\">\n\t\t\t\t\t\t<span class=\"name\"\n\t\t\t\t\t\t\t><b>P</b\n\t\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t\t><strong>{{ file.name }}</strong\n\t\t\t\t\t\t\t\t><small>{{ file.location }}</small></span\n\t\t\t\t\t\t\t></span\n\t\t\t\t\t\t><span>{{ date(file.timestamp) }}</span\n\t\t\t\t\t\t><span>{{ size(file.size) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t} @empty {\n\t\t\t\t\t<p>{{ 'pptx.backstage.noRecent' | translate }}</p>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (actions().length) {\n\t\t\t<div class=\"actions\">\n\t\t\t\t@for (action of actions(); track action.titleKey) {\n\t\t\t\t\t<button type=\"button\" (click)=\"run(action.event)\">\n\t\t\t\t\t\t<b aria-hidden=\"true\">{{ action.icon }}</b\n\t\t\t\t\t\t><span\n\t\t\t\t\t\t\t><strong>{{ action.titleKey | translate }}</strong\n\t\t\t\t\t\t\t><small>{{ action.bodyKey | translate }}</small></span\n\t\t\t\t\t\t>\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t}\n\t\t@if (currentPage() === 'account') {\n\t\t\t<pptx-account-page [accountAuth]=\"accountAuth()\" />\n\t\t}\n\t\t@if (currentPage() === 'options') {\n\t\t\t<section class=\"card\">\n\t\t\t\t<b class=\"avatar\">\u2699</b>\n\t\t\t\t<h2>{{ 'pptx.backstage.optionsTitle' | translate }}</h2>\n\t\t\t\t<p>{{ 'pptx.backstage.optionsBody' | translate }}</p>\n\t\t\t\t<button class=\"primary\" type=\"button\" (click)=\"run(options)\">\n\t\t\t\t\t{{ 'pptx.backstage.openOptions' | translate }}\n\t\t\t\t</button>\n\t\t\t</section>\n\t\t}\n\t\t<footer>\n\t\t\t{{ fileName() || ('pptx.backstage.untitled' | translate) }} \u00B7\n\t\t\t{{ 'pptx.backstage.savedToBrowser' | translate }}\n\t\t</footer>\n\t</main>\n</div>\n", styles: [":host{font-family:Aptos,Segoe UI,sans-serif}.bs{position:fixed;inset:0;z-index:200;display:flex;background:var(--pptx-background, #fafafa);color:var(--pptx-foreground, #242424)}.bs aside{display:flex;width:148px;flex:none;flex-direction:column;border-right:1px solid var(--pptx-border, #d7d7d7);background:var(--pptx-secondary, #f5eee9)}.back-row{display:flex;height:40px;flex:none;border-bottom:1px solid var(--pptx-border, #ddd)}.back{width:100%;height:40px;border:0;background:none;color:inherit;font-size:22px}.back:hover,nav button:not(.active):hover,.recent>button:hover{background:var(--pptx-accent, #eadfd8)}nav{display:flex;min-height:0;flex:1;flex-direction:column;overflow-y:auto;padding:0 0 8px}nav i{flex:1}nav button{display:flex;min-height:40px;flex:none;align-items:center;gap:12px;padding:0 16px;border:0;border-left:2px solid transparent;background:none;color:inherit;font-size:12px;text-align:left}nav button span{display:grid;width:17px;flex:none;place-items:center;font-size:16px}nav button.active{border-left-color:var(--pptx-primary, #c43e1c);background:var(--pptx-card, #fff);color:var(--pptx-primary, #c43e1c)}main{min-width:0;flex:1;overflow:auto;padding:20px clamp(32px,4vw,72px)}h1{margin:0;font-size:24px;font-weight:600}h2{margin:28px 0 18px;font-size:17px}.templates{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:24px}.templates button{border:0;background:none;color:inherit;text-align:left}.templates button>b{display:block;aspect-ratio:16/9;border:1px solid var(--pptx-border, #ccc);box-shadow:0 1px 2px #0002;transition:.15s}.templates button:hover>b{transform:translateY(-2px);border-color:var(--pptx-primary, #c43e1c);box-shadow:0 7px 18px #0002}.templates strong,.templates small{display:block;overflow:hidden;margin-top:8px;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.templates small{margin-top:2px;color:var(--pptx-muted-foreground, #777);font-size:10px}.primary{margin-top:16px;padding:10px 20px;border:0;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-weight:600}.recent{border-top:1px solid var(--pptx-border, #ddd)}.recent header,.recent>button{display:grid;grid-template-columns:1fr 120px 90px;align-items:center;padding:10px 12px}.recent header{color:var(--pptx-muted-foreground, #666);font-size:11px;font-weight:600}.recent>button{width:100%;border:0;border-top:1px solid var(--pptx-border, #e5e5e5);background:none;color:inherit;font-size:11px;text-align:left}.name{display:flex;min-width:0;align-items:center;gap:12px}.name>b{display:grid;width:32px;height:32px;place-items:center;background:var(--pptx-primary, #d24726);color:var(--pptx-primary-foreground, #fff)}.name strong,.name small{display:block;overflow:hidden;font-size:13px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}.name small,.recent p{color:var(--pptx-muted-foreground, #666);font-size:11px}.recent p{text-align:center}.actions{display:grid;max-width:900px;grid-template-columns:1fr 1fr;gap:20px;margin-top:32px}.actions button{display:flex;min-height:112px;gap:16px;padding:20px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424);text-align:left}.actions button:hover{border-color:var(--pptx-primary, #c43e1c);box-shadow:0 5px 15px #0002}.actions button>b{display:grid;width:40px;height:40px;flex:none;place-items:center;background:var(--pptx-accent, #fbe9e3);color:var(--pptx-primary, #c43e1c)}.actions strong,.actions small{display:block;font-size:15px}.actions small{margin-top:7px;color:var(--pptx-muted-foreground, #666);font-size:12px;line-height:1.5}.card{max-width:760px;margin-top:32px;padding:28px;border:1px solid var(--pptx-border, #ddd);background:var(--pptx-card, #fff);color:var(--pptx-card-foreground, #242424)}.avatar{display:grid;width:56px;height:56px;place-items:center;border-radius:50%;background:var(--pptx-primary, #c43e1c);color:var(--pptx-primary-foreground, #fff);font-size:20px}.card p,footer{color:var(--pptx-muted-foreground, #666)}.card p{line-height:1.6}footer{margin-top:48px;font-size:11px}@media(max-width:640px),(pointer:coarse){.bs{flex-direction:column}.bs aside{width:100%;flex-direction:row;align-items:center;overflow-x:auto;border-right:0;border-bottom:1px solid var(--pptx-border, #d7d7d7)}.back-row{width:48px;height:48px;border-bottom:0;border-right:1px solid var(--pptx-border, #ddd)}.back{width:48px;height:48px}nav{flex-direction:row;align-items:center;overflow-y:visible;padding:0}nav i{display:none}nav button{flex-shrink:0;white-space:nowrap;border-left:0;border-bottom:2px solid transparent;padding:0 12px}nav button.active{border-left-color:transparent;border-bottom-color:var(--pptx-primary, #c43e1c)}main{padding:16px}.actions{grid-template-columns:1fr}.recent header,.recent>button{grid-template-columns:1fr 90px}.recent header span:last-child,.recent>button>span:last-child{display:none}}\n"] }]
159339
160484
  }], ctorParameters: () => [], propDecorators: { fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], exporting: [{ type: i0.Input, args: [{ isSignal: true, alias: "exporting", required: false }] }], hasMacros: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMacros", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], recentPresentationsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "recentPresentationsCount", required: false }] }], accountAuth: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountAuth", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], createPresentation: [{ type: i0.Output, args: ["createPresentation"] }], openFile: [{ type: i0.Output, args: ["openFile"] }], openRecentFile: [{ type: i0.Output, args: ["openRecentFile"] }], save: [{ type: i0.Output, args: ["save"] }], savePpsx: [{ type: i0.Output, args: ["savePpsx"] }], savePptm: [{ type: i0.Output, args: ["savePptm"] }], savePpt: [{ type: i0.Output, args: ["savePpt"] }], exportPng: [{ type: i0.Output, args: ["exportPng"] }], exportPdf: [{ type: i0.Output, args: ["exportPdf"] }], exportGif: [{ type: i0.Output, args: ["exportGif"] }], exportVideo: [{ type: i0.Output, args: ["exportVideo"] }], exportJson: [{ type: i0.Output, args: ["exportJson"] }], copySlideAsImage: [{ type: i0.Output, args: ["copySlideAsImage"] }], print: [{ type: i0.Output, args: ["print"] }], info: [{ type: i0.Output, args: ["info"] }], signatures: [{ type: i0.Output, args: ["signatures"] }], replace: [{ type: i0.Output, args: ["replace"] }], openPassword: [{ type: i0.Output, args: ["openPassword"] }], openFontEmbedding: [{ type: i0.Output, args: ["openFontEmbedding"] }], openVersionHistory: [{ type: i0.Output, args: ["openVersionHistory"] }], share: [{ type: i0.Output, args: ["share"] }], options: [{ type: i0.Output, args: ["options"] }] } });
159340
160485
 
159341
160486
  class HeaderFooterRibbonButtonComponent {
@@ -160790,7 +161935,9 @@ class RibbonPrimaryRowComponent {
160790
161935
  this.overflowOpen = signal(false, /* @ts-ignore */
160791
161936
  ...(ngDevMode ? [{ debugName: "overflowOpen" }] : /* istanbul ignore next */ []));
160792
161937
  this.toolbar = toolbarVisibility(this.hiddenActions);
160793
- this.overflowItems = computed(() => visibleOverflowItems(this.hiddenActions()), /* @ts-ignore */
161938
+ /** Host UI customisation (optional: absent outside a viewer). */
161939
+ this.customization = inject(ViewerCustomizationService, { optional: true });
161940
+ this.overflowItems = computed(() => visibleOverflowItems(this.hiddenActions()).filter((item) => item.key !== 'print' || this.customization?.dialogAvailable('print') !== false), /* @ts-ignore */
160794
161941
  ...(ngDevMode ? [{ debugName: "overflowItems" }] : /* istanbul ignore next */ []));
160795
161942
  this.presentRoot = viewChild('presentRoot', /* @ts-ignore */
160796
161943
  ...(ngDevMode ? [{ debugName: "presentRoot" }] : /* istanbul ignore next */ []));
@@ -161002,15 +162149,17 @@ class RibbonPrimaryRowComponent {
161002
162149
  }
161003
162150
 
161004
162151
  <!-- Settings (mirrors React: between the panel toggle and the overflow "...") -->
161005
- <button
161006
- type="button"
161007
- class="pptx-rb-icon text-muted-foreground"
161008
- [title]="'pptx.toolbar.settingsShortcuts' | translate"
161009
- [attr.aria-label]="'pptx.toolbar.settings' | translate"
161010
- (click)="openSettings.emit()"
161011
- >
161012
- <svg lucideSettings class="h-3.5 w-3.5"></svg>
161013
- </button>
162152
+ @if (customization?.dialogAvailable('options') !== false) {
162153
+ <button
162154
+ type="button"
162155
+ class="pptx-rb-icon text-muted-foreground"
162156
+ [title]="'pptx.toolbar.settingsShortcuts' | translate"
162157
+ [attr.aria-label]="'pptx.toolbar.settings' | translate"
162158
+ (click)="openSettings.emit()"
162159
+ >
162160
+ <svg lucideSettings class="h-3.5 w-3.5"></svg>
162161
+ </button>
162162
+ }
161014
162163
 
161015
162164
  <!-- Overflow menu -->
161016
162165
  <div class="relative inline-flex items-center" #overflowRoot>
@@ -161195,15 +162344,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
161195
162344
  }
161196
162345
 
161197
162346
  <!-- Settings (mirrors React: between the panel toggle and the overflow "...") -->
161198
- <button
161199
- type="button"
161200
- class="pptx-rb-icon text-muted-foreground"
161201
- [title]="'pptx.toolbar.settingsShortcuts' | translate"
161202
- [attr.aria-label]="'pptx.toolbar.settings' | translate"
161203
- (click)="openSettings.emit()"
161204
- >
161205
- <svg lucideSettings class="h-3.5 w-3.5"></svg>
161206
- </button>
162347
+ @if (customization?.dialogAvailable('options') !== false) {
162348
+ <button
162349
+ type="button"
162350
+ class="pptx-rb-icon text-muted-foreground"
162351
+ [title]="'pptx.toolbar.settingsShortcuts' | translate"
162352
+ [attr.aria-label]="'pptx.toolbar.settings' | translate"
162353
+ (click)="openSettings.emit()"
162354
+ >
162355
+ <svg lucideSettings class="h-3.5 w-3.5"></svg>
162356
+ </button>
162357
+ }
161207
162358
 
161208
162359
  <!-- Overflow menu -->
161209
162360
  <div class="relative inline-flex items-center" #overflowRoot>
@@ -162925,11 +164076,14 @@ class SlideCanvasContextMenuComponent {
162925
164076
  this.toggleGrid = output();
162926
164077
  this.toggleRulers = output();
162927
164078
  this.host = inject(ElementRef);
162928
- this.entries = computed(() => buildCanvasContextMenuEntries({
164079
+ /** Kept inside the viewport (see `context-menu-position.ts`). */
164080
+ this.position = clampedMenuPosition(this.host, this.x, this.y);
164081
+ this.customization = injectResolvedCustomization();
164082
+ this.entries = computed(() => customizeCanvasContextMenuEntries(buildCanvasContextMenuEntries({
162929
164083
  hasClipboard: this.hasClipboard(),
162930
164084
  showGrid: this.showGrid(),
162931
164085
  showRulers: this.showRulers(),
162932
- }), /* @ts-ignore */
164086
+ }), this.customization()), /* @ts-ignore */
162933
164087
  ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
162934
164088
  this.actions = {
162935
164089
  paste: () => this.paste.emit(),
@@ -162958,71 +164112,81 @@ class SlideCanvasContextMenuComponent {
162958
164112
  this.closed.emit();
162959
164113
  }
162960
164114
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SlideCanvasContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
162961
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: SlideCanvasContextMenuComponent, isStandalone: true, selector: "pptx-slide-canvas-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: true, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: true, transformFunction: null }, hasClipboard: { classPropertyName: "hasClipboard", publicName: "hasClipboard", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", paste: "paste", openLayoutGallery: "openLayoutGallery", resetSlide: "resetSlide", openFormatBackground: "openFormatBackground", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:pointerdown": "onDocumentPointerDown($event)" }, properties: { "style.--pptx-ctx-x": "x() + \"px\"", "style.--pptx-ctx-y": "y() + \"px\"" } }, ngImport: i0, template: `
162962
- <ul
162963
- class="pptx-ctx__menu"
162964
- data-pptx-context-menu="true"
162965
- data-pptx-canvas-context-menu="true"
162966
- role="menu"
162967
- [attr.aria-label]="'pptx.canvasContextMenu.ariaLabel' | translate"
162968
- >
162969
- @for (entry of entries(); track entry.id) {
162970
- @if (entry.separatorBefore) {
162971
- <li role="separator" class="pptx-ctx__divider"></li>
164115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: SlideCanvasContextMenuComponent, isStandalone: true, selector: "pptx-slide-canvas-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: true, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: true, transformFunction: null }, hasClipboard: { classPropertyName: "hasClipboard", publicName: "hasClipboard", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", paste: "paste", openLayoutGallery: "openLayoutGallery", resetSlide: "resetSlide", openFormatBackground: "openFormatBackground", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:pointerdown": "onDocumentPointerDown($event)" }, properties: { "style.--pptx-ctx-x": "position.left() + \"px\"", "style.--pptx-ctx-y": "position.top() + \"px\"" } }, ngImport: i0, template: `
164116
+ <!-- An empty menu (host customisation removed every entry) renders nothing. -->
164117
+ @if (entries().length > 0) {
164118
+ <ul
164119
+ class="pptx-ctx__menu"
164120
+ data-pptx-context-menu="true"
164121
+ data-pptx-canvas-context-menu="true"
164122
+ role="menu"
164123
+ [attr.aria-label]="'pptx.canvasContextMenu.ariaLabel' | translate"
164124
+ >
164125
+ @for (entry of entries(); track entry.id) {
164126
+ @if (entry.separatorBefore) {
164127
+ <li role="separator" class="pptx-ctx__divider"></li>
164128
+ }
164129
+ <li role="none">
164130
+ <button
164131
+ type="button"
164132
+ class="pptx-ctx__item"
164133
+ [attr.role]="entry.checked === undefined ? 'menuitem' : 'menuitemcheckbox'"
164134
+ [attr.aria-checked]="entry.checked === undefined ? null : entry.checked"
164135
+ [disabled]="!!entry.disabled"
164136
+ (click)="run(entry.id)"
164137
+ >
164138
+ @if (entry.checked !== undefined) {
164139
+ <span class="pptx-ctx__check" aria-hidden="true">{{
164140
+ entry.checked ? '✓' : ''
164141
+ }}</span>
164142
+ }
164143
+ {{ entry.labelKey | translate }}
164144
+ </button>
164145
+ </li>
162972
164146
  }
162973
- <li role="none">
162974
- <button
162975
- type="button"
162976
- class="pptx-ctx__item"
162977
- [attr.role]="entry.checked === undefined ? 'menuitem' : 'menuitemcheckbox'"
162978
- [attr.aria-checked]="entry.checked === undefined ? null : entry.checked"
162979
- [disabled]="!!entry.disabled"
162980
- (click)="run(entry.id)"
162981
- >
162982
- @if (entry.checked !== undefined) {
162983
- <span class="pptx-ctx__check" aria-hidden="true">{{ entry.checked ? '✓' : '' }}</span>
162984
- }
162985
- {{ entry.labelKey | translate }}
162986
- </button>
162987
- </li>
162988
- }
162989
- </ul>
164147
+ </ul>
164148
+ }
162990
164149
  `, isInline: true, styles: [":host{position:fixed;left:var(--pptx-ctx-x, 0px);top:var(--pptx-ctx-y, 0px);z-index:9000;display:block}.pptx-ctx__menu{list-style:none;margin:0;padding:4px 0;min-width:160px;background:var(--pptx-ctx-bg, #252526);color:var(--pptx-ctx-fg, #e0e0e0);border:1px solid var(--pptx-ctx-border, #454545);border-radius:4px;box-shadow:0 4px 12px #0006,0 1px 3px #0000004d;font-size:13px;-webkit-user-select:none;user-select:none}.pptx-ctx__item{display:block;width:100%;padding:5px 14px;background:transparent;border:none;color:inherit;text-align:left;cursor:pointer;font-size:inherit;white-space:nowrap}.pptx-ctx__item:hover:not(:disabled){background:var(--pptx-ctx-hover, #094771);color:var(--pptx-ctx-hover-fg, #ffffff)}.pptx-ctx__item:disabled{opacity:.4;pointer-events:none;cursor:default}.pptx-ctx__item--danger{color:var(--pptx-ctx-danger, #f47c7c)}.pptx-ctx__item--danger:hover:not(:disabled){background:var(--pptx-ctx-danger-hover, #4a1a1a);color:var(--pptx-ctx-danger-fg, #ffaaaa)}.pptx-ctx__divider{height:1px;background:var(--pptx-ctx-divider, #454545);margin:3px 0}\n", ".pptx-ctx__check{display:inline-block;width:14px}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
162991
164150
  }
162992
164151
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SlideCanvasContextMenuComponent, decorators: [{
162993
164152
  type: Component,
162994
164153
  args: [{ selector: 'pptx-slide-canvas-context-menu', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: `
162995
- <ul
162996
- class="pptx-ctx__menu"
162997
- data-pptx-context-menu="true"
162998
- data-pptx-canvas-context-menu="true"
162999
- role="menu"
163000
- [attr.aria-label]="'pptx.canvasContextMenu.ariaLabel' | translate"
163001
- >
163002
- @for (entry of entries(); track entry.id) {
163003
- @if (entry.separatorBefore) {
163004
- <li role="separator" class="pptx-ctx__divider"></li>
164154
+ <!-- An empty menu (host customisation removed every entry) renders nothing. -->
164155
+ @if (entries().length > 0) {
164156
+ <ul
164157
+ class="pptx-ctx__menu"
164158
+ data-pptx-context-menu="true"
164159
+ data-pptx-canvas-context-menu="true"
164160
+ role="menu"
164161
+ [attr.aria-label]="'pptx.canvasContextMenu.ariaLabel' | translate"
164162
+ >
164163
+ @for (entry of entries(); track entry.id) {
164164
+ @if (entry.separatorBefore) {
164165
+ <li role="separator" class="pptx-ctx__divider"></li>
164166
+ }
164167
+ <li role="none">
164168
+ <button
164169
+ type="button"
164170
+ class="pptx-ctx__item"
164171
+ [attr.role]="entry.checked === undefined ? 'menuitem' : 'menuitemcheckbox'"
164172
+ [attr.aria-checked]="entry.checked === undefined ? null : entry.checked"
164173
+ [disabled]="!!entry.disabled"
164174
+ (click)="run(entry.id)"
164175
+ >
164176
+ @if (entry.checked !== undefined) {
164177
+ <span class="pptx-ctx__check" aria-hidden="true">{{
164178
+ entry.checked ? '✓' : ''
164179
+ }}</span>
164180
+ }
164181
+ {{ entry.labelKey | translate }}
164182
+ </button>
164183
+ </li>
163005
164184
  }
163006
- <li role="none">
163007
- <button
163008
- type="button"
163009
- class="pptx-ctx__item"
163010
- [attr.role]="entry.checked === undefined ? 'menuitem' : 'menuitemcheckbox'"
163011
- [attr.aria-checked]="entry.checked === undefined ? null : entry.checked"
163012
- [disabled]="!!entry.disabled"
163013
- (click)="run(entry.id)"
163014
- >
163015
- @if (entry.checked !== undefined) {
163016
- <span class="pptx-ctx__check" aria-hidden="true">{{ entry.checked ? '✓' : '' }}</span>
163017
- }
163018
- {{ entry.labelKey | translate }}
163019
- </button>
163020
- </li>
163021
- }
163022
- </ul>
164185
+ </ul>
164186
+ }
163023
164187
  `, host: {
163024
- '[style.--pptx-ctx-x]': 'x() + "px"',
163025
- '[style.--pptx-ctx-y]': 'y() + "px"',
164188
+ '[style.--pptx-ctx-x]': 'position.left() + "px"',
164189
+ '[style.--pptx-ctx-y]': 'position.top() + "px"',
163026
164190
  }, styles: [":host{position:fixed;left:var(--pptx-ctx-x, 0px);top:var(--pptx-ctx-y, 0px);z-index:9000;display:block}.pptx-ctx__menu{list-style:none;margin:0;padding:4px 0;min-width:160px;background:var(--pptx-ctx-bg, #252526);color:var(--pptx-ctx-fg, #e0e0e0);border:1px solid var(--pptx-ctx-border, #454545);border-radius:4px;box-shadow:0 4px 12px #0006,0 1px 3px #0000004d;font-size:13px;-webkit-user-select:none;user-select:none}.pptx-ctx__item{display:block;width:100%;padding:5px 14px;background:transparent;border:none;color:inherit;text-align:left;cursor:pointer;font-size:inherit;white-space:nowrap}.pptx-ctx__item:hover:not(:disabled){background:var(--pptx-ctx-hover, #094771);color:var(--pptx-ctx-hover-fg, #ffffff)}.pptx-ctx__item:disabled{opacity:.4;pointer-events:none;cursor:default}.pptx-ctx__item--danger{color:var(--pptx-ctx-danger, #f47c7c)}.pptx-ctx__item--danger:hover:not(:disabled){background:var(--pptx-ctx-danger-hover, #4a1a1a);color:var(--pptx-ctx-danger-fg, #ffaaaa)}.pptx-ctx__divider{height:1px;background:var(--pptx-ctx-divider, #454545);margin:3px 0}\n", ".pptx-ctx__check{display:inline-block;width:14px}\n"] }]
163027
164191
  }], propDecorators: { x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: true }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: true }] }], hasClipboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClipboard", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], paste: [{ type: i0.Output, args: ["paste"] }], openLayoutGallery: [{ type: i0.Output, args: ["openLayoutGallery"] }], resetSlide: [{ type: i0.Output, args: ["resetSlide"] }], openFormatBackground: [{ type: i0.Output, args: ["openFormatBackground"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], onEscape: [{
163028
164192
  type: HostListener,
@@ -184503,6 +185667,105 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
184503
185667
  }]
184504
185668
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], isDirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDirty", required: false }] }], autosaveStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosaveStatus", required: false }] }], autosaveEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosaveEnabled", required: false }] }], canUndo: [{ type: i0.Input, args: [{ isSignal: true, alias: "canUndo", required: false }] }], canRedo: [{ type: i0.Input, args: [{ isSignal: true, alias: "canRedo", required: false }] }], undoLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "undoLabel", required: false }] }], redoLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "redoLabel", required: false }] }], findReplaceOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "findReplaceOpen", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], quickAccess: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickAccess", required: false }] }], toggleAutosave: [{ type: i0.Output, args: ["toggleAutosave"] }], save: [{ type: i0.Output, args: ["save"] }], undo: [{ type: i0.Output, args: ["undo"] }], redo: [{ type: i0.Output, args: ["redo"] }], quickCommand: [{ type: i0.Output, args: ["quickCommand"] }], toggleFindReplace: [{ type: i0.Output, args: ["toggleFindReplace"] }], commandSearch: [{ type: i0.Output, args: ["commandSearch"] }] } });
184505
185669
 
185670
+ class ViewerCustomizationHandle {
185671
+ get customizationApi() {
185672
+ return this.customizationService.api;
185673
+ }
185674
+ getCustomization() {
185675
+ return this.customizationApi.getCustomization();
185676
+ }
185677
+ setCustomization(next) {
185678
+ this.customizationApi.setCustomization(next);
185679
+ }
185680
+ updateCustomization(patch) {
185681
+ this.customizationApi.updateCustomization(patch);
185682
+ }
185683
+ resetCustomization() {
185684
+ this.customizationApi.resetCustomization();
185685
+ }
185686
+ hideRibbonTab(tab) {
185687
+ this.customizationApi.hideRibbonTab(tab);
185688
+ }
185689
+ showRibbonTab(tab) {
185690
+ this.customizationApi.showRibbonTab(tab);
185691
+ }
185692
+ hideToolbarButton(button) {
185693
+ this.customizationApi.hideToolbarButton(button);
185694
+ }
185695
+ showToolbarButton(button) {
185696
+ this.customizationApi.showToolbarButton(button);
185697
+ }
185698
+ hideOptionsPage(page) {
185699
+ this.customizationApi.hideOptionsPage(page);
185700
+ }
185701
+ showOptionsPage(page) {
185702
+ this.customizationApi.showOptionsPage(page);
185703
+ }
185704
+ hideOptionsSection(section) {
185705
+ this.customizationApi.hideOptionsSection(section);
185706
+ }
185707
+ showOptionsSection(section) {
185708
+ this.customizationApi.showOptionsSection(section);
185709
+ }
185710
+ hideSetting(setting) {
185711
+ this.customizationApi.hideSetting(setting);
185712
+ }
185713
+ showSetting(setting) {
185714
+ this.customizationApi.showSetting(setting);
185715
+ }
185716
+ lockSetting(setting, value, hidden) {
185717
+ this.customizationApi.lockSetting(setting, value, hidden);
185718
+ }
185719
+ unlockSetting(setting) {
185720
+ this.customizationApi.unlockSetting(setting);
185721
+ }
185722
+ setSettingDefault(setting, value) {
185723
+ this.customizationApi.setSettingDefault(setting, value);
185724
+ }
185725
+ hideBackstagePage(page) {
185726
+ this.customizationApi.hideBackstagePage(page);
185727
+ }
185728
+ showBackstagePage(page) {
185729
+ this.customizationApi.showBackstagePage(page);
185730
+ }
185731
+ hideBackstageCard(card) {
185732
+ this.customizationApi.hideBackstageCard(card);
185733
+ }
185734
+ showBackstageCard(card) {
185735
+ this.customizationApi.showBackstageCard(card);
185736
+ }
185737
+ hideContextMenuCommand(command) {
185738
+ this.customizationApi.hideContextMenuCommand(command);
185739
+ }
185740
+ showContextMenuCommand(command) {
185741
+ this.customizationApi.showContextMenuCommand(command);
185742
+ }
185743
+ hideCanvasContextMenuCommand(command) {
185744
+ this.customizationApi.hideCanvasContextMenuCommand(command);
185745
+ }
185746
+ showCanvasContextMenuCommand(command) {
185747
+ this.customizationApi.showCanvasContextMenuCommand(command);
185748
+ }
185749
+ disableShortcut(action) {
185750
+ this.customizationApi.disableShortcut(action);
185751
+ }
185752
+ enableShortcut(action) {
185753
+ this.customizationApi.enableShortcut(action);
185754
+ }
185755
+ remapShortcut(action, chords) {
185756
+ this.customizationApi.remapShortcut(action, chords);
185757
+ }
185758
+ setPanelVisible(panel, visible) {
185759
+ this.customizationApi.setPanelVisible(panel, visible);
185760
+ }
185761
+ setFeatureEnabled(feature, enabled) {
185762
+ this.customizationApi.setFeatureEnabled(feature, enabled);
185763
+ }
185764
+ setDialogAvailable(dialog, available) {
185765
+ this.customizationApi.setDialogAvailable(dialog, available);
185766
+ }
185767
+ }
185768
+
184506
185769
  /**
184507
185770
  * slide-diff-helpers.ts: Pure label / icon helpers for the slide-diff row and
184508
185771
  * its change list. Framework-free so they are unit testable in isolation.
@@ -187751,6 +189014,10 @@ class OptionsPaneComponent {
187751
189014
  this.emit(control, event.target.value);
187752
189015
  }
187753
189016
  emit(control, value) {
189017
+ // A host-locked setting (customization.options.locked) never changes.
189018
+ if (control.readOnly === true) {
189019
+ return;
189020
+ }
187754
189021
  this.valueChange.emit({ group: control.group, key: control.key, value });
187755
189022
  }
187756
189023
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: OptionsPaneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -187784,6 +189051,8 @@ class OptionsPaneComponent {
187784
189051
  class="pptx-ng-options-check"
187785
189052
  [checked]="value(control) === true"
187786
189053
  [attr.aria-label]="control.labelKey | translate"
189054
+ [attr.disabled]="control.readOnly ? '' : null"
189055
+ [attr.title]="control.readOnly ? ('pptx.options.lockedByHost' | translate) : null"
187787
189056
  (change)="emitToggle(control, $event)"
187788
189057
  />
187789
189058
  </label>
@@ -187806,6 +189075,10 @@ class OptionsPaneComponent {
187806
189075
  class="pptx-ng-options-select"
187807
189076
  [value]="value(control)"
187808
189077
  [attr.aria-label]="control.labelKey | translate"
189078
+ [attr.disabled]="control.readOnly ? '' : null"
189079
+ [attr.title]="
189080
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189081
+ "
187809
189082
  (change)="emitSelect(control, $event)"
187810
189083
  >
187811
189084
  @for (choice of selectChoices(control); track choice.value) {
@@ -187823,6 +189096,10 @@ class OptionsPaneComponent {
187823
189096
  [max]="numberMax(control)"
187824
189097
  [value]="value(control)"
187825
189098
  [attr.aria-label]="control.labelKey | translate"
189099
+ [attr.disabled]="control.readOnly ? '' : null"
189100
+ [attr.title]="
189101
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189102
+ "
187826
189103
  (change)="emitNumber(control, $event)"
187827
189104
  />
187828
189105
  @if (numberUnitKey(control); as unitKey) {
@@ -187837,6 +189114,10 @@ class OptionsPaneComponent {
187837
189114
  maxlength="64"
187838
189115
  [value]="value(control) ?? ''"
187839
189116
  [attr.aria-label]="control.labelKey | translate"
189117
+ [attr.disabled]="control.readOnly ? '' : null"
189118
+ [attr.title]="
189119
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189120
+ "
187840
189121
  (change)="emitText(control, $event)"
187841
189122
  />
187842
189123
  }
@@ -187894,6 +189175,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
187894
189175
  class="pptx-ng-options-check"
187895
189176
  [checked]="value(control) === true"
187896
189177
  [attr.aria-label]="control.labelKey | translate"
189178
+ [attr.disabled]="control.readOnly ? '' : null"
189179
+ [attr.title]="control.readOnly ? ('pptx.options.lockedByHost' | translate) : null"
187897
189180
  (change)="emitToggle(control, $event)"
187898
189181
  />
187899
189182
  </label>
@@ -187916,6 +189199,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
187916
189199
  class="pptx-ng-options-select"
187917
189200
  [value]="value(control)"
187918
189201
  [attr.aria-label]="control.labelKey | translate"
189202
+ [attr.disabled]="control.readOnly ? '' : null"
189203
+ [attr.title]="
189204
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189205
+ "
187919
189206
  (change)="emitSelect(control, $event)"
187920
189207
  >
187921
189208
  @for (choice of selectChoices(control); track choice.value) {
@@ -187933,6 +189220,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
187933
189220
  [max]="numberMax(control)"
187934
189221
  [value]="value(control)"
187935
189222
  [attr.aria-label]="control.labelKey | translate"
189223
+ [attr.disabled]="control.readOnly ? '' : null"
189224
+ [attr.title]="
189225
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189226
+ "
187936
189227
  (change)="emitNumber(control, $event)"
187937
189228
  />
187938
189229
  @if (numberUnitKey(control); as unitKey) {
@@ -187947,6 +189238,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
187947
189238
  maxlength="64"
187948
189239
  [value]="value(control) ?? ''"
187949
189240
  [attr.aria-label]="control.labelKey | translate"
189241
+ [attr.disabled]="control.readOnly ? '' : null"
189242
+ [attr.title]="
189243
+ control.readOnly ? ('pptx.options.lockedByHost' | translate) : null
189244
+ "
187950
189245
  (change)="emitText(control, $event)"
187951
189246
  />
187952
189247
  }
@@ -188499,6 +189794,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
188499
189794
  }]
188500
189795
  }], propDecorators: { enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "enabled", required: false }] }], families: [{ type: i0.Input, args: [{ isSignal: true, alias: "families", required: false }] }], registered: [{ type: i0.Output, args: ["registered"] }] } });
188501
189796
 
189797
+ /**
189798
+ * settings-dialog-tabs.ts: the File > Options dialog's tab list and
189799
+ * active-tab resolution, after the host's UI customisation.
189800
+ *
189801
+ * The filtering itself is the shared `customizeOptionsTabs`; this only maps a
189802
+ * requested tab id onto one that is still visible, so a hidden page can never
189803
+ * stay selected.
189804
+ */
189805
+ /** The ten File > Options categories the dialog's rail renders, in order. */
189806
+ const OPTIONS_DIALOG_TABS = VIEWER_OPTIONS_TABS;
189807
+ /** Resolve the active tab definition, falling back to the first visible category. */
189808
+ function resolveOptionsTab(id, tabs = OPTIONS_DIALOG_TABS) {
189809
+ const fallback = (tabs[0] ?? OPTIONS_DIALOG_TABS[0]);
189810
+ return tabs.find((tab) => tab.id === id) ?? fallback;
189811
+ }
189812
+ /**
189813
+ * The tab id the dialog should show for a requested one: the request when it
189814
+ * is still visible, otherwise the first visible category (or the AI page when
189815
+ * it is the only one left).
189816
+ */
189817
+ function resolveVisibleOptionsTabId(requested, tabs, aiVisible) {
189818
+ if (requested === 'ai' ? aiVisible : tabs.some((tab) => tab.id === requested)) {
189819
+ return requested;
189820
+ }
189821
+ return tabs[0]?.id ?? (aiVisible ? 'ai' : 'general');
189822
+ }
189823
+
188502
189824
  /**
188503
189825
  * settings-language-tab.component.ts: File > Options > Language tab.
188504
189826
  *
@@ -188571,13 +189893,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
188571
189893
  * two-column rail layout needs the wide footprint the shared modal shell does
188572
189894
  * not provide, mirroring how `insert-smart-art-dialog` sizes itself.
188573
189895
  */
188574
- /** The ten File > Options categories the dialog's rail renders, in order. */
188575
- const OPTIONS_DIALOG_TABS = VIEWER_OPTIONS_TABS;
188576
- /** Resolve the active tab definition, falling back to the first category. */
188577
- function resolveOptionsTab(id) {
188578
- const fallback = OPTIONS_DIALOG_TABS[0];
188579
- return OPTIONS_DIALOG_TABS.find((tab) => tab.id === id) ?? fallback;
188580
- }
188581
189896
  class SettingsDialogComponent {
188582
189897
  constructor() {
188583
189898
  this.open = input(false, /* @ts-ignore */
@@ -188620,13 +189935,21 @@ class SettingsDialogComponent {
188620
189935
  this.customFontRegistered = output();
188621
189936
  this.localeSelect = output();
188622
189937
  this.close = output();
188623
- this.tabs = OPTIONS_DIALOG_TABS;
188624
- /** Active category id, or the bespoke `'ai'` sentinel for the AI export pane. */
189938
+ this.customization = injectResolvedCustomization();
189939
+ /** The categories after the host's customisation (hidden pages/sections/settings dropped). */
189940
+ this.tabs = computed(() => customizeOptionsTabs(OPTIONS_DIALOG_TABS, this.customization()), /* @ts-ignore */
189941
+ ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
189942
+ this.aiTabVisible = computed(() => this.aiExportVisible() && isOptionsPageVisible(this.customization(), 'ai'), /* @ts-ignore */
189943
+ ...(ngDevMode ? [{ debugName: "aiTabVisible" }] : /* istanbul ignore next */ []));
189944
+ /** Requested category id, or the bespoke `'ai'` sentinel for the AI export pane. */
188625
189945
  this.activeTabId = signal('general', /* @ts-ignore */
188626
189946
  ...(ngDevMode ? [{ debugName: "activeTabId" }] : /* istanbul ignore next */ []));
189947
+ /** The requested category, or the first visible one when the host hid it. */
189948
+ this.shownTabId = computed(() => resolveVisibleOptionsTabId(this.activeTabId(), this.tabs(), this.aiTabVisible()), /* @ts-ignore */
189949
+ ...(ngDevMode ? [{ debugName: "shownTabId" }] : /* istanbul ignore next */ []));
188627
189950
  this.activeTab = computed(() => {
188628
- const id = this.activeTabId();
188629
- return resolveOptionsTab(id === 'ai' ? 'general' : id);
189951
+ const id = this.shownTabId();
189952
+ return resolveOptionsTab(id === 'ai' ? 'general' : id, this.tabs());
188630
189953
  }, /* @ts-ignore */
188631
189954
  ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
188632
189955
  /** Snapshot taken when the dialog opens, restored by Cancel. */
@@ -188682,21 +190005,21 @@ class SettingsDialogComponent {
188682
190005
 
188683
190006
  <div class="pptx-ng-options-layout">
188684
190007
  <nav [attr.aria-label]="'pptx.options.title' | translate">
188685
- @for (tab of tabs; track tab.id) {
190008
+ @for (tab of tabs(); track tab.id) {
188686
190009
  <button
188687
190010
  type="button"
188688
- [attr.aria-current]="activeTabId() === tab.id"
188689
- [class.is-active]="activeTabId() === tab.id"
190011
+ [attr.aria-current]="shownTabId() === tab.id"
190012
+ [class.is-active]="shownTabId() === tab.id"
188690
190013
  (click)="activeTabId.set(tab.id)"
188691
190014
  >
188692
190015
  {{ tab.labelKey | translate }}
188693
190016
  </button>
188694
190017
  }
188695
- @if (aiExportVisible()) {
190018
+ @if (aiTabVisible()) {
188696
190019
  <button
188697
190020
  type="button"
188698
- [attr.aria-current]="activeTabId() === 'ai'"
188699
- [class.is-active]="activeTabId() === 'ai'"
190021
+ [attr.aria-current]="shownTabId() === 'ai'"
190022
+ [class.is-active]="shownTabId() === 'ai'"
188700
190023
  (click)="activeTabId.set('ai')"
188701
190024
  >
188702
190025
  {{ 'pptx.ai.settingsSectionTitle' | translate }}
@@ -188705,7 +190028,7 @@ class SettingsDialogComponent {
188705
190028
  </nav>
188706
190029
 
188707
190030
  <div class="pptx-ng-options-content">
188708
- @if (activeTabId() === 'ai') {
190031
+ @if (shownTabId() === 'ai') {
188709
190032
  <p class="pptx-ng-options-headline">
188710
190033
  {{ 'pptx.ai.settingsSectionTitle' | translate }}
188711
190034
  </p>
@@ -188839,21 +190162,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
188839
190162
 
188840
190163
  <div class="pptx-ng-options-layout">
188841
190164
  <nav [attr.aria-label]="'pptx.options.title' | translate">
188842
- @for (tab of tabs; track tab.id) {
190165
+ @for (tab of tabs(); track tab.id) {
188843
190166
  <button
188844
190167
  type="button"
188845
- [attr.aria-current]="activeTabId() === tab.id"
188846
- [class.is-active]="activeTabId() === tab.id"
190168
+ [attr.aria-current]="shownTabId() === tab.id"
190169
+ [class.is-active]="shownTabId() === tab.id"
188847
190170
  (click)="activeTabId.set(tab.id)"
188848
190171
  >
188849
190172
  {{ tab.labelKey | translate }}
188850
190173
  </button>
188851
190174
  }
188852
- @if (aiExportVisible()) {
190175
+ @if (aiTabVisible()) {
188853
190176
  <button
188854
190177
  type="button"
188855
- [attr.aria-current]="activeTabId() === 'ai'"
188856
- [class.is-active]="activeTabId() === 'ai'"
190178
+ [attr.aria-current]="shownTabId() === 'ai'"
190179
+ [class.is-active]="shownTabId() === 'ai'"
188857
190180
  (click)="activeTabId.set('ai')"
188858
190181
  >
188859
190182
  {{ 'pptx.ai.settingsSectionTitle' | translate }}
@@ -188862,7 +190185,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
188862
190185
  </nav>
188863
190186
 
188864
190187
  <div class="pptx-ng-options-content">
188865
- @if (activeTabId() === 'ai') {
190188
+ @if (shownTabId() === 'ai') {
188866
190189
  <p class="pptx-ng-options-headline">
188867
190190
  {{ 'pptx.ai.settingsSectionTitle' | translate }}
188868
190191
  </p>
@@ -189467,6 +190790,7 @@ class ViewerExtraDialogsComponent {
189467
190790
  this.themeKeySelect = output();
189468
190791
  this.localeSelect = output();
189469
190792
  this.svc = inject(ViewerDialogsService);
190793
+ this.customization = inject(ViewerCustomizationService, { optional: true });
189470
190794
  this.customFonts = inject(CustomFontsService);
189471
190795
  this.viewerOpts = inject(ViewerOptionsService);
189472
190796
  this.compare = inject(ViewerCompareService);
@@ -189646,7 +190970,7 @@ class ViewerExtraDialogsComponent {
189646
190970
  <pptx-shortcut-panel [open]="svc.showShortcuts()" (close)="svc.showShortcuts.set(false)" />
189647
190971
 
189648
190972
  <pptx-settings-dialog
189649
- [open]="svc.showSettings()"
190973
+ [open]="svc.showSettings() && customization?.dialogAvailable('options') !== false"
189650
190974
  [options]="viewerOpts.options()"
189651
190975
  [addinStatus]="addinStatus()"
189652
190976
  [themeKey]="themeKey()"
@@ -189773,7 +191097,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
189773
191097
  <pptx-shortcut-panel [open]="svc.showShortcuts()" (close)="svc.showShortcuts.set(false)" />
189774
191098
 
189775
191099
  <pptx-settings-dialog
189776
- [open]="svc.showSettings()"
191100
+ [open]="svc.showSettings() && customization?.dialogAvailable('options') !== false"
189777
191101
  [options]="viewerOpts.options()"
189778
191102
  [addinStatus]="addinStatus()"
189779
191103
  [themeKey]="themeKey()"
@@ -189904,7 +191228,7 @@ function insertPublicElement(element, target, editor, slideIndex, commitPendingT
189904
191228
  * - React theme context / Vue provide-inject → `themeStyle` CSS vars applied to
189905
191229
  * the root element (app-wide sharing via `provideViewerTheme`).
189906
191230
  */
189907
- class PowerPointViewerComponent {
191231
+ class PowerPointViewerComponent extends ViewerCustomizationHandle {
189908
191232
  /** Lift Protected View's read-only lock for the current document (File > Options > Trust Center). */
189909
191233
  enableEditing() {
189910
191234
  this.protectedViewDismissed.set(true);
@@ -189921,6 +191245,7 @@ class PowerPointViewerComponent {
189921
191245
  this.canvasLayoutGalleryPos.set(null);
189922
191246
  }
189923
191247
  constructor() {
191248
+ super();
189924
191249
  /** PowerPoint content as Uint8Array (or ArrayBuffer). */
189925
191250
  this.content = input(null, /* @ts-ignore */
189926
191251
  ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
@@ -190125,6 +191450,16 @@ class PowerPointViewerComponent {
190125
191450
  */
190126
191451
  this.ai = input(undefined, /* @ts-ignore */
190127
191452
  ...(ngDevMode ? [{ debugName: "ai" }] : /* istanbul ignore next */ []));
191453
+ /**
191454
+ * Framework-neutral UI customisation. See docs/guide/customization.md.
191455
+ * Unioned with `hiddenActions`. A new object identity REPLACES the whole
191456
+ * customisation, including edits made through the imperative helpers
191457
+ * (`hideRibbonTab`, `lockSetting`, ...).
191458
+ */
191459
+ this.customization = input(undefined, /* @ts-ignore */
191460
+ ...(ngDevMode ? [{ debugName: "customization" }] : /* istanbul ignore next */ []));
191461
+ this.customizationService = inject(ViewerCustomizationService);
191462
+ this.customizationInputSync = this.customizationService.bindInput(this.customization);
190128
191463
  /** Fired when the active slide changes. */
190129
191464
  this.activeSlideChange = output();
190130
191465
  /** Fired when the unsaved-changes flag toggles. */
@@ -190263,7 +191598,7 @@ class PowerPointViewerComponent {
190263
191598
  * tab off in Customize Ribbon changes what the pane displays without
190264
191599
  * changing what actually renders.
190265
191600
  */
190266
- this.effectiveHiddenActions = computed(() => mergeHiddenActions(this.hiddenActions(), this.viewerOpts.options().ribbon.hiddenTabIds), /* @ts-ignore */
191601
+ this.effectiveHiddenActions = computed(() => this.customizationService.effectiveHiddenActions(mergeHiddenActions(this.hiddenActions(), this.viewerOpts.options().ribbon.hiddenTabIds)), /* @ts-ignore */
190267
191602
  ...(ngDevMode ? [{ debugName: "effectiveHiddenActions" }] : /* istanbul ignore next */ []));
190268
191603
  /**
190269
191604
  * File > Options > Quick Access Toolbar > Position "Below the Ribbon": the
@@ -190274,7 +191609,7 @@ class PowerPointViewerComponent {
190274
191609
  * under the identical {@link resolveBelowRibbonQuickAccess} condition, so
190275
191610
  * the commands render in exactly one place.
190276
191611
  */
190277
- this.belowRibbonQuickAccess = computed(() => resolveBelowRibbonQuickAccess(this.viewerOpts.options().quickAccess), /* @ts-ignore */
191612
+ this.belowRibbonQuickAccess = computed(() => resolveBelowRibbonQuickAccess(this.customizationService.quickAccess(this.viewerOpts.options().quickAccess)), /* @ts-ignore */
190278
191613
  ...(ngDevMode ? [{ debugName: "belowRibbonQuickAccess" }] : /* istanbul ignore next */ []));
190279
191614
  this.activeSlideIndex = signal(0, /* @ts-ignore */
190280
191615
  ...(ngDevMode ? [{ debugName: "activeSlideIndex" }] : /* istanbul ignore next */ []));
@@ -190582,7 +191917,7 @@ class PowerPointViewerComponent {
190582
191917
  : 0, /* @ts-ignore */
190583
191918
  ...(ngDevMode ? [{ debugName: "compatToastRightInset" }] : /* istanbul ignore next */ []));
190584
191919
  /** Whether the AI assistant toggle is shown (host supplied an `ai` config). */
190585
- this.aiEnabled = computed(() => aiToggleVisible(this.ai()), /* @ts-ignore */
191920
+ this.aiEnabled = computed(() => aiToggleVisible(this.ai()) && this.customizationService.featureEnabled('ai'), /* @ts-ignore */
190586
191921
  ...(ngDevMode ? [{ debugName: "aiEnabled" }] : /* istanbul ignore next */ []));
190587
191922
  /**
190588
191923
  * Stable {@link PptxAiBridge} exposing this viewer's live state + editor to
@@ -191733,7 +193068,7 @@ class PowerPointViewerComponent {
191733
193068
  if (!element) {
191734
193069
  return;
191735
193070
  }
191736
- const node = document.querySelector(`[data-element-id="${element.id}"]`);
193071
+ const node = findCanvasElementNode(document, element.id);
191737
193072
  if (!node) {
191738
193073
  return;
191739
193074
  }
@@ -191777,7 +193112,7 @@ class PowerPointViewerComponent {
191777
193112
  }
191778
193113
  /** Rasterise the mounted node for `elementId` and replace it with a picture, or no-op if unmounted. */
191779
193114
  async rasterizePastedNodeAsPicture(elementId, sourceClone) {
191780
- const node = document.querySelector(`[data-element-id="${elementId}"]`);
193115
+ const node = findCanvasElementNode(document, elementId);
191781
193116
  if (!node) {
191782
193117
  return;
191783
193118
  }
@@ -192242,7 +193577,7 @@ class PowerPointViewerComponent {
192242
193577
  return (this.mainEl()?.nativeElement.querySelector('.pptx-ng-canvas-stage') ?? undefined);
192243
193578
  }
192244
193579
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: PowerPointViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
192245
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: PowerPointViewerComponent, isStandalone: true, selector: "pptx-viewer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, fontsInput: { classPropertyName: "fontsInput", publicName: "fonts", isSignal: true, isRequired: false, transformFunction: null }, canEditInput: { classPropertyName: "canEditInput", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, defaultThemeKey: { classPropertyName: "defaultThemeKey", publicName: "defaultThemeKey", isSignal: true, isRequired: false, transformFunction: null }, availableThemes: { classPropertyName: "availableThemes", publicName: "availableThemes", isSignal: true, isRequired: false, transformFunction: null }, onThemeChange: { classPropertyName: "onThemeChange", publicName: "onThemeChange", isSignal: true, isRequired: false, transformFunction: null }, defaultLocale: { classPropertyName: "defaultLocale", publicName: "defaultLocale", isSignal: true, isRequired: false, transformFunction: null }, availableLocales: { classPropertyName: "availableLocales", publicName: "availableLocales", isSignal: true, isRequired: false, transformFunction: null }, onLocaleChange: { classPropertyName: "onLocaleChange", publicName: "onLocaleChange", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null }, filePath: { classPropertyName: "filePath", publicName: "filePath", isSignal: true, isRequired: false, transformFunction: null }, fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fitPadding: { classPropertyName: "fitPadding", publicName: "fitPadding", isSignal: true, isRequired: false, transformFunction: null }, maxFitScale: { classPropertyName: "maxFitScale", publicName: "maxFitScale", isSignal: true, isRequired: false, transformFunction: null }, autosaveInput: { classPropertyName: "autosaveInput", publicName: "autosave", isSignal: true, isRequired: false, transformFunction: null }, autosaveIntervalMs: { classPropertyName: "autosaveIntervalMs", publicName: "autosaveIntervalMs", isSignal: true, isRequired: false, transformFunction: null }, collaboration: { classPropertyName: "collaboration", publicName: "collaboration", isSignal: true, isRequired: false, transformFunction: null }, authorName: { classPropertyName: "authorName", publicName: "authorName", isSignal: true, isRequired: false, transformFunction: null }, shareDefaults: { classPropertyName: "shareDefaults", publicName: "shareDefaults", isSignal: true, isRequired: false, transformFunction: null }, onOpenFile: { classPropertyName: "onOpenFile", publicName: "onOpenFile", isSignal: true, isRequired: false, transformFunction: null }, smartArt3D: { classPropertyName: "smartArt3D", publicName: "smartArt3D", isSignal: true, isRequired: false, transformFunction: null }, surfaceChart3D: { classPropertyName: "surfaceChart3D", publicName: "surfaceChart3D", isSignal: true, isRequired: false, transformFunction: null }, barChart3D: { classPropertyName: "barChart3D", publicName: "barChart3D", isSignal: true, isRequired: false, transformFunction: null }, lineChart3D: { classPropertyName: "lineChart3D", publicName: "lineChart3D", isSignal: true, isRequired: false, transformFunction: null }, areaChart3D: { classPropertyName: "areaChart3D", publicName: "areaChart3D", isSignal: true, isRequired: false, transformFunction: null }, pieChart3D: { classPropertyName: "pieChart3D", publicName: "pieChart3D", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, ai: { classPropertyName: "ai", publicName: "ai", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeSlideChange: "activeSlideChange", dirtyChange: "dirtyChange", contentChange: "contentChange", propertiesChange: "propertiesChange", modeChange: "modeChange", zoomChange: "zoomChange", selectionChange: "selectionChange", slideCountChange: "slideCountChange", startCollaboration: "startCollaboration", stopCollaboration: "stopCollaboration" }, host: { listeners: { "document:keydown": "onKeyDown($event)", "window:beforeunload": "clearCacheOnUnload()" } }, providers: [...POWER_POINT_VIEWER_PROVIDERS], viewQueries: [{ propertyName: "masterInlineEditor", first: true, predicate: MasterViewCanvasComponent, descendants: true, isSignal: true }, { propertyName: "extraDialogs", first: true, predicate: ViewerExtraDialogsComponent, descendants: true, isSignal: true }, { propertyName: "editorCanvas", first: true, predicate: ["editorCanvas"], descendants: true, isSignal: true }, { propertyName: "mainEl", first: true, predicate: ["mainEl"], descendants: true, isSignal: true }, { propertyName: "viewerRoot", first: true, predicate: ["viewerRoot"], descendants: true, isSignal: true }, { propertyName: "notesBarRef", first: true, predicate: ["notesBar"], descendants: true, isSignal: true }], ngImport: i0, template: `
193580
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: PowerPointViewerComponent, isStandalone: true, selector: "pptx-viewer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, fontsInput: { classPropertyName: "fontsInput", publicName: "fonts", isSignal: true, isRequired: false, transformFunction: null }, canEditInput: { classPropertyName: "canEditInput", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, defaultThemeKey: { classPropertyName: "defaultThemeKey", publicName: "defaultThemeKey", isSignal: true, isRequired: false, transformFunction: null }, availableThemes: { classPropertyName: "availableThemes", publicName: "availableThemes", isSignal: true, isRequired: false, transformFunction: null }, onThemeChange: { classPropertyName: "onThemeChange", publicName: "onThemeChange", isSignal: true, isRequired: false, transformFunction: null }, defaultLocale: { classPropertyName: "defaultLocale", publicName: "defaultLocale", isSignal: true, isRequired: false, transformFunction: null }, availableLocales: { classPropertyName: "availableLocales", publicName: "availableLocales", isSignal: true, isRequired: false, transformFunction: null }, onLocaleChange: { classPropertyName: "onLocaleChange", publicName: "onLocaleChange", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null }, filePath: { classPropertyName: "filePath", publicName: "filePath", isSignal: true, isRequired: false, transformFunction: null }, fileName: { classPropertyName: "fileName", publicName: "fileName", isSignal: true, isRequired: false, transformFunction: null }, fitPadding: { classPropertyName: "fitPadding", publicName: "fitPadding", isSignal: true, isRequired: false, transformFunction: null }, maxFitScale: { classPropertyName: "maxFitScale", publicName: "maxFitScale", isSignal: true, isRequired: false, transformFunction: null }, autosaveInput: { classPropertyName: "autosaveInput", publicName: "autosave", isSignal: true, isRequired: false, transformFunction: null }, autosaveIntervalMs: { classPropertyName: "autosaveIntervalMs", publicName: "autosaveIntervalMs", isSignal: true, isRequired: false, transformFunction: null }, collaboration: { classPropertyName: "collaboration", publicName: "collaboration", isSignal: true, isRequired: false, transformFunction: null }, authorName: { classPropertyName: "authorName", publicName: "authorName", isSignal: true, isRequired: false, transformFunction: null }, shareDefaults: { classPropertyName: "shareDefaults", publicName: "shareDefaults", isSignal: true, isRequired: false, transformFunction: null }, onOpenFile: { classPropertyName: "onOpenFile", publicName: "onOpenFile", isSignal: true, isRequired: false, transformFunction: null }, smartArt3D: { classPropertyName: "smartArt3D", publicName: "smartArt3D", isSignal: true, isRequired: false, transformFunction: null }, surfaceChart3D: { classPropertyName: "surfaceChart3D", publicName: "surfaceChart3D", isSignal: true, isRequired: false, transformFunction: null }, barChart3D: { classPropertyName: "barChart3D", publicName: "barChart3D", isSignal: true, isRequired: false, transformFunction: null }, lineChart3D: { classPropertyName: "lineChart3D", publicName: "lineChart3D", isSignal: true, isRequired: false, transformFunction: null }, areaChart3D: { classPropertyName: "areaChart3D", publicName: "areaChart3D", isSignal: true, isRequired: false, transformFunction: null }, pieChart3D: { classPropertyName: "pieChart3D", publicName: "pieChart3D", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, ai: { classPropertyName: "ai", publicName: "ai", isSignal: true, isRequired: false, transformFunction: null }, customization: { classPropertyName: "customization", publicName: "customization", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeSlideChange: "activeSlideChange", dirtyChange: "dirtyChange", contentChange: "contentChange", propertiesChange: "propertiesChange", modeChange: "modeChange", zoomChange: "zoomChange", selectionChange: "selectionChange", slideCountChange: "slideCountChange", startCollaboration: "startCollaboration", stopCollaboration: "stopCollaboration" }, host: { listeners: { "document:keydown": "onKeyDown($event)", "window:beforeunload": "clearCacheOnUnload()" } }, providers: [...POWER_POINT_VIEWER_PROVIDERS], viewQueries: [{ propertyName: "masterInlineEditor", first: true, predicate: MasterViewCanvasComponent, descendants: true, isSignal: true }, { propertyName: "extraDialogs", first: true, predicate: ViewerExtraDialogsComponent, descendants: true, isSignal: true }, { propertyName: "editorCanvas", first: true, predicate: ["editorCanvas"], descendants: true, isSignal: true }, { propertyName: "mainEl", first: true, predicate: ["mainEl"], descendants: true, isSignal: true }, { propertyName: "viewerRoot", first: true, predicate: ["viewerRoot"], descendants: true, isSignal: true }, { propertyName: "notesBarRef", first: true, predicate: ["notesBar"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
192246
193581
  <div
192247
193582
  #viewerRoot
192248
193583
  class="pptx-ng-viewer"
@@ -192300,27 +193635,29 @@ class PowerPointViewerComponent {
192300
193635
  />
192301
193636
  }
192302
193637
  @if (!mobile.isMobile() && chromeVisible()) {
192303
- <pptx-title-bar
192304
- [canEdit]="canEdit()"
192305
- [fileName]="fileName()"
192306
- [isDirty]="editor.dirty()"
192307
- [autosaveStatus]="autosave.status()"
192308
- [autosaveEnabled]="autosaveActivation().active"
192309
- [canUndo]="editor.canUndo()"
192310
- [canRedo]="editor.canRedo()"
192311
- [undoLabel]="editor.undoLabel()"
192312
- [redoLabel]="editor.redoLabel()"
192313
- [findReplaceOpen]="findReplace.showFind() || findReplace.showFindReplace()"
192314
- [hiddenActions]="effectiveHiddenActions()"
192315
- [quickAccess]="viewerOpts.options().quickAccess"
192316
- (toggleAutosave)="toggleAutosave()"
192317
- (save)="fileIO.saveAsPptx()"
192318
- (undo)="editor.undo()"
192319
- (redo)="editor.redo()"
192320
- (quickCommand)="onQuickAccessCommand($event)"
192321
- (toggleFindReplace)="toggleFindReplace()"
192322
- (commandSearch)="handleCommandSearch($event)"
192323
- />
193638
+ @if (customizationService.panelVisible('titleBar')) {
193639
+ <pptx-title-bar
193640
+ [canEdit]="canEdit()"
193641
+ [fileName]="fileName()"
193642
+ [isDirty]="editor.dirty()"
193643
+ [autosaveStatus]="autosave.status()"
193644
+ [autosaveEnabled]="autosaveActivation().active"
193645
+ [canUndo]="editor.canUndo()"
193646
+ [canRedo]="editor.canRedo()"
193647
+ [undoLabel]="editor.undoLabel()"
193648
+ [redoLabel]="editor.redoLabel()"
193649
+ [findReplaceOpen]="findReplace.showFind() || findReplace.showFindReplace()"
193650
+ [hiddenActions]="effectiveHiddenActions()"
193651
+ [quickAccess]="customizationService.quickAccess(viewerOpts.options().quickAccess)"
193652
+ (toggleAutosave)="toggleAutosave()"
193653
+ (save)="fileIO.saveAsPptx()"
193654
+ (undo)="editor.undo()"
193655
+ (redo)="editor.redo()"
193656
+ (quickCommand)="onQuickAccessCommand($event)"
193657
+ (toggleFindReplace)="toggleFindReplace()"
193658
+ (commandSearch)="handleCommandSearch($event)"
193659
+ />
193660
+ }
192324
193661
  <pptx-ribbon
192325
193662
  [slideIndex]="activeSlideIndex()"
192326
193663
  [slideCount]="slideCount()"
@@ -192472,7 +193809,13 @@ class PowerPointViewerComponent {
192472
193809
  }
192473
193810
 
192474
193811
  <div class="pptx-ng-body">
192475
- @if (canEdit() && !mobile.isMobile() && !slidesPanelCollapsed() && chromeVisible()) {
193812
+ @if (
193813
+ canEdit() &&
193814
+ !mobile.isMobile() &&
193815
+ !slidesPanelCollapsed() &&
193816
+ chromeVisible() &&
193817
+ customizationService.panelVisible('slidesPane')
193818
+ ) {
192476
193819
  <pptx-slides-panel
192477
193820
  [canvasSize]="loader.canvasSize()"
192478
193821
  [mediaDataUrls]="loader.mediaDataUrls()"
@@ -192487,7 +193830,9 @@ class PowerPointViewerComponent {
192487
193830
  goTo($event.index); canvasLayoutGalleryPos.set({ x: $event.x, y: $event.y })
192488
193831
  "
192489
193832
  />
192490
- } @else if (!canEdit() && chromeVisible()) {
193833
+ } @else if (
193834
+ !canEdit() && chromeVisible() && customizationService.panelVisible('slidesPane')
193835
+ ) {
192491
193836
  <nav class="pptx-ng-thumbnails" [attr.aria-label]="'pptx.sections.slides' | translate">
192492
193837
  @for (slide of displaySlides(); track slide.id; let i = $index) {
192493
193838
  <button
@@ -192623,7 +193968,12 @@ class PowerPointViewerComponent {
192623
193968
  swipe past the threshold sets mobileInspectorHidden so the user
192624
193969
  reclaims the canvas.
192625
193970
  -->
192626
- @if (chromeVisible() ? inspectorPanel.visibleInspectorKind() : null; as kind) {
193971
+ @if (
193972
+ chromeVisible() && customizationService.panelVisible('inspector')
193973
+ ? inspectorPanel.visibleInspectorKind()
193974
+ : null;
193975
+ as kind
193976
+ ) {
192627
193977
  <!--
192628
193978
  Mobile-only tap-to-dismiss backdrop behind the inspector sheet
192629
193979
  (hidden on desktop via CSS, mirroring React's MobileDismissSheet).
@@ -192722,7 +194072,7 @@ class PowerPointViewerComponent {
192722
194072
  -->
192723
194073
  @defer (when ai() && aiPanelOpen()) {
192724
194074
  @if (ai(); as aiConfig) {
192725
- @if (aiPanelOpen() && chromeVisible()) {
194075
+ @if (aiPanelOpen() && chromeVisible() && aiEnabled()) {
192726
194076
  <pptx-ai-chat-panel
192727
194077
  [bridge]="aiBridge"
192728
194078
  [config]="aiConfig"
@@ -192739,7 +194089,12 @@ class PowerPointViewerComponent {
192739
194089
  status bar to match React/Vanilla, rather than nested under the
192740
194090
  canvas column inside <main>.
192741
194091
  -->
192742
- @if (canEdit() && !mobile.isMobile() && chromeVisible()) {
194092
+ @if (
194093
+ canEdit() &&
194094
+ !mobile.isMobile() &&
194095
+ chromeVisible() &&
194096
+ customizationService.panelVisible('notes')
194097
+ ) {
192743
194098
  <aside
192744
194099
  #notesBar
192745
194100
  class="pptx-ng-notes"
@@ -192755,7 +194110,9 @@ class PowerPointViewerComponent {
192755
194110
  </aside>
192756
194111
  }
192757
194112
 
192758
- @if (!mobile.isMobile() && chromeVisible()) {
194113
+ @if (
194114
+ !mobile.isMobile() && chromeVisible() && customizationService.panelVisible('statusBar')
194115
+ ) {
192759
194116
  <pptx-status-bar
192760
194117
  [slideIndex]="activeSlideIndex()"
192761
194118
  [slideCount]="slideCount()"
@@ -193107,7 +194464,7 @@ class PowerPointViewerComponent {
193107
194464
  />
193108
194465
 
193109
194466
  <pptx-share-dialog
193110
- [open]="session.showShare()"
194467
+ [open]="session.showShare() && customizationService.dialogAvailable('share')"
193111
194468
  [active]="collab.active()"
193112
194469
  [connected]="collab.connected()"
193113
194470
  [userCount]="collab.connectedCount()"
@@ -193123,7 +194480,7 @@ class PowerPointViewerComponent {
193123
194480
  />
193124
194481
 
193125
194482
  <pptx-broadcast-dialog
193126
- [open]="session.showBroadcast()"
194483
+ [open]="session.showBroadcast() && customizationService.dialogAvailable('broadcast')"
193127
194484
  [active]="collab.active()"
193128
194485
  [connected]="collab.connected()"
193129
194486
  [viewerCount]="collab.presence().length"
@@ -193206,7 +194563,7 @@ class PowerPointViewerComponent {
193206
194563
  the visual viewport ends up below the document on mobile (100vh layout
193207
194564
  viewport < dynamic viewport), leaving its textarea unreachable to taps.
193208
194565
  Mirrors React, where the notes panel is a flow sibling below the canvas. -->
193209
- @if (mobileSheetSvc.showNotes()) {
194566
+ @if (mobileSheetSvc.showNotes() && customizationService.panelVisible('notes')) {
193210
194567
  <div
193211
194568
  class="pptx-ng-mobile-notes-sheet"
193212
194569
  [style.transform]="
@@ -193392,27 +194749,29 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193392
194749
  />
193393
194750
  }
193394
194751
  @if (!mobile.isMobile() && chromeVisible()) {
193395
- <pptx-title-bar
193396
- [canEdit]="canEdit()"
193397
- [fileName]="fileName()"
193398
- [isDirty]="editor.dirty()"
193399
- [autosaveStatus]="autosave.status()"
193400
- [autosaveEnabled]="autosaveActivation().active"
193401
- [canUndo]="editor.canUndo()"
193402
- [canRedo]="editor.canRedo()"
193403
- [undoLabel]="editor.undoLabel()"
193404
- [redoLabel]="editor.redoLabel()"
193405
- [findReplaceOpen]="findReplace.showFind() || findReplace.showFindReplace()"
193406
- [hiddenActions]="effectiveHiddenActions()"
193407
- [quickAccess]="viewerOpts.options().quickAccess"
193408
- (toggleAutosave)="toggleAutosave()"
193409
- (save)="fileIO.saveAsPptx()"
193410
- (undo)="editor.undo()"
193411
- (redo)="editor.redo()"
193412
- (quickCommand)="onQuickAccessCommand($event)"
193413
- (toggleFindReplace)="toggleFindReplace()"
193414
- (commandSearch)="handleCommandSearch($event)"
193415
- />
194752
+ @if (customizationService.panelVisible('titleBar')) {
194753
+ <pptx-title-bar
194754
+ [canEdit]="canEdit()"
194755
+ [fileName]="fileName()"
194756
+ [isDirty]="editor.dirty()"
194757
+ [autosaveStatus]="autosave.status()"
194758
+ [autosaveEnabled]="autosaveActivation().active"
194759
+ [canUndo]="editor.canUndo()"
194760
+ [canRedo]="editor.canRedo()"
194761
+ [undoLabel]="editor.undoLabel()"
194762
+ [redoLabel]="editor.redoLabel()"
194763
+ [findReplaceOpen]="findReplace.showFind() || findReplace.showFindReplace()"
194764
+ [hiddenActions]="effectiveHiddenActions()"
194765
+ [quickAccess]="customizationService.quickAccess(viewerOpts.options().quickAccess)"
194766
+ (toggleAutosave)="toggleAutosave()"
194767
+ (save)="fileIO.saveAsPptx()"
194768
+ (undo)="editor.undo()"
194769
+ (redo)="editor.redo()"
194770
+ (quickCommand)="onQuickAccessCommand($event)"
194771
+ (toggleFindReplace)="toggleFindReplace()"
194772
+ (commandSearch)="handleCommandSearch($event)"
194773
+ />
194774
+ }
193416
194775
  <pptx-ribbon
193417
194776
  [slideIndex]="activeSlideIndex()"
193418
194777
  [slideCount]="slideCount()"
@@ -193564,7 +194923,13 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193564
194923
  }
193565
194924
 
193566
194925
  <div class="pptx-ng-body">
193567
- @if (canEdit() && !mobile.isMobile() && !slidesPanelCollapsed() && chromeVisible()) {
194926
+ @if (
194927
+ canEdit() &&
194928
+ !mobile.isMobile() &&
194929
+ !slidesPanelCollapsed() &&
194930
+ chromeVisible() &&
194931
+ customizationService.panelVisible('slidesPane')
194932
+ ) {
193568
194933
  <pptx-slides-panel
193569
194934
  [canvasSize]="loader.canvasSize()"
193570
194935
  [mediaDataUrls]="loader.mediaDataUrls()"
@@ -193579,7 +194944,9 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193579
194944
  goTo($event.index); canvasLayoutGalleryPos.set({ x: $event.x, y: $event.y })
193580
194945
  "
193581
194946
  />
193582
- } @else if (!canEdit() && chromeVisible()) {
194947
+ } @else if (
194948
+ !canEdit() && chromeVisible() && customizationService.panelVisible('slidesPane')
194949
+ ) {
193583
194950
  <nav class="pptx-ng-thumbnails" [attr.aria-label]="'pptx.sections.slides' | translate">
193584
194951
  @for (slide of displaySlides(); track slide.id; let i = $index) {
193585
194952
  <button
@@ -193715,7 +195082,12 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193715
195082
  swipe past the threshold sets mobileInspectorHidden so the user
193716
195083
  reclaims the canvas.
193717
195084
  -->
193718
- @if (chromeVisible() ? inspectorPanel.visibleInspectorKind() : null; as kind) {
195085
+ @if (
195086
+ chromeVisible() && customizationService.panelVisible('inspector')
195087
+ ? inspectorPanel.visibleInspectorKind()
195088
+ : null;
195089
+ as kind
195090
+ ) {
193719
195091
  <!--
193720
195092
  Mobile-only tap-to-dismiss backdrop behind the inspector sheet
193721
195093
  (hidden on desktop via CSS, mirroring React's MobileDismissSheet).
@@ -193814,7 +195186,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193814
195186
  -->
193815
195187
  @defer (when ai() && aiPanelOpen()) {
193816
195188
  @if (ai(); as aiConfig) {
193817
- @if (aiPanelOpen() && chromeVisible()) {
195189
+ @if (aiPanelOpen() && chromeVisible() && aiEnabled()) {
193818
195190
  <pptx-ai-chat-panel
193819
195191
  [bridge]="aiBridge"
193820
195192
  [config]="aiConfig"
@@ -193831,7 +195203,12 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193831
195203
  status bar to match React/Vanilla, rather than nested under the
193832
195204
  canvas column inside <main>.
193833
195205
  -->
193834
- @if (canEdit() && !mobile.isMobile() && chromeVisible()) {
195206
+ @if (
195207
+ canEdit() &&
195208
+ !mobile.isMobile() &&
195209
+ chromeVisible() &&
195210
+ customizationService.panelVisible('notes')
195211
+ ) {
193835
195212
  <aside
193836
195213
  #notesBar
193837
195214
  class="pptx-ng-notes"
@@ -193847,7 +195224,9 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
193847
195224
  </aside>
193848
195225
  }
193849
195226
 
193850
- @if (!mobile.isMobile() && chromeVisible()) {
195227
+ @if (
195228
+ !mobile.isMobile() && chromeVisible() && customizationService.panelVisible('statusBar')
195229
+ ) {
193851
195230
  <pptx-status-bar
193852
195231
  [slideIndex]="activeSlideIndex()"
193853
195232
  [slideCount]="slideCount()"
@@ -194199,7 +195578,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
194199
195578
  />
194200
195579
 
194201
195580
  <pptx-share-dialog
194202
- [open]="session.showShare()"
195581
+ [open]="session.showShare() && customizationService.dialogAvailable('share')"
194203
195582
  [active]="collab.active()"
194204
195583
  [connected]="collab.connected()"
194205
195584
  [userCount]="collab.connectedCount()"
@@ -194215,7 +195594,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
194215
195594
  />
194216
195595
 
194217
195596
  <pptx-broadcast-dialog
194218
- [open]="session.showBroadcast()"
195597
+ [open]="session.showBroadcast() && customizationService.dialogAvailable('broadcast')"
194219
195598
  [active]="collab.active()"
194220
195599
  [connected]="collab.connected()"
194221
195600
  [viewerCount]="collab.presence().length"
@@ -194298,7 +195677,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
194298
195677
  the visual viewport ends up below the document on mobile (100vh layout
194299
195678
  viewport < dynamic viewport), leaving its textarea unreachable to taps.
194300
195679
  Mirrors React, where the notes panel is a flow sibling below the canvas. -->
194301
- @if (mobileSheetSvc.showNotes()) {
195680
+ @if (mobileSheetSvc.showNotes() && customizationService.panelVisible('notes')) {
194302
195681
  <div
194303
195682
  class="pptx-ng-mobile-notes-sheet"
194304
195683
  [style.transform]="
@@ -194359,7 +195738,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
194359
195738
  </div>
194360
195739
  `,
194361
195740
  }]
194362
- }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], fontsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "fonts", required: false }] }], canEditInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], defaultThemeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultThemeKey", required: false }] }], availableThemes: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableThemes", required: false }] }], onThemeChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onThemeChange", required: false }] }], defaultLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultLocale", required: false }] }], availableLocales: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLocales", required: false }] }], onLocaleChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onLocaleChange", required: false }] }], accountAuth: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountAuth", required: false }] }], filePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "filePath", required: false }] }], fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fitPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitPadding", required: false }] }], maxFitScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFitScale", required: false }] }], autosaveInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosave", required: false }] }], autosaveIntervalMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosaveIntervalMs", required: false }] }], collaboration: [{ type: i0.Input, args: [{ isSignal: true, alias: "collaboration", required: false }] }], authorName: [{ type: i0.Input, args: [{ isSignal: true, alias: "authorName", required: false }] }], shareDefaults: [{ type: i0.Input, args: [{ isSignal: true, alias: "shareDefaults", required: false }] }], onOpenFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "onOpenFile", required: false }] }], smartArt3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "smartArt3D", required: false }] }], surfaceChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceChart3D", required: false }] }], barChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "barChart3D", required: false }] }], lineChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineChart3D", required: false }] }], areaChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "areaChart3D", required: false }] }], pieChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieChart3D", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], ai: [{ type: i0.Input, args: [{ isSignal: true, alias: "ai", required: false }] }], activeSlideChange: [{ type: i0.Output, args: ["activeSlideChange"] }], dirtyChange: [{ type: i0.Output, args: ["dirtyChange"] }], contentChange: [{ type: i0.Output, args: ["contentChange"] }], propertiesChange: [{ type: i0.Output, args: ["propertiesChange"] }], modeChange: [{ type: i0.Output, args: ["modeChange"] }], zoomChange: [{ type: i0.Output, args: ["zoomChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], slideCountChange: [{ type: i0.Output, args: ["slideCountChange"] }], startCollaboration: [{ type: i0.Output, args: ["startCollaboration"] }], stopCollaboration: [{ type: i0.Output, args: ["stopCollaboration"] }], masterInlineEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MasterViewCanvasComponent), { isSignal: true }] }], extraDialogs: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ViewerExtraDialogsComponent), { isSignal: true }] }], editorCanvas: [{ type: i0.ViewChild, args: ['editorCanvas', { isSignal: true }] }], mainEl: [{ type: i0.ViewChild, args: ['mainEl', { isSignal: true }] }], viewerRoot: [{ type: i0.ViewChild, args: ['viewerRoot', { isSignal: true }] }], notesBarRef: [{ type: i0.ViewChild, args: ['notesBar', { isSignal: true }] }], onKeyDown: [{
195741
+ }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], fontsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "fonts", required: false }] }], canEditInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], defaultThemeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultThemeKey", required: false }] }], availableThemes: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableThemes", required: false }] }], onThemeChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onThemeChange", required: false }] }], defaultLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultLocale", required: false }] }], availableLocales: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableLocales", required: false }] }], onLocaleChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onLocaleChange", required: false }] }], accountAuth: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountAuth", required: false }] }], filePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "filePath", required: false }] }], fileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileName", required: false }] }], fitPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitPadding", required: false }] }], maxFitScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFitScale", required: false }] }], autosaveInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosave", required: false }] }], autosaveIntervalMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "autosaveIntervalMs", required: false }] }], collaboration: [{ type: i0.Input, args: [{ isSignal: true, alias: "collaboration", required: false }] }], authorName: [{ type: i0.Input, args: [{ isSignal: true, alias: "authorName", required: false }] }], shareDefaults: [{ type: i0.Input, args: [{ isSignal: true, alias: "shareDefaults", required: false }] }], onOpenFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "onOpenFile", required: false }] }], smartArt3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "smartArt3D", required: false }] }], surfaceChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceChart3D", required: false }] }], barChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "barChart3D", required: false }] }], lineChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineChart3D", required: false }] }], areaChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "areaChart3D", required: false }] }], pieChart3D: [{ type: i0.Input, args: [{ isSignal: true, alias: "pieChart3D", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], ai: [{ type: i0.Input, args: [{ isSignal: true, alias: "ai", required: false }] }], customization: [{ type: i0.Input, args: [{ isSignal: true, alias: "customization", required: false }] }], activeSlideChange: [{ type: i0.Output, args: ["activeSlideChange"] }], dirtyChange: [{ type: i0.Output, args: ["dirtyChange"] }], contentChange: [{ type: i0.Output, args: ["contentChange"] }], propertiesChange: [{ type: i0.Output, args: ["propertiesChange"] }], modeChange: [{ type: i0.Output, args: ["modeChange"] }], zoomChange: [{ type: i0.Output, args: ["zoomChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], slideCountChange: [{ type: i0.Output, args: ["slideCountChange"] }], startCollaboration: [{ type: i0.Output, args: ["startCollaboration"] }], stopCollaboration: [{ type: i0.Output, args: ["stopCollaboration"] }], masterInlineEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MasterViewCanvasComponent), { isSignal: true }] }], extraDialogs: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ViewerExtraDialogsComponent), { isSignal: true }] }], editorCanvas: [{ type: i0.ViewChild, args: ['editorCanvas', { isSignal: true }] }], mainEl: [{ type: i0.ViewChild, args: ['mainEl', { isSignal: true }] }], viewerRoot: [{ type: i0.ViewChild, args: ['viewerRoot', { isSignal: true }] }], notesBarRef: [{ type: i0.ViewChild, args: ['notesBar', { isSignal: true }] }], onKeyDown: [{
194363
195742
  type: HostListener,
194364
195743
  args: ['document:keydown', ['$event']]
194365
195744
  }], clearCacheOnUnload: [{
@@ -196774,5 +198153,5 @@ function cn(...values) {
196774
198153
  * Generated bundle index. Do not edit.
196775
198154
  */
196776
198155
 
196777
- export { ChartAxisOptionsComponent as $, AFTER_ANIMATION_VALUES as A, ActionSettingsPanelComponent as B, CHART_3D_DRAG_THRESHOLD_PX as C, AdvancedChartEditorComponent as D, AiChangeOverlayComponent as E, AiChatPanelComponent as F, AiChatService as G, AiComposerComponent as H, AiFocusBarComponent as I, AiFocusHighlightOverlayComponent as J, AiHistoryMenuComponent as K, AiHistoryService as L, AiMessageListComponent as M, AiPanelStore as N, AiProposalCardComponent as O, AiSettingsSectionComponent as P, AiToolCallCardComponent as Q, AnimationAuthorPanelComponent as R, AnimationPanelComponent as S, AnimationPlaybackService as T, AutosaveRecoveryDialogComponent as U, AutosaveService as V, BroadcastDialogComponent as W, CHART_EDITOR_STYLES as X, CINEMATIC_TRANSITION_KEYFRAMES as Y, CURSOR_PALETTE as Z, CanvasFitService as _, renderChartTextSvg as a, ExportProgressModalComponent as a$, ChartAxisStyleOptionsComponent as a0, ChartComboTypeOptionsComponent as a1, ChartDataEditorComponent as a2, ChartDataLabelOptionsComponent as a3, ChartDatapointMarkerOptionsComponent as a4, ChartDatapointOptionsComponent as a5, ChartDisplayOptionsComponent as a6, ChartElementViewComponent as a7, ChartErrorBarOptionsComponent as a8, ChartMarkerOptionsComponent as a9, DEFAULT_SLIDE_BACKGROUND as aA, DEFAULT_STROKE_COLOR as aB, DEFAULT_STYLE as aC, DEFAULT_TABLE_ROW_HEIGHT as aD, DEFAULT_TEXT_COLOR$2 as aE, DEFAULT_VIEWER_PROFILE as aF, DIRECTIONAL_PRESETS as aG, DIRECTION_OPTIONS as aH, DocumentPropertiesCardComponent as aI, EASE as aJ, EFFECT_SOUND_CATALOGUE as aK, EMBEDDED_FONTS_STYLE_ID as aL, EMPHASIS_PRESETS as aM, ENTRANCE_PRESETS as aN, TEMPLATES as aO, EXIT_PRESETS as aP, EditorContextMenuComponent as aQ, EditorHistory as aR, EditorStateService as aS, EditorToolbarComponent as aT, EffectsPanelComponent as aU, ElementRendererComponent as aV, EmbeddedFontsService as aW, EncryptedFileDialogComponent as aX, EquationEditorDialogComponent as aY, EquationRendererComponent as aZ, EquationTemplateGalleryComponent as a_, ChartPartSelectionService as aa, ChartPrimitivesComponent as ab, ChartRendererComponent as ac, ChartTrendlineOptionsComponent as ad, ChartTypeSelectorComponent as ae, CollaborationCursorsComponent as af, CollaborationService as ag, ColorChangedImageComponent as ah, CommentMarkersOverlayComponent as ai, CommentsPanelComponent as aj, CommentsService as ak, ComparePanelComponent as al, ConnectorRendererComponent as am, ConnectorTextOverlayComponent as an, CustomShowsComponent as ao, DEFAULT_BOUNDS as ap, DEFAULT_BROADCAST_SERVER_URL as aq, DEFAULT_CANVAS_HEIGHT as ar, DEFAULT_CANVAS_WIDTH as as, DEFAULT_COLOR_SCHEME as at, DEFAULT_FILL_COLOR$1 as au, DEFAULT_LAYOUT as av, DEFAULT_MORPH_DURATION_MS as aw, DEFAULT_PALETTE$1 as ax, DEFAULT_PATTERN_FILL_PRESET as ay, DEFAULT_PRINT_SETTINGS as az, appendChartLegendSvg as b, PresentToolbarAutoHide as b$, ExportService as b0, FieldContextService as b1, FindBarComponent as b2, FindReplaceBarComponent as b3, FollowModeBarComponent as b4, FontEmbeddingListComponent as b5, FontEmbeddingPanelComponent as b6, GALLERY_THEME_PRESETS as b7, GOOGLE_WEBFONTS_LINK_ID as b8, GRIDLINE_COLOR$1 as b9, MobileBottomBarComponent as bA, MobileMenuSheetComponent as bB, MobilePresenterViewComponent as bC, MobileSheetComponent as bD, MobileSlidesSheetComponent as bE, MobileToolbarComponent as bF, ModalDialogComponent as bG, Model3DRendererComponent as bH, NotesHandoutCardComponent as bI, NotesPanelComponent as bJ, NotesToolbarComponent as bK, OleRendererComponent as bL, OutlineViewOverlayComponent as bM, P14_TRANSITION_KEYFRAMES as bN, P14_TRANSITION_KEYFRAMES_2 as bO, P14_TRANSITION_KEYFRAMES_ALL as bP, POWER_POINT_VIEWER_PROVIDERS as bQ, PPTX_OPEN_ACCEPT as bR, PRESENTATION_OPEN_EXTENSIONS as bS, PRESENTER_CHANNEL_NAME as bT, PRESENTER_MSG_ORIGIN as bU, PRESENTER_TIMER_SEGMENT_MS as bV, PX_PER_CM as bW, PX_PER_INCH as bX, PasswordProtectionDialogComponent as bY, PasswordStrengthMeterComponent as bZ, PowerPointViewerComponent as b_, GoogleWebfontsService as ba, GradientPickerComponent as bb, HANDOUT_OPTIONS as bc, HeaderFooterDialogComponent as bd, HyperlinkDialogComponent as be, INSTANT as bf, ImagePropertiesPanelComponent as bg, InkDrawingService as bh, InkRendererComponent as bi, InsertSmartArtDialogComponent as bj, InspectorPaneHeaderComponent as bk, InspectorPanelComponent as bl, IsMobileService as bm, KeepAnnotationsDialogComponent as bn, LOCALE_CATALOG as bo, LONG_PRESS_DURATION_MS as bp, LONG_PRESS_MOVE_TOLERANCE_PX as bq, LoadContentService as br, LocalPresencePublisher as bs, MAX_ZOOM_SCALE as bt, MIN_ZOOM_SCALE as bu, MOTION_PATH_COLUMNS as bv, MediaPreviewComponent as bw, MediaPropertiesPanelComponent as bx, MediaRendererComponent as by, MediaTrimTimelineComponent as bz, createSvgEl as c, SettingsAppearanceTabComponent as c$, PresentationAnnotationOverlayComponent as c0, PresentationAnnotationsService as c1, PresentationOverlayComponent as c2, PresentationPropertiesPanelComponent as c3, PresentationSettingsCardComponent as c4, PresentationSubtitleBarComponent as c5, PresentationToolbarComponent as c6, PresentationTransitionOverlayComponent as c7, PresenterViewComponent as c8, PresenterWindowService as c9, RibbonInsertSectionComponent as cA, RibbonMotionPathGalleryComponent as cB, RibbonParagraphControlsComponent as cC, RibbonPrimaryRowComponent as cD, RibbonReviewSectionComponent as cE, RibbonShapeExtrasComponent as cF, RibbonSlideshowSectionComponent as cG, RibbonTransitionsSectionComponent as cH, RibbonViewSectionComponent as cI, RulerGuidesService as cJ, SEQUENCE_OPTIONS as cK, SEVERITY_GROUPS as cL, SEVERITY_LABELS as cM, DEFAULT_TRANSITION_DURATION_MS$1 as cN, SHORTCUT_REFERENCE_ITEMS as cO, SLIDE_TRANSITION_KEYFRAMES as cP, SLIDE_TRANSITION_KEYFRAMES_CSS as cQ, DEFAULT_PALETTE as cR, PALETTES as cS, SMART_ART_COLOR_SCHEMES as cT, SMART_ART_STYLE_OPTIONS as cU, SUB_ITEM_LABEL as cV, SVG_WARP_PRESETS as cW, SWIPE_MAX_VERTICAL_PX as cX, SWIPE_THRESHOLD_PX as cY, SelectionPaneComponent as cZ, SetUpSlideShowDialogComponent as c_, PrintDialogComponent as ca, PrintService as cb, PrintSettingsPanelComponent as cc, PropertiesDialogComponent as cd, RANDOM_ELIGIBLE_TYPES as ce, REPEAT_MODE_OPTIONS as cf, RESIZE_HANDLES as cg, RULER_FONT_SIZE as ch, RULER_THICKNESS as ci, ReadingViewOverlayComponent as cj, RemoteSelectionOverlayComponent as ck, Rendering3DService as cl, RibbonAnimationGalleryComponent as cm, RibbonAnimationsSectionComponent as cn, RibbonArrangeSectionComponent as co, RibbonColorPopoverComponent as cp, RibbonComponent as cq, RibbonDesignSectionComponent as cr, RibbonDrawSectionComponent as cs, RibbonDrawingGroupComponent as ct, RibbonEditingSectionComponent as cu, RibbonFileSectionComponent as cv, RibbonFontControlsComponent as cw, RibbonHomeSectionComponent as cx, RibbonHyperlinkButtonComponent as cy, RibbonInsertFieldsComponent as cz, dragAnchorViewY as d, ViewerDocumentPropertiesService as d$, SettingsDialogComponent as d0, SettingsLanguageTabComponent as d1, ShareDialogComponent as d2, ShortcutPanelComponent as d3, ShowOptionsFieldsetComponent as d4, ShowSlidesFieldsetComponent as d5, SignatureStrippedDialogComponent as d6, SignaturesPanelComponent as d7, SignaturesService as d8, SlideBackgroundCardComponent as d9, TableCellFormattingComponent as dA, TableDataEditorComponent as dB, TablePropertiesComponent as dC, TableRendererComponent as dD, TableResizeOverlayComponent as dE, TableSelectionService as dF, TagsCardComponent as dG, Text3DBevelSectionComponent as dH, Text3DPanelComponent as dI, TextAdvancedPanelComponent as dJ, ThemeEditorFieldsComponent as dK, ThemeGalleryComponent as dL, ThemeSelectorCardComponent as dM, TitleBarComponent as dN, TitleBarSearchComponent as dO, TransitionDirectionPickerComponent as dP, TransitionPreviewComponent as dQ, VALIGN_OPTIONS as dR, VIEWER_THEME as dS, VersionHistoryPanelComponent as dT, ViewerCanvasEditingService as dU, ViewerCollabCursorService as dV, ViewerCollaborationSessionService as dW, ViewerCollaborationShellService as dX, ViewerCompareService as dY, ViewerCustomShowsService as dZ, ViewerDialogsService as d_, SlideCanvasComponent as da, SlideDefaultInspectorComponent as db, SlideDiffChangesComponent as dc, SlideDiffRowComponent as dd, SlideDiffThumbnailsComponent as de, SlideSizeCardComponent as df, SlideSorterOverlayComponent as dg, SlideThemeOverridePanelComponent as dh, SlideTransitionCardComponent as di, SlidesPanelComponent as dj, SmartArt3DRendererComponent as dk, SmartArtPreviewComponent as dl, SmartArtPropertiesComponent as dm, SmartArtRendererComponent as dn, StatusBarComponent as dp, TABLE_STRUCTURE_TOGGLES as dq, TEXT_3D_BOTTOM_BEVEL_KEYS as dr, TEXT_3D_TOP_BEVEL_KEYS as ds, TEXT_DIRECTION_OPTIONS$1 as dt, THEME_CATALOG as du, TIMING_CURVE_OPTIONS as dv, TRANSITION_SPEED_DURATION_MS as dw, TRIGGER_OPTIONS as dx, TYPE_LABELS as dy, TableCellAdvancedFillComponent as dz, advanceChartValueDrag as e, buildCssGradientFromShapeStyle as e$, ViewerExportService as e0, ViewerExtraDialogsComponent as e1, ViewerFileIOService as e2, ViewerFindReplaceService as e3, ViewerFormatPainterService as e4, ViewerInspectorPanelService as e5, ViewerKeyboardService as e6, ViewerMobileSheetService as e7, ViewerPresentationModeService as e8, ViewerThemeGalleryService as e9, applyMove as eA, applyResize as eB, asMediaElement as eC, assignUserColor as eD, attachShowVisibilityPause as eE, attachTouchGestures as eF, axisTickValues as eG, beginDrawingNodeEdit as eH, beginNodeEdit as eI, bevelSizePatch as eJ, boolFromEvent as eK, bringForward as eL, bringToFront as eM, buildBarActions as eN, buildBroadcastConfig as eO, buildBroadcastViewerUrl as eP, buildCategoryLabels as eQ, buildCellParagraphs as eR, buildChartViewModel as eS, buildChatLogExport as eT, buildChatLogMarkdown as eU, buildChromeStyle as eV, buildClearHyperlinkPatch as eW, buildClickGroups as eX, buildColStyles as eY, buildCollaborationConfig as eZ, buildComboViewModel as e_, ViewerTouchGesturesService as ea, ViewerZoomService as eb, WEBM_MIME_CANDIDATES as ec, WHEEL_SPOKE_COUNTS as ed, WriteBackScheduler as ee, ZERO_LINE_COLOR as ef, ZoomNavigationService as eg, ZoomRendererComponent as eh, ZoomTargetService as ei, addCategory as ej, addCommentToList as ek, addGradientStopPatch as el, addItem as em, addSeries as en, addSubItem as eo, advanceStep as ep, affordanceElements as eq, aiToggleVisible as er, alignPatch as es, animationFor as et, animationPresetLabelKey as eu, annotationMapToInkInserts as ev, applyAcceptedDiff as ew, applyAnimationPreset as ex, applyFindReplacements as ey, applyFormatToElement as ez, buildBarChart3DHoverTooltip as f, clearAllLocalViewerData as f$, buildDuotoneFilter as f0, buildDuotoneFilterId as f1, buildEmbeddedFontStyles as f2, buildEquationElement as f3, buildEquationSegment as f4, buildFallbackViewModel as f5, buildFontFaceRule as f6, buildGradientFillCss as f7, buildGridlinesAndLabels as f8, buildHyperlinkPatch as f9, buildZoomContainerStyle as fA, buildZoomViewModel as fB, bulletIndentPx as fC, canAddTopLevelNode as fD, canEditSmartArtNodes as fE, canGroupSelection as fF, canRemoveTopLevelNode as fG, canSetStrokeWidth as fH, canStartBroadcast as fI, canStartShare as fJ, canUngroupSelection as fK, canUseClipboard as fL, captionDisplayText as fM, cellRunStyle as fN, cellStyleToStyleMap as fO, cellTdStyle as fP, changeCountLabel as fQ, changeIcon as fR, characterSpacingPatch as fS, chartPreserveAspectRatio as fT, checkFontAvailable as fU, clampCursorPosition as fV, clampGifDimensions as fW, clampIndex as fX, clampNotesFontSize as fY, clampScale as fZ, clampStep as f_, buildInkContainerStyle as fa, buildInkStrokes as fb, buildLegend as fc, buildLiveInkStrokeView as fd, buildMarkTooltip as fe, buildModel3DContainerStyle as ff, buildModel3DViewModel as fg, buildOleActionModel as fh, buildOleInfoRows as fi, buildPatternFillCss as fj, buildPieViewModel as fk, buildPrintHtmlDocument as fl, buildPropertiesPatch as fm, buildRadarViewModel as fn, buildRegionMapViewModel as fo, buildSaveSlides as fp, buildShareUrl as fq, buildSmartArtInsertElement as fr, buildSmartArtNodes as fs, buildStockViewModel as ft, buildSurfaceViewModel as fu, buildTableViewModel as fv, buildTreemapViewModel as fw, buildTrimFragment as fx, buildWaterfallViewModel as fy, buildZeroLine as fz, beginChartValueDrag as g, demoteNode as g$, clearAudienceContent as g0, cn as g1, collectAccessibilityIssues as g2, collectElementText as g3, collectSlideText as g4, collectStoredChats as g5, collectUsedFontFamilies as g6, columnWidthStyle as g7, commitNodeText as g8, computeAlign as g9, computeSelectionBoxes as gA, computeSingleSelected as gB, computeSlideIndices as gC, computeSnap as gD, computeStackedBarRects as gE, computeStackedValueRange as gF, computeTrendlinePrimitives as gG, computeValueRange as gH, convertOmmlToMathMl as gI, copyFormatFromElement as gJ, countAccessibilityIssues as gK, countAnnotationStrokes as gL, createAngularAiBridge as gM, createCustomShow as gN, createImageElementFromFile as gO, createSwipeDismissDrag as gP, createWebrtcBundle as gQ, createWebsocketBundle as gR, cssObjectToStyleMap as gS, currentColorScheme as gT, currentLayout as gU, currentStyle as gV, defaultCssVars as gW, defaultRadius as gX, defaultThemeColors as gY, deleteElementsByIds as gZ, deleteVersion as g_, computeAxisTitlePrimitives as ga, computeBarRects as gb, computeBubbleRadius as gc, computeCornerHandle as gd, computeDistribute as ge, computeDrawingViewBox as gf, computeErrorBarPrimitives as gg, computeFocusTargets as gh, computeGridSpacingPx as gi, computeHandleBoxes as gj, computeHandoutLayout as gk, computeIsMobile as gl, computeIsTablet as gm, computeLinePoints as gn, computeLinearRegression as go, computePageCount as gp, computePieLayout as gq, computePieSlicePath as gr, computePieSlices as gs, computePlotLayout as gt, computeRSquared as gu, computeRadarPoints as gv, computeResizeHandleBoxes as gw, computeRotateHandleBox as gx, computeScatterDots as gy, computeScatterXDomain as gz, createSurfaceChart3DScene as h, getP14TransitionAnimations as h$, deriveModel3DBlobUrl as h0, derivePresenceList as h1, describeCollaborationShellState as h2, describeSmartArtBounds as h3, disableGlowPatch as h4, disableInnerShadowPatch as h5, disableOuterShadowPatch as h6, disableReflectionPatch as h7, disableSoftEdgePatch as h8, duplicateElementById as h9, formatBytes as hA, formatCursorLabel as hB, formatElapsed as hC, formatFileSize as hD, formatInlineListStyle as hE, formatPropertyDate as hF, formatTime as hG, fpsToFrameIntervalMs as hH, generateBroadcastRoomId as hI, generateCommentId as hJ, generateCustomShowId as hK, generatePressureCircles as hL, generateTicks as hM, getCinematicTransitionAnimations as hN, getClrChangeParams as hO, getContainerStyle as hP, getDuotoneFilterDef as hQ, getEffectSoundAsset as hR, getEffectSoundState as hS, getImageSrc as hT, getLocalStorageUsageSummary as hU, getOleAriaLabel as hV, getOleBadgeLabel as hW, getOleDisplayName as hX, getOleDownloadFileName as hY, getOleTypeColor as hZ, getOleTypeLabel as h_, durationOf as ha, effectsStateOf as hb, enableGlowPatch as hc, enableInnerShadowPatch as hd, enableOuterShadowPatch as he, enableReflectionPatch as hf, enableSoftEdgePatch as hg, encodeGif as hh, endShowMediaCleanup as hi, estimatePageCount as hj, exitPresentationFullscreen as hk, exportAiChatLogs as hl, extractPathPoints as hm, eyedropperAvailable as hn, fillColorOf$1 as ho, findInSlides as hp, findOwningSlideIndex as hq, findSlideIndexByElementId as hr, firstVisibleIndex as hs, fitPolynomial as ht, fitZoom as hu, focusTargetChips as hv, fontMimeForFormat as hw, fontSizeOf as hx, forgetSessionDeck as hy, formatAxisValue as hz, isChartInteractionArmed as i, layoutNodeLabels as i$, getPasswordStrength as i0, getPatternSvg as i1, getPlaceholderStyle as i2, getVersions as i3, getResolvedShapeClipPath as i4, getResolvedShapeClipPathFor as i5, getSessionTabId as i6, getShapeFillStrokeStyle as i7, getSlideBackgroundStyle as i8, getSlideTransitionAnimations as i9, insertTableElementRow as iA, interpolateWidth as iB, isAudienceTab as iC, isBold as iD, isBrowserOpenableMime as iE, isChildNode as iF, isElementInteractive as iG, isInjectableUrl as iH, isItalic as iI, isLegacyBinaryPresentation as iJ, isPpactionUrl as iK, isPresenterMessage as iL, isSigned as iM, isSupportedPresentationFile as iN, isTextElement as iO, isTwoTableFocus as iP, isUnderline as iQ, isUrlSafe as iR, isValidRoomId as iS, isViewportBackgroundPressTarget as iT, isZoomActivationKey as iU, issueTrackKey as iV, issueTypeLabel as iW, keyToLabel as iX, lastVisibleIndex as iY, latexToMathml as iZ, layoutConnectorPaints as i_, getSmartArtNodeBounds as ia, getSpeechRecognitionCtor as ib, getTextBlockStyle as ic, getTextWarp as id, getTouchDistance as ie, getWarpCategory as ig, getWarpPath as ih, gradientStateFromStyle as ii, gradientStateOf as ij, gradientStatePatch as ik, gradientStopColorCommitPatch as il, gridColumns as im, groupIssuesBySeverity as io, hasAnimation as ip, hasCopyableFormat as iq, hasExistingLink as ir, hasExitedFullscreen as is, hasGradientFill as it, hasPressureVariation as iu, hasVisibleSlideAfter as iv, headerLabel as iw, imageDimensions as ix, inkViewBox as iy, insertTableElementColumn as iz, createPieChart3DScene as j, presetByLayout as j$, linePointsToSvgString as j0, lineSpacingPatch as j1, loadAudienceContent as j2, loadSessionDeck as j3, mediaFallbackFor as j4, mediaSurfaceFor as j5, mergeCaptionResults as j6, mergeDown as j7, mergeRight as j8, mergeSelection as j9, numFromEvent as jA, oleActionsVisibleFor as jB, ommlToMathml as jC, ooxmlDashToCssBorderStyle as jD, openNativeEyeDropper as jE, overallStatus as jF, paletteColor as jG, parseAudienceNonce as jH, parseNodeTextarea as jI, partitionSlides as jJ, patchChartData as jK, patchChartStyle as jL, patchTableData as jM, patchTextStyle as jN, patternPresetOptions as jO, pendingElementStyles as jP, pickColorByClickFallback as jQ, pickFile as jR, pickSupportedMimeType as jS, planGifFrames as jT, planVideoSegments as jU, pointFromPointerEvent as jV, pointsToSvgPathD as jW, presenceToCursors as jX, presentationBaseName as jY, presentationStageStyle as jZ, presenterTimerProgress as j_, mergeTablesDirective as ja, moveElementBy as jb, moveNodeDown as jc, moveNodeUp as jd, msToFrameDelayCs as je, narrowToCircle as jf, narrowToPolygon as jg, narrowToRect as jh, newChartElement as ji, newEquationElement as jj, newPresetShapeElement as jk, newShapeElement as jl, newSmartArtElement as jm, newTableElement as jn, newTextElement as jo, nextVisibleIndex as jp, nodeBold as jq, nodeEditBox as jr, nodeFillColor as js, nodeFontColor as jt, nodeIdFromKey as ju, nodeItalic as jv, nodeStyle as jw, normalizeFontFormat as jx, normalizeSlidesPerPage as jy, normalizeValue as jz, createAreaChart3DScene as k, savedPresentationFileName as k$, presetsForCategory as k0, pressuresToWidths as k1, prevVisibleIndex as k2, projectDrawingShapes as k3, promoteNode as k4, provideViewerTheme as k5, radarAngle as k6, radarRingPoints as k7, readAsDataUrl as k8, recordWebm as k9, resolveMediaSrc as kA, resolveOleType as kB, resolveOrientation as kC, resolveParagraphBullet as kD, resolvePresenterNotes as kE, resolveProfileInitial as kF, resolveRegionCode as kG, resolveRibbonCanGroup as kH, resolveSlideAutoAdvanceMs as kI, resolveSlideTransition as kJ, resolvePalette as kK, resolveThemeCatalogEntry as kL, resolveTransitionDuration as kM, resolveTransitionDurationMs as kN, resolveWheelSpokeCount as kO, restoreSessionDeck as kP, revealedElementStyles as kQ, routeOrthogonalConnector as kR, rowStyle as kS, rulerDragToGuidePosition as kT, rulerHighlight as kU, rulerStripTicks as kV, sampleColorFromSlide as kW, sanitizeColor as kX, sanitizeSlideIndex as kY, sanitizeUserName as kZ, saveViewerProfile as k_, registerCrossSlideAudio as ka, rememberSessionDeck as kb, removeAnimation as kc, removeCategory as kd, removeTableElementColumn as ke, removeCommentFromList as kf, removeElementAnimation as kg, removeGradientStopPatch as kh, removeNode as ki, removeTableElementRow as kj, removeSeries as kk, renderToCanvas as kl, reorderAnimationDown as km, reorderAnimationUp as kn, replaceInSlides as ko, replaceMatch as kp, requestPresentationFullscreen as kq, resizeElement as kr, resolveCaptionTracks as ks, resolveChartKind as kt, resolveDirection as ku, resolveDirection8 as kv, resolveFontVariant as kw, resolveHyperlinkHref as kx, resolveInteractiveElementId as ky, resolveLegendAnchorPosition as kz, createLineChart3DScene as l, signatureKey as l$, scanAvailableFonts as l0, searchSlides as l1, seedBroadcastFields as l2, seedHyperlinkDraft as l3, seedPropertiesDraft as l4, seedShareFields as l5, segmentFrameCount as l6, selectValue$3 as l7, sendBackward as l8, sendToBack as l9, setGridlineStyle as lA, setLayout as lB, setLegend as lC, setNodeStyle as lD, setNodeText as lE, setRepeatCount as lF, setRepeatMode as lG, setSequence as lH, setSeriesChartType as lI, setSeriesColor as lJ, setSeriesErrorBars as lK, setSeriesMarker as lL, setSeriesName as lM, setSeriesTrendline as lN, setSeriesValue as lO, setStyle as lP, setTimingCurve as lQ, setTitle as lR, setTrigger as lS, setTriggerShapeId as lT, shapeStylePatch$1 as lU, sheetAfterNavigate as lV, shouldBlockClickAdvance as lW, shouldUseSvgWarp as lX, showDirectionPicker as lY, showsTemplateAffordance as lZ, signatureCountLabel as l_, sequentialColorScale as la, serializeWriteBack as lb, seriesColor as lc, seriesXValues as ld, setAfterAnimation as le, setAfterAnimationColor as lf, setAnimationEmphasis as lg, setAnimationEntrance as lh, setAnimationExit as li, setAxis as lj, setAxisLogScale as lk, setAxisTitleStyle as ll, setCategoryLabel as lm, setCellText as ln, setColorScheme as lo, setDataLabels as lp, setDataPointExplosion as lq, setDataPointFill as lr, setDataPointLabel as ls, setDataPointMarker as lt, setDelay as lu, setDirection as lv, setDuration as lw, setEffectSound as lx, setEffectStockSound as ly, setElementPosition as lz, createBarChart3DScene as m, signatureTimestamp as m0, signerName as m1, statusLabel as m2, slideNumberOf as m3, slidesWithReappliedLayout as m4, smartArtNodes as m5, paletteColour as m6, snapToGridStep as m7, splitCursorCell as m8, splitMergedCell as m9, transformSelectedTextCase as mA, translationsEn as mB, updateElementById as mC, updateGlowPatch as mD, updateGradientStopPatch as mE, updateInnerShadowPatch as mF, updateOuterShadowPatch as mG, updateReflectionPatch as mH, vAlignPatch as mI, validatePassword as mJ, validatePrintSettings as mK, validateRoomId as mL, valueToY as mM, vermilionDarkColors as mN, vermilionDarkTheme as mO, vermilionLightColors as mP, vermilionLightTheme as mQ, vermilionRadius as mR, waypointsToPathD as mS, withManualLayouts as mT, worstStatus as mU, zoomTargetSlideIndex as mV, statusKind as ma, statusLabel$1 as mb, storeAudienceContent as mc, stringFromEvent$5 as md, strokeColorOf as me, strokeToInkElement as mf, strokeWidthOf as mg, styleShadowFilter as mh, surfaceColor as mi, textAdvancedPatch as mj, textAdvancedStateFromStyle as mk, textAdvancedStateOf as ml, textColorOf as mm, textDirectionPatch as mn, textFontSizePatch as mo, textStyleOf as mp, textStylePatch as mq, themeStyle as mr, themeToCssVars as ms, thumbnailHeight as mt, thumbnailZoom as mu, toggleCommentResolvedInList as mv, toggleNodeBold as mw, toggleNodeItalic as mx, toggleSheet as my, topLevelNodeCount as mz, ALIGN_OPTIONS as n, ANIMATION_PRESET_CATEGORIES as o, AUDIENCE_HASH as p, AUDIENCE_NONCE_KEY as q, renderChartLineSvg as r, shade as s, toChatSummary as t, AVATAR_COLOR_SWATCHES as u, AXIS_LABEL_COLOR as v, AccessibilityPanelComponent as w, AccessibilityService as x, AccessibilityTextPanelComponent as y, AccountPageComponent as z };
196778
- //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-lyQkXQuN.mjs.map
198156
+ export { CINEMATIC_TRANSITION_KEYFRAMES as $, AFTER_ANIMATION_VALUES as A, ActionSettingsPanelComponent as B, CHART_3D_DRAG_THRESHOLD_PX as C, AdvancedChartEditorComponent as D, AiChangeOverlayComponent as E, AiChatPanelComponent as F, AiChatService as G, AiComposerComponent as H, AiFocusBarComponent as I, AiFocusHighlightOverlayComponent as J, AiHistoryMenuComponent as K, AiHistoryService as L, AiMessageListComponent as M, AiPanelStore as N, AiProposalCardComponent as O, AiSettingsSectionComponent as P, AiToolCallCardComponent as Q, AnimationAuthorPanelComponent as R, AnimationPanelComponent as S, AnimationPlaybackService as T, AutosaveRecoveryDialogComponent as U, AutosaveService as V, BACKSTAGE_CARD_IDS as W, BACKSTAGE_PAGE_IDS as X, BroadcastDialogComponent as Y, CANVAS_CONTEXT_MENU_COMMAND_IDS as Z, CHART_EDITOR_STYLES as _, renderChartTextSvg as a, EmbeddedFontsService as a$, CURSOR_PALETTE as a0, CanvasFitService as a1, ChartAxisOptionsComponent as a2, ChartAxisStyleOptionsComponent as a3, ChartComboTypeOptionsComponent as a4, ChartDataEditorComponent as a5, ChartDataLabelOptionsComponent as a6, ChartDatapointMarkerOptionsComponent as a7, ChartDatapointOptionsComponent as a8, ChartDisplayOptionsComponent as a9, DEFAULT_PALETTE$1 as aA, DEFAULT_PATTERN_FILL_PRESET as aB, DEFAULT_PRINT_SETTINGS as aC, DEFAULT_SLIDE_BACKGROUND as aD, DEFAULT_STROKE_COLOR as aE, DEFAULT_STYLE as aF, DEFAULT_TABLE_ROW_HEIGHT as aG, DEFAULT_TEXT_COLOR$2 as aH, DEFAULT_VIEWER_PROFILE as aI, DIRECTIONAL_PRESETS as aJ, DIRECTION_OPTIONS as aK, DocumentPropertiesCardComponent as aL, EASE as aM, EDITOR_SHORTCUT_ACTION_IDS as aN, EFFECT_SOUND_CATALOGUE as aO, ELEMENT_CONTEXT_MENU_COMMAND_IDS as aP, EMBEDDED_FONTS_STYLE_ID as aQ, EMPHASIS_PRESETS as aR, ENTRANCE_PRESETS as aS, TEMPLATES as aT, EXIT_PRESETS as aU, EditorContextMenuComponent as aV, EditorHistory as aW, EditorStateService as aX, EditorToolbarComponent as aY, EffectsPanelComponent as aZ, ElementRendererComponent as a_, ChartElementViewComponent as aa, ChartErrorBarOptionsComponent as ab, ChartMarkerOptionsComponent as ac, ChartPartSelectionService as ad, ChartPrimitivesComponent as ae, ChartRendererComponent as af, ChartTrendlineOptionsComponent as ag, ChartTypeSelectorComponent as ah, CollaborationCursorsComponent as ai, CollaborationService as aj, ColorChangedImageComponent as ak, CommentMarkersOverlayComponent as al, CommentsPanelComponent as am, CommentsService as an, ComparePanelComponent as ao, ConnectorRendererComponent as ap, ConnectorTextOverlayComponent as aq, CustomShowsComponent as ar, DEFAULT_BOUNDS as as, DEFAULT_BROADCAST_SERVER_URL as at, DEFAULT_CANVAS_HEIGHT as au, DEFAULT_CANVAS_WIDTH as av, DEFAULT_COLOR_SCHEME as aw, DEFAULT_FILL_COLOR$1 as ax, DEFAULT_LAYOUT as ay, DEFAULT_MORPH_DURATION_MS as az, appendChartLegendSvg as b, PRESENTER_CHANNEL_NAME as b$, EncryptedFileDialogComponent as b0, EquationEditorDialogComponent as b1, EquationRendererComponent as b2, EquationTemplateGalleryComponent as b3, ExportProgressModalComponent as b4, ExportService as b5, FieldContextService as b6, FindBarComponent as b7, FindReplaceBarComponent as b8, FollowModeBarComponent as b9, MOTION_PATH_COLUMNS as bA, MediaPreviewComponent as bB, MediaPropertiesPanelComponent as bC, MediaRendererComponent as bD, MediaTrimTimelineComponent as bE, MobileBottomBarComponent as bF, MobileMenuSheetComponent as bG, MobilePresenterViewComponent as bH, MobileSheetComponent as bI, MobileSlidesSheetComponent as bJ, MobileToolbarComponent as bK, ModalDialogComponent as bL, Model3DRendererComponent as bM, NotesHandoutCardComponent as bN, NotesPanelComponent as bO, NotesToolbarComponent as bP, OPTIONS_PAGE_IDS as bQ, OPTIONS_SECTION_IDS as bR, OPTIONS_SETTING_IDS as bS, OleRendererComponent as bT, OutlineViewOverlayComponent as bU, P14_TRANSITION_KEYFRAMES as bV, P14_TRANSITION_KEYFRAMES_2 as bW, P14_TRANSITION_KEYFRAMES_ALL as bX, POWER_POINT_VIEWER_PROVIDERS as bY, PPTX_OPEN_ACCEPT as bZ, PRESENTATION_OPEN_EXTENSIONS as b_, FontEmbeddingListComponent as ba, FontEmbeddingPanelComponent as bb, GALLERY_THEME_PRESETS as bc, GOOGLE_WEBFONTS_LINK_ID as bd, GRIDLINE_COLOR$1 as be, GoogleWebfontsService as bf, GradientPickerComponent as bg, HANDOUT_OPTIONS as bh, HeaderFooterDialogComponent as bi, HyperlinkDialogComponent as bj, INSTANT as bk, ImagePropertiesPanelComponent as bl, InkDrawingService as bm, InkRendererComponent as bn, InsertSmartArtDialogComponent as bo, InspectorPaneHeaderComponent as bp, InspectorPanelComponent as bq, IsMobileService as br, KeepAnnotationsDialogComponent as bs, LOCALE_CATALOG as bt, LONG_PRESS_DURATION_MS as bu, LONG_PRESS_MOVE_TOLERANCE_PX as bv, LoadContentService as bw, LocalPresencePublisher as bx, MAX_ZOOM_SCALE as by, MIN_ZOOM_SCALE as bz, createSvgEl as c, PALETTES as c$, PRESENTER_MSG_ORIGIN as c0, PRESENTER_TIMER_SEGMENT_MS as c1, PX_PER_CM as c2, PX_PER_INCH as c3, PasswordProtectionDialogComponent as c4, PasswordStrengthMeterComponent as c5, PowerPointViewerComponent as c6, PresentToolbarAutoHide as c7, PresentationAnnotationOverlayComponent as c8, PresentationAnnotationsService as c9, RibbonDesignSectionComponent as cA, RibbonDrawSectionComponent as cB, RibbonDrawingGroupComponent as cC, RibbonEditingSectionComponent as cD, RibbonFileSectionComponent as cE, RibbonFontControlsComponent as cF, RibbonHomeSectionComponent as cG, RibbonHyperlinkButtonComponent as cH, RibbonInsertFieldsComponent as cI, RibbonInsertSectionComponent as cJ, RibbonMotionPathGalleryComponent as cK, RibbonParagraphControlsComponent as cL, RibbonPrimaryRowComponent as cM, RibbonReviewSectionComponent as cN, RibbonShapeExtrasComponent as cO, RibbonSlideshowSectionComponent as cP, RibbonTransitionsSectionComponent as cQ, RibbonViewSectionComponent as cR, RulerGuidesService as cS, SEQUENCE_OPTIONS as cT, SEVERITY_GROUPS as cU, SEVERITY_LABELS as cV, DEFAULT_TRANSITION_DURATION_MS$1 as cW, SHORTCUT_REFERENCE_ITEMS as cX, SLIDE_TRANSITION_KEYFRAMES as cY, SLIDE_TRANSITION_KEYFRAMES_CSS as cZ, DEFAULT_PALETTE as c_, PresentationOverlayComponent as ca, PresentationPropertiesPanelComponent as cb, PresentationSettingsCardComponent as cc, PresentationSubtitleBarComponent as cd, PresentationToolbarComponent as ce, PresentationTransitionOverlayComponent as cf, PresenterViewComponent as cg, PresenterWindowService as ch, PrintDialogComponent as ci, PrintService as cj, PrintSettingsPanelComponent as ck, PropertiesDialogComponent as cl, RANDOM_ELIGIBLE_TYPES as cm, REPEAT_MODE_OPTIONS as cn, RESIZE_HANDLES as co, RIBBON_TAB_IDS as cp, RULER_FONT_SIZE as cq, RULER_THICKNESS as cr, ReadingViewOverlayComponent as cs, RemoteSelectionOverlayComponent as ct, Rendering3DService as cu, RibbonAnimationGalleryComponent as cv, RibbonAnimationsSectionComponent as cw, RibbonArrangeSectionComponent as cx, RibbonColorPopoverComponent as cy, RibbonComponent as cz, dragAnchorViewY as d, VALIGN_OPTIONS as d$, SMART_ART_COLOR_SCHEMES as d0, SMART_ART_STYLE_OPTIONS as d1, SUB_ITEM_LABEL as d2, SVG_WARP_PRESETS as d3, SWIPE_MAX_VERTICAL_PX as d4, SWIPE_THRESHOLD_PX as d5, SelectionPaneComponent as d6, SetUpSlideShowDialogComponent as d7, SettingsAppearanceTabComponent as d8, SettingsDialogComponent as d9, TEXT_3D_BOTTOM_BEVEL_KEYS as dA, TEXT_3D_TOP_BEVEL_KEYS as dB, TEXT_DIRECTION_OPTIONS$1 as dC, THEME_CATALOG as dD, TIMING_CURVE_OPTIONS as dE, TOOLBAR_BUTTON_IDS as dF, TRANSITION_SPEED_DURATION_MS as dG, TRIGGER_OPTIONS as dH, TYPE_LABELS as dI, TableCellAdvancedFillComponent as dJ, TableCellFormattingComponent as dK, TableDataEditorComponent as dL, TablePropertiesComponent as dM, TableRendererComponent as dN, TableResizeOverlayComponent as dO, TableSelectionService as dP, TagsCardComponent as dQ, Text3DBevelSectionComponent as dR, Text3DPanelComponent as dS, TextAdvancedPanelComponent as dT, ThemeEditorFieldsComponent as dU, ThemeGalleryComponent as dV, ThemeSelectorCardComponent as dW, TitleBarComponent as dX, TitleBarSearchComponent as dY, TransitionDirectionPickerComponent as dZ, TransitionPreviewComponent as d_, SettingsLanguageTabComponent as da, ShareDialogComponent as db, ShortcutPanelComponent as dc, ShowOptionsFieldsetComponent as dd, ShowSlidesFieldsetComponent as de, SignatureStrippedDialogComponent as df, SignaturesPanelComponent as dg, SignaturesService as dh, SlideBackgroundCardComponent as di, SlideCanvasComponent as dj, SlideDefaultInspectorComponent as dk, SlideDiffChangesComponent as dl, SlideDiffRowComponent as dm, SlideDiffThumbnailsComponent as dn, SlideSizeCardComponent as dp, SlideSorterOverlayComponent as dq, SlideThemeOverridePanelComponent as dr, SlideTransitionCardComponent as ds, SlidesPanelComponent as dt, SmartArt3DRendererComponent as du, SmartArtPreviewComponent as dv, SmartArtPropertiesComponent as dw, SmartArtRendererComponent as dx, StatusBarComponent as dy, TABLE_STRUCTURE_TOGGLES as dz, advanceChartValueDrag as e, bringForward as e$, VIEWER_DIALOG_IDS as e0, VIEWER_EXPORT_FORMAT_IDS as e1, VIEWER_FEATURE_IDS as e2, VIEWER_PANEL_IDS as e3, VIEWER_THEME as e4, VersionHistoryPanelComponent as e5, ViewerCanvasEditingService as e6, ViewerCollabCursorService as e7, ViewerCollaborationSessionService as e8, ViewerCollaborationShellService as e9, addCommentToList as eA, addGradientStopPatch as eB, addItem as eC, addSeries as eD, addSubItem as eE, advanceStep as eF, affordanceElements as eG, aiToggleVisible as eH, alignPatch as eI, animationFor as eJ, animationPresetLabelKey as eK, annotationMapToInkInserts as eL, applyAcceptedDiff as eM, applyAnimationPreset as eN, applyFindReplacements as eO, applyFormatToElement as eP, applyMove as eQ, applyResize as eR, asMediaElement as eS, assignUserColor as eT, attachShowVisibilityPause as eU, attachTouchGestures as eV, axisTickValues as eW, beginDrawingNodeEdit as eX, beginNodeEdit as eY, bevelSizePatch as eZ, boolFromEvent as e_, ViewerCompareService as ea, ViewerCustomShowsService as eb, ViewerCustomizationHandle as ec, ViewerCustomizationService as ed, ViewerDialogsService as ee, ViewerDocumentPropertiesService as ef, ViewerExportService as eg, ViewerExtraDialogsComponent as eh, ViewerFileIOService as ei, ViewerFindReplaceService as ej, ViewerFormatPainterService as ek, ViewerInspectorPanelService as el, ViewerKeyboardService as em, ViewerMobileSheetService as en, ViewerPresentationModeService as eo, ViewerThemeGalleryService as ep, ViewerTouchGesturesService as eq, ViewerZoomService as er, WEBM_MIME_CANDIDATES as es, WHEEL_SPOKE_COUNTS as et, WriteBackScheduler as eu, ZERO_LINE_COLOR as ev, ZoomNavigationService as ew, ZoomRendererComponent as ex, ZoomTargetService as ey, addCategory as ez, buildBarChart3DHoverTooltip as f, canUseClipboard as f$, bringToFront as f0, buildBarActions as f1, buildBroadcastConfig as f2, buildBroadcastViewerUrl as f3, buildCategoryLabels as f4, buildCellParagraphs as f5, buildChartViewModel as f6, buildChatLogExport as f7, buildChatLogMarkdown as f8, buildChromeStyle as f9, buildPieViewModel as fA, buildPrintHtmlDocument as fB, buildPropertiesPatch as fC, buildRadarViewModel as fD, buildRegionMapViewModel as fE, buildSaveSlides as fF, buildShareUrl as fG, buildSmartArtInsertElement as fH, buildSmartArtNodes as fI, buildStockViewModel as fJ, buildSurfaceViewModel as fK, buildTableViewModel as fL, buildTreemapViewModel as fM, buildTrimFragment as fN, buildWaterfallViewModel as fO, buildZeroLine as fP, buildZoomContainerStyle as fQ, buildZoomViewModel as fR, bulletIndentPx as fS, canAddTopLevelNode as fT, canEditSmartArtNodes as fU, canGroupSelection as fV, canRemoveTopLevelNode as fW, canSetStrokeWidth as fX, canStartBroadcast as fY, canStartShare as fZ, canUngroupSelection as f_, buildClearHyperlinkPatch as fa, buildClickGroups as fb, buildColStyles as fc, buildCollaborationConfig as fd, buildComboViewModel as fe, buildCssGradientFromShapeStyle as ff, buildDuotoneFilter as fg, buildDuotoneFilterId as fh, buildEmbeddedFontStyles as fi, buildEquationElement as fj, buildEquationSegment as fk, buildFallbackViewModel as fl, buildFontFaceRule as fm, buildGradientFillCss as fn, buildGridlinesAndLabels as fo, buildHyperlinkPatch as fp, buildInkContainerStyle as fq, buildInkStrokes as fr, buildLegend as fs, buildLiveInkStrokeView as ft, buildMarkTooltip as fu, buildModel3DContainerStyle as fv, buildModel3DViewModel as fw, buildOleActionModel as fx, buildOleInfoRows as fy, buildPatternFillCss as fz, beginChartValueDrag as g, countAnnotationStrokes as g$, captionDisplayText as g0, cellRunStyle as g1, cellStyleToStyleMap as g2, cellTdStyle as g3, changeCountLabel as g4, changeIcon as g5, characterSpacingPatch as g6, chartPreserveAspectRatio as g7, checkFontAvailable as g8, clampCursorPosition as g9, computeHandoutLayout as gA, computeIsMobile as gB, computeIsTablet as gC, computeLinePoints as gD, computeLinearRegression as gE, computePageCount as gF, computePieLayout as gG, computePieSlicePath as gH, computePieSlices as gI, computePlotLayout as gJ, computeRSquared as gK, computeRadarPoints as gL, computeResizeHandleBoxes as gM, computeRotateHandleBox as gN, computeScatterDots as gO, computeScatterXDomain as gP, computeSelectionBoxes as gQ, computeSingleSelected as gR, computeSlideIndices as gS, computeSnap as gT, computeStackedBarRects as gU, computeStackedValueRange as gV, computeTrendlinePrimitives as gW, computeValueRange as gX, convertOmmlToMathMl as gY, copyFormatFromElement as gZ, countAccessibilityIssues as g_, clampGifDimensions as ga, clampIndex as gb, clampNotesFontSize as gc, clampScale as gd, clampStep as ge, clearAllLocalViewerData as gf, clearAudienceContent as gg, cn as gh, collectAccessibilityIssues as gi, collectElementText as gj, collectSlideText as gk, collectStoredChats as gl, collectUsedFontFamilies as gm, columnWidthStyle as gn, commitNodeText as go, computeAlign as gp, computeAxisTitlePrimitives as gq, computeBarRects as gr, computeBubbleRadius as gs, computeCornerHandle as gt, computeDistribute as gu, computeDrawingViewBox as gv, computeErrorBarPrimitives as gw, computeFocusTargets as gx, computeGridSpacingPx as gy, computeHandleBoxes as gz, createSurfaceChart3DScene as h, generatePressureCircles as h$, createAngularAiBridge as h0, createCustomShow as h1, createImageElementFromFile as h2, createSwipeDismissDrag as h3, createWebrtcBundle as h4, createWebsocketBundle as h5, cssObjectToStyleMap as h6, currentColorScheme as h7, currentLayout as h8, currentStyle as h9, exitPresentationFullscreen as hA, exportAiChatLogs as hB, extractPathPoints as hC, eyedropperAvailable as hD, fillColorOf$1 as hE, findInSlides as hF, findOwningSlideIndex as hG, findSlideIndexByElementId as hH, firstVisibleIndex as hI, fitPolynomial as hJ, fitZoom as hK, focusTargetChips as hL, fontMimeForFormat as hM, fontSizeOf as hN, forgetSessionDeck as hO, formatAxisValue as hP, formatBytes as hQ, formatCursorLabel as hR, formatElapsed as hS, formatFileSize as hT, formatInlineListStyle as hU, formatPropertyDate as hV, formatTime as hW, fpsToFrameIntervalMs as hX, generateBroadcastRoomId as hY, generateCommentId as hZ, generateCustomShowId as h_, defaultCssVars as ha, defaultRadius as hb, defaultThemeColors as hc, deleteElementsByIds as hd, deleteVersion as he, demoteNode as hf, deriveModel3DBlobUrl as hg, derivePresenceList as hh, describeCollaborationShellState as hi, describeSmartArtBounds as hj, disableGlowPatch as hk, disableInnerShadowPatch as hl, disableOuterShadowPatch as hm, disableReflectionPatch as hn, disableSoftEdgePatch as ho, duplicateElementById as hp, durationOf as hq, effectsStateOf as hr, enableGlowPatch as hs, enableInnerShadowPatch as ht, enableOuterShadowPatch as hu, enableReflectionPatch as hv, enableSoftEdgePatch as hw, encodeGif as hx, endShowMediaCleanup as hy, estimatePageCount as hz, isChartInteractionArmed as i, isPpactionUrl as i$, generateTicks as i0, getCinematicTransitionAnimations as i1, getClrChangeParams as i2, getContainerStyle as i3, getDuotoneFilterDef as i4, getEffectSoundAsset as i5, getEffectSoundState as i6, getImageSrc as i7, getLocalStorageUsageSummary as i8, getOleAriaLabel as i9, gradientStateOf as iA, gradientStatePatch as iB, gradientStopColorCommitPatch as iC, gridColumns as iD, groupIssuesBySeverity as iE, hasAnimation as iF, hasCopyableFormat as iG, hasExistingLink as iH, hasExitedFullscreen as iI, hasGradientFill as iJ, hasPressureVariation as iK, hasVisibleSlideAfter as iL, headerLabel as iM, imageDimensions as iN, injectResolvedCustomization as iO, inkViewBox as iP, insertTableElementColumn as iQ, insertTableElementRow as iR, interpolateWidth as iS, isAudienceTab as iT, isBold as iU, isBrowserOpenableMime as iV, isChildNode as iW, isElementInteractive as iX, isInjectableUrl as iY, isItalic as iZ, isLegacyBinaryPresentation as i_, getOleBadgeLabel as ia, getOleDisplayName as ib, getOleDownloadFileName as ic, getOleTypeColor as id, getOleTypeLabel as ie, getP14TransitionAnimations as ig, getPasswordStrength as ih, getPatternSvg as ii, getPlaceholderStyle as ij, getVersions as ik, getResolvedShapeClipPath as il, getResolvedShapeClipPathFor as im, getSessionTabId as io, getShapeFillStrokeStyle as ip, getSlideBackgroundStyle as iq, getSlideTransitionAnimations as ir, getSmartArtNodeBounds as is, getSpeechRecognitionCtor as it, getTextBlockStyle as iu, getTextWarp as iv, getTouchDistance as iw, getWarpCategory as ix, getWarpPath as iy, gradientStateFromStyle as iz, createPieChart3DScene as j, patchChartData as j$, isPresenterMessage as j0, isSigned as j1, isSupportedPresentationFile as j2, isTextElement as j3, isTwoTableFocus as j4, isUnderline as j5, isUrlSafe as j6, isValidRoomId as j7, isViewportBackgroundPressTarget as j8, isZoomActivationKey as j9, newEquationElement as jA, newPresetShapeElement as jB, newShapeElement as jC, newSmartArtElement as jD, newTableElement as jE, newTextElement as jF, nextVisibleIndex as jG, nodeBold as jH, nodeEditBox as jI, nodeFillColor as jJ, nodeFontColor as jK, nodeIdFromKey as jL, nodeItalic as jM, nodeStyle as jN, normalizeFontFormat as jO, normalizeSlidesPerPage as jP, normalizeValue as jQ, numFromEvent as jR, oleActionsVisibleFor as jS, ommlToMathml as jT, ooxmlDashToCssBorderStyle as jU, openNativeEyeDropper as jV, overallStatus as jW, paletteColor as jX, parseAudienceNonce as jY, parseNodeTextarea as jZ, partitionSlides as j_, issueTrackKey as ja, issueTypeLabel as jb, keyToLabel as jc, lastVisibleIndex as jd, latexToMathml as je, layoutConnectorPaints as jf, layoutNodeLabels as jg, linePointsToSvgString as jh, lineSpacingPatch as ji, loadAudienceContent as jj, loadSessionDeck as jk, mediaFallbackFor as jl, mediaSurfaceFor as jm, mergeCaptionResults as jn, mergeDown as jo, mergeRight as jp, mergeSelection as jq, mergeTablesDirective as jr, moveElementBy as js, moveNodeDown as jt, moveNodeUp as ju, msToFrameDelayCs as jv, narrowToCircle as jw, narrowToPolygon as jx, narrowToRect as jy, newChartElement as jz, createAreaChart3DScene as k, resolvePalette as k$, patchChartStyle as k0, patchTableData as k1, patchTextStyle as k2, patternPresetOptions as k3, pendingElementStyles as k4, pickColorByClickFallback as k5, pickFile as k6, pickSupportedMimeType as k7, planGifFrames as k8, planVideoSegments as k9, removeTableElementRow as kA, removeSeries as kB, renderToCanvas as kC, reorderAnimationDown as kD, reorderAnimationUp as kE, replaceInSlides as kF, replaceMatch as kG, requestPresentationFullscreen as kH, resizeElement as kI, resolveCaptionTracks as kJ, resolveChartKind as kK, resolveDirection as kL, resolveDirection8 as kM, resolveFontVariant as kN, resolveHyperlinkHref as kO, resolveInteractiveElementId as kP, resolveLegendAnchorPosition as kQ, resolveMediaSrc as kR, resolveOleType as kS, resolveOrientation as kT, resolveParagraphBullet as kU, resolvePresenterNotes as kV, resolveProfileInitial as kW, resolveRegionCode as kX, resolveRibbonCanGroup as kY, resolveSlideAutoAdvanceMs as kZ, resolveSlideTransition as k_, pointFromPointerEvent as ka, pointsToSvgPathD as kb, presenceToCursors as kc, presentationBaseName as kd, presentationStageStyle as ke, presenterTimerProgress as kf, presetByLayout as kg, presetsForCategory as kh, pressuresToWidths as ki, prevVisibleIndex as kj, projectDrawingShapes as kk, promoteNode as kl, provideViewerTheme as km, radarAngle as kn, radarRingPoints as ko, readAsDataUrl as kp, recordWebm as kq, registerCrossSlideAudio as kr, rememberSessionDeck as ks, removeAnimation as kt, removeCategory as ku, removeTableElementColumn as kv, removeCommentFromList as kw, removeElementAnimation as kx, removeGradientStopPatch as ky, removeNode as kz, createLineChart3DScene as l, setSeriesErrorBars as l$, resolveThemeCatalogEntry as l0, resolveTransitionDuration as l1, resolveTransitionDurationMs as l2, resolveWheelSpokeCount as l3, restoreSessionDeck as l4, revealedElementStyles as l5, routeOrthogonalConnector as l6, rowStyle as l7, rulerDragToGuidePosition as l8, rulerHighlight as l9, setAxis as lA, setAxisLogScale as lB, setAxisTitleStyle as lC, setCategoryLabel as lD, setCellText as lE, setColorScheme as lF, setDataLabels as lG, setDataPointExplosion as lH, setDataPointFill as lI, setDataPointLabel as lJ, setDataPointMarker as lK, setDelay as lL, setDirection as lM, setDuration as lN, setEffectSound as lO, setEffectStockSound as lP, setElementPosition as lQ, setGridlineStyle as lR, setLayout as lS, setLegend as lT, setNodeStyle as lU, setNodeText as lV, setRepeatCount as lW, setRepeatMode as lX, setSequence as lY, setSeriesChartType as lZ, setSeriesColor as l_, rulerStripTicks as la, sampleColorFromSlide as lb, sanitizeColor as lc, sanitizeSlideIndex as ld, sanitizeUserName as le, saveViewerProfile as lf, savedPresentationFileName as lg, scanAvailableFonts as lh, searchSlides as li, seedBroadcastFields as lj, seedHyperlinkDraft as lk, seedPropertiesDraft as ll, seedShareFields as lm, segmentFrameCount as ln, selectValue$3 as lo, sendBackward as lp, sendToBack as lq, sequentialColorScale as lr, serializeWriteBack as ls, seriesColor as lt, seriesXValues as lu, setAfterAnimation as lv, setAfterAnimationColor as lw, setAnimationEmphasis as lx, setAnimationEntrance as ly, setAnimationExit as lz, createBarChart3DScene as m, validatePrintSettings as m$, setSeriesMarker as m0, setSeriesName as m1, setSeriesTrendline as m2, setSeriesValue as m3, setStyle as m4, setTimingCurve as m5, setTitle as m6, setTrigger as m7, setTriggerShapeId as m8, shapeStylePatch$1 as m9, textAdvancedPatch as mA, textAdvancedStateFromStyle as mB, textAdvancedStateOf as mC, textColorOf as mD, textDirectionPatch as mE, textFontSizePatch as mF, textStyleOf as mG, textStylePatch as mH, themeStyle as mI, themeToCssVars as mJ, thumbnailHeight as mK, thumbnailZoom as mL, toggleCommentResolvedInList as mM, toggleNodeBold as mN, toggleNodeItalic as mO, toggleSheet as mP, topLevelNodeCount as mQ, transformSelectedTextCase as mR, translationsEn as mS, updateElementById as mT, updateGlowPatch as mU, updateGradientStopPatch as mV, updateInnerShadowPatch as mW, updateOuterShadowPatch as mX, updateReflectionPatch as mY, vAlignPatch as mZ, validatePassword as m_, sheetAfterNavigate as ma, shouldBlockClickAdvance as mb, shouldUseSvgWarp as mc, showDirectionPicker as md, showsTemplateAffordance as me, signatureCountLabel as mf, signatureKey as mg, signatureTimestamp as mh, signerName as mi, statusLabel as mj, slideNumberOf as mk, slidesWithReappliedLayout as ml, smartArtNodes as mm, paletteColour as mn, snapToGridStep as mo, splitCursorCell as mp, splitMergedCell as mq, statusKind as mr, statusLabel$1 as ms, storeAudienceContent as mt, stringFromEvent$5 as mu, strokeColorOf as mv, strokeToInkElement as mw, strokeWidthOf as mx, styleShadowFilter as my, surfaceColor as mz, ALIGN_OPTIONS as n, validateRoomId as n0, valueToY as n1, vermilionDarkColors as n2, vermilionDarkTheme as n3, vermilionLightColors as n4, vermilionLightTheme as n5, vermilionRadius as n6, waypointsToPathD as n7, withManualLayouts as n8, worstStatus as n9, zoomTargetSlideIndex as na, ANIMATION_PRESET_CATEGORIES as o, AUDIENCE_HASH as p, AUDIENCE_NONCE_KEY as q, renderChartLineSvg as r, shade as s, toChatSummary as t, AVATAR_COLOR_SWATCHES as u, AXIS_LABEL_COLOR as v, AccessibilityPanelComponent as w, AccessibilityService as x, AccessibilityTextPanelComponent as y, AccountPageComponent as z };
198157
+ //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-C2z1kMFI.mjs.map