pptx-angular-viewer 1.11.1 → 1.12.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project are documented here.
4
4
  This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
5
5
  by [git-cliff](https://git-cliff.org); do not edit it by hand.
6
6
 
7
+ ## [1.11.1](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.11.1) - 2026-07-09
8
+
9
+ ### Other
10
+
11
+ - Reconcile with origin/main before push (by @ChristopherVR) ([b8c46bc](https://github.com/ChristopherVR/pptx-viewer/commit/b8c46bc3622e301d3365f5c489144e5aa5401782))
12
+
7
13
  ## [1.11.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.11.0) - 2026-07-09
8
14
 
9
15
  ### Features
package/README.md CHANGED
@@ -115,6 +115,18 @@ bootstrapApplication(AppComponent, {
115
115
  });
116
116
  ```
117
117
 
118
+ Two ready-made presets ship with the package: `vermilionLightTheme` (warm paper
119
+ canvas) and `vermilionDarkTheme` (dimmed presenter room), the same vermilion
120
+ brand look as the [documentation site](https://christophervr.github.io/pptx-viewer/):
121
+
122
+ ```ts
123
+ import { vermilionLightTheme } from 'pptx-angular-viewer';
124
+ // [theme]="vermilionLightTheme" or provideViewerTheme(vermilionLightTheme)
125
+ ```
126
+
127
+ The underlying palettes (`vermilionLightColors`, `vermilionDarkColors`) and
128
+ radius (`vermilionRadius`) are exported too for deriving your own variant.
129
+
118
130
  ### Reading the current presentation back
119
131
 
120
132
  `getContent()` turns the current presentation back into `.pptx` bytes. Reach it
@@ -128,6 +128,72 @@ function defaultCssVars() {
128
128
  return vars;
129
129
  }
130
130
 
131
+ /**
132
+ * Built-in "vermilion" theme presets.
133
+ *
134
+ * These mirror the pptx-viewer brand used on the documentation site:
135
+ * a warm paper canvas in light mode, a dimmed presenter room in dark
136
+ * mode, and the vermilion accent in both. Pass one to the viewer's
137
+ * `theme` prop (React/Vue) or `provideViewerTheme` (Angular), or spread
138
+ * the color objects to derive your own variant.
139
+ */
140
+ /** Light "paper" palette: a projection screen in a bright room. */
141
+ const vermilionLightColors = {
142
+ background: '#fbfaf7',
143
+ foreground: '#1a1d21',
144
+ card: '#ffffff',
145
+ cardForeground: '#1a1d21',
146
+ popover: '#ffffff',
147
+ popoverForeground: '#1a1d21',
148
+ primary: '#c2431f',
149
+ primaryForeground: '#ffffff',
150
+ secondary: '#f2efe8',
151
+ secondaryForeground: '#1a1d21',
152
+ muted: '#f2efe8',
153
+ mutedForeground: '#5a626e',
154
+ accent: 'rgba(194, 67, 31, 0.08)',
155
+ accentForeground: '#1a1d21',
156
+ destructive: '#dc2626',
157
+ destructiveForeground: '#ffffff',
158
+ border: '#e6e2d9',
159
+ input: '#e6e2d9',
160
+ ring: '#c2431f',
161
+ };
162
+ /** Dark "presenter" palette: the presenter room with the lights down. */
163
+ const vermilionDarkColors = {
164
+ background: '#0f1113',
165
+ foreground: '#f0efec',
166
+ card: '#171a1e',
167
+ cardForeground: '#f0efec',
168
+ popover: '#171a1e',
169
+ popoverForeground: '#f0efec',
170
+ primary: '#e86a40',
171
+ primaryForeground: '#ffffff',
172
+ secondary: '#1f242b',
173
+ secondaryForeground: '#f0efec',
174
+ muted: '#1f242b',
175
+ mutedForeground: '#9aa1ab',
176
+ accent: 'rgba(232, 106, 64, 0.1)',
177
+ accentForeground: '#f0efec',
178
+ destructive: '#ef4444',
179
+ destructiveForeground: '#ffffff',
180
+ border: '#272c33',
181
+ input: '#272c33',
182
+ ring: '#e86a40',
183
+ };
184
+ /** Shared border-radius for the vermilion presets (slightly sharper than the default). */
185
+ const vermilionRadius = '0.375rem';
186
+ /** Light vermilion theme, ready for the viewer's `theme` prop. */
187
+ const vermilionLightTheme = {
188
+ colors: vermilionLightColors,
189
+ radius: vermilionRadius,
190
+ };
191
+ /** Dark vermilion theme, ready for the viewer's `theme` prop. */
192
+ const vermilionDarkTheme = {
193
+ colors: vermilionDarkColors,
194
+ radius: vermilionRadius,
195
+ };
196
+
131
197
  /**
132
198
  * Recursively walks an element tree and pushes every media element
133
199
  * into the supplied collector array.
@@ -6292,6 +6358,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
6292
6358
  h,
6293
6359
  fill: seriesColor(series[si], si, palette),
6294
6360
  rx: 1,
6361
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: ci },
6295
6362
  });
6296
6363
  if (showLabels) {
6297
6364
  dataLabels.push({
@@ -6315,7 +6382,18 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
6315
6382
  if (grouping === 'stacked') {
6316
6383
  const rects = computeStackedBarRects(series, catCount, layout, primaryRange, palette);
6317
6384
  for (const r of rects) {
6318
- primitives.push({ kind: 'rect', x: r.x, y: r.y, w: r.w, h: r.h, fill: r.fill, rx: 1 });
6385
+ primitives.push({
6386
+ kind: 'rect',
6387
+ x: r.x,
6388
+ y: r.y,
6389
+ w: r.w,
6390
+ h: r.h,
6391
+ fill: r.fill,
6392
+ rx: 1,
6393
+ part: r.seriesIndex !== undefined && r.pointIndex !== undefined
6394
+ ? { role: 'dataPoint', seriesIndex: r.seriesIndex, pointIndex: r.pointIndex }
6395
+ : undefined,
6396
+ });
6319
6397
  }
6320
6398
  if (showLabels) {
6321
6399
  pushClusteredStackedLabels(series, catCount, layout, primaryRange, dataLabels);
@@ -6349,6 +6427,7 @@ function buildBars(chartData, catCount, layout, primaryRange, secondaryRange, se
6349
6427
  w: barW,
6350
6428
  h,
6351
6429
  fill: seriesColor(series[si], si, palette),
6430
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: ci },
6352
6431
  });
6353
6432
  if (showLabels && Math.abs(val) > 0) {
6354
6433
  dataLabels.push({
@@ -6426,10 +6505,18 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
6426
6505
  stroke: c,
6427
6506
  strokeWidth: 2.4,
6428
6507
  fill: 'none',
6508
+ part: { role: 'series', seriesIndex: si },
6509
+ });
6510
+ pts.forEach((pt, vi) => {
6511
+ primitives.push({
6512
+ kind: 'circle',
6513
+ cx: pt.x,
6514
+ cy: pt.y,
6515
+ r: 2.5,
6516
+ fill: c,
6517
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: vi },
6518
+ });
6429
6519
  });
6430
- for (const pt of pts) {
6431
- primitives.push({ kind: 'circle', cx: pt.x, cy: pt.y, r: 2.5, fill: c });
6432
- }
6433
6520
  if (showLabels) {
6434
6521
  series.values.forEach((val, vi) => {
6435
6522
  const pt = pts[vi];
@@ -6474,6 +6561,7 @@ function buildAreas(chartData, catCount, layout, range) {
6474
6561
  strokeWidth: 0,
6475
6562
  fill: c,
6476
6563
  opacity: 0.25,
6564
+ part: { role: 'series', seriesIndex: si },
6477
6565
  });
6478
6566
  }
6479
6567
  primitives.push({
@@ -6482,6 +6570,7 @@ function buildAreas(chartData, catCount, layout, range) {
6482
6570
  stroke: c,
6483
6571
  strokeWidth: 2,
6484
6572
  fill: 'none',
6573
+ part: { role: 'series', seriesIndex: si },
6485
6574
  });
6486
6575
  if (showLabels) {
6487
6576
  series.values.forEach((val, vi) => {
@@ -6514,7 +6603,7 @@ function buildScatter(chartData, layout, range) {
6514
6603
  const series = chartData.series[si];
6515
6604
  const c = seriesColor(series, si, chartData.colorPalette);
6516
6605
  const dots = computeScatterDots(series.values, maxXIndex, layout, range);
6517
- for (const dot of dots) {
6606
+ dots.forEach((dot, vi) => {
6518
6607
  primitives.push({
6519
6608
  kind: 'circle',
6520
6609
  cx: dot.cx,
@@ -6522,8 +6611,9 @@ function buildScatter(chartData, layout, range) {
6522
6611
  r: 4,
6523
6612
  fill: c,
6524
6613
  opacity: 0.85,
6614
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: vi },
6525
6615
  });
6526
- }
6616
+ });
6527
6617
  if (showLabels) {
6528
6618
  series.values.forEach((val, vi) => {
6529
6619
  const dot = dots[vi];
@@ -6568,6 +6658,7 @@ function buildBubbles(chartData, layout, range) {
6568
6658
  r,
6569
6659
  fill: c,
6570
6660
  opacity: 0.6,
6661
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: vi },
6571
6662
  });
6572
6663
  });
6573
6664
  if (showLabels) {
@@ -7427,6 +7518,18 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
7427
7518
  const dataTablePrims = computeDataTablePrimitives(chartData, layout, chartData.colorPalette);
7428
7519
  primitives.push(...overlays, ...dataTablePrims);
7429
7520
  const title = chartData.style?.hasTitle && chartData.title ? chartData.title : undefined;
7521
+ // Vertical drag-to-value only has a single-value meaning for un-stacked marks:
7522
+ // stacked/percentStacked bar segments sit on running sums, so dragging one
7523
+ // would not track the pointer.
7524
+ const valueDrag = isStacked
7525
+ ? undefined
7526
+ : {
7527
+ range: primaryRange,
7528
+ secondaryRange,
7529
+ secondarySeriesIndexes: useSecondary ? [...secondaryIdx] : undefined,
7530
+ plotTop: layout.plotTop,
7531
+ plotBottom: layout.plotBottom,
7532
+ };
7430
7533
  return {
7431
7534
  svgWidth: layout.svgWidth,
7432
7535
  svgHeight: layout.svgHeight,
@@ -7447,6 +7550,7 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
7447
7550
  secondaryAxisLabels: axisRes.secondaryAxisLabels,
7448
7551
  overlays: overlays.length > 0 ? overlays : undefined,
7449
7552
  dataTable: dataTablePrims.length > 0 ? dataTablePrims : undefined,
7553
+ valueDrag,
7450
7554
  };
7451
7555
  }
7452
7556
 
@@ -9503,12 +9607,28 @@ function computeStackedBarRects(series, catCount, layout, range, colorPalette) {
9503
9607
  valueToY(0, range, layout.plotTop, layout.plotBottom)), 1);
9504
9608
  if (val > 0) {
9505
9609
  const y = posTop - h;
9506
- rects.push({ x, y, w: barW, h, fill: seriesColor(series[si], si, colorPalette) });
9610
+ rects.push({
9611
+ x,
9612
+ y,
9613
+ w: barW,
9614
+ h,
9615
+ fill: seriesColor(series[si], si, colorPalette),
9616
+ seriesIndex: si,
9617
+ pointIndex: ci,
9618
+ });
9507
9619
  posTop = y;
9508
9620
  }
9509
9621
  else {
9510
9622
  const y = negBottom;
9511
- rects.push({ x, y, w: barW, h, fill: seriesColor(series[si], si, colorPalette) });
9623
+ rects.push({
9624
+ x,
9625
+ y,
9626
+ w: barW,
9627
+ h,
9628
+ fill: seriesColor(series[si], si, colorPalette),
9629
+ seriesIndex: si,
9630
+ pointIndex: ci,
9631
+ });
9512
9632
  negBottom = y + h;
9513
9633
  }
9514
9634
  }
@@ -9779,6 +9899,7 @@ function buildPieViewModel(element, chartData, categoryLabels, isDoughnut) {
9779
9899
  fill: chartData.series[0]?.color ?? paletteColor(i, chartData.colorPalette),
9780
9900
  stroke: '#ffffff',
9781
9901
  strokeWidth: 1.5,
9902
+ part: { role: 'dataPoint', seriesIndex: 0, pointIndex: i },
9782
9903
  }));
9783
9904
  const dataLabels = [];
9784
9905
  if (chartData.style?.hasDataLabels) {
@@ -9901,10 +10022,18 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
9901
10022
  opacity: 0.2,
9902
10023
  stroke: c,
9903
10024
  strokeWidth: 1.5,
10025
+ part: { role: 'series', seriesIndex: si },
10026
+ });
10027
+ pts.forEach((p, vi) => {
10028
+ primitives.push({
10029
+ kind: 'circle',
10030
+ cx: p.x,
10031
+ cy: p.y,
10032
+ r: 3,
10033
+ fill: c,
10034
+ part: { role: 'dataPoint', seriesIndex: si, pointIndex: vi },
10035
+ });
9904
10036
  });
9905
- for (const p of pts) {
9906
- primitives.push({ kind: 'circle', cx: p.x, cy: p.y, r: 3, fill: c });
9907
- }
9908
10037
  if (chartData.style?.hasDataLabels) {
9909
10038
  pts.forEach((p, vi) => {
9910
10039
  const val = series.values[vi];
@@ -9945,6 +10074,148 @@ function buildRadarViewModel(element, chartData, categoryLabels) {
9945
10074
  };
9946
10075
  }
9947
10076
 
10077
+ // ─────────────────────────────────────────────────────────────────────────────
10078
+ // DOM data-attribute bridge
10079
+ // ─────────────────────────────────────────────────────────────────────────────
10080
+ /** Attribute carrying the part role ('dataPoint' | 'series' | 'title'). */
10081
+ const CHART_PART_ATTR = 'data-chart-part';
10082
+ /** Attribute carrying the series index of a tagged mark. */
10083
+ const CHART_PART_SERIES_ATTR = 'data-chart-series';
10084
+ /** Attribute carrying the point/category index of a tagged mark. */
10085
+ const CHART_PART_POINT_ATTR = 'data-chart-point';
10086
+ /** Attribute record for a tagged mark, spreadable onto an SVG node. */
10087
+ function chartPartToAttrs(part) {
10088
+ const attrs = {
10089
+ [CHART_PART_ATTR]: part.role,
10090
+ [CHART_PART_SERIES_ATTR]: String(part.seriesIndex),
10091
+ };
10092
+ if (part.pointIndex !== undefined) {
10093
+ attrs[CHART_PART_POINT_ATTR] = String(part.pointIndex);
10094
+ }
10095
+ return attrs;
10096
+ }
10097
+ /** Recover a `ChartPartRef` from a tagged element's attributes. */
10098
+ function chartPartFromElement(el) {
10099
+ if (!el) {
10100
+ return null;
10101
+ }
10102
+ const role = el.getAttribute(CHART_PART_ATTR);
10103
+ if (role !== 'dataPoint' && role !== 'series') {
10104
+ return null;
10105
+ }
10106
+ const seriesIndex = Number.parseInt(el.getAttribute(CHART_PART_SERIES_ATTR) ?? '', 10);
10107
+ if (!Number.isInteger(seriesIndex) || seriesIndex < 0) {
10108
+ return null;
10109
+ }
10110
+ const pointRaw = el.getAttribute(CHART_PART_POINT_ATTR);
10111
+ if (pointRaw === null) {
10112
+ return { role, seriesIndex };
10113
+ }
10114
+ const pointIndex = Number.parseInt(pointRaw, 10);
10115
+ if (!Number.isInteger(pointIndex) || pointIndex < 0) {
10116
+ return { role, seriesIndex };
10117
+ }
10118
+ return { role, seriesIndex, pointIndex };
10119
+ }
10120
+ /**
10121
+ * Resolve the chart part under an event target by walking up to the nearest
10122
+ * tagged ancestor. Accepts the raw `event.target` (unknown) and returns null
10123
+ * for anything that is not an element inside a tagged mark.
10124
+ */
10125
+ function findChartPartTarget(target) {
10126
+ if (!target || typeof target !== 'object') {
10127
+ return null;
10128
+ }
10129
+ const el = target;
10130
+ if (typeof el.closest !== 'function' || typeof el.getAttribute !== 'function') {
10131
+ return null;
10132
+ }
10133
+ return chartPartFromElement(el.closest(`[${CHART_PART_ATTR}]`));
10134
+ }
10135
+ /** Structural equality for (possibly null) part refs. */
10136
+ function isSameChartPart(a, b) {
10137
+ if (!a || !b) {
10138
+ return a === b;
10139
+ }
10140
+ return a.role === b.role && a.seriesIndex === b.seriesIndex && a.pointIndex === b.pointIndex;
10141
+ }
10142
+ // ─────────────────────────────────────────────────────────────────────────────
10143
+ // Drag-to-value math
10144
+ // ─────────────────────────────────────────────────────────────────────────────
10145
+ /**
10146
+ * Inverse of `valueToY`: map a Y coordinate (view-box units) back to a data
10147
+ * value. Mirrors the linear and logarithmic branches of the forward mapping.
10148
+ */
10149
+ function valueFromY(y, range, topY, bottomY) {
10150
+ const usable = bottomY - topY;
10151
+ if (usable === 0) {
10152
+ return range.min;
10153
+ }
10154
+ if (range.logScale && range.logBase) {
10155
+ const base = range.logBase;
10156
+ const logMin = Math.log(range.min) / Math.log(base);
10157
+ const logVal = logMin + ((bottomY - y) / usable) * range.span;
10158
+ return base ** logVal;
10159
+ }
10160
+ return range.min + ((bottomY - y) / usable) * range.span;
10161
+ }
10162
+ /**
10163
+ * Round a dragged value to a step two orders of magnitude below the axis span,
10164
+ * so drags produce human-scale numbers (span 0..500 snaps to whole units,
10165
+ * 0..5 to 0.05) instead of 14-decimal floats.
10166
+ */
10167
+ function roundDragValue(value, range) {
10168
+ if (!Number.isFinite(value) || range.span <= 0) {
10169
+ return value;
10170
+ }
10171
+ const step = 10 ** (Math.floor(Math.log10(range.span)) - 2);
10172
+ const rounded = Math.round(value / step) * step;
10173
+ // Snap away float noise from the multiplication (e.g. 0.30000000000000004).
10174
+ return Number.parseFloat(rounded.toPrecision(12));
10175
+ }
10176
+ /**
10177
+ * Value for a dragged data point at `viewY` (view-box units), using the
10178
+ * secondary range when the part's series is mapped to the secondary axis.
10179
+ */
10180
+ function dragValueForPart(viewY, drag, seriesIndex) {
10181
+ const useSecondary = drag.secondaryRange !== undefined &&
10182
+ (drag.secondarySeriesIndexes?.includes(seriesIndex) ?? false);
10183
+ const range = useSecondary && drag.secondaryRange ? drag.secondaryRange : drag.range;
10184
+ return roundDragValue(valueFromY(viewY, range, drag.plotTop, drag.plotBottom), range);
10185
+ }
10186
+ // ─────────────────────────────────────────────────────────────────────────────
10187
+ // Immutable chart-data edits
10188
+ // ─────────────────────────────────────────────────────────────────────────────
10189
+ /**
10190
+ * Return a copy of `chartData` with one point's value replaced. Returns the
10191
+ * input unchanged when the series or point index is out of range.
10192
+ */
10193
+ function withChartPointValue(chartData, seriesIndex, pointIndex, value) {
10194
+ const series = chartData.series[seriesIndex];
10195
+ if (!series || pointIndex < 0 || pointIndex >= series.values.length) {
10196
+ return chartData;
10197
+ }
10198
+ return {
10199
+ ...chartData,
10200
+ series: chartData.series.map((s, i) => i === seriesIndex
10201
+ ? { ...s, values: s.values.map((v, j) => (j === pointIndex ? value : v)) }
10202
+ : s),
10203
+ };
10204
+ }
10205
+ /**
10206
+ * Return a copy of `chartData` with the title replaced. A non-empty title
10207
+ * turns the title on; an empty one turns it off (matching PowerPoint, where
10208
+ * clearing the title hides it).
10209
+ */
10210
+ function withChartTitle(chartData, title) {
10211
+ const trimmed = title.trim();
10212
+ return {
10213
+ ...chartData,
10214
+ title: trimmed,
10215
+ style: { ...chartData.style, hasTitle: trimmed.length > 0 },
10216
+ };
10217
+ }
10218
+
9948
10219
  /**
9949
10220
  * `animation-css` — pure mapping from a core animation preset to CSS.
9950
10221
  *
@@ -79907,6 +80178,15 @@ class ViewerInspectorPanelService {
79907
80178
  /** True once the user swiped the inspector away on mobile (until reopened). */
79908
80179
  mobileInspectorHidden = signal(false, /* @ts-ignore */
79909
80180
  ...(ngDevMode ? [{ debugName: "mobileInspectorHidden" }] : /* istanbul ignore next */ []));
80181
+ /**
80182
+ * True once the user has explicitly closed the format (element/slide)
80183
+ * panel via the ribbon toggle - independent of selection, mirroring
80184
+ * React's/Vue's own open/closed toggle state. Never affects the explicit
80185
+ * tool panels (comments/accessibility/signatures/selection), which show
80186
+ * regardless of this flag.
80187
+ */
80188
+ formatPanelClosed = signal(false, /* @ts-ignore */
80189
+ ...(ngDevMode ? [{ debugName: "formatPanelClosed" }] : /* istanbul ignore next */ []));
79910
80190
  /**
79911
80191
  * Swipe-to-dismiss drag for the inspector host. The host docks in-flow below
79912
80192
  * the canvas on mobile (same keyboard-reachability reason as the notes
@@ -79961,17 +80241,30 @@ class ViewerInspectorPanelService {
79961
80241
  return null;
79962
80242
  }, /* @ts-ignore */
79963
80243
  ...(ngDevMode ? [{ debugName: "inspectorContent" }] : /* istanbul ignore next */ []));
80244
+ /**
80245
+ * `inspectorContent`, but the format (element/slide) view collapses to
80246
+ * `null` once the user has explicitly closed it via the ribbon toggle.
80247
+ * Explicit tool panels (comments/accessibility/etc.) are untouched.
80248
+ */
80249
+ formatPanelContent = computed(() => {
80250
+ const content = this.inspectorContent();
80251
+ if ((content === 'element' || content === 'slide') && this.formatPanelClosed()) {
80252
+ return null;
80253
+ }
80254
+ return content;
80255
+ }, /* @ts-ignore */
80256
+ ...(ngDevMode ? [{ debugName: "formatPanelContent" }] : /* istanbul ignore next */ []));
79964
80257
  /**
79965
80258
  * Whether the right-docked inspector is showing the format panel (element or
79966
80259
  * slide properties). Drives the top-bar inspector-toggle active state.
79967
80260
  */
79968
80261
  inspectorPaneOpen = computed(() => {
79969
- const content = this.inspectorContent();
80262
+ const content = this.formatPanelContent();
79970
80263
  return content === 'element' || content === 'slide';
79971
80264
  }, /* @ts-ignore */
79972
80265
  ...(ngDevMode ? [{ debugName: "inspectorPaneOpen" }] : /* istanbul ignore next */ []));
79973
80266
  /** Inspector content, but null on mobile once the user has swiped it away. */
79974
- visibleInspectorKind = computed(() => this.mobile.isMobile() && this.mobileInspectorHidden() ? null : this.inspectorContent(), /* @ts-ignore */
80267
+ visibleInspectorKind = computed(() => this.mobile.isMobile() && this.mobileInspectorHidden() ? null : this.formatPanelContent(), /* @ts-ignore */
79975
80268
  ...(ngDevMode ? [{ debugName: "visibleInspectorKind" }] : /* istanbul ignore next */ []));
79976
80269
  /** Accessible-label translation key for the inspector host, by active content. */
79977
80270
  inspectorLabel = computed(() => {
@@ -79999,6 +80292,21 @@ class ViewerInspectorPanelService {
79999
80292
  // Tapping a panel button re-opens the host even after a swipe-dismiss.
80000
80293
  this.mobileInspectorHidden.set(false);
80001
80294
  }
80295
+ /**
80296
+ * Ribbon "toggle inspector" action: if a tool panel is active, return to
80297
+ * the format (element/slide) view; otherwise toggle the format view's
80298
+ * open/closed state, matching React's and Vue's independent open/close
80299
+ * toggle (closing/opening is not tied to selection changes).
80300
+ */
80301
+ toggleFormatPanel() {
80302
+ if (this.activePanel() !== null) {
80303
+ this.activePanel.set(null);
80304
+ this.formatPanelClosed.set(false);
80305
+ }
80306
+ else {
80307
+ this.formatPanelClosed.update((closed) => !closed);
80308
+ }
80309
+ }
80002
80310
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ViewerInspectorPanelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
80003
80311
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ViewerInspectorPanelService });
80004
80312
  }
@@ -81497,7 +81805,7 @@ class PowerPointViewerComponent {
81497
81805
  (exportGif)="xport.exportGif()"
81498
81806
  (exportVideo)="xport.exportVideo()"
81499
81807
  (replace)="findReplace.openFindReplace()"
81500
- (toggleInspector)="inspectorPanel.activePanel.set(null)"
81808
+ (toggleInspector)="inspectorPanel.toggleFormatPanel()"
81501
81809
  (drawToolChange)="onDrawToolChange($event)"
81502
81810
  [showGrid]="showGrid()"
81503
81811
  [showRulers]="showRulers()"
@@ -82173,7 +82481,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
82173
82481
  (exportGif)="xport.exportGif()"
82174
82482
  (exportVideo)="xport.exportVideo()"
82175
82483
  (replace)="findReplace.openFindReplace()"
82176
- (toggleInspector)="inspectorPanel.activePanel.set(null)"
82484
+ (toggleInspector)="inspectorPanel.toggleFormatPanel()"
82177
82485
  (drawToolChange)="onDrawToolChange($event)"
82178
82486
  [showGrid]="showGrid()"
82179
82487
  [showRulers]="showRulers()"
@@ -85260,5 +85568,5 @@ function keyToLabel(key) {
85260
85568
  * Generated bundle index. Do not edit.
85261
85569
  */
85262
85570
 
85263
- export { AUDIENCE_HASH, AUDIENCE_NONCE_KEY, AccessibilityPanelComponent, AccessibilityService, AdvancedChartEditorComponent, AnimationAuthorPanelComponent, AnimationPanelComponent, AnimationPlaybackService, BroadcastDialogComponent, CURSOR_PALETTE, ChartAxisOptionsComponent, ChartAxisStyleOptionsComponent, ChartComboTypeOptionsComponent, ChartDataEditorComponent, ChartDataLabelOptionsComponent, ChartDatapointOptionsComponent, ChartDisplayOptionsComponent, ChartErrorBarOptionsComponent, ChartMarkerOptionsComponent, ChartRendererComponent, ChartTrendlineOptionsComponent, CollaborationCursorsComponent, CollaborationService, CommentsPanelComponent, CommentsService, ComparePanelComponent, ConnectorRendererComponent, ConnectorTextOverlayComponent, DEFAULT_BROADCAST_SERVER_URL, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_PRINT_SETTINGS, DEFAULT_SLIDE_BACKGROUND, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR$1 as DEFAULT_TEXT_COLOR, EMBEDDED_FONTS_STYLE_ID, TEMPLATES as EQUATION_TEMPLATES, EditorContextMenuComponent, EditorHistory, EditorStateService, EditorToolbarComponent, EffectsPanelComponent, ElementRendererComponent, EmbeddedFontsService, EncryptedFileDialogComponent, EquationEditorDialogComponent, EquationRendererComponent, EquationTemplateGalleryComponent, ExportService, FindBarComponent, FindReplaceBarComponent, FontEmbeddingListComponent, FontEmbeddingPanelComponent, GradientPickerComponent, HANDOUT_OPTIONS, HyperlinkDialogComponent, InkRendererComponent, InspectorPanelComponent, IsMobileService, KeepAnnotationsDialogComponent, LoadContentService, MobileBottomBarComponent, MobileMenuSheetComponent, MobilePresenterViewComponent, MobileSheetComponent, MobileSlidesSheetComponent, MobileToolbarComponent, ModalDialogComponent, Model3DRendererComponent, NotesPanelComponent, OleRendererComponent, PRESENTER_CHANNEL_NAME, PRESENTER_MSG_ORIGIN, PasswordProtectionDialogComponent, PasswordStrengthMeterComponent, PowerPointViewerComponent, PresentationAnnotationOverlayComponent, PresentationAnnotationsService, PresentationOverlayComponent, PresentationSubtitleBarComponent, PresentationTransitionOverlayComponent, PresenterViewComponent, PresenterWindowService, PrintDialogComponent, PrintService, PrintSettingsPanelComponent, PropertiesDialogComponent, RESIZE_HANDLES, SEVERITY_GROUPS, SEVERITY_LABELS, SLIDE_TRANSITION_KEYFRAMES, SVG_WARP_PRESETS, SetUpSlideShowDialogComponent, ShareDialogComponent, ShortcutPanelComponent, ShowOptionsFieldsetComponent, ShowSlidesFieldsetComponent, SignatureStrippedDialogComponent, SignaturesPanelComponent, SignaturesService, SlideCanvasComponent, SlideDiffChangesComponent, SlideDiffRowComponent, SlideDiffThumbnailsComponent, SlideSorterOverlayComponent, SlidesPanelComponent, SmartArtRendererComponent, StatusBarComponent, TYPE_LABELS, TableCellAdvancedFillComponent, TableCellFormattingComponent, TableDataEditorComponent, TablePropertiesComponent, TableRendererComponent, TableResizeOverlayComponent, TableSelectionService, TextAdvancedPanelComponent, VIEWER_THEME, VersionHistoryPanelComponent, ViewerCompareService, ViewerDialogsService, ViewerExtraDialogsComponent, WEBM_MIME_CANDIDATES, ZoomRendererComponent, addCommentToList, advanceStep, annotationMapToInkInserts, applyAcceptedDiff, applyFindReplacements, applyFormatToElement, applyMove, applyResize, assignUserColor, bringForward, bringToFront, buildBroadcastConfig, buildBroadcastViewerUrl, buildClearHyperlinkPatch, buildClickGroups, buildCollaborationConfig, buildCssGradientFromShapeStyle, buildDuotoneFilter, buildDuotoneFilterId, buildEmbeddedFontStyles, buildEquationElement, buildEquationSegment, buildFontFaceRule, buildHyperlinkPatch, buildPatternFillCss, buildPrintHtmlDocument as buildPrintDocument, buildPropertiesPatch, buildShareUrl, bulletIndentPx, canStartBroadcast, canStartShare, canUseClipboard, changeCountLabel, changeIcon, checkFontAvailable, clampCursorPosition, clampGifDimensions, clampNotesFontSize, clampStep, clearAudienceContent, cn, collectAccessibilityIssues, collectElementText, collectSlideText, collectUsedFontFamilies, computeHandoutLayout, computeIsMobile, computeIsTablet, computePageCount, computeSlideIndices, computeTimerProgress, convertOmmlToMathMl, copyFormatFromElement, countAccessibilityIssues, countAnnotationStrokes, defaultCssVars, defaultRadius, defaultThemeColors, deleteElementsByIds, deleteVersion as deleteRecoveryVersion, derivePresenceList, duplicateElementById, durationOf, encodeGif, estimatePageCount, findInSlides, fontMimeForFormat, formatAutoNumber, formatCursorLabel, formatElapsed, formatFileSize, formatPropertyDate, formatTime, fpsToFrameIntervalMs, generateBroadcastRoomId, generateCommentId, getContainerStyle, getDuotoneFilterDef, getImageSrc, getPasswordStrength, getPatternSvg, getVersions as getRecoveryVersions, getResolvedShapeClipPath, getResolvedShapeClipPathFor, getShapeFillStrokeStyle, getSlideBackgroundStyle, getSlideTransitionAnimations, getTextBlockStyle, getTextWarp, getWarpCategory, getWarpPath, groupIssuesBySeverity, hasCopyableFormat, hasExistingLink, headerLabel, isAudienceTab, isInjectableUrl, isPpactionUrl, isPresenterMessage, isSigned, isUrlSafe, isValidRoomId, issueTrackKey, issueTypeLabel, keyToLabel, latexToMathml, loadAudienceContent, moveElementBy, msToFrameDelayCs, normalizeFontFormat, normalizeSlidesPerPage, ommlToMathml, overallStatus, parseAudienceNonce, pendingElementStyles, pickSupportedMimeType, planGifFrames, planVideoSegments, presenceToCursors, provideViewerTheme, recordWebm, removeCommentFromList, renderToCanvas, replaceInSlides, replaceMatch, resizeElement, resolveFontVariant, resolveHyperlinkHref, resolveParagraphBullet, resolvePresenterNotes, resolveTransitionDuration, revealedElementStyles, routeOrthogonalConnector, sanitizeColor, sanitizeSlideIndex, sanitizeUserName, scanAvailableFonts, searchSlides, seedBroadcastFields, seedHyperlinkDraft, seedPropertiesDraft, seedShareFields, segmentFrameCount, sendBackward, sendToBack, setElementPosition, shouldUseSvgWarp, signatureCountLabel, signatureKey, signatureTimestamp, signerName, statusLabel as slideDiffStatusLabel, slideNumberOf, statusKind, statusLabel$1 as statusLabel, storeAudienceContent, themeStyle, themeToCssVars, toggleCommentResolvedInList, translationsEn, updateElementById, validatePassword, validatePrintSettings, validateRoomId, waypointsToPathD, worstStatus };
85571
+ export { AUDIENCE_HASH, AUDIENCE_NONCE_KEY, AccessibilityPanelComponent, AccessibilityService, AdvancedChartEditorComponent, AnimationAuthorPanelComponent, AnimationPanelComponent, AnimationPlaybackService, BroadcastDialogComponent, CURSOR_PALETTE, ChartAxisOptionsComponent, ChartAxisStyleOptionsComponent, ChartComboTypeOptionsComponent, ChartDataEditorComponent, ChartDataLabelOptionsComponent, ChartDatapointOptionsComponent, ChartDisplayOptionsComponent, ChartErrorBarOptionsComponent, ChartMarkerOptionsComponent, ChartRendererComponent, ChartTrendlineOptionsComponent, CollaborationCursorsComponent, CollaborationService, CommentsPanelComponent, CommentsService, ComparePanelComponent, ConnectorRendererComponent, ConnectorTextOverlayComponent, DEFAULT_BROADCAST_SERVER_URL, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_PRINT_SETTINGS, DEFAULT_SLIDE_BACKGROUND, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR$1 as DEFAULT_TEXT_COLOR, EMBEDDED_FONTS_STYLE_ID, TEMPLATES as EQUATION_TEMPLATES, EditorContextMenuComponent, EditorHistory, EditorStateService, EditorToolbarComponent, EffectsPanelComponent, ElementRendererComponent, EmbeddedFontsService, EncryptedFileDialogComponent, EquationEditorDialogComponent, EquationRendererComponent, EquationTemplateGalleryComponent, ExportService, FindBarComponent, FindReplaceBarComponent, FontEmbeddingListComponent, FontEmbeddingPanelComponent, GradientPickerComponent, HANDOUT_OPTIONS, HyperlinkDialogComponent, InkRendererComponent, InspectorPanelComponent, IsMobileService, KeepAnnotationsDialogComponent, LoadContentService, MobileBottomBarComponent, MobileMenuSheetComponent, MobilePresenterViewComponent, MobileSheetComponent, MobileSlidesSheetComponent, MobileToolbarComponent, ModalDialogComponent, Model3DRendererComponent, NotesPanelComponent, OleRendererComponent, PRESENTER_CHANNEL_NAME, PRESENTER_MSG_ORIGIN, PasswordProtectionDialogComponent, PasswordStrengthMeterComponent, PowerPointViewerComponent, PresentationAnnotationOverlayComponent, PresentationAnnotationsService, PresentationOverlayComponent, PresentationSubtitleBarComponent, PresentationTransitionOverlayComponent, PresenterViewComponent, PresenterWindowService, PrintDialogComponent, PrintService, PrintSettingsPanelComponent, PropertiesDialogComponent, RESIZE_HANDLES, SEVERITY_GROUPS, SEVERITY_LABELS, SLIDE_TRANSITION_KEYFRAMES, SVG_WARP_PRESETS, SetUpSlideShowDialogComponent, ShareDialogComponent, ShortcutPanelComponent, ShowOptionsFieldsetComponent, ShowSlidesFieldsetComponent, SignatureStrippedDialogComponent, SignaturesPanelComponent, SignaturesService, SlideCanvasComponent, SlideDiffChangesComponent, SlideDiffRowComponent, SlideDiffThumbnailsComponent, SlideSorterOverlayComponent, SlidesPanelComponent, SmartArtRendererComponent, StatusBarComponent, TYPE_LABELS, TableCellAdvancedFillComponent, TableCellFormattingComponent, TableDataEditorComponent, TablePropertiesComponent, TableRendererComponent, TableResizeOverlayComponent, TableSelectionService, TextAdvancedPanelComponent, VIEWER_THEME, VersionHistoryPanelComponent, ViewerCompareService, ViewerDialogsService, ViewerExtraDialogsComponent, WEBM_MIME_CANDIDATES, ZoomRendererComponent, addCommentToList, advanceStep, annotationMapToInkInserts, applyAcceptedDiff, applyFindReplacements, applyFormatToElement, applyMove, applyResize, assignUserColor, bringForward, bringToFront, buildBroadcastConfig, buildBroadcastViewerUrl, buildClearHyperlinkPatch, buildClickGroups, buildCollaborationConfig, buildCssGradientFromShapeStyle, buildDuotoneFilter, buildDuotoneFilterId, buildEmbeddedFontStyles, buildEquationElement, buildEquationSegment, buildFontFaceRule, buildHyperlinkPatch, buildPatternFillCss, buildPrintHtmlDocument as buildPrintDocument, buildPropertiesPatch, buildShareUrl, bulletIndentPx, canStartBroadcast, canStartShare, canUseClipboard, changeCountLabel, changeIcon, checkFontAvailable, clampCursorPosition, clampGifDimensions, clampNotesFontSize, clampStep, clearAudienceContent, cn, collectAccessibilityIssues, collectElementText, collectSlideText, collectUsedFontFamilies, computeHandoutLayout, computeIsMobile, computeIsTablet, computePageCount, computeSlideIndices, computeTimerProgress, convertOmmlToMathMl, copyFormatFromElement, countAccessibilityIssues, countAnnotationStrokes, defaultCssVars, defaultRadius, defaultThemeColors, deleteElementsByIds, deleteVersion as deleteRecoveryVersion, derivePresenceList, duplicateElementById, durationOf, encodeGif, estimatePageCount, findInSlides, fontMimeForFormat, formatAutoNumber, formatCursorLabel, formatElapsed, formatFileSize, formatPropertyDate, formatTime, fpsToFrameIntervalMs, generateBroadcastRoomId, generateCommentId, getContainerStyle, getDuotoneFilterDef, getImageSrc, getPasswordStrength, getPatternSvg, getVersions as getRecoveryVersions, getResolvedShapeClipPath, getResolvedShapeClipPathFor, getShapeFillStrokeStyle, getSlideBackgroundStyle, getSlideTransitionAnimations, getTextBlockStyle, getTextWarp, getWarpCategory, getWarpPath, groupIssuesBySeverity, hasCopyableFormat, hasExistingLink, headerLabel, isAudienceTab, isInjectableUrl, isPpactionUrl, isPresenterMessage, isSigned, isUrlSafe, isValidRoomId, issueTrackKey, issueTypeLabel, keyToLabel, latexToMathml, loadAudienceContent, moveElementBy, msToFrameDelayCs, normalizeFontFormat, normalizeSlidesPerPage, ommlToMathml, overallStatus, parseAudienceNonce, pendingElementStyles, pickSupportedMimeType, planGifFrames, planVideoSegments, presenceToCursors, provideViewerTheme, recordWebm, removeCommentFromList, renderToCanvas, replaceInSlides, replaceMatch, resizeElement, resolveFontVariant, resolveHyperlinkHref, resolveParagraphBullet, resolvePresenterNotes, resolveTransitionDuration, revealedElementStyles, routeOrthogonalConnector, sanitizeColor, sanitizeSlideIndex, sanitizeUserName, scanAvailableFonts, searchSlides, seedBroadcastFields, seedHyperlinkDraft, seedPropertiesDraft, seedShareFields, segmentFrameCount, sendBackward, sendToBack, setElementPosition, shouldUseSvgWarp, signatureCountLabel, signatureKey, signatureTimestamp, signerName, statusLabel as slideDiffStatusLabel, slideNumberOf, statusKind, statusLabel$1 as statusLabel, storeAudienceContent, themeStyle, themeToCssVars, toggleCommentResolvedInList, translationsEn, updateElementById, validatePassword, validatePrintSettings, validateRoomId, vermilionDarkColors, vermilionDarkTheme, vermilionLightColors, vermilionLightTheme, vermilionRadius, waypointsToPathD, worstStatus };
85264
85572
  //# sourceMappingURL=pptx-angular-viewer.mjs.map