pptx-angular-viewer 3.19.2 → 3.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-HvkahiGW.mjs → pptx-angular-viewer-chat-history-idb-DGdVQ5kC.mjs} +2 -2
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-HvkahiGW.mjs.map → pptx-angular-viewer-chat-history-idb-DGdVQ5kC.mjs.map} +1 -1
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-Di10-gYO.mjs → pptx-angular-viewer-pptx-angular-viewer-De1uOCxq.mjs} +1137 -317
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-Di10-gYO.mjs.map → pptx-angular-viewer-pptx-angular-viewer-De1uOCxq.mjs.map} +1 -1
- package/fesm2022/pptx-angular-viewer.mjs +1 -1
- package/i18n/de.cjs +15 -0
- package/i18n/de.mjs +15 -0
- package/i18n/es.cjs +15 -0
- package/i18n/es.mjs +15 -0
- package/i18n/fr.cjs +15 -0
- package/i18n/fr.mjs +15 -0
- package/i18n/zh-CN.cjs +15 -0
- package/i18n/zh-CN.mjs +15 -0
- package/package.json +2 -2
- package/types/pptx-angular-viewer.d.ts +30 -7
- package/types/pptx-angular-viewer.d.ts.map +1 -1
|
@@ -8,7 +8,7 @@ import DOMPurify from 'dompurify';
|
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import * as mcp from 'pptx-viewer-mcp';
|
|
10
10
|
import * as mcpSchemas from 'pptx-viewer-mcp/schemas';
|
|
11
|
-
import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucideLayers, LucideMessageSquare,
|
|
11
|
+
import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucidePlus, LucidePaintbrush, LucideFilter, LucideLayers, LucideMessageSquare, LucideSettings2, LucideStickyNote, LucideDownload, LucideMenu, LucidePresentation, LucideRedo, LucideShare2, LucideSparkles, LucideUndo, LucideChevronRight, LucideChevronLeft, LucideEraser, LucideHighlighter, LucideMousePointer2, LucidePanelRight, LucidePenTool, LucideTimer, LucideArrowLeftRight, LucideCaptions, LucideCirclePause, LucideCirclePlay, LucideGrid2x2, LucideMonitor, LucideMonitorOff, LucideRotateCcw, LucideScan, LucideZoomIn, LucideZoomOut, LucideSave, LucidePlay, LucidePrinter, LucideFileDown, LucideSearch, LucideStar, LucideMoveRight, LucideMousePointerClick, LucideClock3, LucidePencil, LucideType, LucideMinus, LucideSpline, LucideArrowLeft, LucideFilePlus2, LucideFolderOpen, LucideHome, LucideInfo, LucideSettings, LucideUpload, LucideUserRound, LucideAArrowUp, LucideAArrowDown, LucideRemoveFormatting, LucideList, LucideListOrdered, LucideListIndentDecrease, LucideListIndentIncrease, LucideTextAlignJustify, LucideClipboardPaste, LucideFolderPlus, LucideLayoutGrid, LucideLayoutTemplate, LucideScissors, LucideLink, LucideImage, LucideVideo, LucideDatabase, LucidePanelLeft, LucideEllipsis, LucideEye, LucideEyeOff, LucideColumns2, LucideCheck, LucideBug, LucideSend, LucideCrosshair, LucideGitMerge, LucidePin, LucidePinOff, LucideHistory, LucideMessageSquarePlus, LucideWrench, LucideLoaderCircle, LucideTriangleAlert, LucideShapes, LucidePalette, LucideTable, LucideChartColumn, LucideMove, LucideNavigation, LucideFilm, LucideBot, LucideUser } from '@lucide/angular';
|
|
12
12
|
import { XMLParser } from 'fast-xml-parser';
|
|
13
13
|
import JSZip from 'jszip';
|
|
14
14
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
@@ -13504,12 +13504,79 @@ function compileEquationTemplateMathMl() {
|
|
|
13504
13504
|
const NICE_STEPS = [1, 2, 2.5, 5, 10];
|
|
13505
13505
|
/** The fraction of the data span added as headroom beyond the last data point. */
|
|
13506
13506
|
const HEADROOM = 0.05;
|
|
13507
|
+
/**
|
|
13508
|
+
* Plot-area points of vertical room PowerPoint reserves per gridline before it
|
|
13509
|
+
* asks for another one, and the ceiling/floor on how many it will ever ask
|
|
13510
|
+
* for. See {@link axisTargetIntervals}'s doc comment for the PowerPoint COM
|
|
13511
|
+
* measurements these were fit to.
|
|
13512
|
+
*/
|
|
13513
|
+
const POINTS_PER_GRIDLINE = 20;
|
|
13514
|
+
const MIN_TARGET_INTERVALS = 1;
|
|
13515
|
+
const MAX_TARGET_INTERVALS = 10;
|
|
13516
|
+
/**
|
|
13517
|
+
* Pixels per point in the "px" unit `computePlotLayout` (and every renderer in
|
|
13518
|
+
* this engine) works in: 96 px per inch, 72 points per inch, so 4/3 px per pt.
|
|
13519
|
+
* Mirrors `EMU_PER_PIXEL` (core/constants.ts): `EMU_PER_POINT / EMU_PER_PIXEL`
|
|
13520
|
+
* reduces to the same 4/3.
|
|
13521
|
+
*/
|
|
13522
|
+
const PX_PER_POINT$1 = 4 / 3;
|
|
13523
|
+
/** {@link niceValueAxisBounds}'s `targetIntervals` when no plot height is known. */
|
|
13524
|
+
const DEFAULT_TARGET_INTERVALS = 4;
|
|
13507
13525
|
/**
|
|
13508
13526
|
* How close the smaller end of the data has to be to the larger before the axis
|
|
13509
13527
|
* stops anchoring at zero. Below 5/6, zero anchoring keeps the bars readable;
|
|
13510
13528
|
* above it, the data is a narrow band and zero would squash it flat.
|
|
13511
13529
|
*/
|
|
13512
13530
|
const ZERO_ANCHOR_RATIO = 5 / 6;
|
|
13531
|
+
/**
|
|
13532
|
+
* How many gridline intervals PowerPoint's automatic value-axis scale aims
|
|
13533
|
+
* for, given the chart's plot-area height in the "px" unit `computePlotLayout`
|
|
13534
|
+
* returns (96 px/inch; see `PX_PER_POINT` above).
|
|
13535
|
+
*
|
|
13536
|
+
* This is NOT a universal constant (see this module's original doc comment,
|
|
13537
|
+
* which admitted as much: "matches the axes PowerPoint draws for a chart of
|
|
13538
|
+
* ORDINARY height"): a short chart gets fewer, coarser gridlines than a tall
|
|
13539
|
+
* one, up to a point, because PowerPoint only has room to label so many
|
|
13540
|
+
* without the axis text crowding.
|
|
13541
|
+
*
|
|
13542
|
+
* Measured via PowerPoint COM automation (`New-Object -ComObject
|
|
13543
|
+
* PowerPoint.Application`, `Shapes.AddChart2`, reading back
|
|
13544
|
+
* `chart.Axes(2).MinimumScale/.MaximumScale/.MajorUnit`): building a fresh
|
|
13545
|
+
* clustered-column chart at increasing shape heights with the SAME 8-point,
|
|
13546
|
+
* single-category data (values 1.2-3.2, the exact case reported against this
|
|
13547
|
+
* engine, which this engine rendered 0-4 while PowerPoint drew 0-3.5):
|
|
13548
|
+
*
|
|
13549
|
+
* | chart height | plot height | PowerPoint axis | gridlines |
|
|
13550
|
+
* |--------------|-------------|------------------|-----------|
|
|
13551
|
+
* | 100pt | ~33pt | 0 to 5, unit 5 | 1 |
|
|
13552
|
+
* | 150pt | ~83pt | 0 to 4, unit 1 | 4 |
|
|
13553
|
+
* | 200pt | ~133pt | 0 to 3.5, unit 0.5 | 7 |
|
|
13554
|
+
* | 300pt | ~233pt | 0 to 3.5, unit 0.5 | 7 |
|
|
13555
|
+
* | 1000pt | ~933pt | 0 to 3.5, unit 0.5 | 7 (unchanged) |
|
|
13556
|
+
*
|
|
13557
|
+
* Cross-checked against two more datasets (0-52 and 0-9) at the same set of
|
|
13558
|
+
* heights to separate "the target interval count" from "which nice-number
|
|
13559
|
+
* bucket a particular span happens to round into": PowerPoint never asked for
|
|
13560
|
+
* more than about 10 intervals even at a 1000pt-tall chart, it only asks for
|
|
13561
|
+
* FEWER on a plot area too short to fit that many labels. That saturation
|
|
13562
|
+
* (not a straight line) is why this is clamped at the top, not just scaled.
|
|
13563
|
+
*
|
|
13564
|
+
* Modelled as one gridline interval per ~20pt of plot height (roughly one
|
|
13565
|
+
* axis-label line plus padding), clamped to `[1, 10]`. This will not be exact
|
|
13566
|
+
* for every data range: the actual PowerPoint algorithm also nudges the count
|
|
13567
|
+
* by how the span happens to snap to a nice number (see the module doc
|
|
13568
|
+
* comment), which this simplified model does not attempt to reproduce. It is
|
|
13569
|
+
* a large improvement over hard-coding the short-chart answer (4) for every
|
|
13570
|
+
* chart regardless of size, which is the bug this was added to fix.
|
|
13571
|
+
*/
|
|
13572
|
+
function axisTargetIntervals(plotHeightPx) {
|
|
13573
|
+
if (!Number.isFinite(plotHeightPx) || plotHeightPx <= 0) {
|
|
13574
|
+
return DEFAULT_TARGET_INTERVALS;
|
|
13575
|
+
}
|
|
13576
|
+
const plotHeightPt = plotHeightPx / PX_PER_POINT$1;
|
|
13577
|
+
const raw = Math.round(plotHeightPt / POINTS_PER_GRIDLINE);
|
|
13578
|
+
return Math.min(MAX_TARGET_INTERVALS, Math.max(MIN_TARGET_INTERVALS, raw));
|
|
13579
|
+
}
|
|
13513
13580
|
/** The smallest nice step at or above `value`. */
|
|
13514
13581
|
function niceAxisStep(value) {
|
|
13515
13582
|
if (!Number.isFinite(value) || value <= 0) {
|
|
@@ -13534,10 +13601,13 @@ function snap(value, unit, direction) {
|
|
|
13534
13601
|
* @param dataMin Smallest plotted value.
|
|
13535
13602
|
* @param dataMax Largest plotted value.
|
|
13536
13603
|
* @param targetIntervals Roughly how many gridline steps to aim for. The snap to
|
|
13537
|
-
* a round unit means the result is usually one fewer.
|
|
13538
|
-
*
|
|
13604
|
+
* a round unit means the result is usually one fewer. Defaults to 4 only
|
|
13605
|
+
* when the caller has no idea how tall the chart's plot area is; pass
|
|
13606
|
+
* {@link axisTargetIntervals}`(plotHeightPx)` instead whenever that height is
|
|
13607
|
+
* known; see that function's doc comment for why a fixed constant undershot
|
|
13608
|
+
* real PowerPoint on any chart of ordinary-or-larger size.
|
|
13539
13609
|
*/
|
|
13540
|
-
function niceValueAxisBounds(dataMin, dataMax, targetIntervals =
|
|
13610
|
+
function niceValueAxisBounds(dataMin, dataMax, targetIntervals = DEFAULT_TARGET_INTERVALS) {
|
|
13541
13611
|
if (!Number.isFinite(dataMin) || !Number.isFinite(dataMax)) {
|
|
13542
13612
|
return { min: 0, max: 1, majorUnit: 0.5 };
|
|
13543
13613
|
}
|
|
@@ -14131,13 +14201,19 @@ function paletteColor$1(index, styleId, colorPalette) {
|
|
|
14131
14201
|
* sensibly, padded, and rounded out to whole major units. See
|
|
14132
14202
|
* `chart-axis-nice.ts` for the rules. Running the axis to the raw data maximum
|
|
14133
14203
|
* instead put the top gridline on whatever the tallest bar happened to be.
|
|
14204
|
+
*
|
|
14205
|
+
* @param plotHeightPx The chart's plot-area height (same "px" unit
|
|
14206
|
+
* `computePlotLayout` returns), when the caller has it. PowerPoint's real
|
|
14207
|
+
* gridline count depends on how much vertical room the axis has to label
|
|
14208
|
+
* them in; omitting this falls back to a constant tuned for a short chart
|
|
14209
|
+
* (see `axisTargetIntervals`'s doc comment).
|
|
14134
14210
|
*/
|
|
14135
|
-
function computeValueRange$1(series) {
|
|
14211
|
+
function computeValueRange$1(series, plotHeightPx) {
|
|
14136
14212
|
const allValues = series.flatMap((s) => s.values);
|
|
14137
14213
|
if (allValues.length === 0) {
|
|
14138
14214
|
return { min: 0, max: 1, span: 1 };
|
|
14139
14215
|
}
|
|
14140
|
-
const { min, max, majorUnit } = niceValueAxisBounds(Math.min(...allValues), Math.max(...allValues));
|
|
14216
|
+
const { min, max, majorUnit } = niceValueAxisBounds(Math.min(...allValues), Math.max(...allValues), plotHeightPx !== undefined ? axisTargetIntervals(plotHeightPx) : undefined);
|
|
14141
14217
|
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
14142
14218
|
}
|
|
14143
14219
|
/**
|
|
@@ -14704,15 +14780,24 @@ function computeLogValueRange(series, logBase) {
|
|
|
14704
14780
|
logBase,
|
|
14705
14781
|
};
|
|
14706
14782
|
}
|
|
14707
|
-
/**
|
|
14708
|
-
|
|
14783
|
+
/**
|
|
14784
|
+
* Compute a value range using one parsed value axis's scale and bounds.
|
|
14785
|
+
*
|
|
14786
|
+
* @param plotHeightPx The chart's plot-area height, when known; forwarded to
|
|
14787
|
+
* `computeValueRange`'s automatic-scale gridline count (see
|
|
14788
|
+
* `axisTargetIntervals`'s doc comment). Not used on the log-scale branch,
|
|
14789
|
+
* which snaps to powers of the log base regardless of chart size.
|
|
14790
|
+
*/
|
|
14791
|
+
function computeValueRangeForAxis(series, axis, plotHeightPx) {
|
|
14709
14792
|
const requestedLogBase = axis?.logBase ?? 10;
|
|
14710
14793
|
const logBase = axis?.logScale && Number.isFinite(requestedLogBase) && requestedLogBase > 1
|
|
14711
14794
|
? requestedLogBase
|
|
14712
14795
|
: axis?.logScale
|
|
14713
14796
|
? 10
|
|
14714
14797
|
: undefined;
|
|
14715
|
-
const automatic = logBase
|
|
14798
|
+
const automatic = logBase
|
|
14799
|
+
? computeLogValueRange(series, logBase)
|
|
14800
|
+
: computeValueRange$1(series, plotHeightPx);
|
|
14716
14801
|
const validMin = typeof axis?.min === 'number' && Number.isFinite(axis.min) && (!logBase || axis.min > 0)
|
|
14717
14802
|
? axis.min
|
|
14718
14803
|
: undefined;
|
|
@@ -14808,11 +14893,15 @@ function generateMinorAxisTicks(range, axis) {
|
|
|
14808
14893
|
function findLogAxis(axes) {
|
|
14809
14894
|
return axes?.find((axis) => axis.axisType === 'valAx' && axis.logScale);
|
|
14810
14895
|
}
|
|
14811
|
-
/**
|
|
14812
|
-
|
|
14896
|
+
/**
|
|
14897
|
+
* Compute the primary value range for a chart.
|
|
14898
|
+
*
|
|
14899
|
+
* @param plotHeightPx See `computeValueRangeForAxis`'s parameter of the same name.
|
|
14900
|
+
*/
|
|
14901
|
+
function computeValueRangeForChart(series, axes, plotHeightPx) {
|
|
14813
14902
|
const primaryAxis = axes?.find((axis) => axis.axisType === 'valAx' && axis.axPos === 'l') ??
|
|
14814
14903
|
axes?.find((axis) => axis.axisType === 'valAx' && axis.axPos !== 'r');
|
|
14815
|
-
return computeValueRangeForAxis(series, primaryAxis);
|
|
14904
|
+
return computeValueRangeForAxis(series, primaryAxis, plotHeightPx);
|
|
14816
14905
|
}
|
|
14817
14906
|
|
|
14818
14907
|
// ── Display units ────────────────────────────────────────────────
|
|
@@ -15041,6 +15130,160 @@ function shade(hex, amount) {
|
|
|
15041
15130
|
return rgbToHex$3(r * (1 - amount), g * (1 - amount), b * (1 - amount));
|
|
15042
15131
|
}
|
|
15043
15132
|
|
|
15133
|
+
/**
|
|
15134
|
+
* chart-marker-shape.ts: framework-agnostic marker-symbol primitive builder for
|
|
15135
|
+
* line / scatter / area chart data points.
|
|
15136
|
+
*
|
|
15137
|
+
* OOXML line/scatter series carry a `c:marker` with a `c:symbol` (circle,
|
|
15138
|
+
* diamond, square, triangle, star, x, plus, dot, dash, none, ...) and an
|
|
15139
|
+
* optional `c:size` (2-72 points). The base view-model historically drew every
|
|
15140
|
+
* data point as a fixed-radius circle, ignoring both. This helper resolves the
|
|
15141
|
+
* parsed marker into the correct `SvgPrimitive` at the requested size, and
|
|
15142
|
+
* returns `null` for `symbol === 'none'` so no dot is drawn.
|
|
15143
|
+
*
|
|
15144
|
+
* @module chart-marker-shape
|
|
15145
|
+
*/
|
|
15146
|
+
/**
|
|
15147
|
+
* PowerPoint's automatic marker-symbol cycle: the fixed shape sequence a
|
|
15148
|
+
* "Line/Scatter with Markers" chart cycles through when a series' `c:marker`
|
|
15149
|
+
* carries no `c:symbol` (only its fill/line colour is "automatic"; the shape
|
|
15150
|
+
* itself was assumed to always be a circle before this was measured).
|
|
15151
|
+
*
|
|
15152
|
+
* COM-measured ground truth (`PowerPoint.Application`, a stacked
|
|
15153
|
+
* Line-with-Markers chart, N series each with `<c:marker><c:spPr>.../></c:marker>`
|
|
15154
|
+
* and no `c:symbol`, `SeriesCollection(i).MarkerStyle` read back after a real
|
|
15155
|
+
* save/reopen round trip): idx 0..8 resolved to
|
|
15156
|
+
* Diamond, Square, Triangle, X, Star, Circle, Plus, Dot, Dash - a clean
|
|
15157
|
+
* 9-element cycle with no partial/ambiguous entries across 9 independent
|
|
15158
|
+
* series (this is ALSO what the chart-style-driven, explicit-symbol path a
|
|
15159
|
+
* modern "Line with Markers" preset writes on save resolves every series to a
|
|
15160
|
+
* uniform Circle, so that path is unrelated: this cycle is specifically
|
|
15161
|
+
* what PowerPoint's renderer falls back to for a chart with no `c:symbol` at
|
|
15162
|
+
* all). Confirmed against a real-world deck: series `c:idx="1"`/`"2"` (a
|
|
15163
|
+
* gapped, 1-based pair, not `0`/`1`) resolved to Square/Triangle exactly as
|
|
15164
|
+
* this cycle predicts (`AUTOMATIC_MARKER_CYCLE[1]` / `[2]`).
|
|
15165
|
+
*/
|
|
15166
|
+
const AUTOMATIC_MARKER_CYCLE = [
|
|
15167
|
+
'diamond',
|
|
15168
|
+
'square',
|
|
15169
|
+
'triangle',
|
|
15170
|
+
'x',
|
|
15171
|
+
'star',
|
|
15172
|
+
'circle',
|
|
15173
|
+
'plus',
|
|
15174
|
+
'dot',
|
|
15175
|
+
'dash',
|
|
15176
|
+
];
|
|
15177
|
+
/**
|
|
15178
|
+
* Resolve the automatic marker shape for a series with no authored
|
|
15179
|
+
* `c:symbol`, keyed by the series' `c:idx` (or its array position when the
|
|
15180
|
+
* chart has none): {@link AUTOMATIC_MARKER_CYCLE} repeats every 9 series.
|
|
15181
|
+
*/
|
|
15182
|
+
function automaticMarkerSymbol(seriesIdx) {
|
|
15183
|
+
const length = AUTOMATIC_MARKER_CYCLE.length;
|
|
15184
|
+
const normalized = ((seriesIdx % length) + length) % length;
|
|
15185
|
+
return AUTOMATIC_MARKER_CYCLE[normalized];
|
|
15186
|
+
}
|
|
15187
|
+
/** Resolve the drawn radius (px) from the parsed point size or the default. */
|
|
15188
|
+
function markerRadius(size, defaultRadius) {
|
|
15189
|
+
if (size === undefined || !Number.isFinite(size) || size <= 0) {
|
|
15190
|
+
return defaultRadius;
|
|
15191
|
+
}
|
|
15192
|
+
// OOXML marker size is a point diameter; treat 1pt ~ 1px at chart scale.
|
|
15193
|
+
return size / 2;
|
|
15194
|
+
}
|
|
15195
|
+
/** Build the SVG points string for a regular/irregular polygon vertex list. */
|
|
15196
|
+
function polygonPoints(vertices) {
|
|
15197
|
+
return vertices.map(([x, y]) => `${x.toFixed(2)},${y.toFixed(2)}`).join(' ');
|
|
15198
|
+
}
|
|
15199
|
+
function starVertices(cx, cy, r) {
|
|
15200
|
+
const inner = r * 0.5;
|
|
15201
|
+
const out = [];
|
|
15202
|
+
for (let i = 0; i < 10; i++) {
|
|
15203
|
+
const radius = i % 2 === 0 ? r : inner;
|
|
15204
|
+
const angle = -Math.PI / 2 + (Math.PI * i) / 5;
|
|
15205
|
+
out.push([cx + radius * Math.cos(angle), cy + radius * Math.sin(angle)]);
|
|
15206
|
+
}
|
|
15207
|
+
return out;
|
|
15208
|
+
}
|
|
15209
|
+
/**
|
|
15210
|
+
* Build the marker primitive for one data point, honouring `symbol` and `size`.
|
|
15211
|
+
* Returns `null` when `symbol === 'none'` (draw nothing).
|
|
15212
|
+
*/
|
|
15213
|
+
function buildMarkerPrimitive(input) {
|
|
15214
|
+
const { symbol, cx, cy, fill, part } = input;
|
|
15215
|
+
if (symbol === 'none') {
|
|
15216
|
+
return null;
|
|
15217
|
+
}
|
|
15218
|
+
const r = markerRadius(input.size, input.defaultRadius);
|
|
15219
|
+
const stroke = fill;
|
|
15220
|
+
switch (symbol) {
|
|
15221
|
+
case 'square':
|
|
15222
|
+
return { kind: 'rect', x: cx - r, y: cy - r, w: r * 2, h: r * 2, fill, part };
|
|
15223
|
+
case 'dash':
|
|
15224
|
+
return { kind: 'rect', x: cx - r, y: cy - r * 0.32, w: r * 2, h: r * 0.64, fill, part };
|
|
15225
|
+
case 'diamond':
|
|
15226
|
+
return {
|
|
15227
|
+
kind: 'polygon',
|
|
15228
|
+
points: polygonPoints([
|
|
15229
|
+
[cx, cy - r],
|
|
15230
|
+
[cx + r, cy],
|
|
15231
|
+
[cx, cy + r],
|
|
15232
|
+
[cx - r, cy],
|
|
15233
|
+
]),
|
|
15234
|
+
fill,
|
|
15235
|
+
stroke,
|
|
15236
|
+
strokeWidth: 0,
|
|
15237
|
+
part,
|
|
15238
|
+
};
|
|
15239
|
+
case 'triangle':
|
|
15240
|
+
return {
|
|
15241
|
+
kind: 'polygon',
|
|
15242
|
+
points: polygonPoints([
|
|
15243
|
+
[cx, cy - r],
|
|
15244
|
+
[cx + r * 0.9, cy + r * 0.75],
|
|
15245
|
+
[cx - r * 0.9, cy + r * 0.75],
|
|
15246
|
+
]),
|
|
15247
|
+
fill,
|
|
15248
|
+
stroke,
|
|
15249
|
+
strokeWidth: 0,
|
|
15250
|
+
part,
|
|
15251
|
+
};
|
|
15252
|
+
case 'star':
|
|
15253
|
+
return {
|
|
15254
|
+
kind: 'polygon',
|
|
15255
|
+
points: polygonPoints(starVertices(cx, cy, r)),
|
|
15256
|
+
fill,
|
|
15257
|
+
stroke,
|
|
15258
|
+
strokeWidth: 0,
|
|
15259
|
+
part,
|
|
15260
|
+
};
|
|
15261
|
+
case 'plus':
|
|
15262
|
+
return {
|
|
15263
|
+
kind: 'path',
|
|
15264
|
+
d: `M${(cx - r).toFixed(2)},${cy.toFixed(2)} L${(cx + r).toFixed(2)},${cy.toFixed(2)} M${cx.toFixed(2)},${(cy - r).toFixed(2)} L${cx.toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
15265
|
+
fill: 'none',
|
|
15266
|
+
stroke,
|
|
15267
|
+
strokeWidth: Math.max(1, r * 0.4),
|
|
15268
|
+
part,
|
|
15269
|
+
};
|
|
15270
|
+
case 'x':
|
|
15271
|
+
return {
|
|
15272
|
+
kind: 'path',
|
|
15273
|
+
d: `M${(cx - r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx + r).toFixed(2)},${(cy + r).toFixed(2)} M${(cx + r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx - r).toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
15274
|
+
fill: 'none',
|
|
15275
|
+
stroke,
|
|
15276
|
+
strokeWidth: Math.max(1, r * 0.4),
|
|
15277
|
+
part,
|
|
15278
|
+
};
|
|
15279
|
+
case 'dot':
|
|
15280
|
+
return { kind: 'circle', cx, cy, r: Math.max(r * 0.6, 1), fill, part };
|
|
15281
|
+
default:
|
|
15282
|
+
// circle / auto / picture / undefined -> filled circle.
|
|
15283
|
+
return { kind: 'circle', cx, cy, r, fill, part };
|
|
15284
|
+
}
|
|
15285
|
+
}
|
|
15286
|
+
|
|
15044
15287
|
/**
|
|
15045
15288
|
* chart-datapoint-style.ts: framework-agnostic resolution of per-data-point
|
|
15046
15289
|
* formatting overrides (`c:dPt`).
|
|
@@ -15101,11 +15344,25 @@ function resolveDataPointExplosion(series, pointIndex) {
|
|
|
15101
15344
|
* looked at `series.marker`, so editing a point marker changed the file and
|
|
15102
15345
|
* left the canvas untouched. Resolving it here fixes every binding at once,
|
|
15103
15346
|
* since they all paint the same shared view model.
|
|
15347
|
+
*
|
|
15348
|
+
* A resolved symbol of `'auto'` (or a marker present with no `c:symbol` at
|
|
15349
|
+
* all, which the core parser also normalises to `'auto'`) is resolved to a
|
|
15350
|
+
* concrete shape via {@link automaticMarkerSymbol}, keyed by `series.idx`
|
|
15351
|
+
* (falling back to `seriesPosition`, the series' array index, when the chart
|
|
15352
|
+
* carries no `c:idx`). A series/point with NO marker element at all
|
|
15353
|
+
* (`marker` and `point` both `undefined`) keeps `symbol: undefined`
|
|
15354
|
+
* unchanged: that is a chart type that draws no marker at all, not an
|
|
15355
|
+
* automatic one, and must not start cycling shapes.
|
|
15104
15356
|
*/
|
|
15105
|
-
function resolveDataPointMarker(series, pointIndex) {
|
|
15357
|
+
function resolveDataPointMarker(series, pointIndex, seriesPosition = 0) {
|
|
15106
15358
|
const point = findDataPoint(series, pointIndex)?.marker;
|
|
15359
|
+
const hasMarker = point !== undefined || series.marker !== undefined;
|
|
15360
|
+
const rawSymbol = point?.symbol ?? series.marker?.symbol;
|
|
15361
|
+
const symbol = hasMarker && (rawSymbol === undefined || rawSymbol === 'auto')
|
|
15362
|
+
? automaticMarkerSymbol(series.idx ?? seriesPosition)
|
|
15363
|
+
: rawSymbol;
|
|
15107
15364
|
return {
|
|
15108
|
-
symbol
|
|
15365
|
+
symbol,
|
|
15109
15366
|
size: point?.size ?? series.marker?.size,
|
|
15110
15367
|
fill: point?.spPr?.fillColor ?? series.marker?.spPr?.fillColor,
|
|
15111
15368
|
};
|
|
@@ -15837,119 +16094,6 @@ function computeChartLegendLayout(vm) {
|
|
|
15837
16094
|
});
|
|
15838
16095
|
}
|
|
15839
16096
|
|
|
15840
|
-
/**
|
|
15841
|
-
* chart-marker-shape.ts: framework-agnostic marker-symbol primitive builder for
|
|
15842
|
-
* line / scatter / area chart data points.
|
|
15843
|
-
*
|
|
15844
|
-
* OOXML line/scatter series carry a `c:marker` with a `c:symbol` (circle,
|
|
15845
|
-
* diamond, square, triangle, star, x, plus, dot, dash, none, ...) and an
|
|
15846
|
-
* optional `c:size` (2-72 points). The base view-model historically drew every
|
|
15847
|
-
* data point as a fixed-radius circle, ignoring both. This helper resolves the
|
|
15848
|
-
* parsed marker into the correct `SvgPrimitive` at the requested size, and
|
|
15849
|
-
* returns `null` for `symbol === 'none'` so no dot is drawn.
|
|
15850
|
-
*
|
|
15851
|
-
* @module chart-marker-shape
|
|
15852
|
-
*/
|
|
15853
|
-
/** Resolve the drawn radius (px) from the parsed point size or the default. */
|
|
15854
|
-
function markerRadius(size, defaultRadius) {
|
|
15855
|
-
if (size === undefined || !Number.isFinite(size) || size <= 0) {
|
|
15856
|
-
return defaultRadius;
|
|
15857
|
-
}
|
|
15858
|
-
// OOXML marker size is a point diameter; treat 1pt ~ 1px at chart scale.
|
|
15859
|
-
return size / 2;
|
|
15860
|
-
}
|
|
15861
|
-
/** Build the SVG points string for a regular/irregular polygon vertex list. */
|
|
15862
|
-
function polygonPoints(vertices) {
|
|
15863
|
-
return vertices.map(([x, y]) => `${x.toFixed(2)},${y.toFixed(2)}`).join(' ');
|
|
15864
|
-
}
|
|
15865
|
-
function starVertices(cx, cy, r) {
|
|
15866
|
-
const inner = r * 0.5;
|
|
15867
|
-
const out = [];
|
|
15868
|
-
for (let i = 0; i < 10; i++) {
|
|
15869
|
-
const radius = i % 2 === 0 ? r : inner;
|
|
15870
|
-
const angle = -Math.PI / 2 + (Math.PI * i) / 5;
|
|
15871
|
-
out.push([cx + radius * Math.cos(angle), cy + radius * Math.sin(angle)]);
|
|
15872
|
-
}
|
|
15873
|
-
return out;
|
|
15874
|
-
}
|
|
15875
|
-
/**
|
|
15876
|
-
* Build the marker primitive for one data point, honouring `symbol` and `size`.
|
|
15877
|
-
* Returns `null` when `symbol === 'none'` (draw nothing).
|
|
15878
|
-
*/
|
|
15879
|
-
function buildMarkerPrimitive(input) {
|
|
15880
|
-
const { symbol, cx, cy, fill, part } = input;
|
|
15881
|
-
if (symbol === 'none') {
|
|
15882
|
-
return null;
|
|
15883
|
-
}
|
|
15884
|
-
const r = markerRadius(input.size, input.defaultRadius);
|
|
15885
|
-
const stroke = fill;
|
|
15886
|
-
switch (symbol) {
|
|
15887
|
-
case 'square':
|
|
15888
|
-
return { kind: 'rect', x: cx - r, y: cy - r, w: r * 2, h: r * 2, fill, part };
|
|
15889
|
-
case 'dash':
|
|
15890
|
-
return { kind: 'rect', x: cx - r, y: cy - r * 0.32, w: r * 2, h: r * 0.64, fill, part };
|
|
15891
|
-
case 'diamond':
|
|
15892
|
-
return {
|
|
15893
|
-
kind: 'polygon',
|
|
15894
|
-
points: polygonPoints([
|
|
15895
|
-
[cx, cy - r],
|
|
15896
|
-
[cx + r, cy],
|
|
15897
|
-
[cx, cy + r],
|
|
15898
|
-
[cx - r, cy],
|
|
15899
|
-
]),
|
|
15900
|
-
fill,
|
|
15901
|
-
stroke,
|
|
15902
|
-
strokeWidth: 0,
|
|
15903
|
-
part,
|
|
15904
|
-
};
|
|
15905
|
-
case 'triangle':
|
|
15906
|
-
return {
|
|
15907
|
-
kind: 'polygon',
|
|
15908
|
-
points: polygonPoints([
|
|
15909
|
-
[cx, cy - r],
|
|
15910
|
-
[cx + r * 0.9, cy + r * 0.75],
|
|
15911
|
-
[cx - r * 0.9, cy + r * 0.75],
|
|
15912
|
-
]),
|
|
15913
|
-
fill,
|
|
15914
|
-
stroke,
|
|
15915
|
-
strokeWidth: 0,
|
|
15916
|
-
part,
|
|
15917
|
-
};
|
|
15918
|
-
case 'star':
|
|
15919
|
-
return {
|
|
15920
|
-
kind: 'polygon',
|
|
15921
|
-
points: polygonPoints(starVertices(cx, cy, r)),
|
|
15922
|
-
fill,
|
|
15923
|
-
stroke,
|
|
15924
|
-
strokeWidth: 0,
|
|
15925
|
-
part,
|
|
15926
|
-
};
|
|
15927
|
-
case 'plus':
|
|
15928
|
-
return {
|
|
15929
|
-
kind: 'path',
|
|
15930
|
-
d: `M${(cx - r).toFixed(2)},${cy.toFixed(2)} L${(cx + r).toFixed(2)},${cy.toFixed(2)} M${cx.toFixed(2)},${(cy - r).toFixed(2)} L${cx.toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
15931
|
-
fill: 'none',
|
|
15932
|
-
stroke,
|
|
15933
|
-
strokeWidth: Math.max(1, r * 0.4),
|
|
15934
|
-
part,
|
|
15935
|
-
};
|
|
15936
|
-
case 'x':
|
|
15937
|
-
return {
|
|
15938
|
-
kind: 'path',
|
|
15939
|
-
d: `M${(cx - r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx + r).toFixed(2)},${(cy + r).toFixed(2)} M${(cx + r).toFixed(2)},${(cy - r).toFixed(2)} L${(cx - r).toFixed(2)},${(cy + r).toFixed(2)}`,
|
|
15940
|
-
fill: 'none',
|
|
15941
|
-
stroke,
|
|
15942
|
-
strokeWidth: Math.max(1, r * 0.4),
|
|
15943
|
-
part,
|
|
15944
|
-
};
|
|
15945
|
-
case 'dot':
|
|
15946
|
-
return { kind: 'circle', cx, cy, r: Math.max(r * 0.6, 1), fill, part };
|
|
15947
|
-
default:
|
|
15948
|
-
// circle / auto / picture / undefined -> filled circle.
|
|
15949
|
-
return { kind: 'circle', cx, cy, r, fill, part };
|
|
15950
|
-
}
|
|
15951
|
-
}
|
|
15952
|
-
|
|
15953
16097
|
/** Legend swatch line width in px: a fixed icon size, independent of the plotted series' own stroke width. */
|
|
15954
16098
|
const LEGEND_LINE_SWATCH_WIDTH = 2;
|
|
15955
16099
|
/** Legend swatch marker radius in px: a fixed icon size, independent of the series' own `c:marker/c:size`. */
|
|
@@ -15981,8 +16125,8 @@ function resolveLegendSwatchKind(kind) {
|
|
|
15981
16125
|
* `c:marker/c:size`, so the legend icon stays a consistent small size
|
|
15982
16126
|
* regardless of how large the plotted markers are.
|
|
15983
16127
|
*/
|
|
15984
|
-
function buildLineLegendSwatch(series, color) {
|
|
15985
|
-
const resolved = resolveDataPointMarker(series, -1), primitives = [];
|
|
16128
|
+
function buildLineLegendSwatch(series, color, seriesPosition = 0) {
|
|
16129
|
+
const resolved = resolveDataPointMarker(series, -1, seriesPosition), primitives = [];
|
|
15986
16130
|
if (!series.lineNoFill) {
|
|
15987
16131
|
primitives.push({
|
|
15988
16132
|
kind: 'line',
|
|
@@ -16153,8 +16297,12 @@ function seriesColor(series, index, colorPalette) {
|
|
|
16153
16297
|
/**
|
|
16154
16298
|
* Automatic Y-axis range, on PowerPoint's terms. See `chart-axis-nice.ts`; this
|
|
16155
16299
|
* mirrors `computeValueRange` in `chart-helpers.ts`.
|
|
16300
|
+
*
|
|
16301
|
+
* @param plotHeightPx The chart's plot-area height (`PlotLayout.plotHeight`),
|
|
16302
|
+
* when the caller has it; see `axisTargetIntervals`'s doc comment for why
|
|
16303
|
+
* this changes the gridline count PowerPoint's automatic scale picks.
|
|
16156
16304
|
*/
|
|
16157
|
-
function computeValueRange(series) {
|
|
16305
|
+
function computeValueRange(series, plotHeightPx) {
|
|
16158
16306
|
let dataMin = Number.POSITIVE_INFINITY, dataMax = Number.NEGATIVE_INFINITY;
|
|
16159
16307
|
for (const item of series) {
|
|
16160
16308
|
for (const value of item.values) {
|
|
@@ -16169,14 +16317,16 @@ function computeValueRange(series) {
|
|
|
16169
16317
|
if (dataMin === Number.POSITIVE_INFINITY) {
|
|
16170
16318
|
return { min: 0, max: 1, span: 1 };
|
|
16171
16319
|
}
|
|
16172
|
-
const { min, max, majorUnit } = niceValueAxisBounds(dataMin, dataMax);
|
|
16320
|
+
const { min, max, majorUnit } = niceValueAxisBounds(dataMin, dataMax, plotHeightPx !== undefined ? axisTargetIntervals(plotHeightPx) : undefined);
|
|
16173
16321
|
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
16174
16322
|
}
|
|
16175
16323
|
/**
|
|
16176
16324
|
* Value range for a stacked bar: the per-category sums, then the same automatic
|
|
16177
16325
|
* scale as any other value axis.
|
|
16326
|
+
*
|
|
16327
|
+
* @param plotHeightPx See `computeValueRange`'s parameter of the same name.
|
|
16178
16328
|
*/
|
|
16179
|
-
function computeStackedValueRange(series, catCount) {
|
|
16329
|
+
function computeStackedValueRange(series, catCount, plotHeightPx) {
|
|
16180
16330
|
let maxSum = 0, minSum = 0;
|
|
16181
16331
|
for (let ci = 0; ci < catCount; ci++) {
|
|
16182
16332
|
let pos = 0, neg = 0;
|
|
@@ -16192,7 +16342,7 @@ function computeStackedValueRange(series, catCount) {
|
|
|
16192
16342
|
maxSum = Math.max(maxSum, pos);
|
|
16193
16343
|
minSum = Math.min(minSum, neg);
|
|
16194
16344
|
}
|
|
16195
|
-
const { min, max, majorUnit } = niceValueAxisBounds(Math.min(minSum, 0), Math.max(maxSum, 0));
|
|
16345
|
+
const { min, max, majorUnit } = niceValueAxisBounds(Math.min(minSum, 0), Math.max(maxSum, 0), plotHeightPx !== undefined ? axisTargetIntervals(plotHeightPx) : undefined);
|
|
16196
16346
|
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
16197
16347
|
}
|
|
16198
16348
|
/**
|
|
@@ -16271,7 +16421,7 @@ function buildLegend(series, colorPalette, svgWidth, legendPos, svgHeight, plotT
|
|
|
16271
16421
|
return {
|
|
16272
16422
|
color,
|
|
16273
16423
|
label: s.name,
|
|
16274
|
-
...(kind === 'line' ? { lineSwatch: buildLineLegendSwatch(s, color) } : {}),
|
|
16424
|
+
...(kind === 'line' ? { lineSwatch: buildLineLegendSwatch(s, color, i) } : {}),
|
|
16275
16425
|
};
|
|
16276
16426
|
});
|
|
16277
16427
|
let legendX = svgWidth / 2, legendY = svgHeight - 8, legendAnchor = 'middle';
|
|
@@ -17318,8 +17468,8 @@ function xyMarkTooltip(seriesName, xVal, yVal, numberFormat) {
|
|
|
17318
17468
|
* fewer points than the series declares and the override must still land on the
|
|
17319
17469
|
* point the author picked.
|
|
17320
17470
|
*/
|
|
17321
|
-
function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius, part, opacity, title) {
|
|
17322
|
-
const marker = resolveDataPointMarker(series, pointIndex), m = buildMarkerPrimitive({
|
|
17471
|
+
function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius, part, opacity, title, seriesPosition = part.seriesIndex ?? 0) {
|
|
17472
|
+
const marker = resolveDataPointMarker(series, pointIndex, seriesPosition), m = buildMarkerPrimitive({
|
|
17323
17473
|
symbol: marker.symbol,
|
|
17324
17474
|
size: marker.size,
|
|
17325
17475
|
cx,
|
|
@@ -19336,11 +19486,15 @@ function barFill(chartData, series, seriesIndex, pointIndex) {
|
|
|
19336
19486
|
* clustered / stacked / percentStacked geometry with the axes transposed.
|
|
19337
19487
|
*/
|
|
19338
19488
|
function buildHorizontalBarViewModel(element, chartData, categoryLabels) {
|
|
19339
|
-
const layout = computePlotLayout(element.width, element.height, chartData, true), catCount = Math.max(categoryLabels.length, 1), series = chartData.series, grouping = chartData.grouping ?? 'clustered', isStacked = grouping === 'stacked' || grouping === 'percentStacked', isPercent = grouping === 'percentStacked',
|
|
19489
|
+
const layout = computePlotLayout(element.width, element.height, chartData, true), catCount = Math.max(categoryLabels.length, 1), series = chartData.series, grouping = chartData.grouping ?? 'clustered', isStacked = grouping === 'stacked' || grouping === 'percentStacked', isPercent = grouping === 'percentStacked',
|
|
19490
|
+
// The value axis runs along the WIDTH here (categories run down the left,
|
|
19491
|
+
// values along the bottom: this builder transposes the column engine), so
|
|
19492
|
+
// the gridline-count budget is keyed off plotWidth, not plotHeight.
|
|
19493
|
+
range = isPercent
|
|
19340
19494
|
? { min: 0, max: 100, span: 100 }
|
|
19341
19495
|
: isStacked
|
|
19342
|
-
? computeStackedValueRange(series, catCount)
|
|
19343
|
-
: computeValueRangeForChart(series, chartData.axes), { gridlines, axisLabels } = buildTransposedValueAxis(range, layout), zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight), zeroLine = range.min < 0 && range.max > 0
|
|
19496
|
+
? computeStackedValueRange(series, catCount, layout.plotWidth)
|
|
19497
|
+
: computeValueRangeForChart(series, chartData.axes, layout.plotWidth), { gridlines, axisLabels } = buildTransposedValueAxis(range, layout), zeroX = valueToX(0, range, layout.plotLeft, layout.plotRight), zeroLine = range.min < 0 && range.max > 0
|
|
19344
19498
|
? {
|
|
19345
19499
|
kind: 'line',
|
|
19346
19500
|
x1: zeroX,
|
|
@@ -20056,11 +20210,11 @@ function computeTrendlinePrimitives(chartData, catCount, layout, range, mode = '
|
|
|
20056
20210
|
* @module chart-overlays
|
|
20057
20211
|
*/
|
|
20058
20212
|
|
|
20059
|
-
function stackedRange(chartData, catCount, isPercent) {
|
|
20213
|
+
function stackedRange(chartData, catCount, isPercent, plotHeightPx) {
|
|
20060
20214
|
if (isPercent) {
|
|
20061
20215
|
return { min: 0, max: 100, span: 100 };
|
|
20062
20216
|
}
|
|
20063
|
-
return computeStackedValueRange(chartData.series, catCount);
|
|
20217
|
+
return computeStackedValueRange(chartData.series, catCount, plotHeightPx);
|
|
20064
20218
|
}
|
|
20065
20219
|
/**
|
|
20066
20220
|
* Build the enriched cartesian view-model for bar / line / area / scatter /
|
|
@@ -20111,13 +20265,13 @@ function buildCartesianViewModel(element, chartData, categoryLabels, kind) {
|
|
|
20111
20265
|
// eslint-disable-next-line one-var -- pre-existing, unrelated to this change
|
|
20112
20266
|
const primaryRange = isStacked
|
|
20113
20267
|
? {
|
|
20114
|
-
...stackedRange(chartData, catCount, isPercent),
|
|
20268
|
+
...stackedRange(chartData, catCount, isPercent, layout.autoPlotHeight),
|
|
20115
20269
|
...(primaryAxis?.orientation === 'maxMin' ? { reverseOrder: true } : {}),
|
|
20116
20270
|
}
|
|
20117
|
-
: computeValueRangeForChart(primaryPlotSeries.length > 0 ? primaryPlotSeries : chartData.series, chartData.axes);
|
|
20271
|
+
: computeValueRangeForChart(primaryPlotSeries.length > 0 ? primaryPlotSeries : chartData.series, chartData.axes, layout.autoPlotHeight);
|
|
20118
20272
|
// eslint-disable-next-line one-var -- pre-existing, unrelated to this change
|
|
20119
20273
|
const secondaryRange = useSecondary && secondaryPlotSeries.length > 0
|
|
20120
|
-
? computeValueRangeForAxis(secondaryPlotSeries, chartData.axes?.find((axis) => axis.axisType === 'valAx' && axis.axPos === 'r'))
|
|
20274
|
+
? computeValueRangeForAxis(secondaryPlotSeries, chartData.axes?.find((axis) => axis.axisType === 'valAx' && axis.axPos === 'r'), layout.autoPlotHeight)
|
|
20121
20275
|
: undefined;
|
|
20122
20276
|
// eslint-disable-next-line one-var -- pre-existing, unrelated to this change
|
|
20123
20277
|
const axisRes = buildCartesianAxes(chartData, layout, primaryRange, secondaryRange, catCount);
|
|
@@ -20342,9 +20496,9 @@ function buildComboViewModel(element, chartData, categoryLabels) {
|
|
|
20342
20496
|
const primaryAxisId = getPrimaryValueAxisId(chartData.axes);
|
|
20343
20497
|
const primaryAxis = chartData.axes?.find((axis) => axis.axisId === primaryAxisId);
|
|
20344
20498
|
const secondaryAxisFormatting = getSecondaryValueAxis(chartData.axes);
|
|
20345
|
-
const primaryRange = computeValueRangeForAxis(primarySeries, primaryAxis);
|
|
20499
|
+
const primaryRange = computeValueRangeForAxis(primarySeries, primaryAxis, layout.autoPlotHeight);
|
|
20346
20500
|
const secondaryRange = secondary.length > 0
|
|
20347
|
-
? computeValueRangeForAxis(secondary.map((entry) => entry.series), secondaryAxisFormatting)
|
|
20501
|
+
? computeValueRangeForAxis(secondary.map((entry) => entry.series), secondaryAxisFormatting, layout.autoPlotHeight)
|
|
20348
20502
|
: undefined;
|
|
20349
20503
|
const primaryCategoryAxis = chartData.axes?.find((axis) => (axis.axisType === 'catAx' || axis.axisType === 'dateAx') &&
|
|
20350
20504
|
axis.axisId === primaryAxis?.crossAxisId);
|
|
@@ -20503,7 +20657,7 @@ function buildStockViewModel(element, chartData, categoryLabels) {
|
|
|
20503
20657
|
// Through `computeValueRangeForChart`, not the bare linear helper: a stock
|
|
20504
20658
|
// chart is as entitled to a log or display-unit value axis as any other
|
|
20505
20659
|
// cartesian kind, and the bare helper silently ignores `c:scaling`.
|
|
20506
|
-
const range = computeValueRangeForChart(chartData.series, chartData.axes);
|
|
20660
|
+
const range = computeValueRangeForChart(chartData.series, chartData.axes, layout.plotHeight);
|
|
20507
20661
|
const valueAxis = chartData.axes?.find((axis) => axis.axisType === 'valAx' && axis.axPos !== 'r');
|
|
20508
20662
|
const categoryAxis = chartData.axes?.find((axis) => (axis.axisType === 'catAx' || axis.axisType === 'dateAx') &&
|
|
20509
20663
|
axis.axisId === valueAxis?.crossAxisId);
|
|
@@ -21324,22 +21478,26 @@ function buildSunburstViewModel(element, chartData, categoryLabels) {
|
|
|
21324
21478
|
}
|
|
21325
21479
|
|
|
21326
21480
|
/**
|
|
21327
|
-
* Filter deleted entries and attach per-entry text-style overrides
|
|
21328
|
-
*
|
|
21329
|
-
*
|
|
21481
|
+
* Filter deleted entries and attach per-entry text-style overrides, falling
|
|
21482
|
+
* back to the chart-level legend default (`PptxChartStyle.legendTextStyle`,
|
|
21483
|
+
* itself `c:legend/c:txPr` or `c:chartSpace/c:txPr`) for any entry that has no
|
|
21484
|
+
* `c:legendEntry/c:txPr` override of its own. Returns the input array
|
|
21485
|
+
* unchanged (same reference) when there is nothing to apply, so a chart with
|
|
21486
|
+
* neither kind of override pays no extra cost.
|
|
21330
21487
|
*/
|
|
21331
|
-
function applyLegendEntryOverrides(legend, entries) {
|
|
21332
|
-
if (!entries || entries.length === 0) {
|
|
21488
|
+
function applyLegendEntryOverrides(legend, entries, defaultTextStyle) {
|
|
21489
|
+
if ((!entries || entries.length === 0) && !defaultTextStyle) {
|
|
21333
21490
|
return legend;
|
|
21334
21491
|
}
|
|
21335
|
-
const byIndex = new Map(entries.map((entry) => [entry.index, entry]));
|
|
21492
|
+
const byIndex = new Map((entries ?? []).map((entry) => [entry.index, entry]));
|
|
21336
21493
|
const result = [];
|
|
21337
21494
|
legend.forEach((item, index) => {
|
|
21338
21495
|
const override = byIndex.get(index);
|
|
21339
21496
|
if (override?.deleted) {
|
|
21340
21497
|
return;
|
|
21341
21498
|
}
|
|
21342
|
-
|
|
21499
|
+
const textStyle = override?.textStyle ?? defaultTextStyle;
|
|
21500
|
+
result.push(textStyle ? { ...item, textStyle } : item);
|
|
21343
21501
|
});
|
|
21344
21502
|
return result;
|
|
21345
21503
|
}
|
|
@@ -21738,7 +21896,7 @@ function buildSurfaceWallPanels(cols, rows, cellSize, zScale, offsetX, offsetY,
|
|
|
21738
21896
|
*/
|
|
21739
21897
|
function buildIsometricSurfaceViewModel(element, chartData, categoryLabels) {
|
|
21740
21898
|
const layout = computePlotLayout(element.width, element.height, chartData, false);
|
|
21741
|
-
const range = computeValueRange(chartData.series);
|
|
21899
|
+
const range = computeValueRange(chartData.series, layout.autoPlotHeight);
|
|
21742
21900
|
const catCount = Math.max(categoryLabels.length, 1);
|
|
21743
21901
|
const seriesCount = chartData.series.length;
|
|
21744
21902
|
// Grid cell count (vertices = cells + 1 in each dimension).
|
|
@@ -21884,7 +22042,7 @@ function buildIsometricSurfaceViewModel(element, chartData, categoryLabels) {
|
|
|
21884
22042
|
*/
|
|
21885
22043
|
function buildFlatSurfaceViewModel(element, chartData, categoryLabels) {
|
|
21886
22044
|
const layout = computePlotLayout(element.width, element.height, chartData, false);
|
|
21887
|
-
const range = computeValueRange(chartData.series);
|
|
22045
|
+
const range = computeValueRange(chartData.series, layout.autoPlotHeight);
|
|
21888
22046
|
const catCount = Math.max(categoryLabels.length, 1);
|
|
21889
22047
|
const seriesCount = chartData.series.length;
|
|
21890
22048
|
const cellW = layout.plotWidth / Math.max(catCount - 1, 1);
|
|
@@ -23064,6 +23222,9 @@ function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, opti
|
|
|
23064
23222
|
const rowCount = options.dataTableRowCount ?? 1;
|
|
23065
23223
|
plotBottom -= 14 + rowCount * 14;
|
|
23066
23224
|
}
|
|
23225
|
+
// The automatic plot height, before any manual layout override below can
|
|
23226
|
+
// change it: see `PlotLayout.autoPlotHeight`'s doc comment.
|
|
23227
|
+
const autoPlotHeight = Math.max(plotBottom - plotTop, 1);
|
|
23067
23228
|
// c:plotArea/c:layout/c:manualLayout: the author placed the plot area by
|
|
23068
23229
|
// hand. Each field the layout omits keeps the automatic value above, which
|
|
23069
23230
|
// is also what a `factor`-mode offset is relative to. An `outer` target
|
|
@@ -23090,6 +23251,7 @@ function computePlotLayout(elementWidth, elementHeight, chartData, hasAxes, opti
|
|
|
23090
23251
|
plotBottom: plotTop + plotHeight,
|
|
23091
23252
|
plotWidth,
|
|
23092
23253
|
plotHeight,
|
|
23254
|
+
autoPlotHeight,
|
|
23093
23255
|
};
|
|
23094
23256
|
}
|
|
23095
23257
|
|
|
@@ -24093,14 +24255,20 @@ function buildWaterfallSteps(values, options) {
|
|
|
24093
24255
|
}
|
|
24094
24256
|
return steps;
|
|
24095
24257
|
}
|
|
24096
|
-
/**
|
|
24097
|
-
|
|
24258
|
+
/**
|
|
24259
|
+
* Compute a value range containing every cumulative and absolute bar endpoint.
|
|
24260
|
+
*
|
|
24261
|
+
* @param plotHeightPx The chart's plot-area height, when known; see
|
|
24262
|
+
* `axisTargetIntervals`'s doc comment for why this changes the automatic
|
|
24263
|
+
* scale's gridline count.
|
|
24264
|
+
*/
|
|
24265
|
+
function computeWaterfallRange(steps, plotHeightPx) {
|
|
24098
24266
|
return computeValueRange([
|
|
24099
24267
|
{
|
|
24100
24268
|
name: 'Waterfall range',
|
|
24101
24269
|
values: steps.flatMap((step) => [step.startValue, step.endValue]),
|
|
24102
24270
|
},
|
|
24103
|
-
]);
|
|
24271
|
+
], plotHeightPx);
|
|
24104
24272
|
}
|
|
24105
24273
|
|
|
24106
24274
|
/**
|
|
@@ -24143,7 +24311,7 @@ function buildWaterfallViewModel(element, chartData, categoryLabels) {
|
|
|
24143
24311
|
const series = chartData.series[0];
|
|
24144
24312
|
const values = series?.values ?? [];
|
|
24145
24313
|
const steps = buildWaterfallSteps(values, series?.waterfallOptions);
|
|
24146
|
-
const range = computeWaterfallRange(steps);
|
|
24314
|
+
const range = computeWaterfallRange(steps, layout.autoPlotHeight);
|
|
24147
24315
|
const catCount = Math.max(categoryLabels.length, values.length, 1);
|
|
24148
24316
|
const barWidth = (layout.plotWidth / catCount) * 0.6;
|
|
24149
24317
|
const gap = (layout.plotWidth / catCount) * 0.2;
|
|
@@ -24342,7 +24510,7 @@ function withDataPointPictureFills(vm, chartData, elementId) {
|
|
|
24342
24510
|
* `chart-legend-entries.ts`.
|
|
24343
24511
|
*/
|
|
24344
24512
|
function withLegendEntries(vm, chartData) {
|
|
24345
|
-
const legend = applyLegendEntryOverrides(vm.legend, chartData.style?.legendEntries);
|
|
24513
|
+
const legend = applyLegendEntryOverrides(vm.legend, chartData.style?.legendEntries, chartData.style?.legendTextStyle);
|
|
24346
24514
|
return legend === vm.legend ? vm : { ...vm, legend };
|
|
24347
24515
|
}
|
|
24348
24516
|
/**
|
|
@@ -25759,27 +25927,36 @@ function setChartCellValue(data, seriesIndex, categoryIndex, raw) {
|
|
|
25759
25927
|
* Hide a currently-visible series (PowerPoint's Chart Filters "uncheck a
|
|
25760
25928
|
* series"): moves it out of {@link PptxChartData.series} into
|
|
25761
25929
|
* {@link PptxChartData.filteredSeries}, keeping its data and identity. The
|
|
25762
|
-
* chart must keep at least one visible series.
|
|
25763
|
-
*
|
|
25764
|
-
*
|
|
25930
|
+
* chart must keep at least one visible series.
|
|
25931
|
+
*
|
|
25932
|
+
* The new filtered entry's `idx`/`order` reuse the series' OWN `c:idx` when
|
|
25933
|
+
* it has one (every real OOXML `c:ser` does): this value is what
|
|
25934
|
+
* {@link restoreFilteredSeries} and the Chart Filters popover
|
|
25935
|
+
* (`chart-quick-actions.ts`'s `buildFilters`) key a series' position on, so a
|
|
25936
|
+
* chart with non-sequential idx values (a filtered series in the original
|
|
25937
|
+
* file, or one authored idx 1/2 rather than 0/1, both real-world cases)
|
|
25938
|
+
* keeps its true identity instead of being renumbered to "the smallest idx
|
|
25939
|
+
* not yet taken," which used to reorder the Chart Filters list and lose a
|
|
25940
|
+
* restored series' original position. Only a source series with no idx at
|
|
25941
|
+
* all (a synthetic/malformed chart) falls back to that smallest-free-slot
|
|
25942
|
+
* scheme, to guarantee every idx in the combined visible+filtered set stays
|
|
25943
|
+
* distinct.
|
|
25765
25944
|
*/
|
|
25766
25945
|
function hideChartSeries(data, seriesIndex) {
|
|
25767
25946
|
if (data.series.length <= 1 || seriesIndex < 0 || seriesIndex >= data.series.length) {
|
|
25768
25947
|
return null;
|
|
25769
25948
|
}
|
|
25770
25949
|
const series = data.series[seriesIndex];
|
|
25771
|
-
|
|
25772
|
-
|
|
25773
|
-
|
|
25774
|
-
|
|
25775
|
-
|
|
25776
|
-
|
|
25777
|
-
|
|
25778
|
-
|
|
25779
|
-
|
|
25780
|
-
|
|
25781
|
-
while (takenIndices.has(idx)) {
|
|
25782
|
-
idx++;
|
|
25950
|
+
let idx = series.idx;
|
|
25951
|
+
if (idx === undefined) {
|
|
25952
|
+
const taken = new Set([
|
|
25953
|
+
...data.series.map((_, i) => i).filter((i) => i !== seriesIndex),
|
|
25954
|
+
...(data.filteredSeries ?? []).map((f) => f.idx),
|
|
25955
|
+
]);
|
|
25956
|
+
idx = 0;
|
|
25957
|
+
while (taken.has(idx)) {
|
|
25958
|
+
idx++;
|
|
25959
|
+
}
|
|
25783
25960
|
}
|
|
25784
25961
|
const filteredEntry = {
|
|
25785
25962
|
idx,
|
|
@@ -25788,6 +25965,11 @@ function hideChartSeries(data, seriesIndex) {
|
|
|
25788
25965
|
categories: data.categories,
|
|
25789
25966
|
values: series.values,
|
|
25790
25967
|
...(series.uniqueId ? { uniqueId: series.uniqueId } : {}),
|
|
25968
|
+
// Full snapshot so restoreFilteredSeries can bring back everything
|
|
25969
|
+
// (fill/line formatting, marker, data labels, ...), not just name and
|
|
25970
|
+
// values: this used to silently reset a series with a picture fill
|
|
25971
|
+
// or any other non-default formatting to plain defaults on restore.
|
|
25972
|
+
originalSeries: series,
|
|
25791
25973
|
};
|
|
25792
25974
|
return {
|
|
25793
25975
|
...data,
|
|
@@ -25798,11 +25980,15 @@ function hideChartSeries(data, seriesIndex) {
|
|
|
25798
25980
|
/**
|
|
25799
25981
|
* Restore a series PowerPoint's Chart Filters hid (the reverse of
|
|
25800
25982
|
* {@link hideChartSeries}): moves it from {@link PptxChartData.filteredSeries}
|
|
25801
|
-
* back into {@link PptxChartData.series}
|
|
25802
|
-
*
|
|
25803
|
-
*
|
|
25804
|
-
*
|
|
25805
|
-
*
|
|
25983
|
+
* back into {@link PptxChartData.series}, reinserted at the position its
|
|
25984
|
+
* `idx` puts it among the currently-visible series (not always appended
|
|
25985
|
+
* last, which used to leave a restored series permanently reordered to the
|
|
25986
|
+
* end of the chart, its legend, and its plot/stacking order). When the
|
|
25987
|
+
* filtered entry itself carries no cached name (PowerPoint auto-generated
|
|
25988
|
+
* one, e.g. "Series 3"), falls back to {@link PptxChartData.filteredSeriesTitle};
|
|
25989
|
+
* when it carries no cached categories, falls back to
|
|
25990
|
+
* {@link PptxChartData.filteredCategoryTitle} or the chart's current
|
|
25991
|
+
* categories.
|
|
25806
25992
|
*/
|
|
25807
25993
|
function restoreFilteredSeries(data, filteredIndex) {
|
|
25808
25994
|
const filtered = data.filteredSeries?.[filteredIndex];
|
|
@@ -25814,15 +26000,33 @@ function restoreFilteredSeries(data, filteredIndex) {
|
|
|
25814
26000
|
const values = filtered.values ??
|
|
25815
26001
|
(filtered.categories ?? data.filteredCategoryTitle)?.map(() => 0) ??
|
|
25816
26002
|
categories.map(() => 0);
|
|
25817
|
-
|
|
25818
|
-
|
|
25819
|
-
|
|
25820
|
-
|
|
25821
|
-
|
|
26003
|
+
// A series hidden by hideChartSeries this session carries a full
|
|
26004
|
+
// originalSeries snapshot: use it as-is (fill/line formatting, marker,
|
|
26005
|
+
// data labels, everything) rather than the bare name/values reconstruction
|
|
26006
|
+
// below, which used to reset a series with a picture fill or any other
|
|
26007
|
+
// non-default formatting to plain defaults on restore. A filtered series
|
|
26008
|
+
// that came from parsing the file (already hidden when opened) has no
|
|
26009
|
+
// snapshot to draw on, since the parser only reads name/cat/val/uniqueId
|
|
26010
|
+
// off the real c15:ser node; that case keeps the bare reconstruction.
|
|
26011
|
+
const restored = filtered.originalSeries
|
|
26012
|
+
? { ...filtered.originalSeries, idx: filtered.idx }
|
|
26013
|
+
: {
|
|
26014
|
+
name,
|
|
26015
|
+
values,
|
|
26016
|
+
idx: filtered.idx,
|
|
26017
|
+
...(filtered.uniqueId ? { uniqueId: filtered.uniqueId } : {}),
|
|
26018
|
+
};
|
|
26019
|
+
// The first currently-visible series whose own idx sorts after the
|
|
26020
|
+
// restored one; splicing in there reproduces its original relative
|
|
26021
|
+
// position. A series with no idx info at all falls back to its array
|
|
26022
|
+
// position, matching hideChartSeries's own fallback.
|
|
26023
|
+
const insertAt = data.series.findIndex((s, i) => (s.idx ?? i) > filtered.idx);
|
|
26024
|
+
const nextSeries = [...data.series];
|
|
26025
|
+
nextSeries.splice(insertAt === -1 ? nextSeries.length : insertAt, 0, restored);
|
|
25822
26026
|
const remainingFiltered = (data.filteredSeries ?? []).filter((_, i) => i !== filteredIndex);
|
|
25823
26027
|
return {
|
|
25824
26028
|
...data,
|
|
25825
|
-
series:
|
|
26029
|
+
series: nextSeries,
|
|
25826
26030
|
...(remainingFiltered.length > 0
|
|
25827
26031
|
? { filteredSeries: remainingFiltered }
|
|
25828
26032
|
: { filteredSeries: undefined }),
|
|
@@ -25853,6 +26057,248 @@ function setDataLabelsRangeCache(series, pointIndex, text) {
|
|
|
25853
26057
|
};
|
|
25854
26058
|
}
|
|
25855
26059
|
|
|
26060
|
+
/** The curated preset list: (id, label key, source `c:style/@val`). */
|
|
26061
|
+
const CHART_STYLE_PRESETS = [
|
|
26062
|
+
{ id: 'colorful', labelKey: 'pptx.chart.styleColorful', styleId: 2 },
|
|
26063
|
+
{ id: 'monochrome', labelKey: 'pptx.chart.styleMonochrome', styleId: 10 },
|
|
26064
|
+
{ id: 'colorfulLight', labelKey: 'pptx.chart.styleColorfulLight', styleId: 18 },
|
|
26065
|
+
{ id: 'colorfulDark', labelKey: 'pptx.chart.styleColorfulDark', styleId: 26 },
|
|
26066
|
+
{ id: 'mutedDark', labelKey: 'pptx.chart.styleMutedDark', styleId: 34 },
|
|
26067
|
+
{ id: 'pastel', labelKey: 'pptx.chart.stylePastel', styleId: 42 },
|
|
26068
|
+
];
|
|
26069
|
+
function paletteEquals(a, b) {
|
|
26070
|
+
if (!b || a.length !== b.length) {
|
|
26071
|
+
return false;
|
|
26072
|
+
}
|
|
26073
|
+
return a.every((c, i) => c.toLowerCase() === b[i]?.toLowerCase());
|
|
26074
|
+
}
|
|
26075
|
+
/** Resolve the id -> styleId map entry, or `undefined` for an unknown id. */
|
|
26076
|
+
function findPreset(id) {
|
|
26077
|
+
return CHART_STYLE_PRESETS.find((p) => p.id === id);
|
|
26078
|
+
}
|
|
26079
|
+
/**
|
|
26080
|
+
* Build the "Chart Styles" gallery descriptor for the currently-selected
|
|
26081
|
+
* chart: every preset's resolved colours plus whether it is the one
|
|
26082
|
+
* currently applied (its resolved palette matches `chartData.colorPalette`).
|
|
26083
|
+
*/
|
|
26084
|
+
function buildChartStylePresets(chartData) {
|
|
26085
|
+
return CHART_STYLE_PRESETS.map(({ id, labelKey, styleId }) => {
|
|
26086
|
+
const colors = getChartStylePalette(styleId);
|
|
26087
|
+
return {
|
|
26088
|
+
id,
|
|
26089
|
+
labelKey,
|
|
26090
|
+
colors,
|
|
26091
|
+
applied: paletteEquals(colors, chartData.colorPalette),
|
|
26092
|
+
};
|
|
26093
|
+
});
|
|
26094
|
+
}
|
|
26095
|
+
/** Drop a data point's own fill override, keeping every other field. */
|
|
26096
|
+
function clearDataPointFill(point) {
|
|
26097
|
+
const { spPr, marker, ...rest } = point;
|
|
26098
|
+
const nextSpPr = spPr && { ...spPr, fillColor: undefined };
|
|
26099
|
+
const nextMarker = marker?.spPr && {
|
|
26100
|
+
...marker,
|
|
26101
|
+
spPr: { ...marker.spPr, fillColor: undefined },
|
|
26102
|
+
};
|
|
26103
|
+
return { ...rest, ...(spPr && { spPr: nextSpPr }), ...(nextMarker && { marker: nextMarker }) };
|
|
26104
|
+
}
|
|
26105
|
+
/** Drop a series' own colour overrides (and its points'), keeping shape/symbol/size. */
|
|
26106
|
+
function clearSeriesColor(series) {
|
|
26107
|
+
const { color: _color, marker, dataPoints, ...rest } = series;
|
|
26108
|
+
const nextMarker = marker?.spPr && { ...marker, spPr: { ...marker.spPr, fillColor: undefined } };
|
|
26109
|
+
return {
|
|
26110
|
+
...rest,
|
|
26111
|
+
...(marker && { marker: nextMarker ?? marker }),
|
|
26112
|
+
...(dataPoints && { dataPoints: dataPoints.map(clearDataPointFill) }),
|
|
26113
|
+
};
|
|
26114
|
+
}
|
|
26115
|
+
/**
|
|
26116
|
+
* Apply a "Chart Styles" preset by id: resolves its palette via
|
|
26117
|
+
* `getChartStylePalette`, writes it onto `colorPalette` (also mirroring
|
|
26118
|
+
* `style.styleId`), and clears every series'/data-point's own explicit fill
|
|
26119
|
+
* so the new palette is not immediately shadowed by pre-existing colours
|
|
26120
|
+
* (see this module's header). Returns `null` for an unknown preset id so a
|
|
26121
|
+
* caller can no-op instead of silently clearing the chart's palette.
|
|
26122
|
+
*/
|
|
26123
|
+
function applyChartStylePreset(chartData, presetId) {
|
|
26124
|
+
const preset = findPreset(presetId);
|
|
26125
|
+
if (!preset) {
|
|
26126
|
+
return null;
|
|
26127
|
+
}
|
|
26128
|
+
const colors = [...getChartStylePalette(preset.styleId)];
|
|
26129
|
+
return {
|
|
26130
|
+
...chartData,
|
|
26131
|
+
colorPalette: colors,
|
|
26132
|
+
style: { ...chartData.style, styleId: preset.styleId },
|
|
26133
|
+
series: chartData.series.map(clearSeriesColor),
|
|
26134
|
+
};
|
|
26135
|
+
}
|
|
26136
|
+
|
|
26137
|
+
const AXIS_TYPES_WITH_TITLES = [
|
|
26138
|
+
'catAx',
|
|
26139
|
+
'valAx',
|
|
26140
|
+
'dateAx',
|
|
26141
|
+
];
|
|
26142
|
+
/** Default axis title text PowerPoint inserts when a title is turned on with none set. */
|
|
26143
|
+
const DEFAULT_AXIS_TITLE_TEXT = 'Axis Title';
|
|
26144
|
+
/**
|
|
26145
|
+
* Set/clear `deleted` on every category/value/date axis (PowerPoint's "Axes"
|
|
26146
|
+
* checklist item hides the whole axis, not just its gridlines/title).
|
|
26147
|
+
*/
|
|
26148
|
+
function chartAxesVisibilityPatch(chartData, show) {
|
|
26149
|
+
const axes = (chartData.axes ?? []).map((axis) => AXIS_TYPES_WITH_TITLES.includes(axis.axisType) ? { ...axis, deleted: !show } : axis);
|
|
26150
|
+
return { axes };
|
|
26151
|
+
}
|
|
26152
|
+
/** Whether at least one axis is currently visible (not `deleted`). */
|
|
26153
|
+
function chartAxesVisibilityState(chartData) {
|
|
26154
|
+
const relevant = (chartData.axes ?? []).filter((axis) => AXIS_TYPES_WITH_TITLES.includes(axis.axisType));
|
|
26155
|
+
return relevant.length === 0 || relevant.some((axis) => !axis.deleted);
|
|
26156
|
+
}
|
|
26157
|
+
/**
|
|
26158
|
+
* Set/clear `titleText` on every category/value axis. Turning off blanks the
|
|
26159
|
+
* text (PowerPoint's own "None" removes the title box entirely, which this
|
|
26160
|
+
* codebase models as absent/empty `titleText`, see `chart-axis-render.ts`);
|
|
26161
|
+
* turning on with no existing text fills in the same placeholder PowerPoint
|
|
26162
|
+
* inserts ("Axis Title").
|
|
26163
|
+
*/
|
|
26164
|
+
function chartAxisTitlesPatch(chartData, show) {
|
|
26165
|
+
const axes = (chartData.axes ?? []).map((axis) => {
|
|
26166
|
+
if (!AXIS_TYPES_WITH_TITLES.includes(axis.axisType)) {
|
|
26167
|
+
return axis;
|
|
26168
|
+
}
|
|
26169
|
+
if (!show) {
|
|
26170
|
+
return { ...axis, titleText: undefined };
|
|
26171
|
+
}
|
|
26172
|
+
return { ...axis, titleText: axis.titleText || DEFAULT_AXIS_TITLE_TEXT };
|
|
26173
|
+
});
|
|
26174
|
+
return { axes };
|
|
26175
|
+
}
|
|
26176
|
+
/** Whether at least one axis currently shows a non-empty title. */
|
|
26177
|
+
function chartAxisTitlesState(chartData) {
|
|
26178
|
+
return (chartData.axes ?? []).some((axis) => AXIS_TYPES_WITH_TITLES.includes(axis.axisType) && Boolean(axis.titleText));
|
|
26179
|
+
}
|
|
26180
|
+
/**
|
|
26181
|
+
* Apply one "Chart Elements" checklist toggle. The single entry point every
|
|
26182
|
+
* binding's quick-action popover calls on click; see this module's header.
|
|
26183
|
+
*/
|
|
26184
|
+
function applyChartElementToggle(chartData, key, checked) {
|
|
26185
|
+
switch (key) {
|
|
26186
|
+
case 'title':
|
|
26187
|
+
return patchChartData$1(chartData, { style: { ...chartData.style, hasTitle: checked } });
|
|
26188
|
+
case 'legend':
|
|
26189
|
+
return patchChartData$1(chartData, { style: { ...chartData.style, hasLegend: checked } });
|
|
26190
|
+
case 'dataLabels':
|
|
26191
|
+
return patchChartData$1(chartData, { style: { ...chartData.style, hasDataLabels: checked } });
|
|
26192
|
+
case 'gridlines':
|
|
26193
|
+
return patchChartData$1(chartData, chartGridlinesPatch(chartData, checked));
|
|
26194
|
+
case 'axes':
|
|
26195
|
+
return patchChartData$1(chartData, chartAxesVisibilityPatch(chartData, checked));
|
|
26196
|
+
case 'axisTitles':
|
|
26197
|
+
return patchChartData$1(chartData, chartAxisTitlesPatch(chartData, checked));
|
|
26198
|
+
default:
|
|
26199
|
+
return chartData;
|
|
26200
|
+
}
|
|
26201
|
+
}
|
|
26202
|
+
|
|
26203
|
+
/** Button edge length, in the same units as the caller's `selectionBox`. */
|
|
26204
|
+
const CHART_QUICK_ACTION_BUTTON_SIZE = 24;
|
|
26205
|
+
/** Gap between stacked buttons. */
|
|
26206
|
+
const BUTTON_GAP = 6;
|
|
26207
|
+
/** Gap between the chart's selection box and the button column, matching PowerPoint's offset. */
|
|
26208
|
+
const OUTSIDE_GAP = 8;
|
|
26209
|
+
const BUTTON_ORDER = [
|
|
26210
|
+
{ id: 'elements', labelKey: 'pptx.chart.quickElements' },
|
|
26211
|
+
{ id: 'styles', labelKey: 'pptx.chart.quickStyles' },
|
|
26212
|
+
{ id: 'filters', labelKey: 'pptx.chart.quickFilters' },
|
|
26213
|
+
];
|
|
26214
|
+
function buildButtons(selectionBox, showFilters) {
|
|
26215
|
+
const x = selectionBox.x + selectionBox.width + OUTSIDE_GAP;
|
|
26216
|
+
return BUTTON_ORDER.filter((entry) => entry.id !== 'filters' || showFilters).map((entry, i) => ({
|
|
26217
|
+
...entry,
|
|
26218
|
+
x,
|
|
26219
|
+
y: selectionBox.y + i * (CHART_QUICK_ACTION_BUTTON_SIZE + BUTTON_GAP),
|
|
26220
|
+
size: CHART_QUICK_ACTION_BUTTON_SIZE,
|
|
26221
|
+
}));
|
|
26222
|
+
}
|
|
26223
|
+
function buildElements(chartData) {
|
|
26224
|
+
const items = [
|
|
26225
|
+
{ key: 'title', labelKey: 'pptx.chart.showTitle', checked: chartData.style?.hasTitle ?? false },
|
|
26226
|
+
{
|
|
26227
|
+
key: 'legend',
|
|
26228
|
+
labelKey: 'pptx.chart.showLegend',
|
|
26229
|
+
checked: chartData.style?.hasLegend ?? false,
|
|
26230
|
+
},
|
|
26231
|
+
{
|
|
26232
|
+
key: 'gridlines',
|
|
26233
|
+
labelKey: 'pptx.chart.showGridlines',
|
|
26234
|
+
checked: chartGridlinesState(chartData),
|
|
26235
|
+
},
|
|
26236
|
+
{
|
|
26237
|
+
key: 'dataLabels',
|
|
26238
|
+
labelKey: 'pptx.chart.showDataLabels',
|
|
26239
|
+
checked: chartData.style?.hasDataLabels ?? false,
|
|
26240
|
+
},
|
|
26241
|
+
];
|
|
26242
|
+
if (chartData.axes && chartData.axes.length > 0) {
|
|
26243
|
+
items.push({
|
|
26244
|
+
key: 'axes',
|
|
26245
|
+
labelKey: 'pptx.chart.quickAxes',
|
|
26246
|
+
checked: chartAxesVisibilityState(chartData),
|
|
26247
|
+
});
|
|
26248
|
+
items.push({
|
|
26249
|
+
key: 'axisTitles',
|
|
26250
|
+
labelKey: 'pptx.chart.quickAxisTitles',
|
|
26251
|
+
checked: chartAxisTitlesState(chartData),
|
|
26252
|
+
});
|
|
26253
|
+
}
|
|
26254
|
+
return items;
|
|
26255
|
+
}
|
|
26256
|
+
function buildFilters(chartData) {
|
|
26257
|
+
const visibleSeries = chartData.series.map((series, index) => ({
|
|
26258
|
+
key: `visible-${index}`,
|
|
26259
|
+
name: series.name,
|
|
26260
|
+
visible: true,
|
|
26261
|
+
seriesIndex: index,
|
|
26262
|
+
sortKey: series.idx ?? index,
|
|
26263
|
+
}));
|
|
26264
|
+
const filtered = (chartData.filteredSeries ?? []).map((entry, index) => ({
|
|
26265
|
+
key: `filtered-${index}`,
|
|
26266
|
+
name: entry.name ?? chartData.filteredSeriesTitle ?? `Series ${index + 1}`,
|
|
26267
|
+
visible: false,
|
|
26268
|
+
filteredIndex: index,
|
|
26269
|
+
sortKey: entry.idx,
|
|
26270
|
+
}));
|
|
26271
|
+
// PowerPoint's Chart Filters list never reorders rows as they're (un)checked:
|
|
26272
|
+
// every series keeps its original position, keyed by its persistent c:idx
|
|
26273
|
+
// (falling back to array position for a chart with no idx info at all),
|
|
26274
|
+
// not by which of the two underlying arrays (series/filteredSeries)
|
|
26275
|
+
// currently holds it. Concatenating visible-then-filtered instead made a
|
|
26276
|
+
// hidden series jump to the bottom of the list (reported as "unticking
|
|
26277
|
+
// some of them changes the ordering").
|
|
26278
|
+
const series = [...visibleSeries, ...filtered]
|
|
26279
|
+
.sort((a, b) => a.sortKey - b.sortKey)
|
|
26280
|
+
.map(({ sortKey: _sortKey, ...rest }) => rest);
|
|
26281
|
+
return { visible: series.length > 1, series };
|
|
26282
|
+
}
|
|
26283
|
+
/**
|
|
26284
|
+
* Build the quick-action descriptor for the currently-selected element.
|
|
26285
|
+
* Returns `null` when the quick actions should not render (nothing selected,
|
|
26286
|
+
* the selection is not a chart, or the chart has no data yet).
|
|
26287
|
+
*/
|
|
26288
|
+
function buildChartQuickActionsDescriptor(input) {
|
|
26289
|
+
if (!input.isChartSelected || !input.chartData) {
|
|
26290
|
+
return null;
|
|
26291
|
+
}
|
|
26292
|
+
const { chartData, selectionBox } = input;
|
|
26293
|
+
const filters = buildFilters(chartData);
|
|
26294
|
+
return {
|
|
26295
|
+
buttons: buildButtons(selectionBox, filters.visible),
|
|
26296
|
+
elements: buildElements(chartData),
|
|
26297
|
+
filters,
|
|
26298
|
+
styles: { presets: buildChartStylePresets(chartData) },
|
|
26299
|
+
};
|
|
26300
|
+
}
|
|
26301
|
+
|
|
25856
26302
|
const TWO_PI = Math.PI * 2;
|
|
25857
26303
|
/** Keep the dragged span strictly inside (0, 2*PI) so the share never hits 0 or 1. */
|
|
25858
26304
|
const ANGLE_EPSILON = TWO_PI * 0.001;
|
|
@@ -25956,9 +26402,12 @@ function buildStackedDragGeometry(element, chartData, seriesIndex, pointIndex) {
|
|
|
25956
26402
|
if (!draggedValues || pointIndex < 0 || pointIndex >= draggedValues.length) {
|
|
25957
26403
|
return null;
|
|
25958
26404
|
}
|
|
25959
|
-
const percent = grouping === 'percentStacked', catCount = Math.max(chartData.categories.length, ...seriesValues.map((values) => values.length), pointIndex + 1), plots = computeStackedSeriesPlots(seriesValues, catCount, percent), baseValue = plots[seriesIndex]?.base[pointIndex] ?? 0, otherAbsSum = seriesValues.reduce((sum, values, si) => (si === seriesIndex ? sum : sum + Math.abs(values[pointIndex] ?? 0)), 0),
|
|
26405
|
+
const percent = grouping === 'percentStacked', catCount = Math.max(chartData.categories.length, ...seriesValues.map((values) => values.length), pointIndex + 1), plots = computeStackedSeriesPlots(seriesValues, catCount, percent), baseValue = plots[seriesIndex]?.base[pointIndex] ?? 0, otherAbsSum = seriesValues.reduce((sum, values, si) => (si === seriesIndex ? sum : sum + Math.abs(values[pointIndex] ?? 0)), 0), layoutOpts = computeLayoutOptions(chartData.axes, chartData.dataTable, chartData.series.length), layout = computePlotLayout(element.width, element.height, chartData, true, layoutOpts),
|
|
26406
|
+
// Computed from the SAME `layout.autoPlotHeight` `chart-cartesian.ts`'s
|
|
26407
|
+
// `stackedRange` uses, so a drag never disagrees with what is on screen.
|
|
26408
|
+
range = percent
|
|
25960
26409
|
? { min: 0, max: 100, span: 100 }
|
|
25961
|
-
: computeStackedValueRange(chartData.series, catCount
|
|
26410
|
+
: computeStackedValueRange(chartData.series, catCount, layout.autoPlotHeight);
|
|
25962
26411
|
return {
|
|
25963
26412
|
range,
|
|
25964
26413
|
plotTop: layout.plotTop,
|
|
@@ -48733,6 +49182,7 @@ const translationsEn = {
|
|
|
48733
49182
|
'pptx.sections.addAfter': 'Add Section After',
|
|
48734
49183
|
// Notes
|
|
48735
49184
|
'pptx.notes.title': 'Notes',
|
|
49185
|
+
'pptx.notes.hasNotes': '(has notes)',
|
|
48736
49186
|
'pptx.notes.slideN': 'Slide {{n}}',
|
|
48737
49187
|
'pptx.notes.noSlide': 'No slide selected',
|
|
48738
49188
|
'pptx.notes.clickToAddNotes': 'Click to add notes',
|
|
@@ -48933,6 +49383,17 @@ const translationsEn = {
|
|
|
48933
49383
|
'pptx.chart.chartFilters': 'Chart filters',
|
|
48934
49384
|
'pptx.chart.hideSeries': 'Hide {{name}}',
|
|
48935
49385
|
'pptx.chart.showSeries': 'Show {{name}}',
|
|
49386
|
+
'pptx.chart.quickElements': 'Chart Elements',
|
|
49387
|
+
'pptx.chart.quickStyles': 'Chart Styles',
|
|
49388
|
+
'pptx.chart.quickFilters': 'Chart Filters',
|
|
49389
|
+
'pptx.chart.quickAxes': 'Axes',
|
|
49390
|
+
'pptx.chart.quickAxisTitles': 'Axis Titles',
|
|
49391
|
+
'pptx.chart.styleColorful': 'Colorful',
|
|
49392
|
+
'pptx.chart.styleMonochrome': 'Monochrome',
|
|
49393
|
+
'pptx.chart.styleColorfulLight': 'Colorful Light',
|
|
49394
|
+
'pptx.chart.styleColorfulDark': 'Colorful Dark',
|
|
49395
|
+
'pptx.chart.styleMutedDark': 'Muted Dark',
|
|
49396
|
+
'pptx.chart.stylePastel': 'Pastel',
|
|
48936
49397
|
'pptx.chart.valueFromCells': 'Value from cells: {{name}}',
|
|
48937
49398
|
'pptx.chart.removeCategory': 'Remove category',
|
|
48938
49399
|
'pptx.chart.axes': 'Axes',
|
|
@@ -49077,6 +49538,8 @@ const translationsEn = {
|
|
|
49077
49538
|
'pptx.slideShow.subtitles': 'Subtitles',
|
|
49078
49539
|
// Record tab (camera overlay placeholders)
|
|
49079
49540
|
'pptx.record.cameo': 'Cameo',
|
|
49541
|
+
'pptx.record.manage': 'Manage',
|
|
49542
|
+
'pptx.record.camera': 'Camera',
|
|
49080
49543
|
'pptx.record.clear': 'Clear',
|
|
49081
49544
|
'pptx.record.learnMore': 'Learn More',
|
|
49082
49545
|
'pptx.record.resetToCameo': 'Reset to Cameo',
|
|
@@ -51186,6 +51649,7 @@ const translationsEn = {
|
|
|
51186
51649
|
'pptx.textFormatting.paragraphBefore': 'Paragraph Before',
|
|
51187
51650
|
'pptx.textFormatting.textFlow': 'Text Flow',
|
|
51188
51651
|
'pptx.textProperties.advancedTextHeading': 'Advanced Text',
|
|
51652
|
+
'pptx.textProperties.autoFitToShape': 'Auto-fit text to shape',
|
|
51189
51653
|
'pptx.textProperties.defaultFontOption': 'Default ({{font}})',
|
|
51190
51654
|
'pptx.textProperties.firstIndent': 'First Indent',
|
|
51191
51655
|
'pptx.textProperties.leftMargin': 'Left Margin',
|
|
@@ -77278,7 +77742,9 @@ function buildSurfaceChart3DData(chartData, categoryLabels, options) {
|
|
|
77278
77742
|
if (seriesCount === 0 || catCount === 0) {
|
|
77279
77743
|
return null;
|
|
77280
77744
|
}
|
|
77281
|
-
|
|
77745
|
+
// See the matching comment in `bar-chart-3d-data.ts`: the element height
|
|
77746
|
+
// stands in for a plot-area height this 3D scene doesn't separately compute.
|
|
77747
|
+
const range = computeValueRange(chartData.series, options.height);
|
|
77282
77748
|
const heightMap = new Float32Array(seriesCount * catCount);
|
|
77283
77749
|
const colorMap = new Float32Array(seriesCount * catCount * 3);
|
|
77284
77750
|
// Raw (un-normalised) values, kept alongside the [0,1] heightMap so the
|
|
@@ -78419,11 +78885,16 @@ function buildBarChart3DData(chartData, categoryLabels, options) {
|
|
|
78419
78885
|
const isPercent = grouping === 'percentStacked';
|
|
78420
78886
|
const horizontal = chartData.barDirection === 'bar';
|
|
78421
78887
|
const points = buildPoints$1(chartData, cols, isPercent);
|
|
78888
|
+
// No separate plot-area inset exists for the 3D scene the way the flat SVG
|
|
78889
|
+
// engine's `computePlotLayout` reserves one, so the full element height
|
|
78890
|
+
// stands in for it; see `axisTargetIntervals`'s doc comment for why this
|
|
78891
|
+
// only makes the automatic scale saturate at its gridline cap slightly
|
|
78892
|
+
// sooner; it does not change the "ordinary chart" result this was fixed for.
|
|
78422
78893
|
const range = isPercent
|
|
78423
78894
|
? { min: 0, max: 100, span: 100 }
|
|
78424
78895
|
: grouping === 'stacked'
|
|
78425
|
-
? computeStackedValueRange(chartData.series, cols)
|
|
78426
|
-
: computeValueRange(chartData.series);
|
|
78896
|
+
? computeStackedValueRange(chartData.series, cols, options.height)
|
|
78897
|
+
: computeValueRange(chartData.series, options.height);
|
|
78427
78898
|
const depthPercent = chartData.view3D?.depthPercent;
|
|
78428
78899
|
const boxes = layoutBarChart3D(points, cols, rows, range, grouping, depthPercent, horizontal);
|
|
78429
78900
|
return {
|
|
@@ -78610,7 +79081,9 @@ function buildCartesianLine3DSceneData(chartData, categoryLabels, options) {
|
|
|
78610
79081
|
return null;
|
|
78611
79082
|
}
|
|
78612
79083
|
const points = buildPoints(chartData, cols);
|
|
78613
|
-
|
|
79084
|
+
// See the matching comment in `bar-chart-3d-data.ts`: the element height
|
|
79085
|
+
// stands in for a plot-area height this 3D scene doesn't separately compute.
|
|
79086
|
+
const range = computeValueRange(chartData.series, options.height);
|
|
78614
79087
|
const depthPercent = chartData.view3D?.depthPercent;
|
|
78615
79088
|
const series = layoutCartesianLine3DSeries(points, cols, rows, range, depthPercent);
|
|
78616
79089
|
return {
|
|
@@ -107165,7 +107638,7 @@ function createLocalStorageBackend(namespace) {
|
|
|
107165
107638
|
/** Try IndexedDB first; fall back to localStorage on any failure. */
|
|
107166
107639
|
async function resolveBackend(dbName, namespace) {
|
|
107167
107640
|
try {
|
|
107168
|
-
const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-
|
|
107641
|
+
const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-DGdVQ5kC.mjs');
|
|
107169
107642
|
const db = await openChatDb(dbName);
|
|
107170
107643
|
return createIdbBackend(db);
|
|
107171
107644
|
}
|
|
@@ -117837,6 +118310,457 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
117837
118310
|
type: Injectable
|
|
117838
118311
|
}] });
|
|
117839
118312
|
|
|
118313
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118314
|
+
// Direct part-editing gate
|
|
118315
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118316
|
+
/**
|
|
118317
|
+
* May this chart's individual parts (title, series, data points) be entered
|
|
118318
|
+
* for direct on-canvas editing?
|
|
118319
|
+
*
|
|
118320
|
+
* Pure so it is unit-testable without a full Angular injection context:
|
|
118321
|
+
* `ChartElementViewComponent`'s constructor runs an `effect()` that needs a
|
|
118322
|
+
* `ChangeDetectionScheduler` this package's TestBed-free suite doesn't
|
|
118323
|
+
* provide. G8: `a:graphicFrameLocks/@noDrilldown` forbids the drill-down,
|
|
118324
|
+
* even when the chart is otherwise selected + editable.
|
|
118325
|
+
*/
|
|
118326
|
+
function chartCanEditParts(editable, isSelected, hasEditor, element) {
|
|
118327
|
+
return editable && isSelected && hasEditor && canDrillDown(element);
|
|
118328
|
+
}
|
|
118329
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118330
|
+
// Value-drag commit gate
|
|
118331
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118332
|
+
/**
|
|
118333
|
+
* The chart data a finished drag should commit, or null when nothing should
|
|
118334
|
+
* be committed (cancelled, or the press never became a drag).
|
|
118335
|
+
*/
|
|
118336
|
+
function chartDragCommitData(session, commit) {
|
|
118337
|
+
if (!commit || !session?.moved) {
|
|
118338
|
+
return null;
|
|
118339
|
+
}
|
|
118340
|
+
return session.lastData;
|
|
118341
|
+
}
|
|
118342
|
+
/**
|
|
118343
|
+
* Same gate as {@link chartDragCommitData}, for a pie/radar/stacked mark drag
|
|
118344
|
+
* ({@link ChartMarkDragState} carries the same `moved`/`lastData` shape as the
|
|
118345
|
+
* cartesian value-drag session, just resolved through a different geometry).
|
|
118346
|
+
*/
|
|
118347
|
+
function chartMarkDragCommitData(session, commit) {
|
|
118348
|
+
if (!commit || !session?.moved) {
|
|
118349
|
+
return null;
|
|
118350
|
+
}
|
|
118351
|
+
return session.lastData;
|
|
118352
|
+
}
|
|
118353
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118354
|
+
// 3D value-drag commit data (bar3D/line3D/area3D/pie3D/surface3D: no drag
|
|
118355
|
+
// state machine of their own, the shared three.js scene reports the
|
|
118356
|
+
// live/final value directly)
|
|
118357
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118358
|
+
/**
|
|
118359
|
+
* The chart data a 3D scene's `onValueDragPreview`/`onValueDragCommit` should
|
|
118360
|
+
* apply, or `null` when the part carries no point index (a series-level part,
|
|
118361
|
+
* or a part shape the 3D scenes never actually emit for a value drag) or there
|
|
118362
|
+
* is no chart data to update against.
|
|
118363
|
+
*
|
|
118364
|
+
* Pure so it is unit-testable without a WebGL context: `BarChart3DRendererComponent`
|
|
118365
|
+
* / `LineChart3DRendererComponent` / `AreaChart3DRendererComponent` /
|
|
118366
|
+
* `PieChart3DRendererComponent` / `SurfaceChart3DRendererComponent` forward
|
|
118367
|
+
* their `valueDragPreview`/`valueDragCommit` outputs here via
|
|
118368
|
+
* `ChartElementViewComponent`.
|
|
118369
|
+
*/
|
|
118370
|
+
function chart3DPointValueUpdate(chartData, part, value) {
|
|
118371
|
+
if (!chartData || part.pointIndex === undefined) {
|
|
118372
|
+
return null;
|
|
118373
|
+
}
|
|
118374
|
+
return withChartPointValue(chartData, part.seriesIndex, part.pointIndex, value);
|
|
118375
|
+
}
|
|
118376
|
+
/**
|
|
118377
|
+
* Commit an on-canvas chart edit through the editor's normal element-update
|
|
118378
|
+
* path (the exact channel the inspector uses: one history snapshot per call).
|
|
118379
|
+
* No-op without an editor or when the element is not on any slide.
|
|
118380
|
+
*
|
|
118381
|
+
* `templateSlideId` is the id of the slide the hosting canvas renders (from
|
|
118382
|
+
* `SLIDE_CONTEXT`); it resolves template (master/layout) chart elements, which
|
|
118383
|
+
* live in the per-slide template store rather than in `slides[].elements`.
|
|
118384
|
+
*/
|
|
118385
|
+
function commitChartElementData(editor, elementId, chartData, templateSlideId) {
|
|
118386
|
+
if (!editor) {
|
|
118387
|
+
return;
|
|
118388
|
+
}
|
|
118389
|
+
const slideIndex = findOwningSlideIndex(editor.slides(), elementId, templateSlideId);
|
|
118390
|
+
if (slideIndex < 0) {
|
|
118391
|
+
return;
|
|
118392
|
+
}
|
|
118393
|
+
editor.updateElement(slideIndex, elementId, { chartData });
|
|
118394
|
+
}
|
|
118395
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118396
|
+
// Interaction stylesheet (shared base rules + Angular's own badge/editor CSS)
|
|
118397
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
118398
|
+
const STYLE_ELEMENT_ID = 'pptx-ng-chart-interaction-styles';
|
|
118399
|
+
/**
|
|
118400
|
+
* Angular-only interaction CSS, injected once into `document.head` alongside
|
|
118401
|
+
* the shared `[data-chart-part]` / selected-mark rules from
|
|
118402
|
+
* `ensureChartInteractionStyles` (`pptx-viewer-shared`). Component styles are
|
|
118403
|
+
* view-encapsulated in Angular, so they cannot reach into the chart
|
|
118404
|
+
* renderer's SVG or style the badge/title-input this component projects
|
|
118405
|
+
* next to it.
|
|
118406
|
+
*/
|
|
118407
|
+
const INTERACTION_CSS = `
|
|
118408
|
+
.pptx-ng-chart-view { position: relative; width: 100%; height: 100%; }
|
|
118409
|
+
.pptx-ng-chart-drag-badge { position: absolute; top: 4px; right: 4px; z-index: 10; border-radius: 4px; background: rgba(37, 99, 235, 0.9); padding: 2px 6px; font-size: 10px; font-weight: 500; color: #fff; pointer-events: none; }
|
|
118410
|
+
.pptx-ng-chart-title-input { position: absolute; left: 50%; top: 2px; z-index: 10; width: 60%; transform: translateX(-50%); border: 1px solid #94a3b8; border-radius: 4px; background: #fff; padding: 2px 4px; text-align: center; font-size: 11px; color: #0f172a; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
|
|
118411
|
+
`;
|
|
118412
|
+
/**
|
|
118413
|
+
* Inject the interaction stylesheets for chart part hit targets: the shared
|
|
118414
|
+
* base rules (singleton, shared across all five bindings) plus Angular's own
|
|
118415
|
+
* badge/title-input CSS (singleton, this binding only).
|
|
118416
|
+
*/
|
|
118417
|
+
function ensureChartInteractionStyles() {
|
|
118418
|
+
ensureChartInteractionStyles$1();
|
|
118419
|
+
if (typeof document === 'undefined' || document.getElementById(STYLE_ELEMENT_ID)) {
|
|
118420
|
+
return;
|
|
118421
|
+
}
|
|
118422
|
+
const style = document.createElement('style');
|
|
118423
|
+
style.id = STYLE_ELEMENT_ID;
|
|
118424
|
+
style.textContent = INTERACTION_CSS;
|
|
118425
|
+
document.head.appendChild(style);
|
|
118426
|
+
}
|
|
118427
|
+
|
|
118428
|
+
/**
|
|
118429
|
+
* chart-quick-actions-overlay.component.ts: PowerPoint's three floating
|
|
118430
|
+
* quick-action icons ("Chart Elements" +, "Chart Styles" paintbrush, "Chart
|
|
118431
|
+
* Filters" funnel) shown just outside a selected chart's top-right corner.
|
|
118432
|
+
*
|
|
118433
|
+
* Selector: `pptx-chart-quick-actions-overlay`
|
|
118434
|
+
*
|
|
118435
|
+
* Mounted inside `SlideCanvasComponent`'s template as a sibling of the
|
|
118436
|
+
* resize/rotate/adjust handle blocks, inside the same scaled
|
|
118437
|
+
* `.pptx-ng-canvas-stage`. Angular has no CSS inverse-scale variable (unlike
|
|
118438
|
+
* React's `--pptx-handle-inverse-scale`): this component follows the SAME
|
|
118439
|
+
* convention `selection-geometry.ts`'s `computeHandleBoxes`/
|
|
118440
|
+
* `computeCornerHandle` already use, computing every screen-constant
|
|
118441
|
+
* quantity (button size, gaps) as `screenPx / zoom` while leaving the
|
|
118442
|
+
* element's own x/y/width/height in raw slide px.
|
|
118443
|
+
*
|
|
118444
|
+
* All decision-making (which buttons render, checklist/gallery/filter state)
|
|
118445
|
+
* comes from the shared `buildChartQuickActionsDescriptor`; this component
|
|
118446
|
+
* only renders three buttons plus whichever popover is open, and commits
|
|
118447
|
+
* through `commitChartElementData` (the same on-canvas commit helper
|
|
118448
|
+
* `ChartElementViewComponent` uses for mark-drag/inline-title edits), so
|
|
118449
|
+
* undo/redo and the save round-trip are shared with every other on-canvas
|
|
118450
|
+
* chart edit. See the shared module's header for scope notes (Series-only
|
|
118451
|
+
* Chart Filters, no trendline/error-bar/up-down-bars rows).
|
|
118452
|
+
*
|
|
118453
|
+
* @module angular-viewer/chart-quick-actions-overlay
|
|
118454
|
+
*/
|
|
118455
|
+
class ChartQuickActionsOverlayComponent {
|
|
118456
|
+
constructor() {
|
|
118457
|
+
this.element = input.required(/* @ts-ignore */
|
|
118458
|
+
...(ngDevMode ? [{ debugName: "element" }] : /* istanbul ignore next */ []));
|
|
118459
|
+
this.canEdit = input(true, /* @ts-ignore */
|
|
118460
|
+
...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
118461
|
+
/** Effective stage zoom, so screen-constant sizes/gaps divide it out. */
|
|
118462
|
+
this.zoom = input(1, /* @ts-ignore */
|
|
118463
|
+
...(ngDevMode ? [{ debugName: "zoom" }] : /* istanbul ignore next */ []));
|
|
118464
|
+
this.CHART_QUICK_ACTION_BUTTON_SIZE = CHART_QUICK_ACTION_BUTTON_SIZE;
|
|
118465
|
+
this.editor = inject(EditorStateService, { optional: true });
|
|
118466
|
+
this.slideContext = inject(SLIDE_CONTEXT, { optional: true });
|
|
118467
|
+
this.hostRef = inject((ElementRef));
|
|
118468
|
+
this.open = signal(null, /* @ts-ignore */
|
|
118469
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
118470
|
+
/** The stage scale, guarded against 0. */
|
|
118471
|
+
this.scale = computed(() => this.zoom() || 1, /* @ts-ignore */
|
|
118472
|
+
...(ngDevMode ? [{ debugName: "scale" }] : /* istanbul ignore next */ []));
|
|
118473
|
+
/**
|
|
118474
|
+
* The descriptor's geometry, computed against a SCREEN-space box (the
|
|
118475
|
+
* element's box multiplied by the stage scale): every constant the shared
|
|
118476
|
+
* function adds (gaps, button size) is then correctly screen-constant, and
|
|
118477
|
+
* {@link screenPx} divides each resulting quantity back down to the slide
|
|
118478
|
+
* px this component renders in, mirroring `selection-geometry.ts`'s
|
|
118479
|
+
* `computeHandleBoxes`.
|
|
118480
|
+
*/
|
|
118481
|
+
this.descriptor = computed(() => {
|
|
118482
|
+
const el = this.element();
|
|
118483
|
+
const scale = this.scale();
|
|
118484
|
+
return buildChartQuickActionsDescriptor({
|
|
118485
|
+
isChartSelected: true,
|
|
118486
|
+
chartData: el.chartData,
|
|
118487
|
+
selectionBox: {
|
|
118488
|
+
x: el.x * scale,
|
|
118489
|
+
y: el.y * scale,
|
|
118490
|
+
width: el.width * scale,
|
|
118491
|
+
height: el.height * scale,
|
|
118492
|
+
},
|
|
118493
|
+
});
|
|
118494
|
+
}, /* @ts-ignore */
|
|
118495
|
+
...(ngDevMode ? [{ debugName: "descriptor" }] : /* istanbul ignore next */ []));
|
|
118496
|
+
}
|
|
118497
|
+
/** Close whichever popover is open on an outside click, mirroring every other binding's overlay. */
|
|
118498
|
+
onDocumentMouseDown(event) {
|
|
118499
|
+
if (this.open() && !this.hostRef.nativeElement.contains(event.target)) {
|
|
118500
|
+
this.open.set(null);
|
|
118501
|
+
}
|
|
118502
|
+
}
|
|
118503
|
+
/** Convert a screen-space quantity (from {@link descriptor}) back to slide px. */
|
|
118504
|
+
screenPx(value) {
|
|
118505
|
+
return value / this.scale();
|
|
118506
|
+
}
|
|
118507
|
+
toggle(id) {
|
|
118508
|
+
this.open.update((current) => (current === id ? null : id));
|
|
118509
|
+
}
|
|
118510
|
+
commit(chartData) {
|
|
118511
|
+
commitChartElementData(this.editor, this.element().id, chartData, this.slideContext?.slideId() ?? null);
|
|
118512
|
+
}
|
|
118513
|
+
onElementToggle(key, event) {
|
|
118514
|
+
const chartData = this.element().chartData;
|
|
118515
|
+
if (!chartData) {
|
|
118516
|
+
return;
|
|
118517
|
+
}
|
|
118518
|
+
const checked = event.target.checked;
|
|
118519
|
+
this.commit(applyChartElementToggle(chartData, key, checked));
|
|
118520
|
+
}
|
|
118521
|
+
onStylePreset(presetId) {
|
|
118522
|
+
const chartData = this.element().chartData;
|
|
118523
|
+
if (!chartData) {
|
|
118524
|
+
return;
|
|
118525
|
+
}
|
|
118526
|
+
const next = applyChartStylePreset(chartData, presetId);
|
|
118527
|
+
if (next) {
|
|
118528
|
+
this.commit(next);
|
|
118529
|
+
}
|
|
118530
|
+
}
|
|
118531
|
+
onFilterToggle(seriesIndex, filteredIndex) {
|
|
118532
|
+
const chartData = this.element().chartData;
|
|
118533
|
+
if (!chartData) {
|
|
118534
|
+
return;
|
|
118535
|
+
}
|
|
118536
|
+
const next = seriesIndex !== undefined
|
|
118537
|
+
? hideChartSeries(chartData, seriesIndex)
|
|
118538
|
+
: restoreFilteredSeries(chartData, filteredIndex);
|
|
118539
|
+
if (next) {
|
|
118540
|
+
this.commit(next);
|
|
118541
|
+
}
|
|
118542
|
+
}
|
|
118543
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartQuickActionsOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
118544
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ChartQuickActionsOverlayComponent, isStandalone: true, selector: "pptx-chart-quick-actions-overlay", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-pptx-chart-quick-actions": "true", "data-export-ignore": "true" }, listeners: { "pointerdown": "$event.stopPropagation()", "document:mousedown": "onDocumentMouseDown($event)" } }, ngImport: i0, template: `
|
|
118545
|
+
@if (descriptor(); as d) {
|
|
118546
|
+
@for (button of d.buttons; track button.id) {
|
|
118547
|
+
<button
|
|
118548
|
+
type="button"
|
|
118549
|
+
class="pptx-ng-chart-quick-btn"
|
|
118550
|
+
[disabled]="!canEdit()"
|
|
118551
|
+
[attr.data-testid]="'chart-quick-action-' + button.id"
|
|
118552
|
+
[attr.aria-label]="button.labelKey | translate"
|
|
118553
|
+
[title]="button.labelKey | translate"
|
|
118554
|
+
[style.left.px]="screenPx(button.x)"
|
|
118555
|
+
[style.top.px]="screenPx(button.y)"
|
|
118556
|
+
[style.width.px]="screenPx(button.size)"
|
|
118557
|
+
[style.height.px]="screenPx(button.size)"
|
|
118558
|
+
(click)="toggle(button.id)"
|
|
118559
|
+
>
|
|
118560
|
+
@if (button.id === 'elements') {
|
|
118561
|
+
<svg lucidePlus class="pptx-ng-chart-quick-icon"></svg>
|
|
118562
|
+
} @else if (button.id === 'styles') {
|
|
118563
|
+
<svg lucidePaintbrush class="pptx-ng-chart-quick-icon"></svg>
|
|
118564
|
+
} @else {
|
|
118565
|
+
<svg lucideFilter class="pptx-ng-chart-quick-icon"></svg>
|
|
118566
|
+
}
|
|
118567
|
+
</button>
|
|
118568
|
+
|
|
118569
|
+
@if (open() === button.id && button.id === 'elements') {
|
|
118570
|
+
<div
|
|
118571
|
+
class="pptx-ng-chart-quick-card"
|
|
118572
|
+
data-testid="chart-quick-elements-popover"
|
|
118573
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118574
|
+
[style.top.px]="screenPx(button.y)"
|
|
118575
|
+
>
|
|
118576
|
+
<h4 class="pptx-ng-chart-quick-heading">
|
|
118577
|
+
{{ 'pptx.chart.quickElements' | translate }}
|
|
118578
|
+
</h4>
|
|
118579
|
+
@for (item of d.elements; track item.key) {
|
|
118580
|
+
<label class="pptx-ng-chart-quick-check">
|
|
118581
|
+
<input
|
|
118582
|
+
type="checkbox"
|
|
118583
|
+
[disabled]="!canEdit()"
|
|
118584
|
+
[checked]="item.checked"
|
|
118585
|
+
[attr.data-testid]="'chart-quick-element-' + item.key"
|
|
118586
|
+
(change)="onElementToggle(item.key, $event)"
|
|
118587
|
+
/>
|
|
118588
|
+
<span>{{ item.labelKey | translate }}</span>
|
|
118589
|
+
</label>
|
|
118590
|
+
}
|
|
118591
|
+
</div>
|
|
118592
|
+
}
|
|
118593
|
+
|
|
118594
|
+
@if (open() === button.id && button.id === 'styles') {
|
|
118595
|
+
<div
|
|
118596
|
+
class="pptx-ng-chart-quick-card pptx-ng-chart-quick-styles"
|
|
118597
|
+
data-testid="chart-quick-styles-popover"
|
|
118598
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118599
|
+
[style.top.px]="screenPx(button.y)"
|
|
118600
|
+
>
|
|
118601
|
+
@for (preset of d.styles.presets; track preset.id) {
|
|
118602
|
+
<button
|
|
118603
|
+
type="button"
|
|
118604
|
+
class="pptx-ng-chart-quick-swatch"
|
|
118605
|
+
[class.is-applied]="preset.applied"
|
|
118606
|
+
[disabled]="!canEdit()"
|
|
118607
|
+
[attr.data-testid]="'chart-quick-style-' + preset.id"
|
|
118608
|
+
[attr.aria-label]="preset.labelKey | translate"
|
|
118609
|
+
[attr.aria-pressed]="preset.applied"
|
|
118610
|
+
[title]="preset.labelKey | translate"
|
|
118611
|
+
(click)="onStylePreset(preset.id)"
|
|
118612
|
+
>
|
|
118613
|
+
<span class="pptx-ng-chart-quick-swatch-row">
|
|
118614
|
+
@for (c of preset.colors.slice(0, 5); track $index) {
|
|
118615
|
+
<span [style.background-color]="c"></span>
|
|
118616
|
+
}
|
|
118617
|
+
</span>
|
|
118618
|
+
</button>
|
|
118619
|
+
}
|
|
118620
|
+
</div>
|
|
118621
|
+
}
|
|
118622
|
+
|
|
118623
|
+
@if (open() === button.id && button.id === 'filters') {
|
|
118624
|
+
<div
|
|
118625
|
+
class="pptx-ng-chart-quick-card"
|
|
118626
|
+
data-testid="chart-quick-filters-popover"
|
|
118627
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118628
|
+
[style.top.px]="screenPx(button.y)"
|
|
118629
|
+
>
|
|
118630
|
+
<h4 class="pptx-ng-chart-quick-heading">{{ 'pptx.chart.quickFilters' | translate }}</h4>
|
|
118631
|
+
@for (row of d.filters.series; track row.key) {
|
|
118632
|
+
<label class="pptx-ng-chart-quick-check">
|
|
118633
|
+
<input
|
|
118634
|
+
type="checkbox"
|
|
118635
|
+
[disabled]="!canEdit()"
|
|
118636
|
+
[checked]="row.visible"
|
|
118637
|
+
[attr.data-testid]="'chart-quick-filter-' + row.key"
|
|
118638
|
+
(change)="onFilterToggle(row.seriesIndex, row.filteredIndex)"
|
|
118639
|
+
/>
|
|
118640
|
+
<span class="pptx-ng-chart-quick-name">{{ row.name }}</span>
|
|
118641
|
+
</label>
|
|
118642
|
+
}
|
|
118643
|
+
</div>
|
|
118644
|
+
}
|
|
118645
|
+
}
|
|
118646
|
+
}
|
|
118647
|
+
`, isInline: true, styles: [":host{position:absolute;left:0;top:0;z-index:59}.pptx-ng-chart-quick-btn{position:absolute;display:flex;align-items:center;justify-content:center;border-radius:4px;border:1px solid #d1d5db;background:#fff;color:#374151;cursor:pointer}.pptx-ng-chart-quick-btn:hover{background:#f3f4f6}.pptx-ng-chart-quick-btn:disabled{opacity:.6;cursor:not-allowed}.pptx-ng-chart-quick-icon{width:14px;height:14px}.pptx-ng-chart-quick-card{position:absolute;z-index:10;display:flex;flex-direction:column;gap:.35rem;min-width:11rem;padding:.5rem;border-radius:6px;border:1px solid var(--pptx-inspector-border, #444);background:var(--pptx-inspector-input-bg, #2d2d2d);box-shadow:0 4px 16px #00000059}.pptx-ng-chart-quick-heading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);margin:0}.pptx-ng-chart-quick-check{display:flex;align-items:center;gap:.35rem;font-size:11px;cursor:pointer}.pptx-ng-chart-quick-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-chart-quick-styles{display:grid;grid-template-columns:repeat(3,1fr);gap:.35rem;min-width:12rem}.pptx-ng-chart-quick-swatch{border-radius:4px;overflow:hidden;border:1px solid var(--pptx-inspector-border, #444);padding:0;cursor:pointer}.pptx-ng-chart-quick-swatch.is-applied{border-color:var(--pptx-inspector-active, #0078d4);box-shadow:0 0 0 1px var(--pptx-inspector-active, #0078d4)}.pptx-ng-chart-quick-swatch-row{display:flex;height:20px;width:100%}.pptx-ng-chart-quick-swatch-row>span{flex:1 1 auto}\n"], dependencies: [{ kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: LucidePaintbrush, selector: "svg[lucidePaintbrush]" }, { kind: "component", type: LucideFilter, selector: "svg[lucideFunnel], svg[lucideFilter]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
118648
|
+
}
|
|
118649
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ChartQuickActionsOverlayComponent, decorators: [{
|
|
118650
|
+
type: Component,
|
|
118651
|
+
args: [{ selector: 'pptx-chart-quick-actions-overlay', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe, LucidePlus, LucidePaintbrush, LucideFilter], host: {
|
|
118652
|
+
'data-pptx-chart-quick-actions': 'true',
|
|
118653
|
+
'data-export-ignore': 'true',
|
|
118654
|
+
'(pointerdown)': '$event.stopPropagation()',
|
|
118655
|
+
}, template: `
|
|
118656
|
+
@if (descriptor(); as d) {
|
|
118657
|
+
@for (button of d.buttons; track button.id) {
|
|
118658
|
+
<button
|
|
118659
|
+
type="button"
|
|
118660
|
+
class="pptx-ng-chart-quick-btn"
|
|
118661
|
+
[disabled]="!canEdit()"
|
|
118662
|
+
[attr.data-testid]="'chart-quick-action-' + button.id"
|
|
118663
|
+
[attr.aria-label]="button.labelKey | translate"
|
|
118664
|
+
[title]="button.labelKey | translate"
|
|
118665
|
+
[style.left.px]="screenPx(button.x)"
|
|
118666
|
+
[style.top.px]="screenPx(button.y)"
|
|
118667
|
+
[style.width.px]="screenPx(button.size)"
|
|
118668
|
+
[style.height.px]="screenPx(button.size)"
|
|
118669
|
+
(click)="toggle(button.id)"
|
|
118670
|
+
>
|
|
118671
|
+
@if (button.id === 'elements') {
|
|
118672
|
+
<svg lucidePlus class="pptx-ng-chart-quick-icon"></svg>
|
|
118673
|
+
} @else if (button.id === 'styles') {
|
|
118674
|
+
<svg lucidePaintbrush class="pptx-ng-chart-quick-icon"></svg>
|
|
118675
|
+
} @else {
|
|
118676
|
+
<svg lucideFilter class="pptx-ng-chart-quick-icon"></svg>
|
|
118677
|
+
}
|
|
118678
|
+
</button>
|
|
118679
|
+
|
|
118680
|
+
@if (open() === button.id && button.id === 'elements') {
|
|
118681
|
+
<div
|
|
118682
|
+
class="pptx-ng-chart-quick-card"
|
|
118683
|
+
data-testid="chart-quick-elements-popover"
|
|
118684
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118685
|
+
[style.top.px]="screenPx(button.y)"
|
|
118686
|
+
>
|
|
118687
|
+
<h4 class="pptx-ng-chart-quick-heading">
|
|
118688
|
+
{{ 'pptx.chart.quickElements' | translate }}
|
|
118689
|
+
</h4>
|
|
118690
|
+
@for (item of d.elements; track item.key) {
|
|
118691
|
+
<label class="pptx-ng-chart-quick-check">
|
|
118692
|
+
<input
|
|
118693
|
+
type="checkbox"
|
|
118694
|
+
[disabled]="!canEdit()"
|
|
118695
|
+
[checked]="item.checked"
|
|
118696
|
+
[attr.data-testid]="'chart-quick-element-' + item.key"
|
|
118697
|
+
(change)="onElementToggle(item.key, $event)"
|
|
118698
|
+
/>
|
|
118699
|
+
<span>{{ item.labelKey | translate }}</span>
|
|
118700
|
+
</label>
|
|
118701
|
+
}
|
|
118702
|
+
</div>
|
|
118703
|
+
}
|
|
118704
|
+
|
|
118705
|
+
@if (open() === button.id && button.id === 'styles') {
|
|
118706
|
+
<div
|
|
118707
|
+
class="pptx-ng-chart-quick-card pptx-ng-chart-quick-styles"
|
|
118708
|
+
data-testid="chart-quick-styles-popover"
|
|
118709
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118710
|
+
[style.top.px]="screenPx(button.y)"
|
|
118711
|
+
>
|
|
118712
|
+
@for (preset of d.styles.presets; track preset.id) {
|
|
118713
|
+
<button
|
|
118714
|
+
type="button"
|
|
118715
|
+
class="pptx-ng-chart-quick-swatch"
|
|
118716
|
+
[class.is-applied]="preset.applied"
|
|
118717
|
+
[disabled]="!canEdit()"
|
|
118718
|
+
[attr.data-testid]="'chart-quick-style-' + preset.id"
|
|
118719
|
+
[attr.aria-label]="preset.labelKey | translate"
|
|
118720
|
+
[attr.aria-pressed]="preset.applied"
|
|
118721
|
+
[title]="preset.labelKey | translate"
|
|
118722
|
+
(click)="onStylePreset(preset.id)"
|
|
118723
|
+
>
|
|
118724
|
+
<span class="pptx-ng-chart-quick-swatch-row">
|
|
118725
|
+
@for (c of preset.colors.slice(0, 5); track $index) {
|
|
118726
|
+
<span [style.background-color]="c"></span>
|
|
118727
|
+
}
|
|
118728
|
+
</span>
|
|
118729
|
+
</button>
|
|
118730
|
+
}
|
|
118731
|
+
</div>
|
|
118732
|
+
}
|
|
118733
|
+
|
|
118734
|
+
@if (open() === button.id && button.id === 'filters') {
|
|
118735
|
+
<div
|
|
118736
|
+
class="pptx-ng-chart-quick-card"
|
|
118737
|
+
data-testid="chart-quick-filters-popover"
|
|
118738
|
+
[style.left.px]="screenPx(button.x + CHART_QUICK_ACTION_BUTTON_SIZE + 4)"
|
|
118739
|
+
[style.top.px]="screenPx(button.y)"
|
|
118740
|
+
>
|
|
118741
|
+
<h4 class="pptx-ng-chart-quick-heading">{{ 'pptx.chart.quickFilters' | translate }}</h4>
|
|
118742
|
+
@for (row of d.filters.series; track row.key) {
|
|
118743
|
+
<label class="pptx-ng-chart-quick-check">
|
|
118744
|
+
<input
|
|
118745
|
+
type="checkbox"
|
|
118746
|
+
[disabled]="!canEdit()"
|
|
118747
|
+
[checked]="row.visible"
|
|
118748
|
+
[attr.data-testid]="'chart-quick-filter-' + row.key"
|
|
118749
|
+
(change)="onFilterToggle(row.seriesIndex, row.filteredIndex)"
|
|
118750
|
+
/>
|
|
118751
|
+
<span class="pptx-ng-chart-quick-name">{{ row.name }}</span>
|
|
118752
|
+
</label>
|
|
118753
|
+
}
|
|
118754
|
+
</div>
|
|
118755
|
+
}
|
|
118756
|
+
}
|
|
118757
|
+
}
|
|
118758
|
+
`, styles: [":host{position:absolute;left:0;top:0;z-index:59}.pptx-ng-chart-quick-btn{position:absolute;display:flex;align-items:center;justify-content:center;border-radius:4px;border:1px solid #d1d5db;background:#fff;color:#374151;cursor:pointer}.pptx-ng-chart-quick-btn:hover{background:#f3f4f6}.pptx-ng-chart-quick-btn:disabled{opacity:.6;cursor:not-allowed}.pptx-ng-chart-quick-icon{width:14px;height:14px}.pptx-ng-chart-quick-card{position:absolute;z-index:10;display:flex;flex-direction:column;gap:.35rem;min-width:11rem;padding:.5rem;border-radius:6px;border:1px solid var(--pptx-inspector-border, #444);background:var(--pptx-inspector-input-bg, #2d2d2d);box-shadow:0 4px 16px #00000059}.pptx-ng-chart-quick-heading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);margin:0}.pptx-ng-chart-quick-check{display:flex;align-items:center;gap:.35rem;font-size:11px;cursor:pointer}.pptx-ng-chart-quick-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-chart-quick-styles{display:grid;grid-template-columns:repeat(3,1fr);gap:.35rem;min-width:12rem}.pptx-ng-chart-quick-swatch{border-radius:4px;overflow:hidden;border:1px solid var(--pptx-inspector-border, #444);padding:0;cursor:pointer}.pptx-ng-chart-quick-swatch.is-applied{border-color:var(--pptx-inspector-active, #0078d4);box-shadow:0 0 0 1px var(--pptx-inspector-active, #0078d4)}.pptx-ng-chart-quick-swatch-row{display:flex;height:20px;width:100%}.pptx-ng-chart-quick-swatch-row>span{flex:1 1 auto}\n"] }]
|
|
118759
|
+
}], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], onDocumentMouseDown: [{
|
|
118760
|
+
type: HostListener,
|
|
118761
|
+
args: ['document:mousedown', ['$event']]
|
|
118762
|
+
}] } });
|
|
118763
|
+
|
|
117840
118764
|
/**
|
|
117841
118765
|
* Pure geometry for interactive element drag/resize.
|
|
117842
118766
|
*
|
|
@@ -120210,121 +121134,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
120210
121134
|
`, styles: [".pptx-ng-bar-chart-3d-scene{width:100%;height:100%;display:block}\n"] }]
|
|
120211
121135
|
}], ctorParameters: () => [], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], selectedPart: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedPart", required: false }] }], textStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "textStyle", required: false }] }], partSelect: [{ type: i0.Output, args: ["partSelect"] }], valueDragPreview: [{ type: i0.Output, args: ["valueDragPreview"] }], valueDragCommit: [{ type: i0.Output, args: ["valueDragCommit"] }], sceneRef: [{ type: i0.ViewChild, args: ['scene', { isSignal: true }] }] } });
|
|
120212
121136
|
|
|
120213
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120214
|
-
// Direct part-editing gate
|
|
120215
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120216
|
-
/**
|
|
120217
|
-
* May this chart's individual parts (title, series, data points) be entered
|
|
120218
|
-
* for direct on-canvas editing?
|
|
120219
|
-
*
|
|
120220
|
-
* Pure so it is unit-testable without a full Angular injection context:
|
|
120221
|
-
* `ChartElementViewComponent`'s constructor runs an `effect()` that needs a
|
|
120222
|
-
* `ChangeDetectionScheduler` this package's TestBed-free suite doesn't
|
|
120223
|
-
* provide. G8: `a:graphicFrameLocks/@noDrilldown` forbids the drill-down,
|
|
120224
|
-
* even when the chart is otherwise selected + editable.
|
|
120225
|
-
*/
|
|
120226
|
-
function chartCanEditParts(editable, isSelected, hasEditor, element) {
|
|
120227
|
-
return editable && isSelected && hasEditor && canDrillDown(element);
|
|
120228
|
-
}
|
|
120229
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120230
|
-
// Value-drag commit gate
|
|
120231
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120232
|
-
/**
|
|
120233
|
-
* The chart data a finished drag should commit, or null when nothing should
|
|
120234
|
-
* be committed (cancelled, or the press never became a drag).
|
|
120235
|
-
*/
|
|
120236
|
-
function chartDragCommitData(session, commit) {
|
|
120237
|
-
if (!commit || !session?.moved) {
|
|
120238
|
-
return null;
|
|
120239
|
-
}
|
|
120240
|
-
return session.lastData;
|
|
120241
|
-
}
|
|
120242
|
-
/**
|
|
120243
|
-
* Same gate as {@link chartDragCommitData}, for a pie/radar/stacked mark drag
|
|
120244
|
-
* ({@link ChartMarkDragState} carries the same `moved`/`lastData` shape as the
|
|
120245
|
-
* cartesian value-drag session, just resolved through a different geometry).
|
|
120246
|
-
*/
|
|
120247
|
-
function chartMarkDragCommitData(session, commit) {
|
|
120248
|
-
if (!commit || !session?.moved) {
|
|
120249
|
-
return null;
|
|
120250
|
-
}
|
|
120251
|
-
return session.lastData;
|
|
120252
|
-
}
|
|
120253
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120254
|
-
// 3D value-drag commit data (bar3D/line3D/area3D/pie3D/surface3D: no drag
|
|
120255
|
-
// state machine of their own, the shared three.js scene reports the
|
|
120256
|
-
// live/final value directly)
|
|
120257
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120258
|
-
/**
|
|
120259
|
-
* The chart data a 3D scene's `onValueDragPreview`/`onValueDragCommit` should
|
|
120260
|
-
* apply, or `null` when the part carries no point index (a series-level part,
|
|
120261
|
-
* or a part shape the 3D scenes never actually emit for a value drag) or there
|
|
120262
|
-
* is no chart data to update against.
|
|
120263
|
-
*
|
|
120264
|
-
* Pure so it is unit-testable without a WebGL context: `BarChart3DRendererComponent`
|
|
120265
|
-
* / `LineChart3DRendererComponent` / `AreaChart3DRendererComponent` /
|
|
120266
|
-
* `PieChart3DRendererComponent` / `SurfaceChart3DRendererComponent` forward
|
|
120267
|
-
* their `valueDragPreview`/`valueDragCommit` outputs here via
|
|
120268
|
-
* `ChartElementViewComponent`.
|
|
120269
|
-
*/
|
|
120270
|
-
function chart3DPointValueUpdate(chartData, part, value) {
|
|
120271
|
-
if (!chartData || part.pointIndex === undefined) {
|
|
120272
|
-
return null;
|
|
120273
|
-
}
|
|
120274
|
-
return withChartPointValue(chartData, part.seriesIndex, part.pointIndex, value);
|
|
120275
|
-
}
|
|
120276
|
-
/**
|
|
120277
|
-
* Commit an on-canvas chart edit through the editor's normal element-update
|
|
120278
|
-
* path (the exact channel the inspector uses: one history snapshot per call).
|
|
120279
|
-
* No-op without an editor or when the element is not on any slide.
|
|
120280
|
-
*
|
|
120281
|
-
* `templateSlideId` is the id of the slide the hosting canvas renders (from
|
|
120282
|
-
* `SLIDE_CONTEXT`); it resolves template (master/layout) chart elements, which
|
|
120283
|
-
* live in the per-slide template store rather than in `slides[].elements`.
|
|
120284
|
-
*/
|
|
120285
|
-
function commitChartElementData(editor, elementId, chartData, templateSlideId) {
|
|
120286
|
-
if (!editor) {
|
|
120287
|
-
return;
|
|
120288
|
-
}
|
|
120289
|
-
const slideIndex = findOwningSlideIndex(editor.slides(), elementId, templateSlideId);
|
|
120290
|
-
if (slideIndex < 0) {
|
|
120291
|
-
return;
|
|
120292
|
-
}
|
|
120293
|
-
editor.updateElement(slideIndex, elementId, { chartData });
|
|
120294
|
-
}
|
|
120295
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120296
|
-
// Interaction stylesheet (shared base rules + Angular's own badge/editor CSS)
|
|
120297
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
120298
|
-
const STYLE_ELEMENT_ID = 'pptx-ng-chart-interaction-styles';
|
|
120299
|
-
/**
|
|
120300
|
-
* Angular-only interaction CSS, injected once into `document.head` alongside
|
|
120301
|
-
* the shared `[data-chart-part]` / selected-mark rules from
|
|
120302
|
-
* `ensureChartInteractionStyles` (`pptx-viewer-shared`). Component styles are
|
|
120303
|
-
* view-encapsulated in Angular, so they cannot reach into the chart
|
|
120304
|
-
* renderer's SVG or style the badge/title-input this component projects
|
|
120305
|
-
* next to it.
|
|
120306
|
-
*/
|
|
120307
|
-
const INTERACTION_CSS = `
|
|
120308
|
-
.pptx-ng-chart-view { position: relative; width: 100%; height: 100%; }
|
|
120309
|
-
.pptx-ng-chart-drag-badge { position: absolute; top: 4px; right: 4px; z-index: 10; border-radius: 4px; background: rgba(37, 99, 235, 0.9); padding: 2px 6px; font-size: 10px; font-weight: 500; color: #fff; pointer-events: none; }
|
|
120310
|
-
.pptx-ng-chart-title-input { position: absolute; left: 50%; top: 2px; z-index: 10; width: 60%; transform: translateX(-50%); border: 1px solid #94a3b8; border-radius: 4px; background: #fff; padding: 2px 4px; text-align: center; font-size: 11px; color: #0f172a; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
|
|
120311
|
-
`;
|
|
120312
|
-
/**
|
|
120313
|
-
* Inject the interaction stylesheets for chart part hit targets: the shared
|
|
120314
|
-
* base rules (singleton, shared across all five bindings) plus Angular's own
|
|
120315
|
-
* badge/title-input CSS (singleton, this binding only).
|
|
120316
|
-
*/
|
|
120317
|
-
function ensureChartInteractionStyles() {
|
|
120318
|
-
ensureChartInteractionStyles$1();
|
|
120319
|
-
if (typeof document === 'undefined' || document.getElementById(STYLE_ELEMENT_ID)) {
|
|
120320
|
-
return;
|
|
120321
|
-
}
|
|
120322
|
-
const style = document.createElement('style');
|
|
120323
|
-
style.id = STYLE_ELEMENT_ID;
|
|
120324
|
-
style.textContent = INTERACTION_CSS;
|
|
120325
|
-
document.head.appendChild(style);
|
|
120326
|
-
}
|
|
120327
|
-
|
|
120328
121137
|
/**
|
|
120329
121138
|
* chart-part-selection.service.ts: the bridge between on-canvas chart part
|
|
120330
121139
|
* clicks (`ChartElementViewComponent`) and the chart inspector
|
|
@@ -128261,6 +129070,16 @@ class SlideCanvasComponent {
|
|
|
128261
129070
|
return box ? (this.elementById(box.id) ?? null) : null;
|
|
128262
129071
|
}, /* @ts-ignore */
|
|
128263
129072
|
...(ngDevMode ? [{ debugName: "singleSelectedElement" }] : /* istanbul ignore next */ []));
|
|
129073
|
+
/**
|
|
129074
|
+
* The single selected element when (and only when) it is a chart: gates
|
|
129075
|
+
* the "Chart Elements"/"Chart Styles"/"Chart Filters" quick-action overlay,
|
|
129076
|
+
* which only makes sense for exactly one selected chart.
|
|
129077
|
+
*/
|
|
129078
|
+
this.quickActionsChartElement = computed(() => {
|
|
129079
|
+
const el = this.singleSelectedElement();
|
|
129080
|
+
return el && el.type === 'chart' ? el : null;
|
|
129081
|
+
}, /* @ts-ignore */
|
|
129082
|
+
...(ngDevMode ? [{ debugName: "quickActionsChartElement" }] : /* istanbul ignore next */ []));
|
|
128264
129083
|
/**
|
|
128265
129084
|
* Resize-handle render boxes (stage coords) for the single selection. Empty
|
|
128266
129085
|
* for an element whose authored `a:spLocks/@noResize` pins its size.
|
|
@@ -129218,7 +130037,7 @@ class SlideCanvasComponent {
|
|
|
129218
130037
|
// SmartArt), so template (master/layout) element commits can resolve
|
|
129219
130038
|
// their owning slide; template elements are absent from slides[].elements.
|
|
129220
130039
|
{ provide: SLIDE_CONTEXT, useExisting: forwardRef(() => SlideCanvasComponent) },
|
|
129221
|
-
], viewQueries: [{ propertyName: "textEditor", first: true, predicate: ["textEditor"], descendants: true, isSignal: true }, { propertyName: "listEditor", first: true, predicate: InlineListEditorComponent, descendants: true, isSignal: true }, { propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t@let controlArtwork = selectionControlArtwork(h, h.handle);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"resize\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[ngStyle]=\"controlArtwork.frame\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t[style.--pptx-selection-width.px]=\"singleSelected()?.width\"\n\t\t\t\t\t[style.--pptx-selection-height.px]=\"singleSelected()?.height\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t>\n\t\t\t\t\t<span data-pptx-handle-hit [ngStyle]=\"resizeHitAreaStyle(h.handle)\"></span>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"controlArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t@let rotateArtwork = selectionControlArtwork(rh);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.z-index]=\"editingBox() ? 10003 : null\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"rotate\"\n\t\t\t\t\t[pptxRotateHandleFor]=\"singleSelected()?.id\"\n\t\t\t\t\t[pptxRotateHandleStage]=\"stage\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[ngStyle]=\"rotateArtwork.frame\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"rotateArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"adjust\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t@if (inlineListSeed(); as seed) {\n\t\t\t\t\t@for (session of [seed]; track session) {\n\t\t\t\t\t\t<pptx-inline-list-editor\n\t\t\t\t\t\t\t[element]=\"eb.element\"\n\t\t\t\t\t\t\t[seed]=\"session\"\n\t\t\t\t\t\t\t[activationSelection]=\"listActivationSelection()\"\n\t\t\t\t\t\t\t[spellCheck]=\"spellCheck()\"\n\t\t\t\t\t\t\t(textInput)=\"textInput.emit($event)\"\n\t\t\t\t\t\t\t(textCommit)=\"textCommit.emit($event)\"\n\t\t\t\t\t\t\t(textCancel)=\"textCancel.emit()\"\n\t\t\t\t\t\t\t(textFormat)=\"textFormat.emit($event)\"\n\t\t\t\t\t\t\t(listSession)=\"listSession.emit($event)\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t} @else {\n\t\t\t\t\t<textarea\n\t\t\t\t\t\t#textEditor\n\t\t\t\t\t\tdata-inline-editor\n\t\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t></textarea>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\n\t\t\t\tRenders `inkDrawing.liveStrokeView()`: the same plain-path /\n\t\t\t\tpressure-circle / tilt-nib decision `InkRendererComponent` makes for\n\t\t\t\ta committed stroke, so a calligraphic lean or pressure-variable\n\t\t\t\twidth shows up while the pointer is still down, not only after\n\t\t\t\trelease.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveStrokeView() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t@if (inkDrawing.liveStrokeView()?.nibMarks; as nibMarks) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (m of nibMarks; track $index) {\n\t\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"m.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"m.cy\"\n\t\t\t\t\t\t\t\t\t[attr.rx]=\"m.rPerp\"\n\t\t\t\t\t\t\t\t\t[attr.ry]=\"m.rTilt\"\n\t\t\t\t\t\t\t\t\t[attr.transform]=\"'rotate(' + m.rotationDeg + ' ' + m.cx + ' ' + m.cy + ')'\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else if (inkDrawing.liveStrokeView()?.circles; as circles) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (c of circles; track $index) {\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"c.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"c.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"c.r\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveStrokeView()?.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"inkDrawing.liveStrokeView()?.width\"\n\t\t\t\t\t\t\t[attr.stroke-opacity]=\"inkDrawing.liveStrokeView()?.opacity\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: AiFocusHighlightOverlayComponent, selector: "pptx-ai-focus-highlight-overlay", inputs: ["highlights", "elements", "activeSlideIndex"] }, { kind: "component", type: AiChangeOverlayComponent, selector: "pptx-ai-change-overlay", inputs: ["batch", "activeSlideIndex"] }, { kind: "component", type: ActiveXControlsOverlayComponent, selector: "pptx-activex-controls-overlay", inputs: ["controls", "canvasSize"] }, { kind: "component", type: InlineListEditorComponent, selector: "pptx-inline-list-editor", inputs: ["element", "seed", "spellCheck", "activationSelection"], outputs: ["textInput", "textCommit", "textCancel", "textFormat", "listSession"] }, { kind: "directive", type: RotateHandlePlacementDirective, selector: "[pptxRotateHandleFor]", inputs: ["pptxRotateHandleFor", "pptxRotateHandleStage"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
130040
|
+
], viewQueries: [{ propertyName: "textEditor", first: true, predicate: ["textEditor"], descendants: true, isSignal: true }, { propertyName: "listEditor", first: true, predicate: InlineListEditorComponent, descendants: true, isSignal: true }, { propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t@let controlArtwork = selectionControlArtwork(h, h.handle);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"resize\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[ngStyle]=\"controlArtwork.frame\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t[style.--pptx-selection-width.px]=\"singleSelected()?.width\"\n\t\t\t\t\t[style.--pptx-selection-height.px]=\"singleSelected()?.height\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t>\n\t\t\t\t\t<span data-pptx-handle-hit [ngStyle]=\"resizeHitAreaStyle(h.handle)\"></span>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"controlArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t@let rotateArtwork = selectionControlArtwork(rh);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.z-index]=\"editingBox() ? 10003 : null\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"rotate\"\n\t\t\t\t\t[pptxRotateHandleFor]=\"singleSelected()?.id\"\n\t\t\t\t\t[pptxRotateHandleStage]=\"stage\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[ngStyle]=\"rotateArtwork.frame\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"rotateArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"adjust\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tPowerPoint's floating \"Chart Elements\"/\"Chart Styles\"/\"Chart\n\t\t\t\tFilters\" quick-action icons, shown just outside the chart's\n\t\t\t\ttop-right corner when it is the single selected element.\n\t\t\t-->\n\t\t\t@if (editable() && quickActionsChartElement(); as chartEl) {\n\t\t\t\t<pptx-chart-quick-actions-overlay\n\t\t\t\t\t[element]=\"chartEl\"\n\t\t\t\t\t[canEdit]=\"editable()\"\n\t\t\t\t\t[zoom]=\"effectiveScalePublic()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t@if (inlineListSeed(); as seed) {\n\t\t\t\t\t@for (session of [seed]; track session) {\n\t\t\t\t\t\t<pptx-inline-list-editor\n\t\t\t\t\t\t\t[element]=\"eb.element\"\n\t\t\t\t\t\t\t[seed]=\"session\"\n\t\t\t\t\t\t\t[activationSelection]=\"listActivationSelection()\"\n\t\t\t\t\t\t\t[spellCheck]=\"spellCheck()\"\n\t\t\t\t\t\t\t(textInput)=\"textInput.emit($event)\"\n\t\t\t\t\t\t\t(textCommit)=\"textCommit.emit($event)\"\n\t\t\t\t\t\t\t(textCancel)=\"textCancel.emit()\"\n\t\t\t\t\t\t\t(textFormat)=\"textFormat.emit($event)\"\n\t\t\t\t\t\t\t(listSession)=\"listSession.emit($event)\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t} @else {\n\t\t\t\t\t<textarea\n\t\t\t\t\t\t#textEditor\n\t\t\t\t\t\tdata-inline-editor\n\t\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t></textarea>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\n\t\t\t\tRenders `inkDrawing.liveStrokeView()`: the same plain-path /\n\t\t\t\tpressure-circle / tilt-nib decision `InkRendererComponent` makes for\n\t\t\t\ta committed stroke, so a calligraphic lean or pressure-variable\n\t\t\t\twidth shows up while the pointer is still down, not only after\n\t\t\t\trelease.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveStrokeView() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t@if (inkDrawing.liveStrokeView()?.nibMarks; as nibMarks) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (m of nibMarks; track $index) {\n\t\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"m.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"m.cy\"\n\t\t\t\t\t\t\t\t\t[attr.rx]=\"m.rPerp\"\n\t\t\t\t\t\t\t\t\t[attr.ry]=\"m.rTilt\"\n\t\t\t\t\t\t\t\t\t[attr.transform]=\"'rotate(' + m.rotationDeg + ' ' + m.cx + ' ' + m.cy + ')'\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else if (inkDrawing.liveStrokeView()?.circles; as circles) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (c of circles; track $index) {\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"c.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"c.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"c.r\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveStrokeView()?.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"inkDrawing.liveStrokeView()?.width\"\n\t\t\t\t\t\t\t[attr.stroke-opacity]=\"inkDrawing.liveStrokeView()?.opacity\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: AiFocusHighlightOverlayComponent, selector: "pptx-ai-focus-highlight-overlay", inputs: ["highlights", "elements", "activeSlideIndex"] }, { kind: "component", type: AiChangeOverlayComponent, selector: "pptx-ai-change-overlay", inputs: ["batch", "activeSlideIndex"] }, { kind: "component", type: ActiveXControlsOverlayComponent, selector: "pptx-activex-controls-overlay", inputs: ["controls", "canvasSize"] }, { kind: "component", type: InlineListEditorComponent, selector: "pptx-inline-list-editor", inputs: ["element", "seed", "spellCheck", "activationSelection"], outputs: ["textInput", "textCommit", "textCancel", "textFormat", "listSession"] }, { kind: "directive", type: RotateHandlePlacementDirective, selector: "[pptxRotateHandleFor]", inputs: ["pptxRotateHandleFor", "pptxRotateHandleStage"] }, { kind: "component", type: ChartQuickActionsOverlayComponent, selector: "pptx-chart-quick-actions-overlay", inputs: ["element", "canEdit", "zoom"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
129222
130041
|
}
|
|
129223
130042
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: SlideCanvasComponent, decorators: [{
|
|
129224
130043
|
type: Component,
|
|
@@ -129239,7 +130058,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
129239
130058
|
ActiveXControlsOverlayComponent,
|
|
129240
130059
|
InlineListEditorComponent,
|
|
129241
130060
|
RotateHandlePlacementDirective,
|
|
129242
|
-
], template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t@let controlArtwork = selectionControlArtwork(h, h.handle);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"resize\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[ngStyle]=\"controlArtwork.frame\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t[style.--pptx-selection-width.px]=\"singleSelected()?.width\"\n\t\t\t\t\t[style.--pptx-selection-height.px]=\"singleSelected()?.height\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t>\n\t\t\t\t\t<span data-pptx-handle-hit [ngStyle]=\"resizeHitAreaStyle(h.handle)\"></span>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"controlArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t@let rotateArtwork = selectionControlArtwork(rh);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.z-index]=\"editingBox() ? 10003 : null\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"rotate\"\n\t\t\t\t\t[pptxRotateHandleFor]=\"singleSelected()?.id\"\n\t\t\t\t\t[pptxRotateHandleStage]=\"stage\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[ngStyle]=\"rotateArtwork.frame\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"rotateArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"adjust\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t@if (inlineListSeed(); as seed) {\n\t\t\t\t\t@for (session of [seed]; track session) {\n\t\t\t\t\t\t<pptx-inline-list-editor\n\t\t\t\t\t\t\t[element]=\"eb.element\"\n\t\t\t\t\t\t\t[seed]=\"session\"\n\t\t\t\t\t\t\t[activationSelection]=\"listActivationSelection()\"\n\t\t\t\t\t\t\t[spellCheck]=\"spellCheck()\"\n\t\t\t\t\t\t\t(textInput)=\"textInput.emit($event)\"\n\t\t\t\t\t\t\t(textCommit)=\"textCommit.emit($event)\"\n\t\t\t\t\t\t\t(textCancel)=\"textCancel.emit()\"\n\t\t\t\t\t\t\t(textFormat)=\"textFormat.emit($event)\"\n\t\t\t\t\t\t\t(listSession)=\"listSession.emit($event)\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t} @else {\n\t\t\t\t\t<textarea\n\t\t\t\t\t\t#textEditor\n\t\t\t\t\t\tdata-inline-editor\n\t\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t></textarea>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\n\t\t\t\tRenders `inkDrawing.liveStrokeView()`: the same plain-path /\n\t\t\t\tpressure-circle / tilt-nib decision `InkRendererComponent` makes for\n\t\t\t\ta committed stroke, so a calligraphic lean or pressure-variable\n\t\t\t\twidth shows up while the pointer is still down, not only after\n\t\t\t\trelease.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveStrokeView() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t@if (inkDrawing.liveStrokeView()?.nibMarks; as nibMarks) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (m of nibMarks; track $index) {\n\t\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"m.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"m.cy\"\n\t\t\t\t\t\t\t\t\t[attr.rx]=\"m.rPerp\"\n\t\t\t\t\t\t\t\t\t[attr.ry]=\"m.rTilt\"\n\t\t\t\t\t\t\t\t\t[attr.transform]=\"'rotate(' + m.rotationDeg + ' ' + m.cx + ' ' + m.cy + ')'\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else if (inkDrawing.liveStrokeView()?.circles; as circles) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (c of circles; track $index) {\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"c.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"c.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"c.r\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveStrokeView()?.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"inkDrawing.liveStrokeView()?.width\"\n\t\t\t\t\t\t\t[attr.stroke-opacity]=\"inkDrawing.liveStrokeView()?.opacity\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"] }]
|
|
130061
|
+
ChartQuickActionsOverlayComponent,
|
|
130062
|
+
], template: "<div\n\t#viewport\n\tclass=\"pptx-ng-canvas-viewport\"\n\t[attr.data-pptx-viewport]=\"interactive() ? '' : null\"\n\t(pointerdown)=\"onViewportPointerDown($event)\"\n>\n\t<div class=\"pptx-ng-canvas-wrapper\" [ngStyle]=\"wrapperStyle()\">\n\t\t<div\n\t\t\t#stage\n\t\t\tclass=\"pptx-ng-canvas-stage\"\n\t\t\t[class.is-editable]=\"editable()\"\n\t\t\trole=\"region\"\n\t\t\t[attr.aria-roledescription]=\"interactive() || presenting() ? 'slide' : null\"\n\t\t\t[attr.data-pptx-ai-active]=\"aiActive() ? 'true' : null\"\n\t\t\t[ngStyle]=\"stageStyle()\"\n\t\t\t(pointerdown)=\"onStagePointerDown($event)\"\n\t\t\t(contextmenu)=\"onContextMenu($event)\"\n\t\t\t(dblclick)=\"onDblClick($event)\"\n\t\t>\n\t\t\t<!--\n\t\t\t\tTemplate layer: inherited master/layout elements, rendered BEHIND\n\t\t\t\tthe slide's own elements (lower z-index). Interactive + given the\n\t\t\t\tamber editable affordance only while editTemplateMode is on; when\n\t\t\t\toff they render inertly with no affordance, exactly as core\n\t\t\t\tdelivered them. `marked` keeps the data-pptx-element contract on\n\t\t\t\tthem even while locked: the marker means \"rendered slide element\",\n\t\t\t\tnot \"editable right now\".\n\t\t\t-->\n\t\t\t@for (element of visibleTemplateElements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive() && editTemplateMode()\"\n\t\t\t\t\t[marked]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[editable]=\"editable() && editTemplateMode()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"editTemplateMode()\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@for (element of elements(); track element.id; let i = $index) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"element\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"visibleTemplateElements().length + i\"\n\t\t\t\t\t[obstacles]=\"connectorObstacles()\"\n\t\t\t\t\t[canvasWidth]=\"canvasSize().width\"\n\t\t\t\t\t[canvasHeight]=\"canvasSize().height\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementIds()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[editable]=\"editable()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"allElements()\"\n\t\t\t\t\t[editTemplateMode]=\"false\"\n\t\t\t\t\t[editingElementId]=\"editingId()\"\n\t\t\t\t\t(cellCommit)=\"cellCommit.emit($event)\"\n\t\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<pptx-activex-controls-overlay\n\t\t\t\t[controls]=\"slide()?.activeXControls ?? []\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t/>\n\t\t\t@if (aiHighlights().length > 0 || aiActive()) {\n\t\t\t\t<pptx-ai-focus-highlight-overlay\n\t\t\t\t\t[highlights]=\"aiHighlights()\"\n\t\t\t\t\t[elements]=\"elements()\"\n\t\t\t\t\t[activeSlideIndex]=\"aiActiveSlideIndex()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t@if (aiChangeBatch(); as batch) {\n\t\t\t\t<pptx-ai-change-overlay [batch]=\"batch\" [activeSlideIndex]=\"aiActiveSlideIndex()\" />\n\t\t\t}\n\t\t\t@for (box of selectionBoxes(); track box.id) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-selection\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"box.x\"\n\t\t\t\t\t[style.top.px]=\"box.y\"\n\t\t\t\t\t[style.width.px]=\"box.width\"\n\t\t\t\t\t[style.height.px]=\"box.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (h of handleBoxes(); track h.handle) {\n\t\t\t\t@let controlArtwork = selectionControlArtwork(h, h.handle);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"resize\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.resize' | translate: { handle: h.handle }\"\n\t\t\t\t\t[ngStyle]=\"controlArtwork.frame\"\n\t\t\t\t\t[style.cursor]=\"h.cursor\"\n\t\t\t\t\t[style.--pptx-selection-width.px]=\"singleSelected()?.width\"\n\t\t\t\t\t[style.--pptx-selection-height.px]=\"singleSelected()?.height\"\n\t\t\t\t\t(pointerdown)=\"onHandlePointerDown($event, h.handle)\"\n\t\t\t\t\t(keydown)=\"onResizeHandleKeydown($event, h.handle)\"\n\t\t\t\t>\n\t\t\t\t\t<span data-pptx-handle-hit [ngStyle]=\"resizeHitAreaStyle(h.handle)\"></span>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"controlArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t@if (marqueeRect(); as mr) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-marquee\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"mr.x\"\n\t\t\t\t\t[style.top.px]=\"mr.y\"\n\t\t\t\t\t[style.width.px]=\"mr.width\"\n\t\t\t\t\t[style.height.px]=\"mr.height\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (g of snapGuides(); track $index) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-snap-guide\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : g.start\"\n\t\t\t\t\t[style.top.px]=\"g.axis === 'x' ? g.start : g.pos\"\n\t\t\t\t\t[style.width.px]=\"g.axis === 'x' ? 0 : g.end - g.start\"\n\t\t\t\t\t[style.height.px]=\"g.axis === 'x' ? g.end - g.start : 0\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@if (rotateHandle(); as rh) {\n\t\t\t\t@let rotateArtwork = selectionControlArtwork(rh);\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-rotate-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[style.z-index]=\"editingBox() ? 10003 : null\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"rotate\"\n\t\t\t\t\t[pptxRotateHandleFor]=\"singleSelected()?.id\"\n\t\t\t\t\t[pptxRotateHandleStage]=\"stage\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.rotate' | translate\"\n\t\t\t\t\t[ngStyle]=\"rotateArtwork.frame\"\n\t\t\t\t\t(pointerdown)=\"onRotatePointerDown($event)\"\n\t\t\t\t\t(keydown)=\"onRotateHandleKeydown($event)\"\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclass=\"pptx-ng-control-artwork\"\n\t\t\t\t\t\tdata-pptx-handle-artwork\n\t\t\t\t\t\t[ngStyle]=\"rotateArtwork.artwork\"\n\t\t\t\t\t></span>\n\t\t\t\t</button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tShape-adjustment affordances (amber diamonds), ONE per `a:avLst`\n\t\t\t\tguide. Existence, position and cursor all come from the SHARED\n\t\t\t\t`getShapeAdjustmentHandleDescriptors`, so they appear only for a\n\t\t\t\tgeometry with an adjustable parameter, sit where the other four\n\t\t\t\tbindings put them, and are absent for a shape locked with\n\t\t\t\t`noAdjustHandles`. Dragging one writes `shapeAdjustments`; it does\n\t\t\t\tNOT resize the element.\n\t\t\t-->\n\t\t\t@for (ah of adjustHandles(); track ah.key) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-adjust-handle\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\tdata-pptx-compact\n\t\t\t\t\tdata-pptx-handle-kind=\"adjust\"\n\t\t\t\t\t[attr.data-pptx-adjust-key]=\"ah.key\"\n\t\t\t\t\t[attr.aria-label]=\"'pptx.selectionOverlay.adjust' | translate\"\n\t\t\t\t\t[style.left.px]=\"ah.left\"\n\t\t\t\t\t[style.top.px]=\"ah.top\"\n\t\t\t\t\t[style.width.px]=\"ah.size\"\n\t\t\t\t\t[style.height.px]=\"ah.size\"\n\t\t\t\t\t[style.cursor]=\"ah.cursor\"\n\t\t\t\t\t(pointerdown)=\"onAdjustPointerDown($event, ah)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tPowerPoint's floating \"Chart Elements\"/\"Chart Styles\"/\"Chart\n\t\t\t\tFilters\" quick-action icons, shown just outside the chart's\n\t\t\t\ttop-right corner when it is the single selected element.\n\t\t\t-->\n\t\t\t@if (editable() && quickActionsChartElement(); as chartEl) {\n\t\t\t\t<pptx-chart-quick-actions-overlay\n\t\t\t\t\t[element]=\"chartEl\"\n\t\t\t\t\t[canEdit]=\"editable()\"\n\t\t\t\t\t[zoom]=\"effectiveScalePublic()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t\t<!--\n\t\t\t\tConnector endpoint authoring: drag an end onto a shape's connection\n\t\t\t\tpoint to bind it (`a:stCxn` / `a:endCxn`), or off one to detach.\n\t\t\t\tCandidate sites are revealed only while an end is in flight so they\n\t\t\t\tnever obscure the deck at rest.\n\t\t\t-->\n\t\t\t@for (site of connectorSiteCandidates(); track site.key) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-connection-site\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-snapped]=\"site.snapped\"\n\t\t\t\t\tdata-pptx-connection-site\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[style.left.px]=\"site.left\"\n\t\t\t\t\t[style.top.px]=\"site.top\"\n\t\t\t\t\t[style.width.px]=\"site.size\"\n\t\t\t\t\t[style.height.px]=\"site.size\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t@for (ep of connectorEndpoints(); track ep.kind) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-connector-endpoint\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t[class.is-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.data-pptx-connector-endpoint]=\"ep.kind\"\n\t\t\t\t\t[attr.data-pptx-connector-attached]=\"ep.attached\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t(ep.kind === 'start'\n\t\t\t\t\t\t\t? 'pptx.canvas.connectorEndpointStart'\n\t\t\t\t\t\t\t: 'pptx.canvas.connectorEndpointEnd'\n\t\t\t\t\t\t) | translate\n\t\t\t\t\t\"\n\t\t\t\t\t[style.left.px]=\"ep.left\"\n\t\t\t\t\t[style.top.px]=\"ep.top\"\n\t\t\t\t\t[style.width.px]=\"ep.size\"\n\t\t\t\t\t[style.height.px]=\"ep.size\"\n\t\t\t\t\t(pointerdown)=\"onConnectorEndpointPointerDown($event, ep.kind)\"\n\t\t\t\t></button>\n\t\t\t}\n\t\t\t@if (editingBox(); as eb) {\n\t\t\t\t@if (inlineListSeed(); as seed) {\n\t\t\t\t\t@for (session of [seed]; track session) {\n\t\t\t\t\t\t<pptx-inline-list-editor\n\t\t\t\t\t\t\t[element]=\"eb.element\"\n\t\t\t\t\t\t\t[seed]=\"session\"\n\t\t\t\t\t\t\t[activationSelection]=\"listActivationSelection()\"\n\t\t\t\t\t\t\t[spellCheck]=\"spellCheck()\"\n\t\t\t\t\t\t\t(textInput)=\"textInput.emit($event)\"\n\t\t\t\t\t\t\t(textCommit)=\"textCommit.emit($event)\"\n\t\t\t\t\t\t\t(textCancel)=\"textCancel.emit()\"\n\t\t\t\t\t\t\t(textFormat)=\"textFormat.emit($event)\"\n\t\t\t\t\t\t\t(listSession)=\"listSession.emit($event)\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t} @else {\n\t\t\t\t\t<textarea\n\t\t\t\t\t\t#textEditor\n\t\t\t\t\t\tdata-inline-editor\n\t\t\t\t\t\tclass=\"pptx-ng-text-editor\"\n\t\t\t\t\t\taria-label=\"Edit slide text\"\n\t\t\t\t\t\t[spellcheck]=\"spellCheck()\"\n\t\t\t\t\t\t[style.left.px]=\"eb.x\"\n\t\t\t\t\t\t[style.top.px]=\"eb.y\"\n\t\t\t\t\t\t[style.width.px]=\"eb.width\"\n\t\t\t\t\t\t[style.height.px]=\"eb.height\"\n\t\t\t\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t(input)=\"onTextInput($event, eb.id)\"\n\t\t\t\t\t\t(blur)=\"commitText($event, eb.id)\"\n\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t></textarea>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tView overlays: editor aids only, never on thumbnails/preview/presentation.\n\t\t\t\tAll are pointer-events:none so they never break selection/drag.\n\t\t\t\tNone carry data-pptx-element / aria-roledescription / data-pptx-viewport.\n\t\t\t-->\n\t\t\t@if (interactive() && showGrid()) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-grid\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<defs>\n\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t[attr.id]=\"gridPatternId\"\n\t\t\t\t\t\t\t[attr.width]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\t[attr.height]=\"gridSpacingPx()\"\n\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t[attr.cx]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\t[attr.cy]=\"gridSpacingPx() / 2\"\n\t\t\t\t\t\t\t\tr=\"0.6\"\n\t\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.55)\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</pattern>\n\t\t\t\t\t</defs>\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\t\t[attr.fill]=\"'url(#' + gridPatternId + ')'\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t@if (interactive() && showGuides()) {\n\t\t\t\t<!--\n\t\t\t\t\tCenter crosshair: one horizontal line and one vertical line\n\t\t\t\t\tthrough the midpoint of the slide. Static; draggable guides\n\t\t\t\t\tare a follow-up.\n\t\t\t\t-->\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-overlay-guides\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t>\n\t\t\t\t\t<!-- Horizontal center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t\t[attr.y1]=\"canvasSize().height / 2\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height / 2\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t\t<!-- Vertical center guide -->\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"canvasSize().width / 2\"\n\t\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t\t[attr.x2]=\"canvasSize().width / 2\"\n\t\t\t\t\t\t[attr.y2]=\"canvasSize().height\"\n\t\t\t\t\t\tstroke=\"rgba(99,102,241,0.7)\"\n\t\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t\t\tstroke-dasharray=\"6 3\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tUser-created ruler guides.\n\t\t\t\tEach guide has a non-interactive line body and an interactive\n\t\t\t\tdrag handle. Double-click the handle to delete the guide.\n\n\t\t\t\tDeliberately OUTSIDE the showGuides() gate above (which owns the\n\t\t\t\tstatic centre crosshair): a guide the user just dragged off a ruler\n\t\t\t\tstrip must be visible immediately, as it is in Vue and Vanilla.\n\t\t\t\tWhile it lived under that gate, the drag-out gesture silently\n\t\t\t\tproduced an invisible guide unless View > Guides happened to be on.\n\t\t\t-->\n\t\t\t@if (interactive()) {\n\t\t\t\t@for (g of rulerGuidesSvc.rulerGuides(); track g.id) {\n\t\t\t\t\t<!-- Guide line body: pointer-events:none -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-line\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '1px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '1px' : '100%'\"\n\t\t\t\t\t></div>\n\t\t\t\t\t<!-- Drag handle: pointer-events:auto -->\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"pptx-ng-ruler-guide-handle\"\n\t\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\t\t[style.left.px]=\"g.axis === 'x' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.top.px]=\"g.axis === 'y' ? g.pos - 4 : 0\"\n\t\t\t\t\t\t[style.width]=\"g.axis === 'x' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.height]=\"g.axis === 'y' ? '9px' : '100%'\"\n\t\t\t\t\t\t[style.cursor]=\"g.axis === 'x' ? 'col-resize' : 'row-resize'\"\n\t\t\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onGuidePointerDown($event, g.id, g.axis)\"\n\t\t\t\t\t\t(dblclick)=\"rulerGuidesSvc.onGuideDoubleClick($event, g.id)\"\n\t\t\t\t\t\t[title]=\"'pptx.canvas.guideTooltip' | translate\"\n\t\t\t\t\t></div>\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tLive ink stroke preview: shown while the user is drawing.\n\t\t\t\tpointer-events:none so it never intercepts element gestures.\n\t\t\t\tNo data-pptx-element / aria-roledescription / data-pptx-viewport.\n\n\t\t\t\tRenders `inkDrawing.liveStrokeView()`: the same plain-path /\n\t\t\t\tpressure-circle / tilt-nib decision `InkRendererComponent` makes for\n\t\t\t\ta committed stroke, so a calligraphic lean or pressure-variable\n\t\t\t\twidth shows up while the pointer is still down, not only after\n\t\t\t\trelease.\n\t\t\t-->\n\t\t\t@if (inkDrawing.active() && inkDrawing.liveStrokeView() && drawTool() !== 'select') {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-ink-preview\"\n\t\t\t\t\tdata-export-ignore=\"true\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.width]=\"canvasSize().width\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none; z-index: 70\"\n\t\t\t\t>\n\t\t\t\t\t@if (inkDrawing.liveStrokeView()?.nibMarks; as nibMarks) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (m of nibMarks; track $index) {\n\t\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"m.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"m.cy\"\n\t\t\t\t\t\t\t\t\t[attr.rx]=\"m.rPerp\"\n\t\t\t\t\t\t\t\t\t[attr.ry]=\"m.rTilt\"\n\t\t\t\t\t\t\t\t\t[attr.transform]=\"'rotate(' + m.rotationDeg + ' ' + m.cx + ' ' + m.cy + ')'\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else if (inkDrawing.liveStrokeView()?.circles; as circles) {\n\t\t\t\t\t\t<g [attr.opacity]=\"inkDrawing.liveStrokeView()?.opacity\">\n\t\t\t\t\t\t\t@for (c of circles; track $index) {\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"c.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"c.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"c.r\"\n\t\t\t\t\t\t\t\t\t[attr.fill]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</g>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"inkDrawing.liveStrokeView()?.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"inkDrawing.liveStrokeView()?.color\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"inkDrawing.liveStrokeView()?.width\"\n\t\t\t\t\t\t\t[attr.stroke-opacity]=\"inkDrawing.liveStrokeView()?.opacity\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\n\t\t\t<!--\n\t\t\t\tProjected overlays (collaboration cursors + remote selections).\n\t\t\t\tThey live INSIDE the scaled stage so the stage's CSS\n\t\t\t\ttransform:scale() applies the on-screen scale exactly once and\n\t\t\t\tthey can be authored in raw, unscaled slide coordinates, exactly\n\t\t\t\tlike the React/Vue overlays.\n\t\t\t-->\n\t\t\t<ng-content />\n\t\t</div>\n\n\t\t<!--\n\t\t\tRuler strips: siblings to the scaled stage inside the wrapper div,\n\t\t\tabsolutely positioned at top:0/left:0 within the wrapper's padding area.\n\t\t\tThe wrapper's padding (RULER_THICKNESS px top+left) reserves space for\n\t\t\tthese strips so the stage content starts below/right of them.\n\t\t\tpointer-events:none so they never intercept element gestures.\n\t\t-->\n\t\t@if (interactive() && showRulers()) {\n\t\t\t<!-- Corner square at the intersection of the two ruler strips -->\n\t\t\t<div class=\"pptx-ng-ruler-corner\" aria-hidden=\"true\"></div>\n\n\t\t\t<!--\n\t\t\t\tHorizontal ruler: spans the top padding row of the wrapper.\n\t\t\t\tA guide is dropped on pointer-UP (not down), resolved by the shared\n\t\t\t\trulerDragToGuidePosition, so a stray click on the strip cannot\n\t\t\t\tdrop a guide the user never dragged out - the rule React, Vue,\n\t\t\t\tSvelte and Vanilla all follow.\n\t\t\t-->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-h\"\n\t\t\t\tdata-pptx-ruler=\"h\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t[style.cursor]=\"editable() ? 'row-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('h', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('h', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (hRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\t[attr.x]=\"highlight.start\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t[attr.width]=\"highlight.span\"\n\t\t\t\t\t\t[attr.height]=\"rulerThickness\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\t[attr.y1]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.x2]=\"canvasSize().width * effectiveScalePublic()\"\n\t\t\t\t\t[attr.y2]=\"rulerThickness - 0.5\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of hRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"tick.position\"\n\t\t\t\t\t\t[attr.y1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.x2]=\"tick.position\"\n\t\t\t\t\t\t[attr.y2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t[attr.x]=\"tick.position + 2\"\n\t\t\t\t\t\t\t[attr.y]=\"rulerFontSize + 1\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\n\t\t\t<!-- Vertical ruler: spans the left padding column of the wrapper -->\n\t\t\t<svg\n\t\t\t\tclass=\"pptx-ng-ruler-v\"\n\t\t\t\tdata-pptx-ruler=\"v\"\n\t\t\t\trole=\"presentation\"\n\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t[style.cursor]=\"editable() ? 'col-resize' : null\"\n\t\t\t\t(pointerdown)=\"rulerGuidesSvc.onRulerPointerDown('v', $event)\"\n\t\t\t\t(pointerup)=\"rulerGuidesSvc.onRulerPointerUp('v', $event)\"\n\t\t\t>\n\t\t\t\t<rect\n\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t[attr.height]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tfill=\"#1e293b\"\n\t\t\t\t/>\n\t\t\t\t@if (vRulerHighlight(); as highlight) {\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t[attr.y]=\"highlight.start\"\n\t\t\t\t\t\t[attr.width]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.height]=\"highlight.span\"\n\t\t\t\t\t\tfill=\"rgba(96,165,250,0.25)\"\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t\t<line\n\t\t\t\t\t[attr.x1]=\"rulerThickness - 0.5\"\n\t\t\t\t\ty1=\"0\"\n\t\t\t\t\t[attr.x2]=\"rulerThickness - 0.5\"\n\t\t\t\t\t[attr.y2]=\"canvasSize().height * effectiveScalePublic()\"\n\t\t\t\t\tstroke=\"rgba(255,255,255,0.15)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t@for (tick of vRulerTicks(); track $index) {\n\t\t\t\t\t<line\n\t\t\t\t\t\t[attr.x1]=\"rulerThickness\"\n\t\t\t\t\t\t[attr.y1]=\"tick.position\"\n\t\t\t\t\t\t[attr.x2]=\"rulerThickness - rulerThickness * (tick.isMajor ? 0.6 : 0.3)\"\n\t\t\t\t\t\t[attr.y2]=\"tick.position\"\n\t\t\t\t\t\tstroke=\"rgba(156,163,175,0.7)\"\n\t\t\t\t\t\t[attr.stroke-width]=\"tick.isMajor ? 1 : 0.5\"\n\t\t\t\t\t/>\n\t\t\t\t\t@if (tick.label) {\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\t[attr.y]=\"tick.position + rulerFontSize + 2\"\n\t\t\t\t\t\t\t[attr.font-size]=\"rulerFontSize\"\n\t\t\t\t\t\t\tfill=\"rgba(156,163,175,0.9)\"\n\t\t\t\t\t\t\tstyle=\"font-family: system-ui, sans-serif\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ tick.label }}\n\t\t\t\t\t\t</text>\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t}\n\t</div>\n</div>\n", styles: [".pptx-ng-canvas-stage.is-editable{touch-action:none}\n"] }]
|
|
129243
130063
|
}], ctorParameters: () => [], propDecorators: { slide: [{ type: i0.Input, args: [{ isSignal: true, alias: "slide", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], fitPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitPadding", required: false }] }], maxFitScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFitScale", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], rulerUnit: [{ type: i0.Input, args: [{ isSignal: true, alias: "rulerUnit", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], gridSpacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridSpacing", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], guideCommand: [{ type: i0.Input, args: [{ isSignal: true, alias: "guideCommand", required: false }] }], spellCheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheck", required: false }] }], snapToGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGuides", required: false }] }], autoFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFit", required: false }] }], transparentBackground: [{ type: i0.Input, args: [{ isSignal: true, alias: "transparentBackground", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], exposeElementIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "exposeElementIds", required: false }] }], presenting: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenting", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }], editingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "editingId", required: false }] }], editTemplateMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTemplateMode", required: false }] }], templateElements: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateElements", required: false }] }], aiHighlights: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiHighlights", required: false }] }], aiActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiActive", required: false }] }], aiActiveSlideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiActiveSlideIndex", required: false }] }], aiChangeBatch: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiChangeBatch", required: false }] }], aiPickMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiPickMode", required: false }] }], drawTool: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawTool", required: false }] }], drawColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawColor", required: false }] }], drawWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "drawWidth", required: false }] }], elementSelect: [{ type: i0.Output, args: ["elementSelect"] }], backgroundClick: [{ type: i0.Output, args: ["backgroundClick"] }], transformStart: [{ type: i0.Output, args: ["transformStart"] }], transformUpdate: [{ type: i0.Output, args: ["transformUpdate"] }], transformEnd: [{ type: i0.Output, args: ["transformEnd"] }], adjustUpdate: [{ type: i0.Output, args: ["adjustUpdate"] }], connectorEndpointUpdate: [{ type: i0.Output, args: ["connectorEndpointUpdate"] }], contextMenu: [{ type: i0.Output, args: ["contextMenu"] }], textEditStart: [{ type: i0.Output, args: ["textEditStart"] }], textCommit: [{ type: i0.Output, args: ["textCommit"] }], textInput: [{ type: i0.Output, args: ["textInput"] }], textCancel: [{ type: i0.Output, args: ["textCancel"] }], textFormat: [{ type: i0.Output, args: ["textFormat"] }], listSession: [{ type: i0.Output, args: ["listSession"] }], rotateUpdate: [{ type: i0.Output, args: ["rotateUpdate"] }], marqueeSelect: [{ type: i0.Output, args: ["marqueeSelect"] }], inkStrokeComplete: [{ type: i0.Output, args: ["inkStrokeComplete"] }], eraserHit: [{ type: i0.Output, args: ["eraserHit"] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], tableChange: [{ type: i0.Output, args: ["tableChange"] }], textEditor: [{ type: i0.ViewChild, args: ['textEditor', { isSignal: true }] }], listEditor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => InlineListEditorComponent), { isSignal: true }] }], stageRef: [{ type: i0.ViewChild, args: ['stage', { isSignal: true }] }], viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], onPointerMove: [{
|
|
129244
130064
|
type: HostListener,
|
|
129245
130065
|
args: ['document:pointermove', ['$event']]
|
|
@@ -147931,7 +148751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
147931
148751
|
}], 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 }] }] } });
|
|
147932
148752
|
|
|
147933
148753
|
// Generated by scripts/inline-shared.mjs from package.json. Do not edit.
|
|
147934
|
-
const PPTX_ANGULAR_VIEWER_VERSION = "3.
|
|
148754
|
+
const PPTX_ANGULAR_VIEWER_VERSION = "3.20.0";
|
|
147935
148755
|
|
|
147936
148756
|
/**
|
|
147937
148757
|
* account-page.component.ts: File > Account content.
|
|
@@ -154217,8 +155037,8 @@ class AnimationTimelineComponent {
|
|
|
154217
155037
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AnimationTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
154218
155038
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: AnimationTimelineComponent, isStandalone: true, selector: "pptx-animation-timeline", inputs: { animations: { classPropertyName: "animations", publicName: "animations", isSignal: true, isRequired: true, transformFunction: null }, elements: { classPropertyName: "elements", publicName: "elements", isSignal: true, isRequired: false, transformFunction: null }, animationTimelineAnchors: { classPropertyName: "animationTimelineAnchors", publicName: "animationTimelineAnchors", isSignal: true, isRequired: false, transformFunction: null }, selectedElementId: { classPropertyName: "selectedElementId", publicName: "selectedElementId", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { animationsChange: "animationsChange" }, ngImport: i0, template: `
|
|
154219
155039
|
@if (rows().length) {
|
|
154220
|
-
<section class="timeline" aria-label="
|
|
154221
|
-
<h4>
|
|
155040
|
+
<section class="timeline" [attr.aria-label]="'pptx.animation.timeline' | translate">
|
|
155041
|
+
<h4>{{ 'pptx.animation.timeline' | translate }}</h4>
|
|
154222
155042
|
<div class="bar" aria-hidden="true">
|
|
154223
155043
|
@for (item of bars(); track item.elementId) {
|
|
154224
155044
|
<span
|
|
@@ -154271,8 +155091,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
154271
155091
|
type: Component,
|
|
154272
155092
|
args: [{ selector: 'pptx-animation-timeline', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: `
|
|
154273
155093
|
@if (rows().length) {
|
|
154274
|
-
<section class="timeline" aria-label="
|
|
154275
|
-
<h4>
|
|
155094
|
+
<section class="timeline" [attr.aria-label]="'pptx.animation.timeline' | translate">
|
|
155095
|
+
<h4>{{ 'pptx.animation.timeline' | translate }}</h4>
|
|
154276
155096
|
<div class="bar" aria-hidden="true">
|
|
154277
155097
|
@for (item of bars(); track item.elementId) {
|
|
154278
155098
|
<span
|
|
@@ -186196,4 +187016,4 @@ function cn(...values) {
|
|
|
186196
187016
|
*/
|
|
186197
187017
|
|
|
186198
187018
|
export { CollaborationCursorsComponent as $, AFTER_ANIMATION_VALUES as A, AnimationAuthorPanelComponent as B, AnimationPanelComponent as C, AnimationPlaybackService as D, AutosaveRecoveryDialogComponent as E, AutosaveService as F, BroadcastDialogComponent as G, CHART_EDITOR_STYLES as H, CINEMATIC_TRANSITION_KEYFRAMES as I, CURSOR_PALETTE as J, CanvasFitService as K, ChartAxisOptionsComponent as L, ChartAxisStyleOptionsComponent as M, ChartComboTypeOptionsComponent as N, ChartDataEditorComponent as O, ChartDataLabelOptionsComponent as P, ChartDatapointMarkerOptionsComponent as Q, ChartDatapointOptionsComponent as R, ChartDisplayOptionsComponent as S, ChartElementViewComponent as T, ChartErrorBarOptionsComponent as U, ChartMarkerOptionsComponent as V, ChartPartSelectionService as W, ChartPrimitivesComponent as X, ChartRendererComponent as Y, ChartTrendlineOptionsComponent as Z, ChartTypeSelectorComponent as _, ALIGN_OPTIONS as a, INSTANT as a$, CollaborationService as a0, ColorChangedImageComponent as a1, CommentMarkersOverlayComponent as a2, CommentsPanelComponent as a3, CommentsService as a4, ComparePanelComponent as a5, ConnectorRendererComponent as a6, ConnectorTextOverlayComponent as a7, CustomShowsComponent as a8, DEFAULT_BOUNDS as a9, EditorContextMenuComponent as aA, EditorHistory as aB, EditorStateService as aC, EditorToolbarComponent as aD, EffectsPanelComponent as aE, ElementRendererComponent as aF, EmbeddedFontsService as aG, EncryptedFileDialogComponent as aH, EquationEditorDialogComponent as aI, EquationRendererComponent as aJ, EquationTemplateGalleryComponent as aK, ExportProgressModalComponent as aL, ExportService as aM, FieldContextService as aN, FindBarComponent as aO, FindReplaceBarComponent as aP, FollowModeBarComponent as aQ, FontEmbeddingListComponent as aR, FontEmbeddingPanelComponent as aS, GALLERY_THEME_PRESETS as aT, GOOGLE_WEBFONTS_LINK_ID as aU, GRIDLINE_COLOR$1 as aV, GoogleWebfontsService as aW, GradientPickerComponent as aX, HANDOUT_OPTIONS as aY, HeaderFooterDialogComponent as aZ, HyperlinkDialogComponent as a_, DEFAULT_BROADCAST_SERVER_URL as aa, DEFAULT_CANVAS_HEIGHT as ab, DEFAULT_CANVAS_WIDTH as ac, DEFAULT_COLOR_SCHEME as ad, DEFAULT_FILL_COLOR$1 as ae, DEFAULT_LAYOUT as af, DEFAULT_MORPH_DURATION_MS as ag, DEFAULT_PALETTE$1 as ah, DEFAULT_PATTERN_FILL_PRESET as ai, DEFAULT_PRINT_SETTINGS as aj, DEFAULT_SLIDE_BACKGROUND as ak, DEFAULT_STROKE_COLOR as al, DEFAULT_STYLE as am, DEFAULT_TABLE_ROW_HEIGHT as an, DEFAULT_TEXT_COLOR$2 as ao, DEFAULT_VIEWER_PROFILE as ap, DIRECTIONAL_PRESETS as aq, DIRECTION_OPTIONS as ar, DocumentPropertiesCardComponent as as, EASE as at, EFFECT_SOUND_CATALOGUE as au, EMBEDDED_FONTS_STYLE_ID as av, EMPHASIS_PRESETS as aw, ENTRANCE_PRESETS as ax, TEMPLATES as ay, EXIT_PRESETS as az, ANIMATION_PRESET_CATEGORIES as b, REPEAT_MODE_OPTIONS as b$, ImagePropertiesPanelComponent as b0, InkDrawingService as b1, InkRendererComponent as b2, InsertSmartArtDialogComponent as b3, InspectorPaneHeaderComponent as b4, InspectorPanelComponent as b5, IsMobileService as b6, KeepAnnotationsDialogComponent as b7, LOCALE_CATALOG as b8, LONG_PRESS_DURATION_MS as b9, POWER_POINT_VIEWER_PROVIDERS as bA, PPTX_OPEN_ACCEPT as bB, PRESENTATION_OPEN_EXTENSIONS as bC, PRESENTER_CHANNEL_NAME as bD, PRESENTER_MSG_ORIGIN as bE, PRESENTER_TIMER_SEGMENT_MS as bF, PX_PER_CM as bG, PX_PER_INCH as bH, PasswordProtectionDialogComponent as bI, PasswordStrengthMeterComponent as bJ, PowerPointViewerComponent as bK, PresentToolbarAutoHide as bL, PresentationAnnotationOverlayComponent as bM, PresentationAnnotationsService as bN, PresentationOverlayComponent as bO, PresentationPropertiesPanelComponent as bP, PresentationSettingsCardComponent as bQ, PresentationSubtitleBarComponent as bR, PresentationToolbarComponent as bS, PresentationTransitionOverlayComponent as bT, PresenterViewComponent as bU, PresenterWindowService as bV, PrintDialogComponent as bW, PrintService as bX, PrintSettingsPanelComponent as bY, PropertiesDialogComponent as bZ, RANDOM_ELIGIBLE_TYPES as b_, LONG_PRESS_MOVE_TOLERANCE_PX as ba, LoadContentService as bb, LocalPresencePublisher as bc, MAX_ZOOM_SCALE as bd, MIN_ZOOM_SCALE as be, MOTION_PATH_COLUMNS as bf, MediaPreviewComponent as bg, MediaPropertiesPanelComponent as bh, MediaRendererComponent as bi, MediaTrimTimelineComponent as bj, MobileBottomBarComponent as bk, MobileMenuSheetComponent as bl, MobilePresenterViewComponent as bm, MobileSheetComponent as bn, MobileSlidesSheetComponent as bo, MobileToolbarComponent as bp, ModalDialogComponent as bq, Model3DRendererComponent as br, NotesHandoutCardComponent as bs, NotesPanelComponent as bt, NotesToolbarComponent as bu, OleRendererComponent as bv, OutlineViewOverlayComponent as bw, P14_TRANSITION_KEYFRAMES as bx, P14_TRANSITION_KEYFRAMES_2 as by, P14_TRANSITION_KEYFRAMES_ALL as bz, AUDIENCE_HASH as c, SlideSorterOverlayComponent as c$, RESIZE_HANDLES as c0, RULER_FONT_SIZE as c1, RULER_THICKNESS as c2, ReadingViewOverlayComponent as c3, RemoteSelectionOverlayComponent as c4, RibbonAnimationGalleryComponent as c5, RibbonAnimationsSectionComponent as c6, RibbonArrangeSectionComponent as c7, RibbonColorPopoverComponent as c8, RibbonComponent as c9, DEFAULT_PALETTE as cA, PALETTES$1 as cB, SMART_ART_COLOR_SCHEMES as cC, SMART_ART_STYLE_OPTIONS as cD, SUB_ITEM_LABEL as cE, SVG_WARP_PRESETS as cF, SWIPE_MAX_VERTICAL_PX as cG, SWIPE_THRESHOLD_PX as cH, SelectionPaneComponent as cI, SetUpSlideShowDialogComponent as cJ, SettingsAppearanceTabComponent as cK, SettingsDialogComponent as cL, SettingsLanguageTabComponent as cM, ShareDialogComponent as cN, ShortcutPanelComponent as cO, ShowOptionsFieldsetComponent as cP, ShowSlidesFieldsetComponent as cQ, SignatureStrippedDialogComponent as cR, SignaturesPanelComponent as cS, SignaturesService as cT, SlideBackgroundCardComponent as cU, SlideCanvasComponent as cV, SlideDefaultInspectorComponent as cW, SlideDiffChangesComponent as cX, SlideDiffRowComponent as cY, SlideDiffThumbnailsComponent as cZ, SlideSizeCardComponent as c_, 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, AUDIENCE_NONCE_KEY as d, ZoomNavigationService as d$, SlideThemeOverridePanelComponent as d0, SlideTransitionCardComponent as d1, SlidesPanelComponent as d2, SmartArt3DRendererComponent as d3, SmartArt3DService as d4, SmartArtPreviewComponent as d5, SmartArtPropertiesComponent as d6, SmartArtRendererComponent as d7, StatusBarComponent as d8, TABLE_STRUCTURE_TOGGLES as d9, TransitionPreviewComponent as dA, VALIGN_OPTIONS as dB, VIEWER_THEME as dC, VersionHistoryPanelComponent as dD, ViewerCanvasEditingService as dE, ViewerCollabCursorService as dF, ViewerCollaborationSessionService as dG, ViewerCompareService as dH, ViewerCustomShowsService as dI, ViewerDialogsService as dJ, ViewerDocumentPropertiesService as dK, ViewerExportService as dL, ViewerExtraDialogsComponent as dM, ViewerFileIOService as dN, ViewerFindReplaceService as dO, ViewerFormatPainterService as dP, ViewerInspectorPanelService as dQ, ViewerKeyboardService as dR, ViewerMobileSheetService as dS, ViewerPresentationModeService as dT, ViewerThemeGalleryService as dU, ViewerTouchGesturesService as dV, ViewerZoomService as dW, WEBM_MIME_CANDIDATES as dX, WHEEL_SPOKE_COUNTS as dY, WriteBackScheduler as dZ, ZERO_LINE_COLOR as d_, 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, TRANSITION_SPEED_DURATION_MS as df, TRIGGER_OPTIONS as dg, TYPE_LABELS as dh, TableCellAdvancedFillComponent as di, TableCellFormattingComponent as dj, TableDataEditorComponent as dk, TablePropertiesComponent as dl, TableRendererComponent as dm, TableResizeOverlayComponent as dn, 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, AVATAR_COLOR_SWATCHES as e, buildModel3DViewModel as e$, ZoomRendererComponent as e0, ZoomTargetService as e1, addCategory as e2, addCommentToList as e3, addGradientStopPatch as e4, addItem as e5, addSeries as e6, addSubItem as e7, advanceStep as e8, affordanceElements as e9, buildCellParagraphs as eA, buildChartViewModel as eB, buildChatLogExport as eC, buildChatLogMarkdown as eD, buildChromeStyle as eE, buildClearHyperlinkPatch as eF, buildClickGroups as eG, buildColStyles as eH, buildCollaborationConfig as eI, buildComboViewModel as eJ, buildCssGradientFromShapeStyle as eK, buildDuotoneFilter as eL, buildDuotoneFilterId as eM, buildEmbeddedFontStyles as eN, buildEquationElement as eO, buildEquationSegment as eP, buildFallbackViewModel as eQ, buildFontFaceRule as eR, buildGradientFillCss as eS, buildGridlinesAndLabels as eT, buildHyperlinkPatch as eU, buildInkContainerStyle as eV, buildInkStrokes as eW, buildLegend as eX, buildLiveInkStrokeView as eY, buildMarkTooltip as eZ, buildModel3DContainerStyle as e_, aiToggleVisible as ea, alignPatch as eb, animationFor as ec, animationPresetLabelKey as ed, annotationMapToInkInserts as ee, applyAcceptedDiff as ef, applyAnimationPreset as eg, applyFindReplacements as eh, applyFormatToElement as ei, applyMove as ej, applyResize as ek, asMediaElement as el, assignUserColor as em, attachShowVisibilityPause as en, attachTouchGestures as eo, axisTickValues as ep, beginDrawingNodeEdit as eq, beginNodeEdit as er, bevelSizePatch as es, boolFromEvent as et, bringForward as eu, bringToFront as ev, buildBarActions as ew, buildBroadcastConfig as ex, buildBroadcastViewerUrl as ey, buildCategoryLabels as ez, AXIS_LABEL_COLOR as f, computeErrorBarPrimitives as f$, buildOleActionModel as f0, buildOleInfoRows as f1, buildPatternFillCss as f2, buildPieViewModel as f3, buildPrintHtmlDocument as f4, buildPropertiesPatch as f5, buildRadarViewModel as f6, buildRegionMapViewModel as f7, buildSaveSlides as f8, buildShareUrl as f9, changeIcon as fA, characterSpacingPatch as fB, chartPreserveAspectRatio as fC, checkFontAvailable as fD, clampCursorPosition as fE, clampGifDimensions as fF, clampIndex as fG, clampNotesFontSize as fH, clampScale as fI, clampStep as fJ, clearAllLocalViewerData as fK, clearAudienceContent as fL, cn as fM, collectAccessibilityIssues as fN, collectElementText as fO, collectSlideText as fP, collectStoredChats as fQ, collectUsedFontFamilies as fR, columnWidthStyle as fS, commitNodeText as fT, computeAlign as fU, computeAxisTitlePrimitives as fV, computeBarRects as fW, computeBubbleRadius as fX, computeCornerHandle as fY, computeDistribute as fZ, computeDrawingViewBox as f_, buildSmartArtInsertElement as fa, buildSmartArtNodes as fb, buildStockViewModel as fc, buildSurfaceViewModel as fd, buildTableViewModel as fe, buildTreemapViewModel as ff, buildTrimFragment as fg, buildWaterfallViewModel as fh, buildZeroLine as fi, buildZoomContainerStyle as fj, buildZoomViewModel as fk, bulletIndentPx as fl, canAddTopLevelNode as fm, canEditSmartArtNodes as fn, canGroupSelection as fo, canRemoveTopLevelNode as fp, canSetStrokeWidth as fq, canStartBroadcast as fr, canStartShare as fs, canUngroupSelection as ft, canUseClipboard as fu, captionDisplayText as fv, cellRunStyle as fw, cellStyleToStyleMap as fx, cellTdStyle as fy, changeCountLabel as fz, AccessibilityPanelComponent as g, encodeGif as g$, computeFocusTargets as g0, computeGridSpacingPx as g1, computeHandleBoxes as g2, computeHandoutLayout as g3, computeIsMobile as g4, computeIsTablet as g5, computeLinePoints as g6, computeLinearRegression as g7, computePageCount as g8, computePieLayout as g9, createWebsocketBundle as gA, cssObjectToStyleMap as gB, currentColorScheme as gC, currentLayout as gD, currentStyle as gE, defaultCssVars as gF, defaultRadius as gG, defaultThemeColors as gH, deleteElementsByIds as gI, deleteVersion as gJ, demoteNode as gK, deriveModel3DBlobUrl as gL, derivePresenceList as gM, describeSmartArtBounds as gN, disableGlowPatch as gO, disableInnerShadowPatch as gP, disableOuterShadowPatch as gQ, disableReflectionPatch as gR, disableSoftEdgePatch as gS, duplicateElementById as gT, durationOf as gU, effectsStateOf as gV, enableGlowPatch as gW, enableInnerShadowPatch as gX, enableOuterShadowPatch as gY, enableReflectionPatch as gZ, enableSoftEdgePatch as g_, computePieSlicePath as ga, computePieSlices as gb, computePlotLayout as gc, computeRSquared as gd, computeRadarPoints as ge, computeResizeHandleBoxes as gf, computeRotateHandleBox as gg, computeScatterDots as gh, computeScatterXDomain as gi, computeSelectionBoxes as gj, computeSingleSelected as gk, computeSlideIndices as gl, computeSnap as gm, computeStackedBarRects as gn, computeStackedValueRange as go, computeTrendlinePrimitives as gp, computeValueRange as gq, convertOmmlToMathMl as gr, copyFormatFromElement as gs, countAccessibilityIssues as gt, countAnnotationStrokes as gu, createAngularAiBridge as gv, createCustomShow as gw, createImageElementFromFile as gx, createSwipeDismissDrag as gy, createWebrtcBundle as gz, AccessibilityService as h, gradientStateFromStyle as h$, endShowMediaCleanup as h0, estimatePageCount as h1, exitPresentationFullscreen as h2, exportAiChatLogs as h3, extractPathPoints as h4, eyedropperAvailable as h5, fillColorOf$1 as h6, findInSlides as h7, findOwningSlideIndex as h8, findSlideIndexByElementId as h9, getEffectSoundState as hA, getImageSrc as hB, getLocalStorageUsageSummary as hC, getOleAriaLabel as hD, getOleBadgeLabel as hE, getOleDisplayName as hF, getOleDownloadFileName as hG, getOleTypeColor as hH, getOleTypeLabel as hI, getP14TransitionAnimations as hJ, getPasswordStrength as hK, getPatternSvg as hL, getPlaceholderStyle as hM, getVersions as hN, getResolvedShapeClipPath as hO, getResolvedShapeClipPathFor as hP, getSessionTabId as hQ, getShapeFillStrokeStyle as hR, getSlideBackgroundStyle as hS, getSlideTransitionAnimations as hT, getSmartArtNodeBounds as hU, getSpeechRecognitionCtor as hV, getTextBlockStyle as hW, getTextWarp as hX, getTouchDistance as hY, getWarpCategory as hZ, getWarpPath as h_, firstVisibleIndex as ha, fitPolynomial as hb, fitZoom as hc, focusTargetChips as hd, fontMimeForFormat as he, fontSizeOf as hf, forgetSessionDeck as hg, formatAxisValue as hh, formatBytes as hi, formatCursorLabel as hj, formatElapsed as hk, formatFileSize as hl, formatInlineListStyle as hm, formatPropertyDate as hn, formatTime as ho, fpsToFrameIntervalMs as hp, generateBroadcastRoomId as hq, generateCommentId as hr, generateCustomShowId as hs, generatePressureCircles as ht, generateTicks as hu, getCinematicTransitionAnimations as hv, getClrChangeParams as hw, getContainerStyle as hx, getDuotoneFilterDef as hy, getEffectSoundAsset as hz, AccessibilityTextPanelComponent as i, narrowToRect as i$, gradientStateOf as i0, gradientStatePatch as i1, gradientStopColorCommitPatch as i2, gridColumns as i3, groupIssuesBySeverity as i4, hasAnimation as i5, hasCopyableFormat as i6, hasExistingLink as i7, hasExitedFullscreen as i8, hasGradientFill as i9, isValidRoomId as iA, isViewportBackgroundPressTarget as iB, isZoomActivationKey as iC, issueTrackKey as iD, issueTypeLabel as iE, keyToLabel as iF, lastVisibleIndex as iG, latexToMathml as iH, layoutConnectorPaints as iI, layoutNodeLabels as iJ, linePointsToSvgString as iK, lineSpacingPatch as iL, loadAudienceContent as iM, loadSessionDeck as iN, mediaFallbackFor as iO, mediaSurfaceFor as iP, mergeCaptionResults as iQ, mergeDown as iR, mergeRight as iS, mergeSelection as iT, mergeTablesDirective as iU, moveElementBy as iV, moveNodeDown as iW, moveNodeUp as iX, msToFrameDelayCs as iY, narrowToCircle as iZ, narrowToPolygon as i_, hasPressureVariation as ia, hasVisibleSlideAfter as ib, headerLabel as ic, imageDimensions as id, inkViewBox as ie, insertTableElementColumn as ig, insertTableElementRow as ih, interpolateWidth as ii, isAudienceTab as ij, isBold as ik, isBrowserOpenableMime as il, isChildNode as im, isElementInteractive as io, isInjectableUrl as ip, isItalic as iq, isLegacyBinaryPresentation as ir, isPpactionUrl as is, isPresenterMessage as it, isSigned as iu, isSupportedPresentationFile as iv, isTextElement as iw, isTwoTableFocus as ix, isUnderline as iy, isUrlSafe as iz, AccountPageComponent as j, removeNode as j$, newChartElement as j0, newEquationElement as j1, newPresetShapeElement as j2, newShapeElement as j3, newSmartArtElement as j4, newTableElement as j5, newTextElement as j6, nextVisibleIndex as j7, nodeBold as j8, nodeEditBox as j9, planGifFrames as jA, planVideoSegments as jB, pointFromPointerEvent as jC, pointsToSvgPathD as jD, presenceToCursors as jE, presentationBaseName as jF, presentationStageStyle as jG, presenterTimerProgress as jH, presetByLayout as jI, presetsForCategory as jJ, pressuresToWidths as jK, prevVisibleIndex as jL, projectDrawingShapes as jM, promoteNode as jN, provideViewerTheme as jO, radarAngle as jP, radarRingPoints as jQ, readAsDataUrl as jR, recordWebm as jS, registerCrossSlideAudio as jT, rememberSessionDeck as jU, removeAnimation as jV, removeCategory as jW, removeTableElementColumn as jX, removeCommentFromList as jY, removeElementAnimation as jZ, removeGradientStopPatch as j_, nodeFillColor as ja, nodeFontColor as jb, nodeIdFromKey as jc, nodeItalic as jd, nodeStyle as je, normalizeFontFormat as jf, normalizeSlidesPerPage as jg, normalizeValue as jh, numFromEvent as ji, ommlToMathml as jj, ooxmlDashToCssBorderStyle as jk, openNativeEyeDropper as jl, overallStatus as jm, paletteColor as jn, parseAudienceNonce as jo, parseNodeTextarea as jp, partitionSlides as jq, patchChartData as jr, patchChartStyle as js, patchTableData as jt, patchTextStyle as ju, patternPresetOptions as jv, pendingElementStyles as jw, pickColorByClickFallback as jx, pickFile as jy, pickSupportedMimeType as jz, ActionSettingsPanelComponent as k, setAxisLogScale as k$, removeTableElementRow as k0, removeSeries as k1, renderToCanvas as k2, reorderAnimationDown as k3, reorderAnimationUp as k4, replaceInSlides as k5, replaceMatch as k6, requestPresentationFullscreen as k7, resizeElement as k8, resolveCaptionTracks as k9, rulerHighlight as kA, rulerStripTicks as kB, sampleColorFromSlide as kC, sanitizeColor as kD, sanitizeSlideIndex as kE, sanitizeUserName as kF, saveViewerProfile as kG, savedPresentationFileName as kH, scanAvailableFonts as kI, searchSlides as kJ, seedBroadcastFields as kK, seedHyperlinkDraft as kL, seedPropertiesDraft as kM, seedShareFields as kN, segmentFrameCount as kO, selectValue$3 as kP, sendBackward as kQ, sendToBack as kR, sequentialColorScale as kS, serializeWriteBack as kT, seriesColor as kU, setAfterAnimation as kV, setAfterAnimationColor as kW, setAnimationEmphasis as kX, setAnimationEntrance as kY, setAnimationExit as kZ, setAxis as k_, resolveChartKind as ka, resolveDirection as kb, resolveDirection8 as kc, resolveFontVariant as kd, resolveHyperlinkHref as ke, resolveInteractiveElementId as kf, resolveMediaSrc as kg, resolveOleType as kh, resolveOrientation as ki, resolveParagraphBullet as kj, resolvePresenterNotes as kk, resolveProfileInitial as kl, resolveRegionCode as km, resolveRibbonCanGroup as kn, resolveSlideAutoAdvanceMs as ko, resolveSlideTransition as kp, resolvePalette as kq, resolveThemeCatalogEntry as kr, resolveTransitionDuration as ks, resolveTransitionDurationMs as kt, resolveWheelSpokeCount as ku, restoreSessionDeck as kv, revealedElementStyles as kw, routeOrthogonalConnector as kx, rowStyle as ky, rulerDragToGuidePosition as kz, AdvancedChartEditorComponent as l, textAdvancedStateFromStyle as l$, setAxisTitleStyle as l0, setCategoryLabel as l1, setCellText as l2, setColorScheme as l3, setDataLabels as l4, setDataPointExplosion as l5, setDataPointFill as l6, setDataPointLabel as l7, setDataPointMarker as l8, setDelay as l9, sheetAfterNavigate as lA, shouldBlockClickAdvance as lB, shouldUseSvgWarp as lC, showDirectionPicker as lD, showsTemplateAffordance as lE, signatureCountLabel as lF, signatureKey as lG, signatureTimestamp as lH, signerName as lI, statusLabel as lJ, slideNumberOf as lK, slidesWithReappliedLayout as lL, smartArtNodes as lM, paletteColour as lN, snapToGridStep as lO, splitCursorCell as lP, splitMergedCell as lQ, statusKind as lR, statusLabel$1 as lS, storeAudienceContent as lT, stringFromEvent$5 as lU, strokeColorOf as lV, strokeToInkElement as lW, strokeWidthOf as lX, styleShadowFilter as lY, surfaceColor as lZ, textAdvancedPatch as l_, setDirection as la, setDuration as lb, setEffectSound as lc, setEffectStockSound as ld, setElementPosition as le, setGridlineStyle as lf, setLayout as lg, setLegend as lh, setNodeStyle as li, setNodeText as lj, setRepeatCount as lk, setRepeatMode as ll, setSequence as lm, setSeriesChartType as ln, setSeriesColor as lo, setSeriesErrorBars as lp, setSeriesMarker as lq, setSeriesName as lr, setSeriesTrendline as ls, setSeriesValue as lt, setStyle as lu, setTimingCurve as lv, setTitle as lw, setTrigger as lx, setTriggerShapeId as ly, shapeStylePatch$1 as lz, AiChangeOverlayComponent as m, textAdvancedStateOf as m0, textColorOf as m1, textDirectionPatch as m2, textFontSizePatch as m3, textStyleOf as m4, textStylePatch as m5, themeStyle as m6, themeToCssVars as m7, thumbnailHeight as m8, thumbnailZoom as m9, zoomTargetSlideIndex as mA, toggleCommentResolvedInList as ma, toggleNodeBold as mb, toggleNodeItalic as mc, toggleSheet as md, topLevelNodeCount as me, transformSelectedTextCase as mf, translationsEn as mg, updateElementById as mh, updateGlowPatch as mi, updateGradientStopPatch as mj, updateInnerShadowPatch as mk, updateOuterShadowPatch as ml, updateReflectionPatch as mm, vAlignPatch as mn, validatePassword as mo, validatePrintSettings as mp, validateRoomId as mq, valueToY as mr, vermilionDarkColors as ms, vermilionDarkTheme as mt, vermilionLightColors as mu, vermilionLightTheme as mv, vermilionRadius as mw, waypointsToPathD as mx, withManualLayouts as my, worstStatus as mz, AiChatPanelComponent as n, AiChatService as o, AiComposerComponent as p, AiFocusBarComponent as q, AiFocusHighlightOverlayComponent as r, AiHistoryMenuComponent as s, toChatSummary as t, AiHistoryService as u, AiMessageListComponent as v, AiPanelStore as w, AiProposalCardComponent as x, AiSettingsSectionComponent as y, AiToolCallCardComponent as z };
|
|
186199
|
-
//# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-
|
|
187019
|
+
//# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-De1uOCxq.mjs.map
|