pptx-angular-viewer 2.10.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-BqhL79Dq.mjs → pptx-angular-viewer-chat-history-idb-DmCC3jY4.mjs} +2 -2
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-BqhL79Dq.mjs.map → pptx-angular-viewer-chat-history-idb-DmCC3jY4.mjs.map} +1 -1
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-C20L99Zu.mjs → pptx-angular-viewer-pptx-angular-viewer-DS2J9zVf.mjs} +2906 -315
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-C20L99Zu.mjs.map → pptx-angular-viewer-pptx-angular-viewer-DS2J9zVf.mjs.map} +1 -1
- package/fesm2022/pptx-angular-viewer.mjs +1 -1
- package/package.json +2 -2
- package/pptx-angular-viewer.css +1 -1
- package/types/pptx-angular-viewer.d.ts +235 -7
|
@@ -2,12 +2,12 @@ import { NgStyle, NgTemplateOutlet, NgClass } from '@angular/common';
|
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { InjectionToken, input, output, computed, ChangeDetectionStrategy, Component, signal, Injectable, inject, DestroyRef, Injector, effect, viewChild, ElementRef, HostListener, afterNextRender, Renderer2, ViewEncapsulation, forwardRef, untracked } from '@angular/core';
|
|
4
4
|
import { TranslatePipe, TranslateService, translate } from '@ngx-translate/core';
|
|
5
|
-
import { THEME_PRESETS, guideEmuToPx, getShapeClipPath, getAdjustmentAwareClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, ooxmlGradientAngleToCssDegrees, hasShapeProperties, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, isImageLikeElement, hasTextProperties, stripXmlOrderSuffix, orderedXmlKey, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, rebuildTableStructureInRawXml, updateCellTextInRawXml, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$2, getLinkedTextBoxSegments, deriveSlideTitle, getSubstituteFontFamily, svgPathToPolygons, THEME_COLOR_SCHEME_KEYS, createBuiltinVariables, resolveCoordinate, PptxHandler, deobfuscateFont, detectFontFormat, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, PptxMarkdownConverter, ThemePresets, formatCommentTimestamp as formatCommentTimestamp$1, EncryptedFileError, parseSignatureXml, cloneSlide as cloneSlide$1, cloneTemplateElementsBySlideId as cloneTemplateElementsBySlideId$1, cloneElement as cloneElement$1, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, parseDataUrlToBytes, isZoomElement, SvgExporter, applyThemeToData, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointExplosion, chartDataChangeType, getOleObjectTypeLabel, addSmartArtNodeAsChild, removeSmartArtNode, promoteSmartArtNode, demoteSmartArtNode, reorderSmartArtNode, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, TRANSITION_VALID_DIRECTIONS, getAnimationPresetInfo } from 'pptx-viewer-core';
|
|
5
|
+
import { THEME_PRESETS, guideEmuToPx, getShapeClipPath, getAdjustmentAwareClipPath, getShapeClipPathFromPreset, getCloudPathForRendering, ooxmlGradientAngleToCssDegrees, hasShapeProperties, applyDrawingColorTransforms as applyDrawingColorTransforms$1, hslToRgb as hslToRgb$1, PRESET_COLOR_MAP, isImageLikeElement, hasTextProperties, stripXmlOrderSuffix, orderedXmlKey, chartDataAddSeries, chartDataRemoveSeries, chartDataAddCategory, chartDataRemoveCategory, chartDataUpdatePoint, rebuildTableStructureInRawXml, updateCellTextInRawXml, MIN_ELEMENT_SIZE as MIN_ELEMENT_SIZE$2, getLinkedTextBoxSegments, deriveSlideTitle, getSubstituteFontFamily, svgPathToPolygons, THEME_COLOR_SCHEME_KEYS, createBuiltinVariables, resolveCoordinate, PptxHandler, deobfuscateFont, detectFontFormat, checkMissingAltText, checkMissingSlideTitle, checkLowContrast, checkComplexTables, checkBlankSlide, checkDuplicateTitles, createChartElement, PptxMarkdownConverter, ThemePresets, formatCommentTimestamp as formatCommentTimestamp$1, EncryptedFileError, parseSignatureXml, cloneSlide as cloneSlide$1, cloneTemplateElementsBySlideId as cloneTemplateElementsBySlideId$1, cloneElement as cloneElement$1, updateSmartArtNodeText, setSmartArtNodeStyle, isInkElement, parseDataUrlToBytes, isZoomElement, SvgExporter, applyThemeToData, pptxActionToElementAction, elementActionToPptxAction, setChartTitle, setChartLegend, setChartDataLabels, setChartAxis, setChartSeriesTrendline, setChartSeriesErrorBars, setChartDataPointLabel, setChartAxisLogScale, setChartAxisTitleStyle, setChartAxisGridlineStyle, setChartSeriesMarker, setChartSeriesChartType, setChartDataPointFill, setChartDataPointMarker, setChartDataPointExplosion, chartDataChangeType, getOleObjectTypeLabel, addSmartArtNodeAsChild, removeSmartArtNode, promoteSmartArtNode, demoteSmartArtNode, reorderSmartArtNode, switchSmartArtLayout, SWITCHABLE_LAYOUT_TYPES, COLOR_MAP_ALIAS_KEYS, DEFAULT_COLOR_MAP, applyThemeOverrideToSlide, TRANSITION_VALID_DIRECTIONS, getAnimationPresetInfo } from 'pptx-viewer-core';
|
|
6
6
|
import DOMPurify from 'dompurify';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import * as mcp from 'pptx-viewer-mcp';
|
|
9
9
|
import * as mcpSchemas from 'pptx-viewer-mcp/schemas';
|
|
10
|
-
import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucideLayers, LucideMessageSquare, LucidePlus, LucideSettings2, LucideStickyNote, LucideDownload, LucideMenu, LucidePresentation, LucideRedo, LucideShare2, LucideSparkles, LucideUndo, LucideChevronRight, LucidePenTool, LucideHighlighter, LucideEraser, LucideMousePointer2, LucideChevronLeft, LucideStar,
|
|
10
|
+
import { LucideX, LucideSquare, LucideCircle, LucideSlash, LucideCopy, LucideTrash2, LucideChevronsUp, LucideChevronsDown, LucideArrowUp, LucideArrowDown, LucideGroup, LucideUngroup, LucideTextAlignStart, LucideTextAlignCenter, LucideTextAlignEnd, LucideChevronUp, LucideChevronDown, LucideAlignHorizontalSpaceAround, LucideAlignVerticalSpaceAround, LucideLayers, LucideMessageSquare, LucidePlus, LucideSettings2, LucideStickyNote, LucideDownload, LucideMenu, LucidePresentation, LucideRedo, LucideShare2, LucideSparkles, LucideUndo, LucideChevronRight, LucidePenTool, LucideHighlighter, LucideEraser, LucideMousePointer2, LucideChevronLeft, LucideStar, LucideMoveRight, LucidePlay, LucideMousePointerClick, LucidePaintbrush, LucideClock3, LucidePanelRight, LucidePencil, LucideType, LucideMinus, LucideSpline, LucideArrowLeft, LucideFilePlus2, LucideFolderOpen, LucideHome, LucideInfo, LucidePrinter, LucideSave, LucideSettings, LucideUpload, LucideUserRound, LucideAArrowUp, LucideAArrowDown, LucideRemoveFormatting, LucideList, LucideListOrdered, LucideListIndentDecrease, LucideListIndentIncrease, LucideTextAlignJustify, LucideClipboardPaste, LucideFolderPlus, LucideLayoutGrid, LucideRotateCcw, LucideScissors, LucideLink, LucideImage, LucideVideo, LucideDatabase, LucidePanelLeft, LucideEllipsis, LucideEye, LucideEyeOff, LucideMonitor, LucideColumns2, LucideCheck, LucideFileDown, LucideSearch, LucideZoomIn, LucideZoomOut, LucideBug, LucideSend, LucideCrosshair, LucideGitMerge, LucidePin, LucidePinOff, LucideWrench, LucideLoaderCircle, LucideTriangleAlert, LucideShapes, LucidePalette, LucideTable, LucideLayoutTemplate, LucideChartColumn, LucideMove, LucideNavigation, LucideFilm, LucideBot, LucideUser } from '@lucide/angular';
|
|
11
11
|
import { XMLParser } from 'fast-xml-parser';
|
|
12
12
|
import JSZip from 'jszip';
|
|
13
13
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
@@ -7284,6 +7284,30 @@ function resolveDataPointExplosion(series, pointIndex) {
|
|
|
7284
7284
|
const point = findDataPoint(series, pointIndex);
|
|
7285
7285
|
return point?.explosion ?? series.explosion ?? 0;
|
|
7286
7286
|
}
|
|
7287
|
+
/**
|
|
7288
|
+
* Resolve the marker actually drawn for one data point.
|
|
7289
|
+
*
|
|
7290
|
+
* OOXML lets a `c:dPt` carry its own `c:marker`, which overrides the series
|
|
7291
|
+
* `c:ser/c:marker` for that point alone: the classic use is highlighting a
|
|
7292
|
+
* single outlier with a bigger star while the rest of the line keeps its small
|
|
7293
|
+
* circles. Every field falls back independently, matching PowerPoint: a point
|
|
7294
|
+
* marker that sets only `c:symbol` keeps the series size and fill.
|
|
7295
|
+
*
|
|
7296
|
+
* This exists because the per-point marker was a write-only feature. The core
|
|
7297
|
+
* parser read `c:dPt/c:marker`, the save writer round-tripped it, and three
|
|
7298
|
+
* bindings shipped an inspector control for it, but the renderer only ever
|
|
7299
|
+
* looked at `series.marker`, so editing a point marker changed the file and
|
|
7300
|
+
* left the canvas untouched. Resolving it here fixes every binding at once,
|
|
7301
|
+
* since they all paint the same shared view model.
|
|
7302
|
+
*/
|
|
7303
|
+
function resolveDataPointMarker(series, pointIndex) {
|
|
7304
|
+
const point = findDataPoint(series, pointIndex)?.marker;
|
|
7305
|
+
return {
|
|
7306
|
+
symbol: point?.symbol ?? series.marker?.symbol,
|
|
7307
|
+
size: point?.size ?? series.marker?.size,
|
|
7308
|
+
fill: point?.spPr?.fillColor ?? series.marker?.spPr?.fillColor,
|
|
7309
|
+
};
|
|
7310
|
+
}
|
|
7287
7311
|
|
|
7288
7312
|
/**
|
|
7289
7313
|
* chart-sparkline.ts — framework-agnostic inline mini-chart (sparkline) SVG
|
|
@@ -8619,14 +8643,22 @@ function buildMarkerPrimitive(input) {
|
|
|
8619
8643
|
/**
|
|
8620
8644
|
* Build the marker for a data point (honouring `marker.symbol`/`size`) and push
|
|
8621
8645
|
* it, unless the symbol is `none`. Shared by the line / area / scatter builders.
|
|
8646
|
+
*
|
|
8647
|
+
* `pointIndex` is the SOURCE index (the `c:idx` a `c:dPt` is keyed by), not the
|
|
8648
|
+
* display position, because a chart with hidden/filtered categories renders
|
|
8649
|
+
* fewer points than the series declares and the override must still land on the
|
|
8650
|
+
* point the author picked.
|
|
8622
8651
|
*/
|
|
8623
|
-
function pushMarker(out, series, cx, cy, fill, defaultRadius, part, opacity) {
|
|
8652
|
+
function pushMarker(out, series, pointIndex, cx, cy, fill, defaultRadius, part, opacity) {
|
|
8653
|
+
const marker = resolveDataPointMarker(series, pointIndex);
|
|
8624
8654
|
const m = buildMarkerPrimitive({
|
|
8625
|
-
symbol:
|
|
8626
|
-
size:
|
|
8655
|
+
symbol: marker.symbol,
|
|
8656
|
+
size: marker.size,
|
|
8627
8657
|
cx,
|
|
8628
8658
|
cy,
|
|
8629
|
-
fill,
|
|
8659
|
+
// A marker fill (series or per-point) wins over the plot fill, which is
|
|
8660
|
+
// what the line/area body is drawn with.
|
|
8661
|
+
fill: marker.fill ?? fill,
|
|
8630
8662
|
defaultRadius,
|
|
8631
8663
|
part,
|
|
8632
8664
|
});
|
|
@@ -8703,7 +8735,7 @@ function buildLines(chartData, catCount, layout, primaryRange, secondaryRange, s
|
|
|
8703
8735
|
}
|
|
8704
8736
|
const idx = sourceIndices[displayIndex] ?? displayIndex;
|
|
8705
8737
|
const part = { role: 'dataPoint', seriesIndex: si, pointIndex: idx };
|
|
8706
|
-
pushMarker(primitives, series, pt.x, pt.y, resolveDataPointFill(series, idx, c) ?? c, 2.5, part);
|
|
8738
|
+
pushMarker(primitives, series, idx, pt.x, pt.y, resolveDataPointFill(series, idx, c) ?? c, 2.5, part);
|
|
8707
8739
|
});
|
|
8708
8740
|
if (showLabels) {
|
|
8709
8741
|
displayValues.forEach((val, displayIndex) => {
|
|
@@ -8767,7 +8799,7 @@ function buildAreas(chartData, catCount, layout, range, sourceIndices, xPosition
|
|
|
8767
8799
|
pts.forEach((pt, displayIndex) => {
|
|
8768
8800
|
const idx = sourceIndices[displayIndex] ?? displayIndex;
|
|
8769
8801
|
const part = { role: 'dataPoint', seriesIndex: si, pointIndex: idx };
|
|
8770
|
-
pushMarker(primitives, series, pt.x, pt.y, resolveDataPointFill(series, idx, c) ?? c, 2, part);
|
|
8802
|
+
pushMarker(primitives, series, idx, pt.x, pt.y, resolveDataPointFill(series, idx, c) ?? c, 2, part);
|
|
8771
8803
|
});
|
|
8772
8804
|
if (showLabels) {
|
|
8773
8805
|
displayValues.forEach((val, displayIndex) => {
|
|
@@ -8803,7 +8835,7 @@ function buildScatter(chartData, layout, range) {
|
|
|
8803
8835
|
const dots = computeScatterDots(series.values, maxXIndex, layout, range, xValues);
|
|
8804
8836
|
dots.forEach((dot, vi) => {
|
|
8805
8837
|
const part = { role: 'dataPoint', seriesIndex: si, pointIndex: vi };
|
|
8806
|
-
pushMarker(primitives, series, dot.cx, dot.cy, resolveDataPointFill(series, vi, c) ?? c, 4, part, 0.85);
|
|
8838
|
+
pushMarker(primitives, series, vi, dot.cx, dot.cy, resolveDataPointFill(series, vi, c) ?? c, 4, part, 0.85);
|
|
8807
8839
|
});
|
|
8808
8840
|
if (showLabels) {
|
|
8809
8841
|
series.values.forEach((val, vi) => {
|
|
@@ -14591,7 +14623,7 @@ const DIRECTIONAL_PRESETS = new Set([
|
|
|
14591
14623
|
// Defaults for a freshly-created animation entry
|
|
14592
14624
|
// ==========================================================================
|
|
14593
14625
|
const DEFAULT_DURATION_MS$1 = 500;
|
|
14594
|
-
const DEFAULT_TRIGGER = 'onClick';
|
|
14626
|
+
const DEFAULT_TRIGGER$1 = 'onClick';
|
|
14595
14627
|
// ==========================================================================
|
|
14596
14628
|
// Readers
|
|
14597
14629
|
// ==========================================================================
|
|
@@ -14604,11 +14636,15 @@ function animationFor(slideAnimations, elementId) {
|
|
|
14604
14636
|
}
|
|
14605
14637
|
/**
|
|
14606
14638
|
* Returns `true` when the element has at least one active effect (entrance,
|
|
14607
|
-
* exit, or
|
|
14639
|
+
* exit, emphasis, or a motion path) in the slide's animation list.
|
|
14640
|
+
*
|
|
14641
|
+
* The motion path counts because it is driven by the same entry's timing
|
|
14642
|
+
* fields: without it, a motion-path-only element would hide its own
|
|
14643
|
+
* duration / delay / trigger controls.
|
|
14608
14644
|
*/
|
|
14609
14645
|
function hasAnimation(slideAnimations, elementId) {
|
|
14610
14646
|
const entry = animationFor(slideAnimations, elementId);
|
|
14611
|
-
return Boolean(entry && (entry.entrance || entry.exit || entry.emphasis));
|
|
14647
|
+
return Boolean(entry && (entry.entrance || entry.exit || entry.emphasis || entry.motionPath));
|
|
14612
14648
|
}
|
|
14613
14649
|
/**
|
|
14614
14650
|
* Returns `true` when the active animation entry has a preset that supports
|
|
@@ -14644,7 +14680,7 @@ function upsert(anims, elementId, updater) {
|
|
|
14644
14680
|
elementId,
|
|
14645
14681
|
durationMs: DEFAULT_DURATION_MS$1,
|
|
14646
14682
|
order: anims.length,
|
|
14647
|
-
trigger: DEFAULT_TRIGGER,
|
|
14683
|
+
trigger: DEFAULT_TRIGGER$1,
|
|
14648
14684
|
};
|
|
14649
14685
|
const updated = updater(created);
|
|
14650
14686
|
if (updated === null) {
|
|
@@ -14656,7 +14692,9 @@ function setEffect(anims, elementId, group, preset) {
|
|
|
14656
14692
|
const value = preset === 'none' ? undefined : preset;
|
|
14657
14693
|
return upsert(anims, elementId, (cur) => {
|
|
14658
14694
|
const next = { ...cur, [group]: value };
|
|
14659
|
-
|
|
14695
|
+
// A motion path keeps the entry alive: clearing the entrance preset must
|
|
14696
|
+
// not silently delete the path the user drew on the canvas.
|
|
14697
|
+
if (!next.entrance && !next.exit && !next.emphasis && !next.motionPath) {
|
|
14660
14698
|
return null;
|
|
14661
14699
|
}
|
|
14662
14700
|
return next;
|
|
@@ -14785,7 +14823,7 @@ function applyAnimationPreset(animations, elementId, group, preset) {
|
|
|
14785
14823
|
[group]: preset,
|
|
14786
14824
|
durationMs: DEFAULT_DURATION_MS$1,
|
|
14787
14825
|
order: animations.length,
|
|
14788
|
-
trigger: DEFAULT_TRIGGER,
|
|
14826
|
+
trigger: DEFAULT_TRIGGER$1,
|
|
14789
14827
|
},
|
|
14790
14828
|
];
|
|
14791
14829
|
}
|
|
@@ -16026,6 +16064,23 @@ function applyFlyDirection(effect, subtype) {
|
|
|
16026
16064
|
// ==========================================================================
|
|
16027
16065
|
// Dynamic keyframe generation (motion path / rotation / scale / colour)
|
|
16028
16066
|
// ==========================================================================
|
|
16067
|
+
/**
|
|
16068
|
+
* Express one motion-path coordinate as a CSS length measured against the SLIDE.
|
|
16069
|
+
*
|
|
16070
|
+
* OOXML motion-path numbers are fractions of the slide, but a CSS
|
|
16071
|
+
* `translate(%)` resolves against the ELEMENT's own box, so every parsed path
|
|
16072
|
+
* used to under-travel by the ratio between the two (a small shape barely
|
|
16073
|
+
* moved). The offset is therefore emitted as `calc(var(--pptx-slide-w) * f)`;
|
|
16074
|
+
* a binding sets those custom properties on its slide stage, and the fallback
|
|
16075
|
+
* is the default canvas size so an unset stage still travels a sane distance.
|
|
16076
|
+
*
|
|
16077
|
+
* @param percent - Sampled coordinate in percent-of-slide units (path * 100).
|
|
16078
|
+
* @param axis - `w` for the horizontal offset, `h` for the vertical one.
|
|
16079
|
+
*/
|
|
16080
|
+
function slideOffset(percent, axis) {
|
|
16081
|
+
const fallback = axis === 'w' ? '1280px' : '720px';
|
|
16082
|
+
return `calc(var(--pptx-slide-${axis}, ${fallback}) * ${(percent / 100).toFixed(4)})`;
|
|
16083
|
+
}
|
|
16029
16084
|
/**
|
|
16030
16085
|
* Build a dynamic CSS `@keyframes` block for motion path, rotation, scale, or
|
|
16031
16086
|
* colour animations that don't map to a static effect preset. Uses the
|
|
@@ -16043,7 +16098,7 @@ function buildDynamicKeyframes(anim, uid) {
|
|
|
16043
16098
|
const kfLines = [];
|
|
16044
16099
|
for (let i = 0; i < points.length; i++) {
|
|
16045
16100
|
const pct = Math.round((i / (points.length - 1)) * 100);
|
|
16046
|
-
kfLines.push(`\t${pct}% { transform: translate(${points[i].x
|
|
16101
|
+
kfLines.push(`\t${pct}% { transform: translate(${slideOffset(points[i].x, 'w')}, ${slideOffset(points[i].y, 'h')}); }`);
|
|
16047
16102
|
}
|
|
16048
16103
|
return {
|
|
16049
16104
|
keyframeName: name,
|
|
@@ -16102,8 +16157,8 @@ function buildDynamicKeyframe(anim, uid) {
|
|
|
16102
16157
|
const lines = [];
|
|
16103
16158
|
for (let i = 0; i < points.length; i++) {
|
|
16104
16159
|
const pct = Math.round((i / (points.length - 1)) * 100);
|
|
16105
|
-
const tx = points[i].x
|
|
16106
|
-
const ty = points[i].y
|
|
16160
|
+
const tx = slideOffset(points[i].x, 'w');
|
|
16161
|
+
const ty = slideOffset(points[i].y, 'h');
|
|
16107
16162
|
if (anim.motionPathRotateAuto) {
|
|
16108
16163
|
// Compute the tangent angle at this point using the direction
|
|
16109
16164
|
// to the next point (or from the previous point for the last one).
|
|
@@ -16112,10 +16167,10 @@ function buildDynamicKeyframe(anim, uid) {
|
|
|
16112
16167
|
const dx = i < points.length - 1 ? next.x - points[i].x : points[i].x - prev.x;
|
|
16113
16168
|
const dy = i < points.length - 1 ? next.y - points[i].y : points[i].y - prev.y;
|
|
16114
16169
|
const angleDeg = Math.atan2(dy, dx) * (180 / Math.PI);
|
|
16115
|
-
lines.push(`\t${pct}% { transform: translate(${tx}
|
|
16170
|
+
lines.push(`\t${pct}% { transform: translate(${tx}, ${ty}) rotate(${angleDeg.toFixed(2)}deg); }`);
|
|
16116
16171
|
}
|
|
16117
16172
|
else {
|
|
16118
|
-
lines.push(`\t${pct}% { transform: translate(${tx}
|
|
16173
|
+
lines.push(`\t${pct}% { transform: translate(${tx}, ${ty}); }`);
|
|
16119
16174
|
}
|
|
16120
16175
|
}
|
|
16121
16176
|
return {
|
|
@@ -17877,6 +17932,662 @@ class TimelineEngine {
|
|
|
17877
17932
|
}
|
|
17878
17933
|
}
|
|
17879
17934
|
|
|
17935
|
+
/**
|
|
17936
|
+
* `animation-preview` — pure preview-descriptor construction for the editor's
|
|
17937
|
+
* animation panel: map an editor preset (+ direction / timing) to a CSS
|
|
17938
|
+
* keyframe name, definition and shorthand. The DOM player that injects the
|
|
17939
|
+
* `<style>` and toggles the element animation stays in each binding.
|
|
17940
|
+
*
|
|
17941
|
+
* @module render/animation-preview
|
|
17942
|
+
*/
|
|
17943
|
+
// ==========================================================================
|
|
17944
|
+
// Preview keyframes generation
|
|
17945
|
+
// ==========================================================================
|
|
17946
|
+
/** Map editor-level animation presets to the internal effect names used by
|
|
17947
|
+
* the keyframe definition table. */
|
|
17948
|
+
const PRESET_TO_EFFECT = {
|
|
17949
|
+
fadeIn: 'fadeIn',
|
|
17950
|
+
flyIn: 'flyInBottom',
|
|
17951
|
+
zoomIn: 'zoomIn',
|
|
17952
|
+
fadeOut: 'fadeOut',
|
|
17953
|
+
flyOut: 'flyOutBottom',
|
|
17954
|
+
zoomOut: 'zoomOut',
|
|
17955
|
+
spin: 'spin',
|
|
17956
|
+
pulse: 'pulse',
|
|
17957
|
+
colorWave: 'colorWave',
|
|
17958
|
+
bounce: 'bounce',
|
|
17959
|
+
flash: 'flash',
|
|
17960
|
+
};
|
|
17961
|
+
/** Direction-aware fly-in/out effect name overrides. */
|
|
17962
|
+
const DIRECTION_FLY_MAP = {
|
|
17963
|
+
fromLeft: { flyIn: 'flyInLeft', flyOut: 'flyOutLeft' },
|
|
17964
|
+
fromRight: { flyIn: 'flyInRight', flyOut: 'flyOutRight' },
|
|
17965
|
+
fromTop: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
17966
|
+
fromBottom: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
17967
|
+
fromTopLeft: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
17968
|
+
fromTopRight: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
17969
|
+
fromBottomLeft: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
17970
|
+
fromBottomRight: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
17971
|
+
};
|
|
17972
|
+
/**
|
|
17973
|
+
* Resolve the CSS @keyframes effect name for a given preset and direction.
|
|
17974
|
+
*/
|
|
17975
|
+
function resolvePreviewEffect(preset, direction) {
|
|
17976
|
+
if ((preset === 'flyIn' || preset === 'flyOut') && direction) {
|
|
17977
|
+
const dirMap = DIRECTION_FLY_MAP[direction];
|
|
17978
|
+
if (dirMap) {
|
|
17979
|
+
return preset === 'flyIn' ? dirMap.flyIn : dirMap.flyOut;
|
|
17980
|
+
}
|
|
17981
|
+
}
|
|
17982
|
+
return PRESET_TO_EFFECT[preset];
|
|
17983
|
+
}
|
|
17984
|
+
/**
|
|
17985
|
+
* Map a timing curve name to a CSS easing string.
|
|
17986
|
+
* Supports the standard OOXML timing curves plus cubic-bezier extraction.
|
|
17987
|
+
*/
|
|
17988
|
+
function timingCurveToCss(curve, cubicBezierValues) {
|
|
17989
|
+
if (cubicBezierValues) {
|
|
17990
|
+
// Validate cubic-bezier format: "x1,y1,x2,y2"
|
|
17991
|
+
const parts = cubicBezierValues.split(',').map((s) => s.trim());
|
|
17992
|
+
if (parts.length === 4 && parts.every((p) => !Number.isNaN(Number(p)))) {
|
|
17993
|
+
return `cubic-bezier(${parts.join(', ')})`;
|
|
17994
|
+
}
|
|
17995
|
+
}
|
|
17996
|
+
switch (curve) {
|
|
17997
|
+
case 'ease':
|
|
17998
|
+
return 'ease';
|
|
17999
|
+
case 'ease-in':
|
|
18000
|
+
return 'ease-in';
|
|
18001
|
+
case 'ease-out':
|
|
18002
|
+
return 'ease-out';
|
|
18003
|
+
case 'linear':
|
|
18004
|
+
return 'linear';
|
|
18005
|
+
default:
|
|
18006
|
+
return 'ease';
|
|
18007
|
+
}
|
|
18008
|
+
}
|
|
18009
|
+
/**
|
|
18010
|
+
* Build a preview animation descriptor for a given preset.
|
|
18011
|
+
*
|
|
18012
|
+
* Returns `undefined` if the preset doesn't have a known effect.
|
|
18013
|
+
*/
|
|
18014
|
+
function buildPreviewAnimation(preset, options) {
|
|
18015
|
+
if (preset === 'none') {
|
|
18016
|
+
return undefined;
|
|
18017
|
+
}
|
|
18018
|
+
const effectName = resolvePreviewEffect(preset, options?.direction);
|
|
18019
|
+
if (!effectName) {
|
|
18020
|
+
return undefined;
|
|
18021
|
+
}
|
|
18022
|
+
const keyframeName = `pptx-${effectName}`;
|
|
18023
|
+
const keyframesCss = getEffectKeyframes(effectName);
|
|
18024
|
+
if (!keyframesCss) {
|
|
18025
|
+
return undefined;
|
|
18026
|
+
}
|
|
18027
|
+
const duration = options?.durationMs ?? 600;
|
|
18028
|
+
const easing = timingCurveToCss(options?.timingCurve, options?.cubicBezier);
|
|
18029
|
+
return {
|
|
18030
|
+
keyframeName,
|
|
18031
|
+
keyframesCss,
|
|
18032
|
+
cssAnimation: `${keyframeName} ${duration}ms ${easing} 0ms 1 normal both`,
|
|
18033
|
+
durationMs: duration,
|
|
18034
|
+
};
|
|
18035
|
+
}
|
|
18036
|
+
// ==========================================================================
|
|
18037
|
+
// Timing curve extraction from OOXML bezier values
|
|
18038
|
+
// ==========================================================================
|
|
18039
|
+
/**
|
|
18040
|
+
* Parse OOXML timing curve bezier values from `a:cTn/a:timing/a:curve`.
|
|
18041
|
+
*
|
|
18042
|
+
* OOXML stores bezier control points as attributes:
|
|
18043
|
+
* - `x1`, `y1` — first control point (0..100000 range)
|
|
18044
|
+
* - `x2`, `y2` — second control point (0..100000 range)
|
|
18045
|
+
*
|
|
18046
|
+
* Returns a CSS `cubic-bezier()` string, or undefined if not parseable.
|
|
18047
|
+
*/
|
|
18048
|
+
function parseOoxmlBezierCurve(x1, y1, x2, y2) {
|
|
18049
|
+
if (x1 === undefined || y1 === undefined || x2 === undefined || y2 === undefined) {
|
|
18050
|
+
return undefined;
|
|
18051
|
+
}
|
|
18052
|
+
// OOXML values are in 0..100000 range, CSS cubic-bezier uses 0..1
|
|
18053
|
+
const cx1 = Math.max(0, Math.min(1, x1 / 100000));
|
|
18054
|
+
const cy1 = y1 / 100000; // y can exceed 0..1 range for overshoot
|
|
18055
|
+
const cx2 = Math.max(0, Math.min(1, x2 / 100000));
|
|
18056
|
+
const cy2 = y2 / 100000;
|
|
18057
|
+
return `${cx1.toFixed(4)},${cy1.toFixed(4)},${cx2.toFixed(4)},${cy2.toFixed(4)}`;
|
|
18058
|
+
}
|
|
18059
|
+
|
|
18060
|
+
/**
|
|
18061
|
+
* `motion-path-geometry`: turn an OOXML motion path into the things the
|
|
18062
|
+
* authoring UI needs - an SVG outline to draw over the canvas, the draggable
|
|
18063
|
+
* start/end handles, an edited path string after a drag, and the `@keyframes`
|
|
18064
|
+
* block that plays the motion.
|
|
18065
|
+
*
|
|
18066
|
+
* WHY this is separate from `animation-motion-path`: that module samples a path
|
|
18067
|
+
* into waypoints for the native-timeline playback engine and expresses them as
|
|
18068
|
+
* percentages of the element box. Authoring needs the *slide* space PowerPoint
|
|
18069
|
+
* actually stores (`@path` numbers are fractions of the slide, measured from
|
|
18070
|
+
* the element centre), plus the ability to write a modified path back out. Both
|
|
18071
|
+
* share the sampler; only this module knows about pixels and editing.
|
|
18072
|
+
*
|
|
18073
|
+
* @module render/motion-path-geometry
|
|
18074
|
+
*/
|
|
18075
|
+
/** Commands this module can rewrite. Anything else makes a path read-only. */
|
|
18076
|
+
const EDITABLE = new Set(['M', 'L', 'C', 'Z', 'm', 'l', 'c', 'z']);
|
|
18077
|
+
/** Coordinate count per command letter. */
|
|
18078
|
+
const ARITY = { m: 2, l: 2, c: 6, z: 0 };
|
|
18079
|
+
/**
|
|
18080
|
+
* Tokenise a path into segments. Returns `undefined` when the path contains a
|
|
18081
|
+
* command this module cannot faithfully rewrite (arcs, quadratics, PowerPoint's
|
|
18082
|
+
* trailing `E` marker), so callers can fall back to read-only behaviour instead
|
|
18083
|
+
* of silently corrupting the geometry.
|
|
18084
|
+
*/
|
|
18085
|
+
function scanPath(path) {
|
|
18086
|
+
const tokens = path.match(/[A-Za-z]|-?\d*\.?\d+(?:[eE][-+]?\d+)?/gu);
|
|
18087
|
+
if (!tokens) {
|
|
18088
|
+
return undefined;
|
|
18089
|
+
}
|
|
18090
|
+
const segments = [];
|
|
18091
|
+
let i = 0;
|
|
18092
|
+
let cmd = '';
|
|
18093
|
+
while (i < tokens.length) {
|
|
18094
|
+
if (/^[A-Za-z]$/u.test(tokens[i])) {
|
|
18095
|
+
cmd = tokens[i];
|
|
18096
|
+
i++;
|
|
18097
|
+
if (!EDITABLE.has(cmd)) {
|
|
18098
|
+
return undefined;
|
|
18099
|
+
}
|
|
18100
|
+
if (cmd === 'Z' || cmd === 'z') {
|
|
18101
|
+
segments.push({ cmd, coords: [] });
|
|
18102
|
+
}
|
|
18103
|
+
continue;
|
|
18104
|
+
}
|
|
18105
|
+
const arity = ARITY[cmd.toLowerCase()];
|
|
18106
|
+
if (!arity) {
|
|
18107
|
+
return undefined;
|
|
18108
|
+
}
|
|
18109
|
+
const coords = [];
|
|
18110
|
+
for (let n = 0; n < arity; n++) {
|
|
18111
|
+
const value = Number(tokens[i++]);
|
|
18112
|
+
if (!Number.isFinite(value)) {
|
|
18113
|
+
return undefined;
|
|
18114
|
+
}
|
|
18115
|
+
coords.push(value);
|
|
18116
|
+
}
|
|
18117
|
+
segments.push({ cmd, coords });
|
|
18118
|
+
// A repeated coordinate run after `M` is an implicit lineto, as in SVG.
|
|
18119
|
+
if (cmd === 'M') {
|
|
18120
|
+
cmd = 'L';
|
|
18121
|
+
}
|
|
18122
|
+
else if (cmd === 'm') {
|
|
18123
|
+
cmd = 'l';
|
|
18124
|
+
}
|
|
18125
|
+
}
|
|
18126
|
+
return segments.length > 0 ? segments : undefined;
|
|
18127
|
+
}
|
|
18128
|
+
/** Render segments back to a path string, trimming float noise. */
|
|
18129
|
+
function formatPath(segments) {
|
|
18130
|
+
return segments
|
|
18131
|
+
.map((segment) => segment.coords.length === 0
|
|
18132
|
+
? segment.cmd
|
|
18133
|
+
: `${segment.cmd} ${segment.coords.map((n) => trimNumber(n)).join(' ')}`)
|
|
18134
|
+
.join(' ');
|
|
18135
|
+
}
|
|
18136
|
+
/** Format a coordinate with at most 4 decimals and no trailing zeros. */
|
|
18137
|
+
function trimNumber(value) {
|
|
18138
|
+
return String(Number(value.toFixed(4)));
|
|
18139
|
+
}
|
|
18140
|
+
/**
|
|
18141
|
+
* Sample the path into points expressed as slide fractions relative to the
|
|
18142
|
+
* element centre (the same space the path string uses).
|
|
18143
|
+
*/
|
|
18144
|
+
function motionPathFractionPoints(path) {
|
|
18145
|
+
// `parseMotionPathPoints` returns percentages; authoring works in fractions.
|
|
18146
|
+
return parseMotionPathPoints(path).map((point) => ({ x: point.x / 100, y: point.y / 100 }));
|
|
18147
|
+
}
|
|
18148
|
+
/** Convert a fraction-space point to slide pixels within `frame`. */
|
|
18149
|
+
function toPixels(point, frame) {
|
|
18150
|
+
return {
|
|
18151
|
+
x: frame.originX + point.x * frame.slideWidth,
|
|
18152
|
+
y: frame.originY + point.y * frame.slideHeight,
|
|
18153
|
+
};
|
|
18154
|
+
}
|
|
18155
|
+
/**
|
|
18156
|
+
* Build an SVG `d` attribute (slide pixels) tracing the motion the element will
|
|
18157
|
+
* make, so the canvas can draw the path where the shape will travel.
|
|
18158
|
+
*/
|
|
18159
|
+
function motionPathToSvgD(path, frame) {
|
|
18160
|
+
const points = motionPathFractionPoints(path).map((point) => toPixels(point, frame));
|
|
18161
|
+
if (points.length === 0) {
|
|
18162
|
+
return '';
|
|
18163
|
+
}
|
|
18164
|
+
const head = `M ${trimNumber(frame.originX)} ${trimNumber(frame.originY)}`;
|
|
18165
|
+
const rest = points.map((point) => `L ${trimNumber(point.x)} ${trimNumber(point.y)}`);
|
|
18166
|
+
return [head, ...rest].join(' ');
|
|
18167
|
+
}
|
|
18168
|
+
/** The path's final waypoint in slide pixels (the draggable end handle). */
|
|
18169
|
+
function motionPathEndPixel(path, frame) {
|
|
18170
|
+
const points = motionPathFractionPoints(path);
|
|
18171
|
+
// Indexed rather than `.at(-1)`: Angular vendors this file and compiles it
|
|
18172
|
+
// against an ES2021 lib, where `Array.prototype.at` does not exist.
|
|
18173
|
+
const last = points.length > 0 ? points[points.length - 1] : undefined;
|
|
18174
|
+
return last ? toPixels(last, frame) : { x: frame.originX, y: frame.originY };
|
|
18175
|
+
}
|
|
18176
|
+
/** The path's final waypoint in slide fractions. */
|
|
18177
|
+
function motionPathEndFraction(path) {
|
|
18178
|
+
// Indexed rather than `.at(-1)`: see the note in {@link motionPathEndPixel}.
|
|
18179
|
+
const points = motionPathFractionPoints(path);
|
|
18180
|
+
return points.length > 0 ? points[points.length - 1] : { x: 0, y: 0 };
|
|
18181
|
+
}
|
|
18182
|
+
/**
|
|
18183
|
+
* Move the path's end point to `(x, y)` (slide fractions), returning a new path
|
|
18184
|
+
* string. The last drawn command's endpoint is rewritten; a bezier's control
|
|
18185
|
+
* handles shift with it so the curve keeps its shape instead of kinking.
|
|
18186
|
+
* Returns the input unchanged for closed or unparseable paths, which have no
|
|
18187
|
+
* meaningful free end.
|
|
18188
|
+
*/
|
|
18189
|
+
function setMotionPathEnd(path, x, y) {
|
|
18190
|
+
const segments = scanPath(path);
|
|
18191
|
+
if (!segments) {
|
|
18192
|
+
return path;
|
|
18193
|
+
}
|
|
18194
|
+
// Reverse scan rather than `findLastIndex`: Angular vendors this file and
|
|
18195
|
+
// compiles it against an ES2021 lib, where that method does not exist.
|
|
18196
|
+
let lastIndex = -1;
|
|
18197
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
18198
|
+
if (segments[i].coords.length > 0) {
|
|
18199
|
+
lastIndex = i;
|
|
18200
|
+
break;
|
|
18201
|
+
}
|
|
18202
|
+
}
|
|
18203
|
+
if (lastIndex < 0 || segments.some((segment) => segment.cmd === 'Z' || segment.cmd === 'z')) {
|
|
18204
|
+
return path;
|
|
18205
|
+
}
|
|
18206
|
+
const last = segments[lastIndex];
|
|
18207
|
+
if (last.cmd === last.cmd.toLowerCase()) {
|
|
18208
|
+
// Relative commands would need the running cursor; not worth the risk.
|
|
18209
|
+
return path;
|
|
18210
|
+
}
|
|
18211
|
+
const coords = [...last.coords];
|
|
18212
|
+
const endX = coords[coords.length - 2];
|
|
18213
|
+
const endY = coords[coords.length - 1];
|
|
18214
|
+
const dx = x - endX;
|
|
18215
|
+
const dy = y - endY;
|
|
18216
|
+
coords[coords.length - 2] = x;
|
|
18217
|
+
coords[coords.length - 1] = y;
|
|
18218
|
+
if (last.cmd === 'C') {
|
|
18219
|
+
// Drag the trailing control point along so the tangent is preserved.
|
|
18220
|
+
coords[2] += dx;
|
|
18221
|
+
coords[3] += dy;
|
|
18222
|
+
}
|
|
18223
|
+
const next = segments.map((segment, index) => index === lastIndex ? { ...last, coords } : segment);
|
|
18224
|
+
return formatPath(next);
|
|
18225
|
+
}
|
|
18226
|
+
/**
|
|
18227
|
+
* Shift every absolute coordinate by `(dx, dy)` slide fractions: the "drag the
|
|
18228
|
+
* whole path" gesture. Relative commands are deltas and stay untouched.
|
|
18229
|
+
*/
|
|
18230
|
+
function translateMotionPath(path, dx, dy) {
|
|
18231
|
+
const segments = scanPath(path);
|
|
18232
|
+
if (!segments) {
|
|
18233
|
+
return path;
|
|
18234
|
+
}
|
|
18235
|
+
const moved = segments.map((segment) => {
|
|
18236
|
+
if (segment.cmd === segment.cmd.toLowerCase() || segment.coords.length === 0) {
|
|
18237
|
+
return segment;
|
|
18238
|
+
}
|
|
18239
|
+
return {
|
|
18240
|
+
cmd: segment.cmd,
|
|
18241
|
+
coords: segment.coords.map((value, index) => (index % 2 === 0 ? value + dx : value + dy)),
|
|
18242
|
+
};
|
|
18243
|
+
});
|
|
18244
|
+
return formatPath(moved);
|
|
18245
|
+
}
|
|
18246
|
+
/** Whether a path can be edited by {@link setMotionPathEnd} / drag handles. */
|
|
18247
|
+
function isEditableMotionPath(path) {
|
|
18248
|
+
const segments = scanPath(path);
|
|
18249
|
+
if (!segments) {
|
|
18250
|
+
return false;
|
|
18251
|
+
}
|
|
18252
|
+
return !segments.some((segment) => segment.cmd === 'Z' || segment.cmd === 'z');
|
|
18253
|
+
}
|
|
18254
|
+
/**
|
|
18255
|
+
* Build the `@keyframes` block that plays a motion path.
|
|
18256
|
+
*
|
|
18257
|
+
* WHY pixels and not percentages: a CSS `translate(%)` resolves against the
|
|
18258
|
+
* ELEMENT's own box, while the path is a fraction of the SLIDE. A 25%-of-slide
|
|
18259
|
+
* move on a small shape would otherwise travel a fraction of the intended
|
|
18260
|
+
* distance, so the frame's slide size is baked in here.
|
|
18261
|
+
*/
|
|
18262
|
+
function buildMotionPathKeyframes(args) {
|
|
18263
|
+
const points = motionPathFractionPoints(args.path);
|
|
18264
|
+
if (points.length < 2) {
|
|
18265
|
+
return undefined;
|
|
18266
|
+
}
|
|
18267
|
+
const frames = points.map((point, index) => {
|
|
18268
|
+
const percent = Math.round((index / (points.length - 1)) * 100);
|
|
18269
|
+
const x = trimNumber(point.x * args.slideWidth);
|
|
18270
|
+
const y = trimNumber(point.y * args.slideHeight);
|
|
18271
|
+
return `\t${percent}% { transform: translate(${x}px, ${y}px); }`;
|
|
18272
|
+
});
|
|
18273
|
+
return {
|
|
18274
|
+
keyframeName: args.keyframeName,
|
|
18275
|
+
css: `@keyframes ${args.keyframeName} {\n${frames.join('\n')}\n}`,
|
|
18276
|
+
};
|
|
18277
|
+
}
|
|
18278
|
+
|
|
18279
|
+
/**
|
|
18280
|
+
* `motion-path-presets`: the authoring catalogue of PowerPoint motion-path
|
|
18281
|
+
* effects (Lines, Arcs, Turns, Shapes, Loops).
|
|
18282
|
+
*
|
|
18283
|
+
* WHY a path string and not a preset id: OOXML carries a motion path as free
|
|
18284
|
+
* form geometry in `p:animMotion/@path`; the integer `presetID` on a `path`
|
|
18285
|
+
* class node is informational and is NOT how PowerPoint reconstructs the
|
|
18286
|
+
* curve. So a preset here is a *named path string*, and applying one simply
|
|
18287
|
+
* writes that string onto the element's animation. Anything the user then
|
|
18288
|
+
* drags stays representable, and a deck authored elsewhere round-trips through
|
|
18289
|
+
* the same field.
|
|
18290
|
+
*
|
|
18291
|
+
* Coordinate space: the numbers are fractions of the SLIDE box, measured from
|
|
18292
|
+
* the animated element's own centre (`pathEditMode="relative"`), which is what
|
|
18293
|
+
* PowerPoint emits. `0.25 0` means "a quarter of the slide width to the right
|
|
18294
|
+
* of where the shape sits". Keeping the catalogue in the wire units means no
|
|
18295
|
+
* conversion happens on apply or save, only on render.
|
|
18296
|
+
*
|
|
18297
|
+
* The shapes/loops use x fractions of 0.125 against y fractions of 0.2222 so
|
|
18298
|
+
* they read as visually round on the 16:9 canvas the viewer renders at
|
|
18299
|
+
* (0.125 * 1280 === 0.2222 * 720 === 160 px).
|
|
18300
|
+
*
|
|
18301
|
+
* @module render/motion-path-presets
|
|
18302
|
+
*/
|
|
18303
|
+
/** Bezier handle length for a circular quadrant (4/3 * tan(pi/8)). */
|
|
18304
|
+
const K = 0.5523;
|
|
18305
|
+
/** Half-extents used by the closed shapes, equal in rendered pixels on 16:9. */
|
|
18306
|
+
const RX = 0.125;
|
|
18307
|
+
const RY = 0.2222;
|
|
18308
|
+
const CIRCLE = [
|
|
18309
|
+
'M 0 0',
|
|
18310
|
+
`C ${-K * RX} 0 ${-RX} ${-RY + K * RY} ${-RX} ${-RY}`,
|
|
18311
|
+
`C ${-RX} ${-RY - K * RY} ${-K * RX} ${-2 * RY} 0 ${-2 * RY}`,
|
|
18312
|
+
`C ${K * RX} ${-2 * RY} ${RX} ${-RY - K * RY} ${RX} ${-RY}`,
|
|
18313
|
+
`C ${RX} ${-RY + K * RY} ${K * RX} 0 0 0`,
|
|
18314
|
+
]
|
|
18315
|
+
.join(' ')
|
|
18316
|
+
.replace(/(\d\.\d{4})\d+/gu, '$1');
|
|
18317
|
+
/**
|
|
18318
|
+
* Every motion-path preset, grouped by family in gallery order. Lines travel a
|
|
18319
|
+
* quarter of the slide, matching the distance PowerPoint's own line presets use
|
|
18320
|
+
* for a shape dropped near the middle of a slide.
|
|
18321
|
+
*/
|
|
18322
|
+
const MOTION_PATH_PRESETS = [
|
|
18323
|
+
// -- Lines ---------------------------------------------------------------
|
|
18324
|
+
{ id: 'lineRight', family: 'lines', path: 'M 0 0 L 0.25 0' },
|
|
18325
|
+
{ id: 'lineLeft', family: 'lines', path: 'M 0 0 L -0.25 0' },
|
|
18326
|
+
{ id: 'lineDown', family: 'lines', path: 'M 0 0 L 0 0.25' },
|
|
18327
|
+
{ id: 'lineUp', family: 'lines', path: 'M 0 0 L 0 -0.25' },
|
|
18328
|
+
{ id: 'lineDiagonalUpRight', family: 'lines', path: 'M 0 0 L 0.25 -0.25' },
|
|
18329
|
+
{ id: 'lineDiagonalDownRight', family: 'lines', path: 'M 0 0 L 0.25 0.25' },
|
|
18330
|
+
{ id: 'lineDiagonalUpLeft', family: 'lines', path: 'M 0 0 L -0.25 -0.25' },
|
|
18331
|
+
{ id: 'lineDiagonalDownLeft', family: 'lines', path: 'M 0 0 L -0.25 0.25' },
|
|
18332
|
+
// -- Arcs ----------------------------------------------------------------
|
|
18333
|
+
{
|
|
18334
|
+
id: 'arcUp',
|
|
18335
|
+
family: 'arcs',
|
|
18336
|
+
path: 'M 0 0 C 0 -0.1227 0.0559 -0.2222 0.125 -0.2222 C 0.1941 -0.2222 0.25 -0.1227 0.25 0',
|
|
18337
|
+
},
|
|
18338
|
+
{
|
|
18339
|
+
id: 'arcDown',
|
|
18340
|
+
family: 'arcs',
|
|
18341
|
+
path: 'M 0 0 C 0 0.1227 0.0559 0.2222 0.125 0.2222 C 0.1941 0.2222 0.25 0.1227 0.25 0',
|
|
18342
|
+
},
|
|
18343
|
+
{
|
|
18344
|
+
id: 'arcRight',
|
|
18345
|
+
family: 'arcs',
|
|
18346
|
+
path: 'M 0 0 C 0.069 0 0.125 0.0995 0.125 0.2222 C 0.125 0.3449 0.069 0.4444 0 0.4444',
|
|
18347
|
+
},
|
|
18348
|
+
{
|
|
18349
|
+
id: 'arcLeft',
|
|
18350
|
+
family: 'arcs',
|
|
18351
|
+
path: 'M 0 0 C -0.069 0 -0.125 0.0995 -0.125 0.2222 C -0.125 0.3449 -0.069 0.4444 0 0.4444',
|
|
18352
|
+
},
|
|
18353
|
+
// -- Turns ---------------------------------------------------------------
|
|
18354
|
+
{ id: 'turnUp', family: 'turns', path: 'M 0 0 L 0.25 0 L 0.25 -0.25' },
|
|
18355
|
+
{ id: 'turnDown', family: 'turns', path: 'M 0 0 L 0.25 0 L 0.25 0.25' },
|
|
18356
|
+
{ id: 'turnRight', family: 'turns', path: 'M 0 0 L 0 0.25 L 0.25 0.25' },
|
|
18357
|
+
{ id: 'turnLeft', family: 'turns', path: 'M 0 0 L 0 0.25 L -0.25 0.25' },
|
|
18358
|
+
{
|
|
18359
|
+
id: 'sCurve',
|
|
18360
|
+
family: 'turns',
|
|
18361
|
+
path: 'M 0 0 C 0.0833 -0.1111 0.1667 0.1111 0.25 0',
|
|
18362
|
+
},
|
|
18363
|
+
{
|
|
18364
|
+
id: 'zigzag',
|
|
18365
|
+
family: 'turns',
|
|
18366
|
+
path: 'M 0 0 L 0.0625 -0.1111 L 0.125 0 L 0.1875 -0.1111 L 0.25 0',
|
|
18367
|
+
},
|
|
18368
|
+
// -- Shapes --------------------------------------------------------------
|
|
18369
|
+
{ id: 'circle', family: 'shapes', path: CIRCLE },
|
|
18370
|
+
{ id: 'square', family: 'shapes', path: 'M 0 0 L 0.125 0 L 0.125 -0.2222 L 0 -0.2222 Z' },
|
|
18371
|
+
{ id: 'triangle', family: 'shapes', path: 'M 0 0 L 0.0625 -0.2222 L 0.125 0 Z' },
|
|
18372
|
+
{
|
|
18373
|
+
id: 'diamond',
|
|
18374
|
+
family: 'shapes',
|
|
18375
|
+
path: 'M 0 0 L 0.0625 -0.1111 L 0.125 0 L 0.0625 0.1111 Z',
|
|
18376
|
+
},
|
|
18377
|
+
{
|
|
18378
|
+
id: 'hexagon',
|
|
18379
|
+
family: 'shapes',
|
|
18380
|
+
path: 'M 0 0 L 0.0417 -0.1111 L 0.125 -0.1111 L 0.1667 0 L 0.125 0.1111 L 0.0417 0.1111 Z',
|
|
18381
|
+
},
|
|
18382
|
+
// -- Loops ---------------------------------------------------------------
|
|
18383
|
+
{
|
|
18384
|
+
id: 'loopDeLoop',
|
|
18385
|
+
family: 'loops',
|
|
18386
|
+
path: 'M 0 0 C 0.0625 0 0.0972 -0.2222 0.1667 -0.2222 C 0.2361 -0.2222 0.2708 0 0.1667 0 L 0.3333 0',
|
|
18387
|
+
},
|
|
18388
|
+
{
|
|
18389
|
+
id: 'figureEight',
|
|
18390
|
+
family: 'loops',
|
|
18391
|
+
path: 'M 0 0 C -0.0833 0 -0.0833 -0.2222 0 -0.2222 C 0.0833 -0.2222 0.0833 0 0.1667 0 C 0.25 0 0.25 -0.2222 0.1667 -0.2222 C 0.0833 -0.2222 0.0833 0 0 0',
|
|
18392
|
+
},
|
|
18393
|
+
{
|
|
18394
|
+
id: 'spiral',
|
|
18395
|
+
family: 'loops',
|
|
18396
|
+
path: 'M 0 0 C 0.0417 0 0.0417 -0.0741 0 -0.0741 C -0.0625 -0.0741 -0.0625 -0.1852 0 -0.1852 C 0.0833 -0.1852 0.0833 -0.3333 0 -0.3333',
|
|
18397
|
+
},
|
|
18398
|
+
];
|
|
18399
|
+
/** The five families in gallery order, for building grouped UI. */
|
|
18400
|
+
const MOTION_PATH_FAMILIES = [
|
|
18401
|
+
'lines',
|
|
18402
|
+
'arcs',
|
|
18403
|
+
'turns',
|
|
18404
|
+
'shapes',
|
|
18405
|
+
'loops',
|
|
18406
|
+
];
|
|
18407
|
+
/** i18n key for a family heading (`Lines`, `Arcs`, ...). */
|
|
18408
|
+
function motionPathFamilyLabelKey(family) {
|
|
18409
|
+
return `pptx.animation.motionPath.family.${family}`;
|
|
18410
|
+
}
|
|
18411
|
+
/** i18n key for a preset's label (`Right`, `Arc Up`, ...). */
|
|
18412
|
+
function motionPathPresetLabelKey(presetId) {
|
|
18413
|
+
return `pptx.animation.motionPath.preset.${presetId}`;
|
|
18414
|
+
}
|
|
18415
|
+
/** Look a preset up by id. */
|
|
18416
|
+
function motionPathPresetById(presetId) {
|
|
18417
|
+
return MOTION_PATH_PRESETS.find((preset) => preset.id === presetId);
|
|
18418
|
+
}
|
|
18419
|
+
/** Every preset in one family, in catalogue order. */
|
|
18420
|
+
function motionPathPresetsByFamily(family) {
|
|
18421
|
+
return MOTION_PATH_PRESETS.filter((preset) => preset.family === family);
|
|
18422
|
+
}
|
|
18423
|
+
/**
|
|
18424
|
+
* Reverse lookup: the preset id whose path string matches `path`, or
|
|
18425
|
+
* `undefined` for a hand-dragged (custom) path. Lets the panel name the applied
|
|
18426
|
+
* effect instead of showing raw path data.
|
|
18427
|
+
*/
|
|
18428
|
+
function motionPathPresetIdForPath(path) {
|
|
18429
|
+
if (!path) {
|
|
18430
|
+
return undefined;
|
|
18431
|
+
}
|
|
18432
|
+
const normalized = path.trim().replace(/\s+/gu, ' ');
|
|
18433
|
+
return MOTION_PATH_PRESETS.find((preset) => preset.path.trim().replace(/\s+/gu, ' ') === normalized)?.id;
|
|
18434
|
+
}
|
|
18435
|
+
/** The path applied by the ribbon's one-click "Path Animation" command. */
|
|
18436
|
+
const DEFAULT_MOTION_PATH_PRESET_ID = 'lineRight';
|
|
18437
|
+
|
|
18438
|
+
/**
|
|
18439
|
+
* `motion-path-authoring`: apply, edit, remove and preview a motion path on the
|
|
18440
|
+
* editor's slide-level `animations[]` model.
|
|
18441
|
+
*
|
|
18442
|
+
* WHY a bucket of its own: `PptxElementAnimation` models entrance / emphasis /
|
|
18443
|
+
* exit as named presets, but a motion path is geometry, not a preset name. It
|
|
18444
|
+
* therefore lives in the sibling `motionPath` field (which core already
|
|
18445
|
+
* serialises to a real `p:animMotion` node AND preserves in the editor
|
|
18446
|
+
* extension), and the same entry's `trigger` / `durationMs` / `delayMs` /
|
|
18447
|
+
* `order` drive it exactly as they drive the other three buckets. That is why
|
|
18448
|
+
* these helpers upsert the SAME entry rather than adding a second one: one
|
|
18449
|
+
* element, one timeline row, whichever effects it carries.
|
|
18450
|
+
*
|
|
18451
|
+
* Pure: no DOM, no framework. Bindings own the gallery, the canvas overlay and
|
|
18452
|
+
* the `<style>` injection.
|
|
18453
|
+
*
|
|
18454
|
+
* @module render/motion-path-authoring
|
|
18455
|
+
*/
|
|
18456
|
+
/** Duration PowerPoint gives a freshly applied motion path. */
|
|
18457
|
+
const DEFAULT_MOTION_PATH_DURATION_MS = 2000;
|
|
18458
|
+
/** Trigger a freshly applied motion path gets, matching the other buckets. */
|
|
18459
|
+
const DEFAULT_TRIGGER = 'onClick';
|
|
18460
|
+
/** Read the motion path applied to an element, if any. */
|
|
18461
|
+
function motionPathFor(animations, elementId) {
|
|
18462
|
+
return animations.find((animation) => animation.elementId === elementId)?.motionPath;
|
|
18463
|
+
}
|
|
18464
|
+
/** Whether the element currently carries a motion path. */
|
|
18465
|
+
function hasMotionPath(animations, elementId) {
|
|
18466
|
+
return Boolean(motionPathFor(animations, elementId));
|
|
18467
|
+
}
|
|
18468
|
+
/**
|
|
18469
|
+
* Set (or replace) the raw motion path on an element, creating the animation
|
|
18470
|
+
* entry when the element had none. `pathEditMode` is pinned to `relative`
|
|
18471
|
+
* because the catalogue's coordinates are offsets from the element centre,
|
|
18472
|
+
* which is what a `relative` path means on the wire.
|
|
18473
|
+
*/
|
|
18474
|
+
function setMotionPath(animations, elementId, path) {
|
|
18475
|
+
const index = animations.findIndex((animation) => animation.elementId === elementId);
|
|
18476
|
+
if (index >= 0) {
|
|
18477
|
+
return animations.map((animation, i) => i === index
|
|
18478
|
+
? {
|
|
18479
|
+
...animation,
|
|
18480
|
+
motionPath: path,
|
|
18481
|
+
motionPathEditMode: animation.motionPathEditMode ?? 'relative',
|
|
18482
|
+
durationMs: animation.durationMs ?? DEFAULT_MOTION_PATH_DURATION_MS,
|
|
18483
|
+
}
|
|
18484
|
+
: animation);
|
|
18485
|
+
}
|
|
18486
|
+
return [
|
|
18487
|
+
...animations,
|
|
18488
|
+
{
|
|
18489
|
+
elementId,
|
|
18490
|
+
motionPath: path,
|
|
18491
|
+
motionPathEditMode: 'relative',
|
|
18492
|
+
durationMs: DEFAULT_MOTION_PATH_DURATION_MS,
|
|
18493
|
+
order: animations.length,
|
|
18494
|
+
trigger: DEFAULT_TRIGGER,
|
|
18495
|
+
},
|
|
18496
|
+
];
|
|
18497
|
+
}
|
|
18498
|
+
/**
|
|
18499
|
+
* Apply a catalogue preset by id. Unknown ids leave the list untouched so a
|
|
18500
|
+
* stale UI id can never blank an existing path.
|
|
18501
|
+
*/
|
|
18502
|
+
function applyMotionPathPreset(animations, elementId, presetId) {
|
|
18503
|
+
const preset = motionPathPresetById(presetId);
|
|
18504
|
+
if (!preset) {
|
|
18505
|
+
return [...animations];
|
|
18506
|
+
}
|
|
18507
|
+
return setMotionPath(animations, elementId, preset.path);
|
|
18508
|
+
}
|
|
18509
|
+
/**
|
|
18510
|
+
* Clear the motion path. The whole entry is dropped when nothing else is left
|
|
18511
|
+
* on it, so removing the only effect does not leave an empty timeline row
|
|
18512
|
+
* behind (the same rule the preset setters follow).
|
|
18513
|
+
*/
|
|
18514
|
+
function clearMotionPath(animations, elementId) {
|
|
18515
|
+
const index = animations.findIndex((animation) => animation.elementId === elementId);
|
|
18516
|
+
if (index < 0) {
|
|
18517
|
+
return [...animations];
|
|
18518
|
+
}
|
|
18519
|
+
const current = animations[index];
|
|
18520
|
+
const stillHasEffect = Boolean(current.entrance || current.emphasis || current.exit);
|
|
18521
|
+
if (!stillHasEffect) {
|
|
18522
|
+
return animations
|
|
18523
|
+
.filter((animation) => animation.elementId !== elementId)
|
|
18524
|
+
.map((animation, i) => ({ ...animation, order: i }));
|
|
18525
|
+
}
|
|
18526
|
+
return animations.map((animation, i) => i === index
|
|
18527
|
+
? {
|
|
18528
|
+
...animation,
|
|
18529
|
+
motionPath: undefined,
|
|
18530
|
+
motionPathEditMode: undefined,
|
|
18531
|
+
motionPtsTypes: undefined,
|
|
18532
|
+
}
|
|
18533
|
+
: animation);
|
|
18534
|
+
}
|
|
18535
|
+
/**
|
|
18536
|
+
* Project the editor's motion paths onto the native-timeline model so a path
|
|
18537
|
+
* applied in this session plays in the slide show BEFORE the deck is saved.
|
|
18538
|
+
*
|
|
18539
|
+
* WHY it is needed: the slide-show engine reads `slide.nativeAnimations`, which
|
|
18540
|
+
* is only regenerated from `slide.animations` when the file is written. Without
|
|
18541
|
+
* this bridge a user would apply a path, press play, see nothing, and only get
|
|
18542
|
+
* the motion after a save + reload round trip.
|
|
18543
|
+
*
|
|
18544
|
+
* Any element already carrying a native motion path is skipped, so a reloaded
|
|
18545
|
+
* deck (where the same path exists in BOTH models) never plays it twice.
|
|
18546
|
+
*/
|
|
18547
|
+
function motionPathNativeAnimations(slide) {
|
|
18548
|
+
const native = slide.nativeAnimations ?? [];
|
|
18549
|
+
const alreadyNative = new Set(native.filter((animation) => animation.motionPath).map((animation) => animation.targetId));
|
|
18550
|
+
return (slide.animations ?? [])
|
|
18551
|
+
.filter((animation) => Boolean(animation.motionPath) && !alreadyNative.has(animation.elementId))
|
|
18552
|
+
.map((animation) => ({
|
|
18553
|
+
targetId: animation.elementId,
|
|
18554
|
+
trigger: animation.trigger ?? DEFAULT_TRIGGER,
|
|
18555
|
+
triggerShapeId: animation.triggerShapeId,
|
|
18556
|
+
presetClass: 'path',
|
|
18557
|
+
durationMs: animation.durationMs ?? DEFAULT_MOTION_PATH_DURATION_MS,
|
|
18558
|
+
delayMs: animation.delayMs ?? 0,
|
|
18559
|
+
motionPath: animation.motionPath,
|
|
18560
|
+
motionPathEditMode: animation.motionPathEditMode ?? 'relative',
|
|
18561
|
+
}));
|
|
18562
|
+
}
|
|
18563
|
+
/**
|
|
18564
|
+
* Build the preview descriptor that plays a motion path on the canvas: the
|
|
18565
|
+
* `@keyframes` block plus the `animation` shorthand a binding assigns to the
|
|
18566
|
+
* element. Mirrors {@link buildPreviewAnimation} for the preset buckets so a
|
|
18567
|
+
* binding's existing preview player only needs one extra branch.
|
|
18568
|
+
*/
|
|
18569
|
+
function buildMotionPathPreview(args) {
|
|
18570
|
+
const keyframeName = `pptx-motion-preview-${args.uid ?? 0}`;
|
|
18571
|
+
const keyframes = buildMotionPathKeyframes({
|
|
18572
|
+
path: args.path,
|
|
18573
|
+
slideWidth: args.slideWidth,
|
|
18574
|
+
slideHeight: args.slideHeight,
|
|
18575
|
+
keyframeName,
|
|
18576
|
+
});
|
|
18577
|
+
if (!keyframes) {
|
|
18578
|
+
return undefined;
|
|
18579
|
+
}
|
|
18580
|
+
const durationMs = args.durationMs ?? DEFAULT_MOTION_PATH_DURATION_MS;
|
|
18581
|
+
const delayMs = args.delayMs ?? 0;
|
|
18582
|
+
const easing = timingCurveToCss(args.timingCurve);
|
|
18583
|
+
return {
|
|
18584
|
+
keyframeName,
|
|
18585
|
+
keyframesCss: keyframes.css,
|
|
18586
|
+
cssAnimation: `${keyframeName} ${durationMs}ms ${easing} ${delayMs}ms 1 normal both`,
|
|
18587
|
+
durationMs,
|
|
18588
|
+
};
|
|
18589
|
+
}
|
|
18590
|
+
|
|
17880
18591
|
/**
|
|
17881
18592
|
* `presentation-animation-controller`: a pure, framework-agnostic controller
|
|
17882
18593
|
* that encapsulates the native-animation (`p:timing`) element playback a binding
|
|
@@ -17954,7 +18665,10 @@ class PresentationAnimationController {
|
|
|
17954
18665
|
* id list (base element ids + text-build sub-element ids) to track.
|
|
17955
18666
|
*/
|
|
17956
18667
|
static fromSlide(slide) {
|
|
17957
|
-
|
|
18668
|
+
// Motion paths authored in this session live on the editor model until the
|
|
18669
|
+
// deck is saved; project them in so pressing play right after applying one
|
|
18670
|
+
// actually moves the shape.
|
|
18671
|
+
const nativeAnims = [...(slide.nativeAnimations ?? []), ...motionPathNativeAnimations(slide)];
|
|
17958
18672
|
const segmentCounts = buildSegmentCounts(slide, nativeAnims);
|
|
17959
18673
|
const expandedAnims = segmentCounts.size > 0 ? expandTextBuildAnimations(nativeAnims, segmentCounts) : nativeAnims;
|
|
17960
18674
|
const engine = TimelineEngine.fromAnimations(expandedAnims);
|
|
@@ -18208,131 +18922,6 @@ function executeMediaCommandInDom(command, frameRoot) {
|
|
|
18208
18922
|
return runMediaCommand(command, (targetId) => findMediaElementByElementId(targetId, frameRoot?.() ?? null));
|
|
18209
18923
|
}
|
|
18210
18924
|
|
|
18211
|
-
/**
|
|
18212
|
-
* `animation-preview` — pure preview-descriptor construction for the editor's
|
|
18213
|
-
* animation panel: map an editor preset (+ direction / timing) to a CSS
|
|
18214
|
-
* keyframe name, definition and shorthand. The DOM player that injects the
|
|
18215
|
-
* `<style>` and toggles the element animation stays in each binding.
|
|
18216
|
-
*
|
|
18217
|
-
* @module render/animation-preview
|
|
18218
|
-
*/
|
|
18219
|
-
// ==========================================================================
|
|
18220
|
-
// Preview keyframes generation
|
|
18221
|
-
// ==========================================================================
|
|
18222
|
-
/** Map editor-level animation presets to the internal effect names used by
|
|
18223
|
-
* the keyframe definition table. */
|
|
18224
|
-
const PRESET_TO_EFFECT = {
|
|
18225
|
-
fadeIn: 'fadeIn',
|
|
18226
|
-
flyIn: 'flyInBottom',
|
|
18227
|
-
zoomIn: 'zoomIn',
|
|
18228
|
-
fadeOut: 'fadeOut',
|
|
18229
|
-
flyOut: 'flyOutBottom',
|
|
18230
|
-
zoomOut: 'zoomOut',
|
|
18231
|
-
spin: 'spin',
|
|
18232
|
-
pulse: 'pulse',
|
|
18233
|
-
colorWave: 'colorWave',
|
|
18234
|
-
bounce: 'bounce',
|
|
18235
|
-
flash: 'flash',
|
|
18236
|
-
};
|
|
18237
|
-
/** Direction-aware fly-in/out effect name overrides. */
|
|
18238
|
-
const DIRECTION_FLY_MAP = {
|
|
18239
|
-
fromLeft: { flyIn: 'flyInLeft', flyOut: 'flyOutLeft' },
|
|
18240
|
-
fromRight: { flyIn: 'flyInRight', flyOut: 'flyOutRight' },
|
|
18241
|
-
fromTop: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
18242
|
-
fromBottom: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
18243
|
-
fromTopLeft: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
18244
|
-
fromTopRight: { flyIn: 'flyInTop', flyOut: 'flyOutTop' },
|
|
18245
|
-
fromBottomLeft: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
18246
|
-
fromBottomRight: { flyIn: 'flyInBottom', flyOut: 'flyOutBottom' },
|
|
18247
|
-
};
|
|
18248
|
-
/**
|
|
18249
|
-
* Resolve the CSS @keyframes effect name for a given preset and direction.
|
|
18250
|
-
*/
|
|
18251
|
-
function resolvePreviewEffect(preset, direction) {
|
|
18252
|
-
if ((preset === 'flyIn' || preset === 'flyOut') && direction) {
|
|
18253
|
-
const dirMap = DIRECTION_FLY_MAP[direction];
|
|
18254
|
-
if (dirMap) {
|
|
18255
|
-
return preset === 'flyIn' ? dirMap.flyIn : dirMap.flyOut;
|
|
18256
|
-
}
|
|
18257
|
-
}
|
|
18258
|
-
return PRESET_TO_EFFECT[preset];
|
|
18259
|
-
}
|
|
18260
|
-
/**
|
|
18261
|
-
* Map a timing curve name to a CSS easing string.
|
|
18262
|
-
* Supports the standard OOXML timing curves plus cubic-bezier extraction.
|
|
18263
|
-
*/
|
|
18264
|
-
function timingCurveToCss(curve, cubicBezierValues) {
|
|
18265
|
-
if (cubicBezierValues) {
|
|
18266
|
-
// Validate cubic-bezier format: "x1,y1,x2,y2"
|
|
18267
|
-
const parts = cubicBezierValues.split(',').map((s) => s.trim());
|
|
18268
|
-
if (parts.length === 4 && parts.every((p) => !Number.isNaN(Number(p)))) {
|
|
18269
|
-
return `cubic-bezier(${parts.join(', ')})`;
|
|
18270
|
-
}
|
|
18271
|
-
}
|
|
18272
|
-
switch (curve) {
|
|
18273
|
-
case 'ease':
|
|
18274
|
-
return 'ease';
|
|
18275
|
-
case 'ease-in':
|
|
18276
|
-
return 'ease-in';
|
|
18277
|
-
case 'ease-out':
|
|
18278
|
-
return 'ease-out';
|
|
18279
|
-
case 'linear':
|
|
18280
|
-
return 'linear';
|
|
18281
|
-
default:
|
|
18282
|
-
return 'ease';
|
|
18283
|
-
}
|
|
18284
|
-
}
|
|
18285
|
-
/**
|
|
18286
|
-
* Build a preview animation descriptor for a given preset.
|
|
18287
|
-
*
|
|
18288
|
-
* Returns `undefined` if the preset doesn't have a known effect.
|
|
18289
|
-
*/
|
|
18290
|
-
function buildPreviewAnimation(preset, options) {
|
|
18291
|
-
if (preset === 'none') {
|
|
18292
|
-
return undefined;
|
|
18293
|
-
}
|
|
18294
|
-
const effectName = resolvePreviewEffect(preset, options?.direction);
|
|
18295
|
-
if (!effectName) {
|
|
18296
|
-
return undefined;
|
|
18297
|
-
}
|
|
18298
|
-
const keyframeName = `pptx-${effectName}`;
|
|
18299
|
-
const keyframesCss = getEffectKeyframes(effectName);
|
|
18300
|
-
if (!keyframesCss) {
|
|
18301
|
-
return undefined;
|
|
18302
|
-
}
|
|
18303
|
-
const duration = options?.durationMs ?? 600;
|
|
18304
|
-
const easing = timingCurveToCss(options?.timingCurve, options?.cubicBezier);
|
|
18305
|
-
return {
|
|
18306
|
-
keyframeName,
|
|
18307
|
-
keyframesCss,
|
|
18308
|
-
cssAnimation: `${keyframeName} ${duration}ms ${easing} 0ms 1 normal both`,
|
|
18309
|
-
durationMs: duration,
|
|
18310
|
-
};
|
|
18311
|
-
}
|
|
18312
|
-
// ==========================================================================
|
|
18313
|
-
// Timing curve extraction from OOXML bezier values
|
|
18314
|
-
// ==========================================================================
|
|
18315
|
-
/**
|
|
18316
|
-
* Parse OOXML timing curve bezier values from `a:cTn/a:timing/a:curve`.
|
|
18317
|
-
*
|
|
18318
|
-
* OOXML stores bezier control points as attributes:
|
|
18319
|
-
* - `x1`, `y1` — first control point (0..100000 range)
|
|
18320
|
-
* - `x2`, `y2` — second control point (0..100000 range)
|
|
18321
|
-
*
|
|
18322
|
-
* Returns a CSS `cubic-bezier()` string, or undefined if not parseable.
|
|
18323
|
-
*/
|
|
18324
|
-
function parseOoxmlBezierCurve(x1, y1, x2, y2) {
|
|
18325
|
-
if (x1 === undefined || y1 === undefined || x2 === undefined || y2 === undefined) {
|
|
18326
|
-
return undefined;
|
|
18327
|
-
}
|
|
18328
|
-
// OOXML values are in 0..100000 range, CSS cubic-bezier uses 0..1
|
|
18329
|
-
const cx1 = Math.max(0, Math.min(1, x1 / 100000));
|
|
18330
|
-
const cy1 = y1 / 100000; // y can exceed 0..1 range for overshoot
|
|
18331
|
-
const cx2 = Math.max(0, Math.min(1, x2 / 100000));
|
|
18332
|
-
const cy2 = y2 / 100000;
|
|
18333
|
-
return `${cx1.toFixed(4)},${cy1.toFixed(4)},${cx2.toFixed(4)},${cy2.toFixed(4)}`;
|
|
18334
|
-
}
|
|
18335
|
-
|
|
18336
18925
|
/**
|
|
18337
18926
|
* Camera-preset → CSS perspective/rotation mapping (framework-agnostic).
|
|
18338
18927
|
*
|
|
@@ -24756,7 +25345,7 @@ const DEBOUNCE_MS = 600;
|
|
|
24756
25345
|
const EXPANDED_MAX_HEIGHT = 200;
|
|
24757
25346
|
const PX_TO_PT = 0.75;
|
|
24758
25347
|
const MAX_INDENT_LEVEL = 4;
|
|
24759
|
-
const INDENT_PX = 24;
|
|
25348
|
+
const INDENT_PX$1 = 24;
|
|
24760
25349
|
/* ------------------------------------------------------------------ */
|
|
24761
25350
|
/* Utility helpers */
|
|
24762
25351
|
/* ------------------------------------------------------------------ */
|
|
@@ -24821,7 +25410,7 @@ function buildParagraph(segments) {
|
|
|
24821
25410
|
}
|
|
24822
25411
|
}
|
|
24823
25412
|
if (first?.style.paragraphMarginLeft) {
|
|
24824
|
-
indentLevel = Math.min(MAX_INDENT_LEVEL, Math.max(0, Math.round(first.style.paragraphMarginLeft / INDENT_PX)));
|
|
25413
|
+
indentLevel = Math.min(MAX_INDENT_LEVEL, Math.max(0, Math.round(first.style.paragraphMarginLeft / INDENT_PX$1)));
|
|
24825
25414
|
}
|
|
24826
25415
|
return {
|
|
24827
25416
|
segments: segments.length > 0 ? segments : [{ text: '', style: {} }],
|
|
@@ -24867,7 +25456,7 @@ function paragraphsToSegments(paragraphs) {
|
|
|
24867
25456
|
para.segments.forEach((seg, sIdx) => {
|
|
24868
25457
|
const updated = { ...seg, style: { ...seg.style } };
|
|
24869
25458
|
if (para.indentLevel > 0) {
|
|
24870
|
-
updated.style.paragraphMarginLeft = para.indentLevel * INDENT_PX;
|
|
25459
|
+
updated.style.paragraphMarginLeft = para.indentLevel * INDENT_PX$1;
|
|
24871
25460
|
}
|
|
24872
25461
|
else {
|
|
24873
25462
|
delete updated.style.paragraphMarginLeft;
|
|
@@ -25240,7 +25829,7 @@ function parseSegmentsFromRichEditor(root) {
|
|
|
25240
25829
|
if (paraIndent > 0) {
|
|
25241
25830
|
segments[i].style = {
|
|
25242
25831
|
...segments[i].style,
|
|
25243
|
-
paragraphMarginLeft: paraIndent * INDENT_PX,
|
|
25832
|
+
paragraphMarginLeft: paraIndent * INDENT_PX$1,
|
|
25244
25833
|
};
|
|
25245
25834
|
}
|
|
25246
25835
|
break;
|
|
@@ -25311,7 +25900,7 @@ function segmentsToEditorHtml(segments) {
|
|
|
25311
25900
|
if (para.indentLevel > 0) {
|
|
25312
25901
|
attrs.push(`data-indent-level="${para.indentLevel}"`);
|
|
25313
25902
|
}
|
|
25314
|
-
const indent = para.indentLevel * INDENT_PX;
|
|
25903
|
+
const indent = para.indentLevel * INDENT_PX$1;
|
|
25315
25904
|
const divStyles = [];
|
|
25316
25905
|
if (indent > 0) {
|
|
25317
25906
|
divStyles.push(`padding-left:${indent}px`);
|
|
@@ -41268,6 +41857,740 @@ function clampIndex$1(index, slideCount) {
|
|
|
41268
41857
|
return Math.min(Math.max(Math.trunc(index), 0), slideCount - 1);
|
|
41269
41858
|
}
|
|
41270
41859
|
|
|
41860
|
+
/**
|
|
41861
|
+
* PowerPoint's Outline view, as a framework-agnostic model of the deck's text.
|
|
41862
|
+
*
|
|
41863
|
+
* Outline view shows a deck as an indented text document: one line per slide
|
|
41864
|
+
* title at the far left, that slide's body text indented beneath it. It is the
|
|
41865
|
+
* fastest way to draft or restructure a deck, and no binding shipped it.
|
|
41866
|
+
*
|
|
41867
|
+
* This module owns the READ half (deck -> rows) plus the paragraph read/write
|
|
41868
|
+
* primitives the edit half builds on. `outline-view-edit` owns the WRITE half.
|
|
41869
|
+
* Both are pure: the bindings own the markup and the event listeners, and own
|
|
41870
|
+
* no rule about what a row is or what Tab does.
|
|
41871
|
+
*
|
|
41872
|
+
* Three decisions are worth stating up front, because they are the ones a
|
|
41873
|
+
* reader will otherwise assume were oversights:
|
|
41874
|
+
*
|
|
41875
|
+
* 1. **Placeholders first, then a fallback.** PowerPoint's outline shows only
|
|
41876
|
+
* placeholder text, and free text boxes never appear. Applying that alone
|
|
41877
|
+
* here would blank the outline for the many decks (and every deck this repo
|
|
41878
|
+
* hand-authors as a fixture) that carry no `<p:ph>` at all, which reads as a
|
|
41879
|
+
* broken feature rather than as fidelity. So placeholders win when present,
|
|
41880
|
+
* and a slide with none falls back to its text-bearing elements in document
|
|
41881
|
+
* order. See {@link resolveSlideOutlineElements}.
|
|
41882
|
+
* 2. **A slide always contributes at least one row.** A slide with no title
|
|
41883
|
+
* placeholder, or no text whatsoever, still gets a title row (with a null
|
|
41884
|
+
* `elementId`). Without it the outline silently hides slides, and hiding a
|
|
41885
|
+
* slide from the view whose entire job is to show the deck's structure is
|
|
41886
|
+
* the worst failure this feature has.
|
|
41887
|
+
* 3. **A row is one (element, paragraph) pair**, keyed by ids rather than by
|
|
41888
|
+
* position, so a key survives an edit that inserts a slide above it.
|
|
41889
|
+
*
|
|
41890
|
+
* @module render/outline-view
|
|
41891
|
+
*/
|
|
41892
|
+
// ---------------------------------------------------------------------------
|
|
41893
|
+
// DOM contract
|
|
41894
|
+
// ---------------------------------------------------------------------------
|
|
41895
|
+
/**
|
|
41896
|
+
* Marks the outline-view root in every binding.
|
|
41897
|
+
*
|
|
41898
|
+
* A neutral data attribute rather than a class or a test id, for the same
|
|
41899
|
+
* reason `READING_VIEW_ATTR` is one: `e2e/` addresses all five viewers through
|
|
41900
|
+
* one selector, and a class name is a styling decision each binding may make
|
|
41901
|
+
* differently.
|
|
41902
|
+
*/
|
|
41903
|
+
const OUTLINE_VIEW_ATTR = 'data-pptx-outline-view';
|
|
41904
|
+
/** Marks one editable outline line. Its value is the row's {@link OutlineRow.key}. */
|
|
41905
|
+
const OUTLINE_ROW_ATTR = 'data-pptx-outline-row';
|
|
41906
|
+
/** Marks a row's slide number, so a binding can group rows per slide. */
|
|
41907
|
+
const OUTLINE_SLIDE_ATTR = 'data-pptx-outline-slide';
|
|
41908
|
+
/** Marks a row's outline level, so styling and tests read it without parsing CSS. */
|
|
41909
|
+
const OUTLINE_LEVEL_ATTR = 'data-pptx-outline-level';
|
|
41910
|
+
/** Highest `a:pPr/@lvl` OOXML allows (ECMA-376 CT_TextParagraphProperties). */
|
|
41911
|
+
const MAX_PARAGRAPH_LEVEL = 8;
|
|
41912
|
+
/** Placeholder types PowerPoint treats as the slide's title. */
|
|
41913
|
+
const TITLE_PH_TYPES = new Set(['title', 'ctrtitle']);
|
|
41914
|
+
/**
|
|
41915
|
+
* Placeholder types that never belong in an outline.
|
|
41916
|
+
*
|
|
41917
|
+
* Header / footer / date / slide-number repeat on every slide, so listing them
|
|
41918
|
+
* would bury the actual content under four rows of chrome per slide.
|
|
41919
|
+
*/
|
|
41920
|
+
const CHROME_PH_TYPES = new Set(['ftr', 'hdr', 'dt', 'sldnum']);
|
|
41921
|
+
/** Name given to a title element the outline creates for a slide that lacked one. */
|
|
41922
|
+
const OUTLINE_TITLE_ELEMENT_NAME = 'Title';
|
|
41923
|
+
/**
|
|
41924
|
+
* Read an element's placeholder type from its preserved raw XML.
|
|
41925
|
+
*
|
|
41926
|
+
* Returns `'body'` for a `<p:ph>` that declares no `@type`: the schema default
|
|
41927
|
+
* for `CT_Placeholder/@type` is `body`, and a content placeholder authored as
|
|
41928
|
+
* `<p:ph idx="1"/>` is extremely common. Treating it as "not a placeholder"
|
|
41929
|
+
* dropped the body of most real decks from the outline.
|
|
41930
|
+
*/
|
|
41931
|
+
function placeholderType(element) {
|
|
41932
|
+
const ph = element.rawXml?.['p:nvSpPr']?.['p:nvPr']?.['p:ph'];
|
|
41933
|
+
if (!ph) {
|
|
41934
|
+
return undefined;
|
|
41935
|
+
}
|
|
41936
|
+
const type = typeof ph['@_type'] === 'string' ? ph['@_type'].trim().toLowerCase() : '';
|
|
41937
|
+
return type.length > 0 ? type : 'body';
|
|
41938
|
+
}
|
|
41939
|
+
/** Whether an element can carry outline text at all. */
|
|
41940
|
+
function isTextBearing(element) {
|
|
41941
|
+
return hasTextProperties(element);
|
|
41942
|
+
}
|
|
41943
|
+
/** Plain text of an element, used only to decide whether it is worth a row. */
|
|
41944
|
+
function elementHasText(element) {
|
|
41945
|
+
if (!hasTextProperties(element)) {
|
|
41946
|
+
return false;
|
|
41947
|
+
}
|
|
41948
|
+
if (typeof element.text === 'string' && element.text.trim().length > 0) {
|
|
41949
|
+
return true;
|
|
41950
|
+
}
|
|
41951
|
+
return (element.textSegments ?? []).some((segment) => segment.text.trim().length > 0);
|
|
41952
|
+
}
|
|
41953
|
+
/**
|
|
41954
|
+
* Decide which of a slide's elements the outline reads.
|
|
41955
|
+
*
|
|
41956
|
+
* Placeholder-bearing slides resolve exactly as PowerPoint does: the
|
|
41957
|
+
* title/ctrTitle placeholder titles the slide and the remaining content
|
|
41958
|
+
* placeholders supply the body, with header/footer/date/slide-number chrome
|
|
41959
|
+
* excluded. A slide with no usable placeholder falls back to its text-bearing
|
|
41960
|
+
* elements in document order, first as the title and the rest as body: see the
|
|
41961
|
+
* module docstring for why the strict rule alone was not shippable here.
|
|
41962
|
+
*
|
|
41963
|
+
* A slide that has never had a title also matches an element NAMED `Title`,
|
|
41964
|
+
* which is what {@link OUTLINE_TITLE_ELEMENT_NAME} stamps on the element the
|
|
41965
|
+
* outline creates when someone types into an empty title row. Without that the
|
|
41966
|
+
* newly created title would be re-read as body text on the very next render.
|
|
41967
|
+
*/
|
|
41968
|
+
function resolveSlideOutlineElements(slide) {
|
|
41969
|
+
const elements = (slide.elements ?? []).filter(isTextBearing);
|
|
41970
|
+
const placeholderTitle = elements.find((element) => {
|
|
41971
|
+
const type = placeholderType(element);
|
|
41972
|
+
return type !== undefined && TITLE_PH_TYPES.has(type);
|
|
41973
|
+
});
|
|
41974
|
+
const placeholderBody = elements.filter((element) => {
|
|
41975
|
+
const type = placeholderType(element);
|
|
41976
|
+
return type !== undefined && !TITLE_PH_TYPES.has(type) && !CHROME_PH_TYPES.has(type);
|
|
41977
|
+
});
|
|
41978
|
+
if (placeholderTitle || placeholderBody.length > 0) {
|
|
41979
|
+
return { title: placeholderTitle ?? null, body: placeholderBody };
|
|
41980
|
+
}
|
|
41981
|
+
const named = elements.find((element) => (element.name ?? '').trim().toLowerCase() === OUTLINE_TITLE_ELEMENT_NAME.toLowerCase());
|
|
41982
|
+
const withText = elements.filter(elementHasText);
|
|
41983
|
+
const title = named ?? withText[0] ?? null;
|
|
41984
|
+
return { title, body: withText.filter((element) => element !== title) };
|
|
41985
|
+
}
|
|
41986
|
+
/**
|
|
41987
|
+
* Whether a segment is the display-only bullet marker core inserts on load.
|
|
41988
|
+
*
|
|
41989
|
+
* Mirrors the save writer's own `isRenderedBulletMarker`: the marker is not
|
|
41990
|
+
* authored text, it is a rendering convenience, and letting it into an outline
|
|
41991
|
+
* row would show "• Item" in the editable line and then write the glyph back
|
|
41992
|
+
* into the deck as literal characters on the next keystroke.
|
|
41993
|
+
*/
|
|
41994
|
+
function isBulletMarker(segment) {
|
|
41995
|
+
const bullet = segment.bulletInfo;
|
|
41996
|
+
if (!bullet) {
|
|
41997
|
+
return false;
|
|
41998
|
+
}
|
|
41999
|
+
const marker = bullet.char
|
|
42000
|
+
? `${bullet.char} `
|
|
42001
|
+
: bullet.imageRelId || bullet.imageDataUrl
|
|
42002
|
+
? '\u{1F4CE} '
|
|
42003
|
+
: bullet.autoNumType
|
|
42004
|
+
? undefined
|
|
42005
|
+
: '• ';
|
|
42006
|
+
return marker ? segment.text === marker : bullet.paragraphIndex !== undefined;
|
|
42007
|
+
}
|
|
42008
|
+
function isParagraphSeparator(segment) {
|
|
42009
|
+
return Boolean(segment.isParagraphBreak) || (segment.text === '\n' && !segment.isLineBreak);
|
|
42010
|
+
}
|
|
42011
|
+
/**
|
|
42012
|
+
* Split an element's segments into paragraph groups.
|
|
42013
|
+
*
|
|
42014
|
+
* Falls back to splitting `element.text` when the element carries no segments
|
|
42015
|
+
* (SDK-built and freshly inserted elements), so every downstream helper can
|
|
42016
|
+
* assume groups exist and none of them has to special-case a bare string.
|
|
42017
|
+
*/
|
|
42018
|
+
function groupElementParagraphs(element) {
|
|
42019
|
+
const withText = hasTextProperties(element) ? element : undefined;
|
|
42020
|
+
const segments = withText?.textSegments;
|
|
42021
|
+
if (!segments || segments.length === 0) {
|
|
42022
|
+
const style = { ...(withText?.textStyle ?? {}) };
|
|
42023
|
+
return (withText?.text ?? '').split('\n').map((text) => ({
|
|
42024
|
+
content: [{ text, style: { ...style } }],
|
|
42025
|
+
}));
|
|
42026
|
+
}
|
|
42027
|
+
const groups = [{ content: [] }];
|
|
42028
|
+
for (const segment of segments) {
|
|
42029
|
+
if (isParagraphSeparator(segment)) {
|
|
42030
|
+
groups.push({ content: [] });
|
|
42031
|
+
continue;
|
|
42032
|
+
}
|
|
42033
|
+
const current = groups[groups.length - 1];
|
|
42034
|
+
if (current.content.length === 0 && current.marker === undefined && isBulletMarker(segment)) {
|
|
42035
|
+
current.marker = segment;
|
|
42036
|
+
continue;
|
|
42037
|
+
}
|
|
42038
|
+
current.content.push(segment);
|
|
42039
|
+
}
|
|
42040
|
+
return groups;
|
|
42041
|
+
}
|
|
42042
|
+
/**
|
|
42043
|
+
* Plain text of one paragraph group.
|
|
42044
|
+
*
|
|
42045
|
+
* A soft line break (`a:br`) becomes a single space rather than a newline: an
|
|
42046
|
+
* outline row is one line, and emitting "\n" here would make the row's text
|
|
42047
|
+
* indistinguishable from a paragraph break and silently convert the soft break
|
|
42048
|
+
* into a hard one the first time the row was written back.
|
|
42049
|
+
*/
|
|
42050
|
+
function paragraphGroupText(group) {
|
|
42051
|
+
return group.content.map((segment) => (segment.isLineBreak ? ' ' : segment.text)).join('');
|
|
42052
|
+
}
|
|
42053
|
+
/** Raw `a:pPr/@lvl` of a paragraph group, read from its first segment. */
|
|
42054
|
+
function paragraphGroupLevel(group) {
|
|
42055
|
+
const first = group.marker ?? group.content[0];
|
|
42056
|
+
const level = first?.paragraphLevel;
|
|
42057
|
+
return typeof level === 'number' && level > 0 ? Math.min(level, MAX_PARAGRAPH_LEVEL) : 0;
|
|
42058
|
+
}
|
|
42059
|
+
/**
|
|
42060
|
+
* Read an element's paragraphs as the outline sees them.
|
|
42061
|
+
*
|
|
42062
|
+
* Trailing empty paragraphs are dropped, matching `buildParagraphs`: both the
|
|
42063
|
+
* load path and the edit-remap path leave a separator behind, and showing an
|
|
42064
|
+
* always-blank last row under every block would double the outline's length
|
|
42065
|
+
* with lines the deck never draws.
|
|
42066
|
+
*/
|
|
42067
|
+
function readElementParagraphs(element) {
|
|
42068
|
+
const groups = groupElementParagraphs(element);
|
|
42069
|
+
const paragraphs = groups.map((group) => ({
|
|
42070
|
+
text: paragraphGroupText(group),
|
|
42071
|
+
level: paragraphGroupLevel(group),
|
|
42072
|
+
}));
|
|
42073
|
+
let last = paragraphs.length - 1;
|
|
42074
|
+
while (last >= 0 && paragraphs[last].text.length === 0) {
|
|
42075
|
+
last -= 1;
|
|
42076
|
+
}
|
|
42077
|
+
return paragraphs.slice(0, last + 1);
|
|
42078
|
+
}
|
|
42079
|
+
// ---------------------------------------------------------------------------
|
|
42080
|
+
// Rows
|
|
42081
|
+
// ---------------------------------------------------------------------------
|
|
42082
|
+
/** Build a row key from the parts that identify it. */
|
|
42083
|
+
function outlineRowKey(slideId, elementId, paragraphIndex) {
|
|
42084
|
+
return `${slideId}|${elementId ?? 'new-title'}|${paragraphIndex}`;
|
|
42085
|
+
}
|
|
42086
|
+
function pushElementRows(rows, element, kind, slide, slideIndex) {
|
|
42087
|
+
for (const [paragraphIndex, paragraph] of readElementParagraphs(element).entries()) {
|
|
42088
|
+
rows.push({
|
|
42089
|
+
key: outlineRowKey(slide.id, element.id, paragraphIndex),
|
|
42090
|
+
slideIndex,
|
|
42091
|
+
slideId: slide.id,
|
|
42092
|
+
kind,
|
|
42093
|
+
elementId: element.id,
|
|
42094
|
+
paragraphIndex,
|
|
42095
|
+
// A title always sits in the leftmost column; body text is pushed one
|
|
42096
|
+
// column right of it, so authored level 0 reads as outline level 1.
|
|
42097
|
+
level: kind === 'title' ? 0 : paragraph.level + 1,
|
|
42098
|
+
text: paragraph.text,
|
|
42099
|
+
});
|
|
42100
|
+
}
|
|
42101
|
+
}
|
|
42102
|
+
/**
|
|
42103
|
+
* Build the whole deck's outline.
|
|
42104
|
+
*
|
|
42105
|
+
* Every slide contributes at least one row even when it holds no text: see the
|
|
42106
|
+
* module docstring, decision 2.
|
|
42107
|
+
*/
|
|
42108
|
+
function buildOutline(slides) {
|
|
42109
|
+
const rows = [];
|
|
42110
|
+
for (const [slideIndex, slide] of slides.entries()) {
|
|
42111
|
+
const { title, body } = resolveSlideOutlineElements(slide);
|
|
42112
|
+
const before = rows.length;
|
|
42113
|
+
if (title) {
|
|
42114
|
+
pushElementRows(rows, title, 'title', slide, slideIndex);
|
|
42115
|
+
}
|
|
42116
|
+
if (rows.length === before) {
|
|
42117
|
+
// No title element, or one whose text is entirely empty: emit the
|
|
42118
|
+
// synthetic row so the slide is still visible and still typeable.
|
|
42119
|
+
rows.push({
|
|
42120
|
+
key: outlineRowKey(slide.id, title?.id ?? null, 0),
|
|
42121
|
+
slideIndex,
|
|
42122
|
+
slideId: slide.id,
|
|
42123
|
+
kind: 'title',
|
|
42124
|
+
elementId: title?.id ?? null,
|
|
42125
|
+
paragraphIndex: 0,
|
|
42126
|
+
level: 0,
|
|
42127
|
+
text: '',
|
|
42128
|
+
});
|
|
42129
|
+
}
|
|
42130
|
+
for (const element of body) {
|
|
42131
|
+
pushElementRows(rows, element, 'body', slide, slideIndex);
|
|
42132
|
+
}
|
|
42133
|
+
}
|
|
42134
|
+
return rows;
|
|
42135
|
+
}
|
|
42136
|
+
/** Find a row by key, or `undefined`. */
|
|
42137
|
+
function findOutlineRow(rows, key) {
|
|
42138
|
+
return rows.find((row) => row.key === key);
|
|
42139
|
+
}
|
|
42140
|
+
|
|
42141
|
+
/** MIME type bindings should use when writing the payload as a custom clipboard format. */
|
|
42142
|
+
const ELEMENT_CLIPBOARD_MIME_TYPE = 'application/x-pptx-viewer-elements+json';
|
|
42143
|
+
/** Marker identifying a serialized element-clipboard payload. */
|
|
42144
|
+
const ELEMENT_CLIPBOARD_MARKER = 'pptx-viewer/elements';
|
|
42145
|
+
/** Current codec version; {@link deserializeElementClipboard} rejects others. */
|
|
42146
|
+
const ELEMENT_CLIPBOARD_VERSION = 1;
|
|
42147
|
+
/** Standard paste/duplicate cascade offset in px (applied to both axes). */
|
|
42148
|
+
const PASTE_OFFSET_PX = 20;
|
|
42149
|
+
/** Generate a unique element id (`el-<timestamp>-<random>`). */
|
|
42150
|
+
function generateElementId() {
|
|
42151
|
+
return `el-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
42152
|
+
}
|
|
42153
|
+
/**
|
|
42154
|
+
* Build the id for a pasted / duplicated clone so that it routes to the same
|
|
42155
|
+
* store it is inserted into.
|
|
42156
|
+
*
|
|
42157
|
+
* In edit-template mode the clone lands in the template store, so it must keep
|
|
42158
|
+
* a template (`master-` / `layout-`) prefix; otherwise later edits (which route
|
|
42159
|
+
* by id prefix) would target the wrong store and be lost. Outside template mode
|
|
42160
|
+
* a normal id is generated.
|
|
42161
|
+
*/
|
|
42162
|
+
function makeCloneId(intoTemplate, sourceId) {
|
|
42163
|
+
if (!intoTemplate) {
|
|
42164
|
+
return generateElementId();
|
|
42165
|
+
}
|
|
42166
|
+
if (sourceId.startsWith('master-')) {
|
|
42167
|
+
return `master-${generateElementId()}`;
|
|
42168
|
+
}
|
|
42169
|
+
return `layout-${generateElementId()}`;
|
|
42170
|
+
}
|
|
42171
|
+
/**
|
|
42172
|
+
* Snapshot a copied/cut element into the in-memory clipboard payload.
|
|
42173
|
+
* Deep-clones so later canvas edits never mutate the clipboard content.
|
|
42174
|
+
*/
|
|
42175
|
+
function buildElementClipboardPayload(element, isTemplate) {
|
|
42176
|
+
return { element: structuredClone(element), isTemplate };
|
|
42177
|
+
}
|
|
42178
|
+
/**
|
|
42179
|
+
* Produce the clone inserted by paste/duplicate: a deep copy with a fresh
|
|
42180
|
+
* (template-prefix aware) id and the standard cascade offset applied.
|
|
42181
|
+
*/
|
|
42182
|
+
function cloneElementForPaste(element, options = {}) {
|
|
42183
|
+
const clone = structuredClone(element);
|
|
42184
|
+
clone.id = makeCloneId(options.intoTemplate ?? false, element.id);
|
|
42185
|
+
clone.x += options.offsetX ?? PASTE_OFFSET_PX;
|
|
42186
|
+
clone.y += options.offsetY ?? PASTE_OFFSET_PX;
|
|
42187
|
+
return clone;
|
|
42188
|
+
}
|
|
42189
|
+
/** Clone every element in decoded clipboard data for insertion (fresh ids + offset). */
|
|
42190
|
+
function prepareElementsForPaste(data, options = {}) {
|
|
42191
|
+
return data.elements.map((element) => cloneElementForPaste(element, options));
|
|
42192
|
+
}
|
|
42193
|
+
/** Tag used to mark base64-encoded binary fields inside the JSON payload. */
|
|
42194
|
+
const BINARY_TAG = '__pptxU8';
|
|
42195
|
+
function uint8ToBase64(bytes) {
|
|
42196
|
+
let binary = '';
|
|
42197
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
42198
|
+
binary += String.fromCharCode(bytes[i]);
|
|
42199
|
+
}
|
|
42200
|
+
return btoa(binary);
|
|
42201
|
+
}
|
|
42202
|
+
function base64ToUint8(base64) {
|
|
42203
|
+
const binary = atob(base64);
|
|
42204
|
+
const bytes = new Uint8Array(binary.length);
|
|
42205
|
+
for (let i = 0; i < binary.length; i++) {
|
|
42206
|
+
bytes[i] = binary.charCodeAt(i);
|
|
42207
|
+
}
|
|
42208
|
+
return bytes;
|
|
42209
|
+
}
|
|
42210
|
+
/**
|
|
42211
|
+
* Serialize elements to the marked, versioned JSON clipboard string.
|
|
42212
|
+
* `Uint8Array` fields anywhere in the element tree (embedded workbooks, raw
|
|
42213
|
+
* part bytes) are base64-tagged so they survive the text round trip.
|
|
42214
|
+
*/
|
|
42215
|
+
function serializeElementClipboard(elements, isTemplate = false) {
|
|
42216
|
+
return JSON.stringify({
|
|
42217
|
+
marker: ELEMENT_CLIPBOARD_MARKER,
|
|
42218
|
+
version: ELEMENT_CLIPBOARD_VERSION,
|
|
42219
|
+
isTemplate,
|
|
42220
|
+
elements,
|
|
42221
|
+
}, (_key, value) => {
|
|
42222
|
+
if (value instanceof Uint8Array) {
|
|
42223
|
+
return { [BINARY_TAG]: uint8ToBase64(value) };
|
|
42224
|
+
}
|
|
42225
|
+
return value;
|
|
42226
|
+
});
|
|
42227
|
+
}
|
|
42228
|
+
function isElementLike(value) {
|
|
42229
|
+
if (typeof value !== 'object' || value === null) {
|
|
42230
|
+
return false;
|
|
42231
|
+
}
|
|
42232
|
+
const candidate = value;
|
|
42233
|
+
return (typeof candidate.id === 'string' &&
|
|
42234
|
+
typeof candidate.type === 'string' &&
|
|
42235
|
+
typeof candidate.x === 'number' &&
|
|
42236
|
+
typeof candidate.y === 'number' &&
|
|
42237
|
+
typeof candidate.width === 'number' &&
|
|
42238
|
+
typeof candidate.height === 'number');
|
|
42239
|
+
}
|
|
42240
|
+
/**
|
|
42241
|
+
* Decode a clipboard string produced by {@link serializeElementClipboard}.
|
|
42242
|
+
* Returns `null` for anything else (foreign clipboard text, malformed JSON,
|
|
42243
|
+
* wrong marker/version, or structurally invalid elements), so callers can fall
|
|
42244
|
+
* back to their plain-text paste path.
|
|
42245
|
+
*/
|
|
42246
|
+
function deserializeElementClipboard(text) {
|
|
42247
|
+
let parsed;
|
|
42248
|
+
try {
|
|
42249
|
+
parsed = JSON.parse(text, (_key, value) => {
|
|
42250
|
+
if (typeof value === 'object' && value !== null) {
|
|
42251
|
+
const tagged = value[BINARY_TAG];
|
|
42252
|
+
if (typeof tagged === 'string') {
|
|
42253
|
+
return base64ToUint8(tagged);
|
|
42254
|
+
}
|
|
42255
|
+
}
|
|
42256
|
+
return value;
|
|
42257
|
+
});
|
|
42258
|
+
}
|
|
42259
|
+
catch {
|
|
42260
|
+
return null;
|
|
42261
|
+
}
|
|
42262
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
42263
|
+
return null;
|
|
42264
|
+
}
|
|
42265
|
+
const candidate = parsed;
|
|
42266
|
+
if (candidate.marker !== ELEMENT_CLIPBOARD_MARKER ||
|
|
42267
|
+
candidate.version !== ELEMENT_CLIPBOARD_VERSION ||
|
|
42268
|
+
!Array.isArray(candidate.elements) ||
|
|
42269
|
+
candidate.elements.length === 0 ||
|
|
42270
|
+
!candidate.elements.every(isElementLike)) {
|
|
42271
|
+
return null;
|
|
42272
|
+
}
|
|
42273
|
+
return {
|
|
42274
|
+
elements: candidate.elements,
|
|
42275
|
+
isTemplate: candidate.isTemplate === true,
|
|
42276
|
+
};
|
|
42277
|
+
}
|
|
42278
|
+
|
|
42279
|
+
/**
|
|
42280
|
+
* The WRITE half of Outline view: turn a keystroke into a new deck.
|
|
42281
|
+
*
|
|
42282
|
+
* Pure and total: `applyOutlineEdit` takes the slides it is given and returns
|
|
42283
|
+
* new slides, never mutating the input. That shape is deliberate. Every binding
|
|
42284
|
+
* already has a history mechanism that watches its slide state, so handing back
|
|
42285
|
+
* a fresh `PptxSlide[]` makes undo/redo work through the machinery each binding
|
|
42286
|
+
* already has instead of asking five of them to grow an outline-specific
|
|
42287
|
+
* history path.
|
|
42288
|
+
*
|
|
42289
|
+
* What is intentionally NOT implemented, so nobody reads its absence as a bug:
|
|
42290
|
+
*
|
|
42291
|
+
* **Tab on a title row does nothing.** In PowerPoint, demoting a title merges
|
|
42292
|
+
* that slide into the one above it and promoting a top-level bullet splits a
|
|
42293
|
+
* new slide out. Both are safe there because PowerPoint's outline owns the
|
|
42294
|
+
* whole slide. Here a slide carries arbitrary elements (images, charts, tables,
|
|
42295
|
+
* ink) that the outline cannot see, so merging two slides would silently
|
|
42296
|
+
* destroy content the user never had on screen. Levels move within a body,
|
|
42297
|
+
* slides are created by Enter on a title, and nothing in this view deletes a
|
|
42298
|
+
* slide.
|
|
42299
|
+
*
|
|
42300
|
+
* @module render/outline-view-edit
|
|
42301
|
+
*/
|
|
42302
|
+
/**
|
|
42303
|
+
* Translate a key press inside an outline row into an edit.
|
|
42304
|
+
*
|
|
42305
|
+
* Both of PowerPoint's spellings are honoured: bare Tab / Shift+Tab, and the
|
|
42306
|
+
* Alt+Shift+Arrow chords that work anywhere in PowerPoint's outline. Anything
|
|
42307
|
+
* with Ctrl or Meta is left alone so the browser keeps its own shortcuts, and
|
|
42308
|
+
* so Ctrl+Z reaches the binding's undo rather than being eaten here.
|
|
42309
|
+
*/
|
|
42310
|
+
function mapOutlineKey(input, rowKey) {
|
|
42311
|
+
const none = { edit: null, preventDefault: false };
|
|
42312
|
+
if (input.ctrlKey || input.metaKey) {
|
|
42313
|
+
return none;
|
|
42314
|
+
}
|
|
42315
|
+
if (input.key === 'Tab' && !input.altKey) {
|
|
42316
|
+
return {
|
|
42317
|
+
edit: { type: 'indent', key: rowKey, delta: input.shiftKey ? -1 : 1 },
|
|
42318
|
+
preventDefault: true,
|
|
42319
|
+
};
|
|
42320
|
+
}
|
|
42321
|
+
if (input.altKey && input.shiftKey && (input.key === 'ArrowRight' || input.key === 'ArrowLeft')) {
|
|
42322
|
+
return {
|
|
42323
|
+
edit: { type: 'indent', key: rowKey, delta: input.key === 'ArrowRight' ? 1 : -1 },
|
|
42324
|
+
preventDefault: true,
|
|
42325
|
+
};
|
|
42326
|
+
}
|
|
42327
|
+
if (input.key === 'Enter' && !input.shiftKey && !input.altKey) {
|
|
42328
|
+
return { edit: { type: 'insertAfter', key: rowKey }, preventDefault: true };
|
|
42329
|
+
}
|
|
42330
|
+
return none;
|
|
42331
|
+
}
|
|
42332
|
+
// ---------------------------------------------------------------------------
|
|
42333
|
+
// Paragraph writing
|
|
42334
|
+
// ---------------------------------------------------------------------------
|
|
42335
|
+
/** Clone a segment list, stamping (or clearing) the paragraph's `a:pPr/@lvl`. */
|
|
42336
|
+
function withLevel(segments, level) {
|
|
42337
|
+
return segments.map((segment, index) => {
|
|
42338
|
+
if (index > 0) {
|
|
42339
|
+
return segment;
|
|
42340
|
+
}
|
|
42341
|
+
const next = { ...segment };
|
|
42342
|
+
if (level > 0) {
|
|
42343
|
+
next.paragraphLevel = Math.min(level, MAX_PARAGRAPH_LEVEL);
|
|
42344
|
+
}
|
|
42345
|
+
else {
|
|
42346
|
+
delete next.paragraphLevel;
|
|
42347
|
+
}
|
|
42348
|
+
return next;
|
|
42349
|
+
});
|
|
42350
|
+
}
|
|
42351
|
+
/**
|
|
42352
|
+
* Rebuild one paragraph's segments for `text`.
|
|
42353
|
+
*
|
|
42354
|
+
* An UNCHANGED paragraph is reused verbatim rather than remapped. That is what
|
|
42355
|
+
* keeps equations, fields, hyperlinks and soft line breaks intact while someone
|
|
42356
|
+
* types on a different line: remapping redistributes characters across runs,
|
|
42357
|
+
* which is exactly right for the line being edited and pure loss for every
|
|
42358
|
+
* other line in the same text body.
|
|
42359
|
+
*/
|
|
42360
|
+
function rebuildParagraph(group, donor, text, elementStyle) {
|
|
42361
|
+
if (group && paragraphGroupText(group) === text) {
|
|
42362
|
+
return [...(group.marker ? [group.marker] : []), ...group.content];
|
|
42363
|
+
}
|
|
42364
|
+
const source = group ?? donor;
|
|
42365
|
+
const marker = source?.marker ? [source.marker] : [];
|
|
42366
|
+
const content = remapTextToSegments(text, source?.content, elementStyle);
|
|
42367
|
+
return [...marker, ...content];
|
|
42368
|
+
}
|
|
42369
|
+
/**
|
|
42370
|
+
* Write paragraphs back onto an element, returning a new element.
|
|
42371
|
+
*
|
|
42372
|
+
* `element.text` is rewritten from the row text, which means it no longer
|
|
42373
|
+
* carries the bullet glyphs core prefixes on load. That is correct rather than
|
|
42374
|
+
* lossy: `textSegments` is what both the renderer and the save writer read when
|
|
42375
|
+
* it exists, and the glyph is re-derived from the paragraph's own bullet
|
|
42376
|
+
* properties, which travel on the preserved marker segment.
|
|
42377
|
+
*/
|
|
42378
|
+
function writeElementParagraphs(element, paragraphs) {
|
|
42379
|
+
const groups = groupElementParagraphs(element);
|
|
42380
|
+
const donor = groups[groups.length - 1];
|
|
42381
|
+
const style = hasTextProperties(element) ? element.textStyle : undefined;
|
|
42382
|
+
const segments = [];
|
|
42383
|
+
for (const [index, paragraph] of paragraphs.entries()) {
|
|
42384
|
+
if (index > 0) {
|
|
42385
|
+
const previous = segments[segments.length - 1];
|
|
42386
|
+
segments.push({
|
|
42387
|
+
text: '\n',
|
|
42388
|
+
style: { ...(previous?.style ?? style ?? {}) },
|
|
42389
|
+
isParagraphBreak: true,
|
|
42390
|
+
});
|
|
42391
|
+
}
|
|
42392
|
+
segments.push(...withLevel(rebuildParagraph(groups[index], donor, paragraph.text, style), paragraph.level));
|
|
42393
|
+
}
|
|
42394
|
+
return {
|
|
42395
|
+
...element,
|
|
42396
|
+
text: paragraphs.map((paragraph) => paragraph.text).join('\n'),
|
|
42397
|
+
textSegments: segments,
|
|
42398
|
+
};
|
|
42399
|
+
}
|
|
42400
|
+
// ---------------------------------------------------------------------------
|
|
42401
|
+
// Element / slide creation
|
|
42402
|
+
// ---------------------------------------------------------------------------
|
|
42403
|
+
const DEFAULT_CANVAS = { width: 960, height: 540 };
|
|
42404
|
+
/**
|
|
42405
|
+
* Build the title element for a slide that had none.
|
|
42406
|
+
*
|
|
42407
|
+
* Created WITHOUT `rawXml`: the save writer only synthesises a well-formed
|
|
42408
|
+
* `<p:sp>` for elements that carry no raw XML, so handing it a fabricated
|
|
42409
|
+
* `<p:ph>` stub would short-circuit that and emit a shape with no `spPr` and no
|
|
42410
|
+
* `txBody`. The element is identified as the title by its NAME instead, which
|
|
42411
|
+
* `resolveSlideOutlineElements` matches.
|
|
42412
|
+
*/
|
|
42413
|
+
function createTitleElement(text, options) {
|
|
42414
|
+
const canvas = options.canvas ?? DEFAULT_CANVAS;
|
|
42415
|
+
return {
|
|
42416
|
+
type: 'text',
|
|
42417
|
+
id: options.idGenerator ? options.idGenerator() : generateElementId(),
|
|
42418
|
+
name: OUTLINE_TITLE_ELEMENT_NAME,
|
|
42419
|
+
x: Math.round(canvas.width * 0.06),
|
|
42420
|
+
y: Math.round(canvas.height * 0.08),
|
|
42421
|
+
width: Math.round(canvas.width * 0.88),
|
|
42422
|
+
height: Math.round(canvas.height * 0.17),
|
|
42423
|
+
text,
|
|
42424
|
+
textStyle: { fontSize: 36, bold: true },
|
|
42425
|
+
textSegments: [{ text, style: { fontSize: 36, bold: true } }],
|
|
42426
|
+
};
|
|
42427
|
+
}
|
|
42428
|
+
/** Renumber slides so `slideNumber` still matches document order after an insert. */
|
|
42429
|
+
function renumber(slides) {
|
|
42430
|
+
return slides.map((slide, index) => ({ ...slide, slideNumber: index + 1 }));
|
|
42431
|
+
}
|
|
42432
|
+
// ---------------------------------------------------------------------------
|
|
42433
|
+
// Apply
|
|
42434
|
+
// ---------------------------------------------------------------------------
|
|
42435
|
+
function unchanged(slides, row) {
|
|
42436
|
+
return {
|
|
42437
|
+
slides,
|
|
42438
|
+
changed: false,
|
|
42439
|
+
focusKey: row?.key ?? null,
|
|
42440
|
+
activeSlideIndex: row?.slideIndex ?? 0,
|
|
42441
|
+
};
|
|
42442
|
+
}
|
|
42443
|
+
/** Replace one element on one slide, returning fresh slide + deck arrays. */
|
|
42444
|
+
function replaceElement(slides, slideIndex, elementId, next) {
|
|
42445
|
+
return slides.map((slide, index) => index === slideIndex
|
|
42446
|
+
? {
|
|
42447
|
+
...slide,
|
|
42448
|
+
elements: (slide.elements ?? []).map((element) => element.id === elementId ? next : element),
|
|
42449
|
+
}
|
|
42450
|
+
: slide);
|
|
42451
|
+
}
|
|
42452
|
+
function editParagraphs(slides, row, mutate) {
|
|
42453
|
+
const slide = slides[row.slideIndex];
|
|
42454
|
+
const element = (slide?.elements ?? []).find((candidate) => candidate.id === row.elementId);
|
|
42455
|
+
if (!element) {
|
|
42456
|
+
return null;
|
|
42457
|
+
}
|
|
42458
|
+
const paragraphs = readElementParagraphs(element);
|
|
42459
|
+
// A row can address the paragraph one past the end: an element whose text is
|
|
42460
|
+
// entirely empty reads as zero paragraphs but still owns row 0.
|
|
42461
|
+
while (paragraphs.length <= row.paragraphIndex) {
|
|
42462
|
+
paragraphs.push({ text: '', level: 0 });
|
|
42463
|
+
}
|
|
42464
|
+
const next = mutate(paragraphs);
|
|
42465
|
+
if (!next) {
|
|
42466
|
+
return null;
|
|
42467
|
+
}
|
|
42468
|
+
return {
|
|
42469
|
+
slides: replaceElement(slides, row.slideIndex, element.id, writeElementParagraphs(element, next)),
|
|
42470
|
+
changed: true,
|
|
42471
|
+
focusKey: row.key,
|
|
42472
|
+
activeSlideIndex: row.slideIndex,
|
|
42473
|
+
};
|
|
42474
|
+
}
|
|
42475
|
+
/**
|
|
42476
|
+
* An outline row is one LINE. Newlines a paste drags in are folded to spaces
|
|
42477
|
+
* rather than split into extra paragraphs, because splitting here would leave
|
|
42478
|
+
* the caller's row keys addressing paragraphs that had silently moved.
|
|
42479
|
+
*/
|
|
42480
|
+
function oneLine(text) {
|
|
42481
|
+
return text.replace(/[\r\n]+/g, ' ');
|
|
42482
|
+
}
|
|
42483
|
+
function applySetText(slides, row, raw, options) {
|
|
42484
|
+
const text = oneLine(raw);
|
|
42485
|
+
if (row.elementId === null) {
|
|
42486
|
+
if (text.length === 0) {
|
|
42487
|
+
return unchanged([...slides], row);
|
|
42488
|
+
}
|
|
42489
|
+
const element = createTitleElement(text, options);
|
|
42490
|
+
// Prepended, not appended: the fallback resolver reads the FIRST
|
|
42491
|
+
// text-bearing element as the title, and a slide reaching this branch has
|
|
42492
|
+
// no placeholder to anchor that decision to.
|
|
42493
|
+
const next = slides.map((slide, index) => index === row.slideIndex
|
|
42494
|
+
? { ...slide, elements: [element, ...(slide.elements ?? [])] }
|
|
42495
|
+
: slide);
|
|
42496
|
+
return {
|
|
42497
|
+
slides: next,
|
|
42498
|
+
changed: true,
|
|
42499
|
+
focusKey: outlineRowKey(row.slideId, element.id, 0),
|
|
42500
|
+
activeSlideIndex: row.slideIndex,
|
|
42501
|
+
};
|
|
42502
|
+
}
|
|
42503
|
+
const result = editParagraphs(slides, row, (paragraphs) => {
|
|
42504
|
+
if (paragraphs[row.paragraphIndex].text === text) {
|
|
42505
|
+
return null;
|
|
42506
|
+
}
|
|
42507
|
+
const next = [...paragraphs];
|
|
42508
|
+
next[row.paragraphIndex] = { ...next[row.paragraphIndex], text };
|
|
42509
|
+
return next;
|
|
42510
|
+
});
|
|
42511
|
+
return result ?? unchanged([...slides], row);
|
|
42512
|
+
}
|
|
42513
|
+
function applyIndent(slides, row, delta) {
|
|
42514
|
+
// Titles are the outline's leftmost column and there is nothing to promote
|
|
42515
|
+
// them into: see the module docstring for why demoting one does not merge
|
|
42516
|
+
// slides here.
|
|
42517
|
+
if (row.kind !== 'body' || row.elementId === null || delta === 0) {
|
|
42518
|
+
return unchanged([...slides], row);
|
|
42519
|
+
}
|
|
42520
|
+
const result = editParagraphs(slides, row, (paragraphs) => {
|
|
42521
|
+
const current = paragraphs[row.paragraphIndex];
|
|
42522
|
+
const level = Math.min(Math.max(current.level + (delta > 0 ? 1 : -1), 0), MAX_PARAGRAPH_LEVEL);
|
|
42523
|
+
if (level === current.level) {
|
|
42524
|
+
return null;
|
|
42525
|
+
}
|
|
42526
|
+
const next = [...paragraphs];
|
|
42527
|
+
next[row.paragraphIndex] = { ...current, level };
|
|
42528
|
+
return next;
|
|
42529
|
+
});
|
|
42530
|
+
return result ?? unchanged([...slides], row);
|
|
42531
|
+
}
|
|
42532
|
+
function applyInsertAfter(slides, row, options) {
|
|
42533
|
+
if (row.kind === 'title') {
|
|
42534
|
+
// PowerPoint's defining outline gesture: Enter on a title starts a slide.
|
|
42535
|
+
const slide = {
|
|
42536
|
+
id: makeSlideId(options.idGenerator),
|
|
42537
|
+
rId: '',
|
|
42538
|
+
slideNumber: row.slideIndex + 2,
|
|
42539
|
+
elements: [],
|
|
42540
|
+
};
|
|
42541
|
+
const next = renumber([
|
|
42542
|
+
...slides.slice(0, row.slideIndex + 1),
|
|
42543
|
+
slide,
|
|
42544
|
+
...slides.slice(row.slideIndex + 1),
|
|
42545
|
+
]);
|
|
42546
|
+
return {
|
|
42547
|
+
slides: next,
|
|
42548
|
+
changed: true,
|
|
42549
|
+
focusKey: outlineRowKey(slide.id, null, 0),
|
|
42550
|
+
activeSlideIndex: row.slideIndex + 1,
|
|
42551
|
+
};
|
|
42552
|
+
}
|
|
42553
|
+
const result = editParagraphs(slides, row, (paragraphs) => {
|
|
42554
|
+
const next = [...paragraphs];
|
|
42555
|
+
next.splice(row.paragraphIndex + 1, 0, {
|
|
42556
|
+
text: '',
|
|
42557
|
+
level: paragraphs[row.paragraphIndex].level,
|
|
42558
|
+
});
|
|
42559
|
+
return next;
|
|
42560
|
+
});
|
|
42561
|
+
if (!result) {
|
|
42562
|
+
return unchanged([...slides], row);
|
|
42563
|
+
}
|
|
42564
|
+
return {
|
|
42565
|
+
...result,
|
|
42566
|
+
focusKey: outlineRowKey(row.slideId, row.elementId, row.paragraphIndex + 1),
|
|
42567
|
+
};
|
|
42568
|
+
}
|
|
42569
|
+
/**
|
|
42570
|
+
* Apply one outline edit to a deck.
|
|
42571
|
+
*
|
|
42572
|
+
* Always returns a result, never throws: a key that no longer resolves (the row
|
|
42573
|
+
* was removed by a concurrent collaborator, or the deck reloaded under the
|
|
42574
|
+
* pane) yields `changed: false` rather than an exception thrown at someone who
|
|
42575
|
+
* was only typing.
|
|
42576
|
+
*/
|
|
42577
|
+
function applyOutlineEdit(slides, edit, options = {}) {
|
|
42578
|
+
const row = findOutlineRow(buildOutline(slides), edit.key);
|
|
42579
|
+
if (!row) {
|
|
42580
|
+
return unchanged([...slides]);
|
|
42581
|
+
}
|
|
42582
|
+
switch (edit.type) {
|
|
42583
|
+
case 'setText':
|
|
42584
|
+
return applySetText(slides, row, edit.text, options);
|
|
42585
|
+
case 'indent':
|
|
42586
|
+
return applyIndent(slides, row, edit.delta);
|
|
42587
|
+
case 'insertAfter':
|
|
42588
|
+
return applyInsertAfter(slides, row, options);
|
|
42589
|
+
default:
|
|
42590
|
+
return unchanged([...slides], row);
|
|
42591
|
+
}
|
|
42592
|
+
}
|
|
42593
|
+
|
|
41271
42594
|
/**
|
|
41272
42595
|
* The editor keymap: one source of truth for "what does this key do".
|
|
41273
42596
|
*
|
|
@@ -45493,144 +46816,6 @@ const COMMON_FONTS = [
|
|
|
45493
46816
|
'Verdana',
|
|
45494
46817
|
];
|
|
45495
46818
|
|
|
45496
|
-
/** MIME type bindings should use when writing the payload as a custom clipboard format. */
|
|
45497
|
-
const ELEMENT_CLIPBOARD_MIME_TYPE = 'application/x-pptx-viewer-elements+json';
|
|
45498
|
-
/** Marker identifying a serialized element-clipboard payload. */
|
|
45499
|
-
const ELEMENT_CLIPBOARD_MARKER = 'pptx-viewer/elements';
|
|
45500
|
-
/** Current codec version; {@link deserializeElementClipboard} rejects others. */
|
|
45501
|
-
const ELEMENT_CLIPBOARD_VERSION = 1;
|
|
45502
|
-
/** Standard paste/duplicate cascade offset in px (applied to both axes). */
|
|
45503
|
-
const PASTE_OFFSET_PX = 20;
|
|
45504
|
-
/** Generate a unique element id (`el-<timestamp>-<random>`). */
|
|
45505
|
-
function generateElementId() {
|
|
45506
|
-
return `el-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
45507
|
-
}
|
|
45508
|
-
/**
|
|
45509
|
-
* Build the id for a pasted / duplicated clone so that it routes to the same
|
|
45510
|
-
* store it is inserted into.
|
|
45511
|
-
*
|
|
45512
|
-
* In edit-template mode the clone lands in the template store, so it must keep
|
|
45513
|
-
* a template (`master-` / `layout-`) prefix; otherwise later edits (which route
|
|
45514
|
-
* by id prefix) would target the wrong store and be lost. Outside template mode
|
|
45515
|
-
* a normal id is generated.
|
|
45516
|
-
*/
|
|
45517
|
-
function makeCloneId(intoTemplate, sourceId) {
|
|
45518
|
-
if (!intoTemplate) {
|
|
45519
|
-
return generateElementId();
|
|
45520
|
-
}
|
|
45521
|
-
if (sourceId.startsWith('master-')) {
|
|
45522
|
-
return `master-${generateElementId()}`;
|
|
45523
|
-
}
|
|
45524
|
-
return `layout-${generateElementId()}`;
|
|
45525
|
-
}
|
|
45526
|
-
/**
|
|
45527
|
-
* Snapshot a copied/cut element into the in-memory clipboard payload.
|
|
45528
|
-
* Deep-clones so later canvas edits never mutate the clipboard content.
|
|
45529
|
-
*/
|
|
45530
|
-
function buildElementClipboardPayload(element, isTemplate) {
|
|
45531
|
-
return { element: structuredClone(element), isTemplate };
|
|
45532
|
-
}
|
|
45533
|
-
/**
|
|
45534
|
-
* Produce the clone inserted by paste/duplicate: a deep copy with a fresh
|
|
45535
|
-
* (template-prefix aware) id and the standard cascade offset applied.
|
|
45536
|
-
*/
|
|
45537
|
-
function cloneElementForPaste(element, options = {}) {
|
|
45538
|
-
const clone = structuredClone(element);
|
|
45539
|
-
clone.id = makeCloneId(options.intoTemplate ?? false, element.id);
|
|
45540
|
-
clone.x += options.offsetX ?? PASTE_OFFSET_PX;
|
|
45541
|
-
clone.y += options.offsetY ?? PASTE_OFFSET_PX;
|
|
45542
|
-
return clone;
|
|
45543
|
-
}
|
|
45544
|
-
/** Clone every element in decoded clipboard data for insertion (fresh ids + offset). */
|
|
45545
|
-
function prepareElementsForPaste(data, options = {}) {
|
|
45546
|
-
return data.elements.map((element) => cloneElementForPaste(element, options));
|
|
45547
|
-
}
|
|
45548
|
-
/** Tag used to mark base64-encoded binary fields inside the JSON payload. */
|
|
45549
|
-
const BINARY_TAG = '__pptxU8';
|
|
45550
|
-
function uint8ToBase64(bytes) {
|
|
45551
|
-
let binary = '';
|
|
45552
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
45553
|
-
binary += String.fromCharCode(bytes[i]);
|
|
45554
|
-
}
|
|
45555
|
-
return btoa(binary);
|
|
45556
|
-
}
|
|
45557
|
-
function base64ToUint8(base64) {
|
|
45558
|
-
const binary = atob(base64);
|
|
45559
|
-
const bytes = new Uint8Array(binary.length);
|
|
45560
|
-
for (let i = 0; i < binary.length; i++) {
|
|
45561
|
-
bytes[i] = binary.charCodeAt(i);
|
|
45562
|
-
}
|
|
45563
|
-
return bytes;
|
|
45564
|
-
}
|
|
45565
|
-
/**
|
|
45566
|
-
* Serialize elements to the marked, versioned JSON clipboard string.
|
|
45567
|
-
* `Uint8Array` fields anywhere in the element tree (embedded workbooks, raw
|
|
45568
|
-
* part bytes) are base64-tagged so they survive the text round trip.
|
|
45569
|
-
*/
|
|
45570
|
-
function serializeElementClipboard(elements, isTemplate = false) {
|
|
45571
|
-
return JSON.stringify({
|
|
45572
|
-
marker: ELEMENT_CLIPBOARD_MARKER,
|
|
45573
|
-
version: ELEMENT_CLIPBOARD_VERSION,
|
|
45574
|
-
isTemplate,
|
|
45575
|
-
elements,
|
|
45576
|
-
}, (_key, value) => {
|
|
45577
|
-
if (value instanceof Uint8Array) {
|
|
45578
|
-
return { [BINARY_TAG]: uint8ToBase64(value) };
|
|
45579
|
-
}
|
|
45580
|
-
return value;
|
|
45581
|
-
});
|
|
45582
|
-
}
|
|
45583
|
-
function isElementLike(value) {
|
|
45584
|
-
if (typeof value !== 'object' || value === null) {
|
|
45585
|
-
return false;
|
|
45586
|
-
}
|
|
45587
|
-
const candidate = value;
|
|
45588
|
-
return (typeof candidate.id === 'string' &&
|
|
45589
|
-
typeof candidate.type === 'string' &&
|
|
45590
|
-
typeof candidate.x === 'number' &&
|
|
45591
|
-
typeof candidate.y === 'number' &&
|
|
45592
|
-
typeof candidate.width === 'number' &&
|
|
45593
|
-
typeof candidate.height === 'number');
|
|
45594
|
-
}
|
|
45595
|
-
/**
|
|
45596
|
-
* Decode a clipboard string produced by {@link serializeElementClipboard}.
|
|
45597
|
-
* Returns `null` for anything else (foreign clipboard text, malformed JSON,
|
|
45598
|
-
* wrong marker/version, or structurally invalid elements), so callers can fall
|
|
45599
|
-
* back to their plain-text paste path.
|
|
45600
|
-
*/
|
|
45601
|
-
function deserializeElementClipboard(text) {
|
|
45602
|
-
let parsed;
|
|
45603
|
-
try {
|
|
45604
|
-
parsed = JSON.parse(text, (_key, value) => {
|
|
45605
|
-
if (typeof value === 'object' && value !== null) {
|
|
45606
|
-
const tagged = value[BINARY_TAG];
|
|
45607
|
-
if (typeof tagged === 'string') {
|
|
45608
|
-
return base64ToUint8(tagged);
|
|
45609
|
-
}
|
|
45610
|
-
}
|
|
45611
|
-
return value;
|
|
45612
|
-
});
|
|
45613
|
-
}
|
|
45614
|
-
catch {
|
|
45615
|
-
return null;
|
|
45616
|
-
}
|
|
45617
|
-
if (typeof parsed !== 'object' || parsed === null) {
|
|
45618
|
-
return null;
|
|
45619
|
-
}
|
|
45620
|
-
const candidate = parsed;
|
|
45621
|
-
if (candidate.marker !== ELEMENT_CLIPBOARD_MARKER ||
|
|
45622
|
-
candidate.version !== ELEMENT_CLIPBOARD_VERSION ||
|
|
45623
|
-
!Array.isArray(candidate.elements) ||
|
|
45624
|
-
candidate.elements.length === 0 ||
|
|
45625
|
-
!candidate.elements.every(isElementLike)) {
|
|
45626
|
-
return null;
|
|
45627
|
-
}
|
|
45628
|
-
return {
|
|
45629
|
-
elements: candidate.elements,
|
|
45630
|
-
isTemplate: candidate.isTemplate === true,
|
|
45631
|
-
};
|
|
45632
|
-
}
|
|
45633
|
-
|
|
45634
46819
|
/** Immutably replace one slide's inherited element list. */
|
|
45635
46820
|
function setTemplateElements(map, slideId, elements) {
|
|
45636
46821
|
return { ...map, [slideId]: elements };
|
|
@@ -53251,6 +54436,48 @@ const translationsEn = {
|
|
|
53251
54436
|
'pptx.animation.sequence.byParagraph': 'By Paragraph',
|
|
53252
54437
|
'pptx.animation.sequence.byWord': 'By Word',
|
|
53253
54438
|
'pptx.animation.sequence.byLetter': 'By Letter',
|
|
54439
|
+
// Motion-path authoring: the gallery families/presets, the panel row, and
|
|
54440
|
+
// the on-canvas path editor handles.
|
|
54441
|
+
'pptx.animation.motionPath': 'Motion Paths',
|
|
54442
|
+
'pptx.animation.motionPath.family.lines': 'Lines',
|
|
54443
|
+
'pptx.animation.motionPath.family.arcs': 'Arcs',
|
|
54444
|
+
'pptx.animation.motionPath.family.turns': 'Turns',
|
|
54445
|
+
'pptx.animation.motionPath.family.shapes': 'Shapes',
|
|
54446
|
+
'pptx.animation.motionPath.family.loops': 'Loops',
|
|
54447
|
+
'pptx.animation.motionPath.preset.lineRight': 'Right',
|
|
54448
|
+
'pptx.animation.motionPath.preset.lineLeft': 'Left',
|
|
54449
|
+
'pptx.animation.motionPath.preset.lineDown': 'Down',
|
|
54450
|
+
'pptx.animation.motionPath.preset.lineUp': 'Up',
|
|
54451
|
+
'pptx.animation.motionPath.preset.lineDiagonalUpRight': 'Diagonal Up Right',
|
|
54452
|
+
'pptx.animation.motionPath.preset.lineDiagonalDownRight': 'Diagonal Down Right',
|
|
54453
|
+
'pptx.animation.motionPath.preset.lineDiagonalUpLeft': 'Diagonal Up Left',
|
|
54454
|
+
'pptx.animation.motionPath.preset.lineDiagonalDownLeft': 'Diagonal Down Left',
|
|
54455
|
+
'pptx.animation.motionPath.preset.arcUp': 'Arc Up',
|
|
54456
|
+
'pptx.animation.motionPath.preset.arcDown': 'Arc Down',
|
|
54457
|
+
'pptx.animation.motionPath.preset.arcRight': 'Arc Right',
|
|
54458
|
+
'pptx.animation.motionPath.preset.arcLeft': 'Arc Left',
|
|
54459
|
+
'pptx.animation.motionPath.preset.turnUp': 'Turn Up',
|
|
54460
|
+
'pptx.animation.motionPath.preset.turnDown': 'Turn Down',
|
|
54461
|
+
'pptx.animation.motionPath.preset.turnRight': 'Turn Right',
|
|
54462
|
+
'pptx.animation.motionPath.preset.turnLeft': 'Turn Left',
|
|
54463
|
+
'pptx.animation.motionPath.preset.sCurve': 'S Curve',
|
|
54464
|
+
'pptx.animation.motionPath.preset.zigzag': 'Zigzag',
|
|
54465
|
+
'pptx.animation.motionPath.preset.circle': 'Circle',
|
|
54466
|
+
'pptx.animation.motionPath.preset.square': 'Square',
|
|
54467
|
+
'pptx.animation.motionPath.preset.triangle': 'Triangle',
|
|
54468
|
+
'pptx.animation.motionPath.preset.diamond': 'Diamond',
|
|
54469
|
+
'pptx.animation.motionPath.preset.hexagon': 'Hexagon',
|
|
54470
|
+
'pptx.animation.motionPath.preset.loopDeLoop': 'Loop de Loop',
|
|
54471
|
+
'pptx.animation.motionPath.preset.figureEight': 'Figure 8',
|
|
54472
|
+
'pptx.animation.motionPath.preset.spiral': 'Spiral',
|
|
54473
|
+
'pptx.animation.motionPath.label': 'Motion Path',
|
|
54474
|
+
'pptx.animation.motionPath.custom': 'Custom Path',
|
|
54475
|
+
'pptx.animation.motionPath.none': 'No motion path',
|
|
54476
|
+
'pptx.animation.motionPath.remove': 'Remove motion path',
|
|
54477
|
+
'pptx.animation.motionPath.editHint': 'Drag the end point on the slide to retarget the path',
|
|
54478
|
+
'pptx.animation.motionPath.endHandle': 'Motion path end point',
|
|
54479
|
+
'pptx.animation.motionPath.overlay': 'Motion path preview',
|
|
54480
|
+
'pptx.animations.motionPathGalleryAria': 'Motion Paths: Lines, Arcs, Turns, Shapes, and Loops',
|
|
53254
54481
|
// --- 2026-07-03 missing-key sweep: keys used by Vue/Angular with no
|
|
53255
54482
|
// existing dictionary entry (React has 0 such gaps and is the ground-
|
|
53256
54483
|
// truth reference these were derived from). Appended flat rather than
|
|
@@ -53408,6 +54635,11 @@ const translationsEn = {
|
|
|
53408
54635
|
'pptx.view.masterViews': 'Master Views',
|
|
53409
54636
|
'pptx.view.normal': 'Normal',
|
|
53410
54637
|
'pptx.view.presentationViews': 'Presentation Views',
|
|
54638
|
+
'pptx.view.outlineView': 'Outline View',
|
|
54639
|
+
'pptx.view.outlineViewTooltip': 'Outline view: edit the deck as indented text',
|
|
54640
|
+
'pptx.outline.titleLine': 'Slide title',
|
|
54641
|
+
'pptx.outline.bodyLine': 'Outline line',
|
|
54642
|
+
'pptx.outline.hint': 'Tab and Shift+Tab change the level. Enter adds a line; on a title it adds a slide.',
|
|
53411
54643
|
'pptx.view.readingView': 'Reading View',
|
|
53412
54644
|
'pptx.view.selection': 'Selection',
|
|
53413
54645
|
'pptx.view.slideMasterTooltip': 'Edit slide masters and layouts',
|
|
@@ -56270,7 +57502,7 @@ function createLocalStorageBackend(namespace) {
|
|
|
56270
57502
|
/** Try IndexedDB first; fall back to localStorage on any failure. */
|
|
56271
57503
|
async function resolveBackend(dbName, namespace) {
|
|
56272
57504
|
try {
|
|
56273
|
-
const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-
|
|
57505
|
+
const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-DmCC3jY4.mjs');
|
|
56274
57506
|
const db = await openChatDb(dbName);
|
|
56275
57507
|
return createIdbBackend(db);
|
|
56276
57508
|
}
|
|
@@ -74602,6 +75834,11 @@ class SlideCanvasComponent {
|
|
|
74602
75834
|
position: 'relative',
|
|
74603
75835
|
overflow: 'hidden',
|
|
74604
75836
|
'box-shadow': '0 10px 40px rgba(0, 0, 0, 0.35)',
|
|
75837
|
+
// Motion-path keyframes translate by a fraction of the SLIDE, not of the
|
|
75838
|
+
// animated element's own box, so the stage publishes its size for those
|
|
75839
|
+
// `calc(var(--pptx-slide-w) * f)` offsets to resolve against.
|
|
75840
|
+
'--pptx-slide-w': `${size.width}px`,
|
|
75841
|
+
'--pptx-slide-h': `${size.height}px`,
|
|
74605
75842
|
// Resolved slide background: image → gradient → pattern → solid colour.
|
|
74606
75843
|
// A stacked overlay layer (the morph departing slide) opts out entirely
|
|
74607
75844
|
// and stays see-through, so it cannot occlude the stage beneath it.
|
|
@@ -77582,6 +78819,249 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
77582
78819
|
`, styles: [":host{display:block}.pptx-ng-mtoolbar{position:relative;z-index:20;display:flex;align-items:center;gap:.25rem;padding:.25rem .5rem;min-height:52px;background:color-mix(in srgb,var(--pptx-secondary, #1f2937) 50%,transparent);border-bottom:1px solid var(--pptx-border, #374151);padding-top:max(env(safe-area-inset-top,0px),.25rem)}.pptx-ng-mtoolbar-spacer{flex:1 1 auto}.pptx-ng-mtoolbar-btn{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;border:none;border-radius:.375rem;background:transparent;color:color-mix(in srgb,var(--pptx-foreground, #f3f4f6) 80%,transparent);cursor:pointer;touch-action:manipulation;transition:background .12s,transform .08s;-webkit-tap-highlight-color:transparent}.pptx-ng-mtoolbar-btn:active:not([disabled]){transform:scale(.92)}.pptx-ng-mtoolbar-btn:hover:not([disabled]){background:color-mix(in srgb,var(--pptx-accent, #1f2937) 60%,transparent)}.pptx-ng-mtoolbar-btn.is-active{color:var(--pptx-primary, #6366f1)}.pptx-ng-mtoolbar-btn[disabled]{opacity:.35;cursor:not-allowed}.pptx-ng-mtoolbar-present{color:var(--pptx-primary, #6366f1)}.pptx-ng-mtoolbar-share{padding:0 .75rem;background:var(--pptx-primary, #6366f1);color:var(--pptx-primary-foreground, #ffffff)}.pptx-ng-mtoolbar-share:hover:not([disabled]){background:color-mix(in srgb,var(--pptx-primary, #6366f1) 90%,transparent)}.pptx-ng-mtoolbar-icon{width:1.25rem;height:1.25rem;flex-shrink:0}.pptx-ng-mtoolbar-icon.is-sm{width:1rem;height:1rem}\n"] }]
|
|
77583
78820
|
}], propDecorators: { canUndo: [{ type: i0.Input, args: [{ isSignal: true, alias: "canUndo", required: false }] }], canRedo: [{ type: i0.Input, args: [{ isSignal: true, alias: "canRedo", required: false }] }], canPresent: [{ type: i0.Input, args: [{ isSignal: true, alias: "canPresent", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], menuOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuOpen", required: false }] }], aiEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiEnabled", required: false }] }], aiPanelOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiPanelOpen", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], toggleMenu: [{ type: i0.Output, args: ["toggleMenu"] }], toggleAiPanel: [{ type: i0.Output, args: ["toggleAiPanel"] }], undo: [{ type: i0.Output, args: ["undo"] }], redo: [{ type: i0.Output, args: ["redo"] }], share: [{ type: i0.Output, args: ["share"] }], save: [{ type: i0.Output, args: ["save"] }], present: [{ type: i0.Output, args: ["present"] }] } });
|
|
77584
78821
|
|
|
78822
|
+
/**
|
|
78823
|
+
* motion-path-overlay.component.ts: draws the selected element's motion path on
|
|
78824
|
+
* the slide stage and lets the user drag its end point.
|
|
78825
|
+
*
|
|
78826
|
+
* Selector: `pptx-motion-path-overlay`
|
|
78827
|
+
*
|
|
78828
|
+
* WHY it is a stage-level sibling and not part of the element's own adorners: a
|
|
78829
|
+
* motion path routinely extends far outside the shape's bounding box, and the
|
|
78830
|
+
* element wrapper carries the shape's rotation / flip transform, which would
|
|
78831
|
+
* skew the path. Projected into the scaled stage (like the collaboration
|
|
78832
|
+
* overlays) it shares the stage's UNSCALED slide-pixel space, so the stage's
|
|
78833
|
+
* own `transform: scale()` applies the on-screen zoom exactly once and the only
|
|
78834
|
+
* zoom maths left is converting a pointer delta back into slide pixels.
|
|
78835
|
+
*
|
|
78836
|
+
* The DOM contract (`data-pptx-motion-path-overlay`,
|
|
78837
|
+
* `data-pptx-motion-path-handle="end"`) is deliberately neutral and identical
|
|
78838
|
+
* in every binding, so `e2e/` can address one viewer the same way it addresses
|
|
78839
|
+
* the next.
|
|
78840
|
+
*
|
|
78841
|
+
* Reference binding: packages/react/src/viewer/components/canvas/MotionPathOverlay.tsx
|
|
78842
|
+
*
|
|
78843
|
+
* @module viewer/motion-path-overlay
|
|
78844
|
+
*/
|
|
78845
|
+
/** Slide size assumed when the stage cannot be measured (detached overlay). */
|
|
78846
|
+
const FALLBACK_CANVAS = { width: 1280, height: 720 };
|
|
78847
|
+
class MotionPathOverlayComponent {
|
|
78848
|
+
/** The selected element; its centre is the path origin. */
|
|
78849
|
+
element = input(null, /* @ts-ignore */
|
|
78850
|
+
...(ngDevMode ? [{ debugName: "element" }] : /* istanbul ignore next */ []));
|
|
78851
|
+
/** The active slide's animations; the path is read off the matching entry. */
|
|
78852
|
+
animations = input([], /* @ts-ignore */
|
|
78853
|
+
...(ngDevMode ? [{ debugName: "animations" }] : /* istanbul ignore next */ []));
|
|
78854
|
+
/** Stage size in slide pixels: the unit the path fractions scale by. */
|
|
78855
|
+
canvasSize = input(FALLBACK_CANVAS, /* @ts-ignore */
|
|
78856
|
+
...(ngDevMode ? [{ debugName: "canvasSize" }] : /* istanbul ignore next */ []));
|
|
78857
|
+
/** Whether the deck is editable; a read-only deck draws no overlay at all. */
|
|
78858
|
+
canEdit = input(false, /* @ts-ignore */
|
|
78859
|
+
...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
78860
|
+
/** Emits an edited path (drag of the end handle) for the host to commit. */
|
|
78861
|
+
pathChange = output();
|
|
78862
|
+
overlayRef = viewChild('overlay', /* @ts-ignore */
|
|
78863
|
+
...(ngDevMode ? [{ debugName: "overlayRef" }] : /* istanbul ignore next */ []));
|
|
78864
|
+
drag = null;
|
|
78865
|
+
/** Guards a divide-by-zero when a host passes an unmeasured stage. */
|
|
78866
|
+
size = computed(() => {
|
|
78867
|
+
const size = this.canvasSize();
|
|
78868
|
+
return size.width > 0 && size.height > 0 ? size : FALLBACK_CANVAS;
|
|
78869
|
+
}, /* @ts-ignore */
|
|
78870
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
78871
|
+
/** The path applied to the selected element, or `''` when there is none. */
|
|
78872
|
+
path = computed(() => {
|
|
78873
|
+
const element = this.element();
|
|
78874
|
+
if (!element || !this.canEdit()) {
|
|
78875
|
+
return '';
|
|
78876
|
+
}
|
|
78877
|
+
return motionPathFor(this.animations(), element.id) ?? '';
|
|
78878
|
+
}, /* @ts-ignore */
|
|
78879
|
+
...(ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []));
|
|
78880
|
+
/** Slide-pixel frame the path fractions are measured against. */
|
|
78881
|
+
frame = computed(() => {
|
|
78882
|
+
const element = this.element();
|
|
78883
|
+
const size = this.size();
|
|
78884
|
+
return {
|
|
78885
|
+
originX: element ? element.x + element.width / 2 : 0,
|
|
78886
|
+
originY: element ? element.y + element.height / 2 : 0,
|
|
78887
|
+
slideWidth: size.width,
|
|
78888
|
+
slideHeight: size.height,
|
|
78889
|
+
};
|
|
78890
|
+
}, /* @ts-ignore */
|
|
78891
|
+
...(ngDevMode ? [{ debugName: "frame" }] : /* istanbul ignore next */ []));
|
|
78892
|
+
/** The `d` attribute of the drawn path; empty when nothing is drawable. */
|
|
78893
|
+
pathD = computed(() => {
|
|
78894
|
+
const path = this.path();
|
|
78895
|
+
return path ? motionPathToSvgD(path, this.frame()) : '';
|
|
78896
|
+
}, /* @ts-ignore */
|
|
78897
|
+
...(ngDevMode ? [{ debugName: "pathD" }] : /* istanbul ignore next */ []));
|
|
78898
|
+
/** Where the end handle sits, in slide pixels. */
|
|
78899
|
+
endPoint = computed(() => motionPathEndPixel(this.path(), this.frame()), /* @ts-ignore */
|
|
78900
|
+
...(ngDevMode ? [{ debugName: "endPoint" }] : /* istanbul ignore next */ []));
|
|
78901
|
+
/** A closed shape has no free end, so its handle stays inert. */
|
|
78902
|
+
editable = computed(() => this.canEdit() && isEditableMotionPath(this.path()), /* @ts-ignore */
|
|
78903
|
+
...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
|
|
78904
|
+
onHandlePointerDown(event) {
|
|
78905
|
+
if (!this.editable()) {
|
|
78906
|
+
return;
|
|
78907
|
+
}
|
|
78908
|
+
event.stopPropagation();
|
|
78909
|
+
event.preventDefault();
|
|
78910
|
+
capturePointer(event);
|
|
78911
|
+
this.drag = { pointerId: event.pointerId, clientX: event.clientX, clientY: event.clientY };
|
|
78912
|
+
}
|
|
78913
|
+
onHandlePointerMove(event) {
|
|
78914
|
+
const drag = this.drag;
|
|
78915
|
+
if (!drag || drag.pointerId !== event.pointerId) {
|
|
78916
|
+
return;
|
|
78917
|
+
}
|
|
78918
|
+
event.stopPropagation();
|
|
78919
|
+
const path = this.path();
|
|
78920
|
+
const frame = this.frame();
|
|
78921
|
+
const scale = this.stageScale();
|
|
78922
|
+
const end = this.endPoint();
|
|
78923
|
+
const nextX = (end.x + (event.clientX - drag.clientX) / scale - frame.originX) / frame.slideWidth;
|
|
78924
|
+
const nextY = (end.y + (event.clientY - drag.clientY) / scale - frame.originY) / frame.slideHeight;
|
|
78925
|
+
const next = setMotionPathEnd(path, nextX, nextY);
|
|
78926
|
+
if (next === path) {
|
|
78927
|
+
return;
|
|
78928
|
+
}
|
|
78929
|
+
// Re-anchor to the pointer so the next move measures from where the path
|
|
78930
|
+
// actually ended up, not from where the gesture began.
|
|
78931
|
+
this.drag = { pointerId: event.pointerId, clientX: event.clientX, clientY: event.clientY };
|
|
78932
|
+
this.pathChange.emit(next);
|
|
78933
|
+
}
|
|
78934
|
+
onHandlePointerUp(event) {
|
|
78935
|
+
if (this.drag?.pointerId !== event.pointerId) {
|
|
78936
|
+
return;
|
|
78937
|
+
}
|
|
78938
|
+
releasePointer(event);
|
|
78939
|
+
this.drag = null;
|
|
78940
|
+
}
|
|
78941
|
+
/**
|
|
78942
|
+
* The stage's on-screen scale, measured rather than plumbed.
|
|
78943
|
+
*
|
|
78944
|
+
* The overlay is rendered INSIDE the scaled stage at slide-pixel size, so the
|
|
78945
|
+
* ratio between its rendered width and the slide width is exactly the scale
|
|
78946
|
+
* the stage transform applied (auto-fit folded with the user's zoom). Reading
|
|
78947
|
+
* it here avoids threading a value the canvas owns privately, per instance,
|
|
78948
|
+
* through the whole viewer.
|
|
78949
|
+
*/
|
|
78950
|
+
stageScale() {
|
|
78951
|
+
const svg = this.overlayRef()?.nativeElement;
|
|
78952
|
+
if (!svg) {
|
|
78953
|
+
return 1;
|
|
78954
|
+
}
|
|
78955
|
+
const rendered = svg.getBoundingClientRect().width;
|
|
78956
|
+
return rendered > 0 ? rendered / this.size().width : 1;
|
|
78957
|
+
}
|
|
78958
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MotionPathOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
78959
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MotionPathOverlayComponent, isStandalone: true, selector: "pptx-motion-path-overlay", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: false, transformFunction: null }, animations: { classPropertyName: "animations", publicName: "animations", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pathChange: "pathChange" }, viewQueries: [{ propertyName: "overlayRef", first: true, predicate: ["overlay"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
78960
|
+
@if (pathD(); as d) {
|
|
78961
|
+
<svg
|
|
78962
|
+
#overlay
|
|
78963
|
+
class="pptx-ng-motion-path-overlay"
|
|
78964
|
+
data-pptx-motion-path-overlay="true"
|
|
78965
|
+
role="img"
|
|
78966
|
+
[attr.aria-label]="'pptx.animation.motionPath.overlay' | translate"
|
|
78967
|
+
[attr.width]="size().width"
|
|
78968
|
+
[attr.height]="size().height"
|
|
78969
|
+
>
|
|
78970
|
+
<path
|
|
78971
|
+
[attr.d]="d"
|
|
78972
|
+
fill="none"
|
|
78973
|
+
stroke="#0ea5e9"
|
|
78974
|
+
stroke-width="2"
|
|
78975
|
+
stroke-dasharray="6 4"
|
|
78976
|
+
vector-effect="non-scaling-stroke"
|
|
78977
|
+
/>
|
|
78978
|
+
<circle
|
|
78979
|
+
[attr.cx]="frame().originX"
|
|
78980
|
+
[attr.cy]="frame().originY"
|
|
78981
|
+
r="5"
|
|
78982
|
+
fill="#0ea5e9"
|
|
78983
|
+
opacity="0.55"
|
|
78984
|
+
/>
|
|
78985
|
+
<circle
|
|
78986
|
+
data-pptx-motion-path-handle="end"
|
|
78987
|
+
[class.is-editable]="editable()"
|
|
78988
|
+
[attr.cx]="endPoint().x"
|
|
78989
|
+
[attr.cy]="endPoint().y"
|
|
78990
|
+
r="7"
|
|
78991
|
+
fill="#ffffff"
|
|
78992
|
+
stroke="#0ea5e9"
|
|
78993
|
+
stroke-width="2"
|
|
78994
|
+
[attr.aria-label]="'pptx.animation.motionPath.endHandle' | translate"
|
|
78995
|
+
(pointerdown)="onHandlePointerDown($event)"
|
|
78996
|
+
(pointermove)="onHandlePointerMove($event)"
|
|
78997
|
+
(pointerup)="onHandlePointerUp($event)"
|
|
78998
|
+
(pointercancel)="onHandlePointerUp($event)"
|
|
78999
|
+
/>
|
|
79000
|
+
</svg>
|
|
79001
|
+
}
|
|
79002
|
+
`, isInline: true, styles: [":host{position:absolute;inset:0;pointer-events:none;overflow:visible}.pptx-ng-motion-path-overlay{position:absolute;top:0;left:0;z-index:45;pointer-events:none;overflow:visible}circle.is-editable{pointer-events:auto;cursor:move}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
79003
|
+
}
|
|
79004
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MotionPathOverlayComponent, decorators: [{
|
|
79005
|
+
type: Component,
|
|
79006
|
+
args: [{ selector: 'pptx-motion-path-overlay', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: `
|
|
79007
|
+
@if (pathD(); as d) {
|
|
79008
|
+
<svg
|
|
79009
|
+
#overlay
|
|
79010
|
+
class="pptx-ng-motion-path-overlay"
|
|
79011
|
+
data-pptx-motion-path-overlay="true"
|
|
79012
|
+
role="img"
|
|
79013
|
+
[attr.aria-label]="'pptx.animation.motionPath.overlay' | translate"
|
|
79014
|
+
[attr.width]="size().width"
|
|
79015
|
+
[attr.height]="size().height"
|
|
79016
|
+
>
|
|
79017
|
+
<path
|
|
79018
|
+
[attr.d]="d"
|
|
79019
|
+
fill="none"
|
|
79020
|
+
stroke="#0ea5e9"
|
|
79021
|
+
stroke-width="2"
|
|
79022
|
+
stroke-dasharray="6 4"
|
|
79023
|
+
vector-effect="non-scaling-stroke"
|
|
79024
|
+
/>
|
|
79025
|
+
<circle
|
|
79026
|
+
[attr.cx]="frame().originX"
|
|
79027
|
+
[attr.cy]="frame().originY"
|
|
79028
|
+
r="5"
|
|
79029
|
+
fill="#0ea5e9"
|
|
79030
|
+
opacity="0.55"
|
|
79031
|
+
/>
|
|
79032
|
+
<circle
|
|
79033
|
+
data-pptx-motion-path-handle="end"
|
|
79034
|
+
[class.is-editable]="editable()"
|
|
79035
|
+
[attr.cx]="endPoint().x"
|
|
79036
|
+
[attr.cy]="endPoint().y"
|
|
79037
|
+
r="7"
|
|
79038
|
+
fill="#ffffff"
|
|
79039
|
+
stroke="#0ea5e9"
|
|
79040
|
+
stroke-width="2"
|
|
79041
|
+
[attr.aria-label]="'pptx.animation.motionPath.endHandle' | translate"
|
|
79042
|
+
(pointerdown)="onHandlePointerDown($event)"
|
|
79043
|
+
(pointermove)="onHandlePointerMove($event)"
|
|
79044
|
+
(pointerup)="onHandlePointerUp($event)"
|
|
79045
|
+
(pointercancel)="onHandlePointerUp($event)"
|
|
79046
|
+
/>
|
|
79047
|
+
</svg>
|
|
79048
|
+
}
|
|
79049
|
+
`, styles: [":host{position:absolute;inset:0;pointer-events:none;overflow:visible}.pptx-ng-motion-path-overlay{position:absolute;top:0;left:0;z-index:45;pointer-events:none;overflow:visible}circle.is-editable{pointer-events:auto;cursor:move}\n"] }]
|
|
79050
|
+
}], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: false }] }], animations: [{ type: i0.Input, args: [{ isSignal: true, alias: "animations", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], pathChange: [{ type: i0.Output, args: ["pathChange"] }], overlayRef: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }] } });
|
|
79051
|
+
/** Capture the pointer on the handle so a fast drag cannot outrun it. */
|
|
79052
|
+
function capturePointer(event) {
|
|
79053
|
+
const target = event.target;
|
|
79054
|
+
if (target instanceof Element && typeof target.setPointerCapture === 'function') {
|
|
79055
|
+
target.setPointerCapture(event.pointerId);
|
|
79056
|
+
}
|
|
79057
|
+
}
|
|
79058
|
+
function releasePointer(event) {
|
|
79059
|
+
const target = event.target;
|
|
79060
|
+
if (target instanceof Element && typeof target.releasePointerCapture === 'function') {
|
|
79061
|
+
target.releasePointerCapture(event.pointerId);
|
|
79062
|
+
}
|
|
79063
|
+
}
|
|
79064
|
+
|
|
77585
79065
|
/**
|
|
77586
79066
|
* notes-toolbar.component.ts: formatting toolbar for the rich speaker-notes
|
|
77587
79067
|
* editor. Private child of {@link NotesPanelComponent} (not exported from the
|
|
@@ -78246,6 +79726,315 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
78246
79726
|
`, styles: [":host{display:block}.pptx-ng-notes-panel{display:flex;flex-direction:column;border-top:1px solid var(--pptx-border, rgba(0, 0, 0, .1));background:var(--pptx-background, #ffffff);color:var(--pptx-foreground, #111827)}.pptx-ng-notes-header{display:flex;width:100%;align-items:center;justify-content:space-between;padding:.5rem .75rem;border:none;background:transparent;font-size:.8125rem;font-weight:600;color:var(--pptx-muted-foreground, #6b7280);cursor:pointer}.pptx-ng-notes-header:hover{color:var(--pptx-foreground, #111827)}.pptx-ng-notes-body{padding:0 .75rem .75rem}.pptx-ng-notes-rich,.pptx-ng-notes-textarea{box-sizing:border-box;width:100%;min-height:5rem;padding:.5rem;border:1px solid rgba(0,0,0,.15);border-radius:.375rem;background:#00000008;font:inherit;font-size:.8125rem;line-height:1.5;color:#111827}.pptx-ng-notes-rich{overflow:auto;resize:vertical}.pptx-ng-notes-textarea{resize:vertical}.pptx-ng-notes-rich:focus,.pptx-ng-notes-textarea:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 1px #6366f14d}.pptx-ng-notes-textarea:disabled{cursor:not-allowed;opacity:.6}\n"] }]
|
|
78247
79727
|
}], ctorParameters: () => [], propDecorators: { slide: [{ type: i0.Input, args: [{ isSignal: true, alias: "slide", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], update: [{ type: i0.Output, args: ["update"] }], notesToggle: [{ type: i0.Output, args: ["notesToggle"] }], richEditor: [{ type: i0.ViewChild, args: ['richEditor', { isSignal: true }] }], textarea: [{ type: i0.ViewChild, args: ['textarea', { isSignal: true }] }] } });
|
|
78248
79728
|
|
|
79729
|
+
/**
|
|
79730
|
+
* outline-view-overlay.styles.ts: CSS for PowerPoint's Outline view.
|
|
79731
|
+
*
|
|
79732
|
+
* Lifted out of the component (as `reading-view-overlay.styles.ts` was) so that
|
|
79733
|
+
* file stays a template plus its wiring and keeps under this repo's 300-LOC
|
|
79734
|
+
* cap. A plain exported const still compiles AOT: ng-packagr statically
|
|
79735
|
+
* evaluates the imported string.
|
|
79736
|
+
*
|
|
79737
|
+
* @module angular-viewer/outline-view-overlay.styles
|
|
79738
|
+
*/
|
|
79739
|
+
/**
|
|
79740
|
+
* Styles for `pptx-outline-view-overlay`.
|
|
79741
|
+
*
|
|
79742
|
+
* `position: fixed; inset: 0` fills the browser WINDOW without the Fullscreen
|
|
79743
|
+
* API, matching the sibling reading view and slide sorter overlays.
|
|
79744
|
+
*/
|
|
79745
|
+
const OUTLINE_VIEW_OVERLAY_STYLES = `
|
|
79746
|
+
.pptx-ng-outline-root {
|
|
79747
|
+
position: fixed;
|
|
79748
|
+
inset: 0;
|
|
79749
|
+
z-index: 1300;
|
|
79750
|
+
display: flex;
|
|
79751
|
+
flex-direction: column;
|
|
79752
|
+
background: #171717;
|
|
79753
|
+
color: #f5f5f5;
|
|
79754
|
+
}
|
|
79755
|
+
|
|
79756
|
+
.pptx-ng-outline-bar {
|
|
79757
|
+
display: flex;
|
|
79758
|
+
align-items: center;
|
|
79759
|
+
gap: 0.75rem;
|
|
79760
|
+
padding: 0.5rem 1rem;
|
|
79761
|
+
border-bottom: 1px solid rgb(255 255 255 / 0.1);
|
|
79762
|
+
}
|
|
79763
|
+
|
|
79764
|
+
.pptx-ng-outline-title {
|
|
79765
|
+
font-size: 0.875rem;
|
|
79766
|
+
font-weight: 600;
|
|
79767
|
+
}
|
|
79768
|
+
|
|
79769
|
+
.pptx-ng-outline-hint {
|
|
79770
|
+
flex: 1 1 auto;
|
|
79771
|
+
overflow: hidden;
|
|
79772
|
+
font-size: 0.6875rem;
|
|
79773
|
+
color: rgb(255 255 255 / 0.5);
|
|
79774
|
+
text-overflow: ellipsis;
|
|
79775
|
+
white-space: nowrap;
|
|
79776
|
+
}
|
|
79777
|
+
|
|
79778
|
+
.pptx-ng-outline-btn {
|
|
79779
|
+
display: inline-flex;
|
|
79780
|
+
align-items: center;
|
|
79781
|
+
justify-content: center;
|
|
79782
|
+
width: 2rem;
|
|
79783
|
+
height: 2rem;
|
|
79784
|
+
padding: 0;
|
|
79785
|
+
color: rgb(255 255 255 / 0.8);
|
|
79786
|
+
background: transparent;
|
|
79787
|
+
border: 0;
|
|
79788
|
+
border-radius: 0.25rem;
|
|
79789
|
+
cursor: pointer;
|
|
79790
|
+
}
|
|
79791
|
+
|
|
79792
|
+
.pptx-ng-outline-btn:hover {
|
|
79793
|
+
color: #ffffff;
|
|
79794
|
+
background: rgb(255 255 255 / 0.15);
|
|
79795
|
+
}
|
|
79796
|
+
|
|
79797
|
+
.pptx-ng-outline-rows {
|
|
79798
|
+
flex: 1 1 auto;
|
|
79799
|
+
min-height: 0;
|
|
79800
|
+
overflow: auto;
|
|
79801
|
+
padding: 0.75rem 1rem;
|
|
79802
|
+
}
|
|
79803
|
+
|
|
79804
|
+
.pptx-ng-outline-row {
|
|
79805
|
+
display: flex;
|
|
79806
|
+
align-items: center;
|
|
79807
|
+
gap: 0.5rem;
|
|
79808
|
+
padding: 0.125rem 0;
|
|
79809
|
+
}
|
|
79810
|
+
|
|
79811
|
+
.pptx-ng-outline-number {
|
|
79812
|
+
width: 1.5rem;
|
|
79813
|
+
flex: 0 0 auto;
|
|
79814
|
+
font-size: 0.625rem;
|
|
79815
|
+
font-variant-numeric: tabular-nums;
|
|
79816
|
+
color: rgb(255 255 255 / 0.4);
|
|
79817
|
+
text-align: right;
|
|
79818
|
+
}
|
|
79819
|
+
|
|
79820
|
+
.pptx-ng-outline-input {
|
|
79821
|
+
width: 100%;
|
|
79822
|
+
padding: 0.125rem 0.25rem;
|
|
79823
|
+
font-size: 0.8125rem;
|
|
79824
|
+
color: rgb(255 255 255 / 0.8);
|
|
79825
|
+
background: transparent;
|
|
79826
|
+
border: 0;
|
|
79827
|
+
border-radius: 0.25rem;
|
|
79828
|
+
outline: none;
|
|
79829
|
+
}
|
|
79830
|
+
|
|
79831
|
+
.pptx-ng-outline-input.is-title {
|
|
79832
|
+
font-size: 0.875rem;
|
|
79833
|
+
font-weight: 600;
|
|
79834
|
+
color: #f5f5f5;
|
|
79835
|
+
}
|
|
79836
|
+
|
|
79837
|
+
.pptx-ng-outline-input:focus {
|
|
79838
|
+
background: rgb(255 255 255 / 0.1);
|
|
79839
|
+
}
|
|
79840
|
+
`;
|
|
79841
|
+
|
|
79842
|
+
/**
|
|
79843
|
+
* outline-view-overlay.component.ts: PowerPoint's Outline view, Angular binding.
|
|
79844
|
+
*
|
|
79845
|
+
* The deck as an editable indented text document: one row per slide title at
|
|
79846
|
+
* the left margin, that slide's body lines stepped in beneath it. Typing edits
|
|
79847
|
+
* the slide, Tab and Shift+Tab change a line's outline level, and Enter on a
|
|
79848
|
+
* title starts a new slide.
|
|
79849
|
+
*
|
|
79850
|
+
* Every rule (what a row is, what Tab does, which edit produces a new slide)
|
|
79851
|
+
* comes from `render/outline-view` and `render/outline-view-edit` in
|
|
79852
|
+
* `pptx-viewer-shared`, so the five bindings cannot drift apart. Nothing in
|
|
79853
|
+
* this file decides what an outline gesture means.
|
|
79854
|
+
*
|
|
79855
|
+
* The deck it edits is the EDITABLE one, never the merged display deck: Angular
|
|
79856
|
+
* partitions each slide's inherited master/layout elements into a separate
|
|
79857
|
+
* store, and committing a merged deck back would bake that whole template layer
|
|
79858
|
+
* into every slide's own elements.
|
|
79859
|
+
*
|
|
79860
|
+
* Reference binding: packages/react/src/viewer/components/OutlineViewOverlay.tsx
|
|
79861
|
+
*/
|
|
79862
|
+
/** Indent per outline level, in pixels. Level 0 (a title) sits flush left. */
|
|
79863
|
+
const INDENT_PX = 22;
|
|
79864
|
+
class OutlineViewOverlayComponent {
|
|
79865
|
+
/** The editable (template-free) deck. See the class docstring for why. */
|
|
79866
|
+
slides = input([], /* @ts-ignore */
|
|
79867
|
+
...(ngDevMode ? [{ debugName: "slides" }] : /* istanbul ignore next */ []));
|
|
79868
|
+
canvasSize = input.required(/* @ts-ignore */
|
|
79869
|
+
...(ngDevMode ? [{ debugName: "canvasSize" }] : /* istanbul ignore next */ []));
|
|
79870
|
+
canEdit = input(false, /* @ts-ignore */
|
|
79871
|
+
...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
79872
|
+
/** Emits the deck after an edit, so the host records ONE undo entry. */
|
|
79873
|
+
commit = output();
|
|
79874
|
+
closed = output();
|
|
79875
|
+
INDENT_PX = INDENT_PX;
|
|
79876
|
+
rows = computed(() => buildOutline(this.slides()), /* @ts-ignore */
|
|
79877
|
+
...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
79878
|
+
rowsHost = viewChild('rowsHost', /* @ts-ignore */
|
|
79879
|
+
...(ngDevMode ? [{ debugName: "rowsHost" }] : /* istanbul ignore next */ []));
|
|
79880
|
+
onInput(event, key) {
|
|
79881
|
+
const target = event.target;
|
|
79882
|
+
this.run({ type: 'setText', key, text: target?.value ?? '' });
|
|
79883
|
+
}
|
|
79884
|
+
onRowKeyDown(event, key) {
|
|
79885
|
+
const { edit, preventDefault } = mapOutlineKey(event, key);
|
|
79886
|
+
if (preventDefault) {
|
|
79887
|
+
// Tab would otherwise walk out of the outline entirely, and Enter would
|
|
79888
|
+
// submit a surrounding form on a host page that has one.
|
|
79889
|
+
event.preventDefault();
|
|
79890
|
+
}
|
|
79891
|
+
if (edit) {
|
|
79892
|
+
this.run(edit);
|
|
79893
|
+
}
|
|
79894
|
+
}
|
|
79895
|
+
run(edit) {
|
|
79896
|
+
if (!this.canEdit()) {
|
|
79897
|
+
return;
|
|
79898
|
+
}
|
|
79899
|
+
const result = applyOutlineEdit(this.slides(), edit, { canvas: this.canvasSize() });
|
|
79900
|
+
if (!result.changed) {
|
|
79901
|
+
return;
|
|
79902
|
+
}
|
|
79903
|
+
this.commit.emit({ slides: result.slides, activeSlideIndex: result.activeSlideIndex });
|
|
79904
|
+
this.focusRow(result.focusKey);
|
|
79905
|
+
}
|
|
79906
|
+
/**
|
|
79907
|
+
* Restore the caret after the host has re-fed the new deck.
|
|
79908
|
+
*
|
|
79909
|
+
* Deferred to a microtask because the row that should take focus may not
|
|
79910
|
+
* exist yet: a new slide's title row only enters the DOM once change
|
|
79911
|
+
* detection has run over the committed deck.
|
|
79912
|
+
*/
|
|
79913
|
+
focusRow(key) {
|
|
79914
|
+
if (!key) {
|
|
79915
|
+
return;
|
|
79916
|
+
}
|
|
79917
|
+
queueMicrotask(() => {
|
|
79918
|
+
const selector = `[${OUTLINE_ROW_ATTR}="${CSS.escape(key)}"]`;
|
|
79919
|
+
const target = this.rowsHost()?.nativeElement.querySelector(selector);
|
|
79920
|
+
if (target && document.activeElement !== target) {
|
|
79921
|
+
target.focus();
|
|
79922
|
+
target.setSelectionRange(target.value.length, target.value.length);
|
|
79923
|
+
}
|
|
79924
|
+
});
|
|
79925
|
+
}
|
|
79926
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: OutlineViewOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79927
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: OutlineViewOverlayComponent, isStandalone: true, selector: "pptx-outline-view-overlay", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { commit: "commit", closed: "closed" }, viewQueries: [{ propertyName: "rowsHost", first: true, predicate: ["rowsHost"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
79928
|
+
<div
|
|
79929
|
+
class="pptx-ng-outline-root"
|
|
79930
|
+
[attr.data-pptx-outline-view]="'true'"
|
|
79931
|
+
role="region"
|
|
79932
|
+
[attr.aria-label]="'pptx.view.outlineView' | translate"
|
|
79933
|
+
>
|
|
79934
|
+
<div class="pptx-ng-outline-bar">
|
|
79935
|
+
<span class="pptx-ng-outline-title">{{ 'pptx.view.outlineView' | translate }}</span>
|
|
79936
|
+
<span class="pptx-ng-outline-hint">{{ 'pptx.outline.hint' | translate }}</span>
|
|
79937
|
+
<button
|
|
79938
|
+
type="button"
|
|
79939
|
+
class="pptx-ng-outline-btn"
|
|
79940
|
+
[attr.aria-label]="'pptx.statusBar.normalView' | translate"
|
|
79941
|
+
[title]="'pptx.statusBar.normalView' | translate"
|
|
79942
|
+
(click)="closed.emit()"
|
|
79943
|
+
>
|
|
79944
|
+
<svg lucideX class="h-4 w-4"></svg>
|
|
79945
|
+
</button>
|
|
79946
|
+
</div>
|
|
79947
|
+
|
|
79948
|
+
<div #rowsHost class="pptx-ng-outline-rows">
|
|
79949
|
+
@for (row of rows(); track row.key) {
|
|
79950
|
+
<div class="pptx-ng-outline-row" [style.padding-left.px]="row.level * INDENT_PX">
|
|
79951
|
+
<!--
|
|
79952
|
+
The slide number is drawn only on a slide's first row, which is
|
|
79953
|
+
always its title row, so the outline reads as a list of slides
|
|
79954
|
+
rather than as one undifferentiated wall of lines.
|
|
79955
|
+
-->
|
|
79956
|
+
<span class="pptx-ng-outline-number">{{
|
|
79957
|
+
row.kind === 'title' ? row.slideIndex + 1 : ''
|
|
79958
|
+
}}</span>
|
|
79959
|
+
<input
|
|
79960
|
+
type="text"
|
|
79961
|
+
class="pptx-ng-outline-input"
|
|
79962
|
+
[class.is-title]="row.kind === 'title'"
|
|
79963
|
+
[value]="row.text"
|
|
79964
|
+
[readOnly]="!canEdit()"
|
|
79965
|
+
[attr.data-pptx-outline-row]="row.key"
|
|
79966
|
+
[attr.data-pptx-outline-slide]="row.slideIndex + 1"
|
|
79967
|
+
[attr.data-pptx-outline-level]="row.level"
|
|
79968
|
+
[attr.aria-label]="
|
|
79969
|
+
(row.kind === 'title' ? 'pptx.outline.titleLine' : 'pptx.outline.bodyLine')
|
|
79970
|
+
| translate
|
|
79971
|
+
"
|
|
79972
|
+
(input)="onInput($event, row.key)"
|
|
79973
|
+
(keydown)="onRowKeyDown($event, row.key)"
|
|
79974
|
+
/>
|
|
79975
|
+
</div>
|
|
79976
|
+
}
|
|
79977
|
+
</div>
|
|
79978
|
+
</div>
|
|
79979
|
+
`, isInline: true, styles: [".pptx-ng-outline-root{position:fixed;inset:0;z-index:1300;display:flex;flex-direction:column;background:#171717;color:#f5f5f5}.pptx-ng-outline-bar{display:flex;align-items:center;gap:.75rem;padding:.5rem 1rem;border-bottom:1px solid rgb(255 255 255 / .1)}.pptx-ng-outline-title{font-size:.875rem;font-weight:600}.pptx-ng-outline-hint{flex:1 1 auto;overflow:hidden;font-size:.6875rem;color:#ffffff80;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-outline-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;color:#fffc;background:transparent;border:0;border-radius:.25rem;cursor:pointer}.pptx-ng-outline-btn:hover{color:#fff;background:#ffffff26}.pptx-ng-outline-rows{flex:1 1 auto;min-height:0;overflow:auto;padding:.75rem 1rem}.pptx-ng-outline-row{display:flex;align-items:center;gap:.5rem;padding:.125rem 0}.pptx-ng-outline-number{width:1.5rem;flex:0 0 auto;font-size:.625rem;font-variant-numeric:tabular-nums;color:#fff6;text-align:right}.pptx-ng-outline-input{width:100%;padding:.125rem .25rem;font-size:.8125rem;color:#fffc;background:transparent;border:0;border-radius:.25rem;outline:none}.pptx-ng-outline-input.is-title{font-size:.875rem;font-weight:600;color:#f5f5f5}.pptx-ng-outline-input:focus{background:#ffffff1a}\n"], dependencies: [{ kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
79980
|
+
}
|
|
79981
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: OutlineViewOverlayComponent, decorators: [{
|
|
79982
|
+
type: Component,
|
|
79983
|
+
args: [{ selector: 'pptx-outline-view-overlay', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe, LucideX], template: `
|
|
79984
|
+
<div
|
|
79985
|
+
class="pptx-ng-outline-root"
|
|
79986
|
+
[attr.data-pptx-outline-view]="'true'"
|
|
79987
|
+
role="region"
|
|
79988
|
+
[attr.aria-label]="'pptx.view.outlineView' | translate"
|
|
79989
|
+
>
|
|
79990
|
+
<div class="pptx-ng-outline-bar">
|
|
79991
|
+
<span class="pptx-ng-outline-title">{{ 'pptx.view.outlineView' | translate }}</span>
|
|
79992
|
+
<span class="pptx-ng-outline-hint">{{ 'pptx.outline.hint' | translate }}</span>
|
|
79993
|
+
<button
|
|
79994
|
+
type="button"
|
|
79995
|
+
class="pptx-ng-outline-btn"
|
|
79996
|
+
[attr.aria-label]="'pptx.statusBar.normalView' | translate"
|
|
79997
|
+
[title]="'pptx.statusBar.normalView' | translate"
|
|
79998
|
+
(click)="closed.emit()"
|
|
79999
|
+
>
|
|
80000
|
+
<svg lucideX class="h-4 w-4"></svg>
|
|
80001
|
+
</button>
|
|
80002
|
+
</div>
|
|
80003
|
+
|
|
80004
|
+
<div #rowsHost class="pptx-ng-outline-rows">
|
|
80005
|
+
@for (row of rows(); track row.key) {
|
|
80006
|
+
<div class="pptx-ng-outline-row" [style.padding-left.px]="row.level * INDENT_PX">
|
|
80007
|
+
<!--
|
|
80008
|
+
The slide number is drawn only on a slide's first row, which is
|
|
80009
|
+
always its title row, so the outline reads as a list of slides
|
|
80010
|
+
rather than as one undifferentiated wall of lines.
|
|
80011
|
+
-->
|
|
80012
|
+
<span class="pptx-ng-outline-number">{{
|
|
80013
|
+
row.kind === 'title' ? row.slideIndex + 1 : ''
|
|
80014
|
+
}}</span>
|
|
80015
|
+
<input
|
|
80016
|
+
type="text"
|
|
80017
|
+
class="pptx-ng-outline-input"
|
|
80018
|
+
[class.is-title]="row.kind === 'title'"
|
|
80019
|
+
[value]="row.text"
|
|
80020
|
+
[readOnly]="!canEdit()"
|
|
80021
|
+
[attr.data-pptx-outline-row]="row.key"
|
|
80022
|
+
[attr.data-pptx-outline-slide]="row.slideIndex + 1"
|
|
80023
|
+
[attr.data-pptx-outline-level]="row.level"
|
|
80024
|
+
[attr.aria-label]="
|
|
80025
|
+
(row.kind === 'title' ? 'pptx.outline.titleLine' : 'pptx.outline.bodyLine')
|
|
80026
|
+
| translate
|
|
80027
|
+
"
|
|
80028
|
+
(input)="onInput($event, row.key)"
|
|
80029
|
+
(keydown)="onRowKeyDown($event, row.key)"
|
|
80030
|
+
/>
|
|
80031
|
+
</div>
|
|
80032
|
+
}
|
|
80033
|
+
</div>
|
|
80034
|
+
</div>
|
|
80035
|
+
`, styles: [".pptx-ng-outline-root{position:fixed;inset:0;z-index:1300;display:flex;flex-direction:column;background:#171717;color:#f5f5f5}.pptx-ng-outline-bar{display:flex;align-items:center;gap:.75rem;padding:.5rem 1rem;border-bottom:1px solid rgb(255 255 255 / .1)}.pptx-ng-outline-title{font-size:.875rem;font-weight:600}.pptx-ng-outline-hint{flex:1 1 auto;overflow:hidden;font-size:.6875rem;color:#ffffff80;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-outline-btn{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;color:#fffc;background:transparent;border:0;border-radius:.25rem;cursor:pointer}.pptx-ng-outline-btn:hover{color:#fff;background:#ffffff26}.pptx-ng-outline-rows{flex:1 1 auto;min-height:0;overflow:auto;padding:.75rem 1rem}.pptx-ng-outline-row{display:flex;align-items:center;gap:.5rem;padding:.125rem 0}.pptx-ng-outline-number{width:1.5rem;flex:0 0 auto;font-size:.625rem;font-variant-numeric:tabular-nums;color:#fff6;text-align:right}.pptx-ng-outline-input{width:100%;padding:.125rem .25rem;font-size:.8125rem;color:#fffc;background:transparent;border:0;border-radius:.25rem;outline:none}.pptx-ng-outline-input.is-title{font-size:.875rem;font-weight:600;color:#f5f5f5}.pptx-ng-outline-input:focus{background:#ffffff1a}\n"] }]
|
|
80036
|
+
}], propDecorators: { slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], commit: [{ type: i0.Output, args: ["commit"] }], closed: [{ type: i0.Output, args: ["closed"] }], rowsHost: [{ type: i0.ViewChild, args: ['rowsHost', { isSignal: true }] }] } });
|
|
80037
|
+
|
|
78249
80038
|
/**
|
|
78250
80039
|
* A drop-in replacement for `html2canvas(element, options)` that first
|
|
78251
80040
|
* resolves any oklch / oklab / lch / lab / color() values in the cloned
|
|
@@ -83587,6 +85376,13 @@ class PresentationOverlayComponent {
|
|
|
83587
85376
|
width: `${size.width * z}px`,
|
|
83588
85377
|
height: `${size.height * z}px`,
|
|
83589
85378
|
transform: 'translate(-50%, -50%)',
|
|
85379
|
+
// Motion-path keyframes translate by a fraction of the SLIDE (see
|
|
85380
|
+
// `slideOffset` in the shared timeline helpers), so the presentation
|
|
85381
|
+
// stage publishes the slide size the same way the editing stage does.
|
|
85382
|
+
// Without it every parsed path falls back to the 1280x720 default and a
|
|
85383
|
+
// deck authored at another size under-travels.
|
|
85384
|
+
'--pptx-slide-w': `${size.width}px`,
|
|
85385
|
+
'--pptx-slide-h': `${size.height}px`,
|
|
83590
85386
|
};
|
|
83591
85387
|
}, /* @ts-ignore */
|
|
83592
85388
|
...(ngDevMode ? [{ debugName: "stageContainerStyle" }] : /* istanbul ignore next */ []));
|
|
@@ -86936,6 +88732,121 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
86936
88732
|
}]
|
|
86937
88733
|
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], addAnimation: [{ type: i0.Output, args: ["addAnimation"] }] } });
|
|
86938
88734
|
|
|
88735
|
+
/**
|
|
88736
|
+
* ribbon-motion-path-gallery.component.ts: the Animations tab's motion-path
|
|
88737
|
+
* gallery (PowerPoint's Lines / Arcs / Turns / Shapes / Loops families).
|
|
88738
|
+
*
|
|
88739
|
+
* Its own component rather than more markup inside
|
|
88740
|
+
* {@link RibbonAnimationsSectionComponent} for the same reason
|
|
88741
|
+
* {@link RibbonAnimationGalleryComponent} is: the catalogue is thirty-odd
|
|
88742
|
+
* buttons, which would push that file past this repo's 300-LOC cap on its own.
|
|
88743
|
+
*
|
|
88744
|
+
* WHY it is a SIBLING of the entrance/emphasis/exit gallery and not a fourth
|
|
88745
|
+
* column of it: a motion path is not one of those three buckets. It is
|
|
88746
|
+
* geometry that coexists with them on the SAME animation entry, so folding it
|
|
88747
|
+
* into the preset columns would imply a mutually exclusive choice the model
|
|
88748
|
+
* does not make (an element can fade in AND travel a path).
|
|
88749
|
+
*
|
|
88750
|
+
* Every path is a real <button> carrying its translated name as both `title`
|
|
88751
|
+
* and visible text, because `e2e/ribbon-control-inventory.spec.ts` inventories
|
|
88752
|
+
* each tab by accessible name and diffs every binding against React: a gallery
|
|
88753
|
+
* hidden behind a hover menu, or one whose buttons are named by an icon only,
|
|
88754
|
+
* is a gallery a screen-reader user (and that spec) does not have. The columns
|
|
88755
|
+
* come from the shared catalogue rather than a hand-written list so a preset
|
|
88756
|
+
* added there needs no follow-up in five bindings.
|
|
88757
|
+
*/
|
|
88758
|
+
/**
|
|
88759
|
+
* The gallery's columns, in the shared catalogue's own (ribbon) order.
|
|
88760
|
+
*
|
|
88761
|
+
* Built once at module load: the catalogue is static, so recomputing it per
|
|
88762
|
+
* change-detection pass would allocate thirty view models for nothing.
|
|
88763
|
+
*/
|
|
88764
|
+
const MOTION_PATH_COLUMNS = MOTION_PATH_FAMILIES.map((family) => ({
|
|
88765
|
+
family,
|
|
88766
|
+
labelKey: motionPathFamilyLabelKey(family),
|
|
88767
|
+
presets: motionPathPresetsByFamily(family).map((preset) => ({
|
|
88768
|
+
id: preset.id,
|
|
88769
|
+
labelKey: motionPathPresetLabelKey(preset.id),
|
|
88770
|
+
})),
|
|
88771
|
+
}));
|
|
88772
|
+
class RibbonMotionPathGalleryComponent {
|
|
88773
|
+
/** True when the deck is not editable or nothing is selected. */
|
|
88774
|
+
disabled = input(true, /* @ts-ignore */
|
|
88775
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
88776
|
+
/** Emits the catalogue preset id of the pressed path. */
|
|
88777
|
+
applyMotionPath = output();
|
|
88778
|
+
columns = MOTION_PATH_COLUMNS;
|
|
88779
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonMotionPathGalleryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
88780
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: RibbonMotionPathGalleryComponent, isStandalone: true, selector: "pptx-ribbon-motion-path-gallery", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { applyMotionPath: "applyMotionPath" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
88781
|
+
<div
|
|
88782
|
+
role="group"
|
|
88783
|
+
class="flex max-h-[62px] items-start gap-2 overflow-y-auto rounded-sm border border-border/60 bg-muted/30 px-1.5 py-1"
|
|
88784
|
+
[attr.aria-label]="'pptx.animations.motionPathGalleryAria' | translate"
|
|
88785
|
+
>
|
|
88786
|
+
@for (column of columns; track column.family) {
|
|
88787
|
+
<div class="flex flex-col gap-0.5">
|
|
88788
|
+
<span class="text-[9px] font-semibold leading-3 text-muted-foreground">
|
|
88789
|
+
{{ column.labelKey | translate }}
|
|
88790
|
+
</span>
|
|
88791
|
+
<div class="flex max-w-[150px] flex-wrap gap-0.5">
|
|
88792
|
+
@for (preset of column.presets; track preset.id) {
|
|
88793
|
+
<button
|
|
88794
|
+
type="button"
|
|
88795
|
+
class="inline-flex items-center gap-0.5 rounded-sm px-1 py-0.5 text-[9px] leading-3 text-foreground transition-colors hover:bg-accent disabled:opacity-35"
|
|
88796
|
+
[disabled]="disabled()"
|
|
88797
|
+
[title]="preset.labelKey | translate"
|
|
88798
|
+
(click)="applyMotionPath.emit(preset.id)"
|
|
88799
|
+
>
|
|
88800
|
+
<svg lucideMoveRight aria-hidden="true" class="h-2.5 w-2.5 text-sky-500"></svg>
|
|
88801
|
+
<span class="whitespace-nowrap">{{ preset.labelKey | translate }}</span>
|
|
88802
|
+
</button>
|
|
88803
|
+
}
|
|
88804
|
+
</div>
|
|
88805
|
+
</div>
|
|
88806
|
+
}
|
|
88807
|
+
</div>
|
|
88808
|
+
`, isInline: true, dependencies: [{ kind: "component", type: LucideMoveRight, selector: "svg[lucideMoveRight]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
88809
|
+
}
|
|
88810
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonMotionPathGalleryComponent, decorators: [{
|
|
88811
|
+
type: Component,
|
|
88812
|
+
args: [{
|
|
88813
|
+
selector: 'pptx-ribbon-motion-path-gallery',
|
|
88814
|
+
standalone: true,
|
|
88815
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
88816
|
+
host: { class: 'contents' },
|
|
88817
|
+
imports: [TranslatePipe, LucideMoveRight],
|
|
88818
|
+
template: `
|
|
88819
|
+
<div
|
|
88820
|
+
role="group"
|
|
88821
|
+
class="flex max-h-[62px] items-start gap-2 overflow-y-auto rounded-sm border border-border/60 bg-muted/30 px-1.5 py-1"
|
|
88822
|
+
[attr.aria-label]="'pptx.animations.motionPathGalleryAria' | translate"
|
|
88823
|
+
>
|
|
88824
|
+
@for (column of columns; track column.family) {
|
|
88825
|
+
<div class="flex flex-col gap-0.5">
|
|
88826
|
+
<span class="text-[9px] font-semibold leading-3 text-muted-foreground">
|
|
88827
|
+
{{ column.labelKey | translate }}
|
|
88828
|
+
</span>
|
|
88829
|
+
<div class="flex max-w-[150px] flex-wrap gap-0.5">
|
|
88830
|
+
@for (preset of column.presets; track preset.id) {
|
|
88831
|
+
<button
|
|
88832
|
+
type="button"
|
|
88833
|
+
class="inline-flex items-center gap-0.5 rounded-sm px-1 py-0.5 text-[9px] leading-3 text-foreground transition-colors hover:bg-accent disabled:opacity-35"
|
|
88834
|
+
[disabled]="disabled()"
|
|
88835
|
+
[title]="preset.labelKey | translate"
|
|
88836
|
+
(click)="applyMotionPath.emit(preset.id)"
|
|
88837
|
+
>
|
|
88838
|
+
<svg lucideMoveRight aria-hidden="true" class="h-2.5 w-2.5 text-sky-500"></svg>
|
|
88839
|
+
<span class="whitespace-nowrap">{{ preset.labelKey | translate }}</span>
|
|
88840
|
+
</button>
|
|
88841
|
+
}
|
|
88842
|
+
</div>
|
|
88843
|
+
</div>
|
|
88844
|
+
}
|
|
88845
|
+
</div>
|
|
88846
|
+
`,
|
|
88847
|
+
}]
|
|
88848
|
+
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], applyMotionPath: [{ type: i0.Output, args: ["applyMotionPath"] }] } });
|
|
88849
|
+
|
|
86939
88850
|
/**
|
|
86940
88851
|
* ribbon-animations-section.component.ts: the Animations ribbon tab (Preview,
|
|
86941
88852
|
* the entrance/emphasis/exit gallery, the Advanced Animation group, and the
|
|
@@ -86969,10 +88880,36 @@ class RibbonAnimationsSectionComponent {
|
|
|
86969
88880
|
canAuthor() {
|
|
86970
88881
|
return canAuthorAnimation(this.canEdit(), this.hasSel());
|
|
86971
88882
|
}
|
|
88883
|
+
/** The path the one-click "Path Animation" command applies. */
|
|
88884
|
+
defaultMotionPathPresetId = DEFAULT_MOTION_PATH_PRESET_ID;
|
|
86972
88885
|
/** Apply the preset a gallery button asked for. */
|
|
86973
88886
|
onGalleryPick(pick) {
|
|
86974
88887
|
this.addAnimation(pick.preset, pick.group);
|
|
86975
88888
|
}
|
|
88889
|
+
/**
|
|
88890
|
+
* Apply a catalogue motion path to the selected element.
|
|
88891
|
+
*
|
|
88892
|
+
* Separate from {@link addAnimation} because a path is written to the
|
|
88893
|
+
* `motionPath` field of the SAME animation entry the preset buckets use, not
|
|
88894
|
+
* to one of those buckets: applying a path must not wipe an entrance the
|
|
88895
|
+
* element already carries, and clearing that entrance later must not wipe
|
|
88896
|
+
* the path. The shared helper owns both rules.
|
|
88897
|
+
*/
|
|
88898
|
+
applyMotionPath(presetId) {
|
|
88899
|
+
if (!this.canEdit()) {
|
|
88900
|
+
return;
|
|
88901
|
+
}
|
|
88902
|
+
const el = this.selectedElement();
|
|
88903
|
+
if (!el) {
|
|
88904
|
+
return;
|
|
88905
|
+
}
|
|
88906
|
+
const slide = this.editor.slides()[this.slideIndex()];
|
|
88907
|
+
if (!slide) {
|
|
88908
|
+
return;
|
|
88909
|
+
}
|
|
88910
|
+
const updated = applyMotionPathPreset(slide.animations ?? [], el.id, presetId);
|
|
88911
|
+
this.editor.updateSlide(this.slideIndex(), { animations: updated });
|
|
88912
|
+
}
|
|
86976
88913
|
/**
|
|
86977
88914
|
* Add an animation preset to the selected element on the active slide.
|
|
86978
88915
|
* Delegates to the immutable helpers in animation-author-helpers.ts and
|
|
@@ -87038,6 +88975,28 @@ class RibbonAnimationsSectionComponent {
|
|
|
87038
88975
|
(addAnimation)="onGalleryPick($event)"
|
|
87039
88976
|
/>
|
|
87040
88977
|
<span class="pptx-rb-sep"></span>
|
|
88978
|
+
<!--
|
|
88979
|
+
Motion Paths: its own captioned group (a path is geometry that coexists
|
|
88980
|
+
with the preset buckets, not a fourth bucket of them), capped at React's
|
|
88981
|
+
own 420px. Uncapped, five 150px family columns claim ~800px of a
|
|
88982
|
+
single-row ribbon and squeeze the Advanced Animation pills beside them
|
|
88983
|
+
until their labels overlap.
|
|
88984
|
+
-->
|
|
88985
|
+
<section
|
|
88986
|
+
class="relative flex max-w-[420px] shrink items-start gap-1 overflow-hidden pb-3"
|
|
88987
|
+
[attr.aria-label]="'pptx.animation.motionPath' | translate"
|
|
88988
|
+
>
|
|
88989
|
+
<pptx-ribbon-motion-path-gallery
|
|
88990
|
+
[disabled]="!canAuthor()"
|
|
88991
|
+
(applyMotionPath)="applyMotionPath($event)"
|
|
88992
|
+
/>
|
|
88993
|
+
<span
|
|
88994
|
+
class="pointer-events-none absolute inset-x-1 bottom-0 truncate text-center text-[9px] leading-3 text-muted-foreground"
|
|
88995
|
+
>
|
|
88996
|
+
{{ 'pptx.animation.motionPath' | translate }}
|
|
88997
|
+
</span>
|
|
88998
|
+
</section>
|
|
88999
|
+
<span class="pptx-rb-sep"></span>
|
|
87041
89000
|
<!-- Advanced Animation -->
|
|
87042
89001
|
<button
|
|
87043
89002
|
type="button"
|
|
@@ -87048,11 +89007,15 @@ class RibbonAnimationsSectionComponent {
|
|
|
87048
89007
|
<svg lucideStar class="h-4 w-4 text-red-500"></svg>
|
|
87049
89008
|
{{ 'pptx.animations.exitEffects' | translate }}
|
|
87050
89009
|
</button>
|
|
89010
|
+
<!--
|
|
89011
|
+
One-click default path (Lines: Right). It used to apply a Fly In
|
|
89012
|
+
entrance, which is not a path at all.
|
|
89013
|
+
-->
|
|
87051
89014
|
<button
|
|
87052
89015
|
type="button"
|
|
87053
89016
|
class="pptx-rb-pill"
|
|
87054
89017
|
[disabled]="!canAuthor()"
|
|
87055
|
-
(click)="
|
|
89018
|
+
(click)="applyMotionPath(defaultMotionPathPresetId)"
|
|
87056
89019
|
>
|
|
87057
89020
|
<svg lucideMoveRight class="h-4 w-4"></svg>
|
|
87058
89021
|
{{ 'pptx.animations.pathAnimation' | translate }}
|
|
@@ -87128,7 +89091,7 @@ class RibbonAnimationsSectionComponent {
|
|
|
87128
89091
|
disabled
|
|
87129
89092
|
/>
|
|
87130
89093
|
</div>
|
|
87131
|
-
`, isInline: true, dependencies: [{ kind: "component", type: LucidePlay, selector: "svg[lucidePlay]" }, { kind: "component", type: LucideSparkles, selector: "svg[lucideSparkles], svg[lucideStars]" }, { kind: "component", type: LucideStar, selector: "svg[lucideStar]" }, { kind: "component", type: LucideMoveRight, selector: "svg[lucideMoveRight]" }, { kind: "component", type: LucideMousePointerClick, selector: "svg[lucideMousePointerClick]" }, { kind: "component", type: LucidePaintbrush, selector: "svg[lucidePaintbrush]" }, { kind: "component", type: LucideClock3, selector: "svg[lucideClock3]" }, { kind: "component", type: LucideTrash2, selector: "svg[lucideTrash2]" }, { kind: "component", type: LucidePanelRight, selector: "svg[lucidePanelRight]" }, { kind: "component", type: RibbonAnimationGalleryComponent, selector: "pptx-ribbon-animation-gallery", inputs: ["disabled"], outputs: ["addAnimation"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
89094
|
+
`, isInline: true, dependencies: [{ kind: "component", type: LucidePlay, selector: "svg[lucidePlay]" }, { kind: "component", type: LucideSparkles, selector: "svg[lucideSparkles], svg[lucideStars]" }, { kind: "component", type: LucideStar, selector: "svg[lucideStar]" }, { kind: "component", type: LucideMoveRight, selector: "svg[lucideMoveRight]" }, { kind: "component", type: LucideMousePointerClick, selector: "svg[lucideMousePointerClick]" }, { kind: "component", type: LucidePaintbrush, selector: "svg[lucidePaintbrush]" }, { kind: "component", type: LucideClock3, selector: "svg[lucideClock3]" }, { kind: "component", type: LucideTrash2, selector: "svg[lucideTrash2]" }, { kind: "component", type: LucidePanelRight, selector: "svg[lucidePanelRight]" }, { kind: "component", type: RibbonAnimationGalleryComponent, selector: "pptx-ribbon-animation-gallery", inputs: ["disabled"], outputs: ["addAnimation"] }, { kind: "component", type: RibbonMotionPathGalleryComponent, selector: "pptx-ribbon-motion-path-gallery", inputs: ["disabled"], outputs: ["applyMotionPath"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
87132
89095
|
}
|
|
87133
89096
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonAnimationsSectionComponent, decorators: [{
|
|
87134
89097
|
type: Component,
|
|
@@ -87149,6 +89112,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
87149
89112
|
LucideTrash2,
|
|
87150
89113
|
LucidePanelRight,
|
|
87151
89114
|
RibbonAnimationGalleryComponent,
|
|
89115
|
+
RibbonMotionPathGalleryComponent,
|
|
87152
89116
|
],
|
|
87153
89117
|
template: `
|
|
87154
89118
|
<!-- Preview: plays presentation from this slide; no element-only preview API yet -->
|
|
@@ -87168,6 +89132,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
87168
89132
|
(addAnimation)="onGalleryPick($event)"
|
|
87169
89133
|
/>
|
|
87170
89134
|
<span class="pptx-rb-sep"></span>
|
|
89135
|
+
<!--
|
|
89136
|
+
Motion Paths: its own captioned group (a path is geometry that coexists
|
|
89137
|
+
with the preset buckets, not a fourth bucket of them), capped at React's
|
|
89138
|
+
own 420px. Uncapped, five 150px family columns claim ~800px of a
|
|
89139
|
+
single-row ribbon and squeeze the Advanced Animation pills beside them
|
|
89140
|
+
until their labels overlap.
|
|
89141
|
+
-->
|
|
89142
|
+
<section
|
|
89143
|
+
class="relative flex max-w-[420px] shrink items-start gap-1 overflow-hidden pb-3"
|
|
89144
|
+
[attr.aria-label]="'pptx.animation.motionPath' | translate"
|
|
89145
|
+
>
|
|
89146
|
+
<pptx-ribbon-motion-path-gallery
|
|
89147
|
+
[disabled]="!canAuthor()"
|
|
89148
|
+
(applyMotionPath)="applyMotionPath($event)"
|
|
89149
|
+
/>
|
|
89150
|
+
<span
|
|
89151
|
+
class="pointer-events-none absolute inset-x-1 bottom-0 truncate text-center text-[9px] leading-3 text-muted-foreground"
|
|
89152
|
+
>
|
|
89153
|
+
{{ 'pptx.animation.motionPath' | translate }}
|
|
89154
|
+
</span>
|
|
89155
|
+
</section>
|
|
89156
|
+
<span class="pptx-rb-sep"></span>
|
|
87171
89157
|
<!-- Advanced Animation -->
|
|
87172
89158
|
<button
|
|
87173
89159
|
type="button"
|
|
@@ -87178,11 +89164,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
87178
89164
|
<svg lucideStar class="h-4 w-4 text-red-500"></svg>
|
|
87179
89165
|
{{ 'pptx.animations.exitEffects' | translate }}
|
|
87180
89166
|
</button>
|
|
89167
|
+
<!--
|
|
89168
|
+
One-click default path (Lines: Right). It used to apply a Fly In
|
|
89169
|
+
entrance, which is not a path at all.
|
|
89170
|
+
-->
|
|
87181
89171
|
<button
|
|
87182
89172
|
type="button"
|
|
87183
89173
|
class="pptx-rb-pill"
|
|
87184
89174
|
[disabled]="!canAuthor()"
|
|
87185
|
-
(click)="
|
|
89175
|
+
(click)="applyMotionPath(defaultMotionPathPresetId)"
|
|
87186
89176
|
>
|
|
87187
89177
|
<svg lucideMoveRight class="h-4 w-4"></svg>
|
|
87188
89178
|
{{ 'pptx.animations.pathAnimation' | translate }}
|
|
@@ -88484,6 +90474,8 @@ class RibbonViewSectionComponent {
|
|
|
88484
90474
|
openSorter = output();
|
|
88485
90475
|
/** Enter Reading View: the deck full-window, NOT the fullscreen slide show. */
|
|
88486
90476
|
openReadingView = output();
|
|
90477
|
+
/** Enter Outline view: the deck as editable indented text. */
|
|
90478
|
+
openOutlineView = output();
|
|
88487
90479
|
openMasterView = output();
|
|
88488
90480
|
toggleGrid = output();
|
|
88489
90481
|
toggleRulers = output();
|
|
@@ -88495,7 +90487,7 @@ class RibbonViewSectionComponent {
|
|
|
88495
90487
|
zoomToFit = output();
|
|
88496
90488
|
toggleEyedropper = output();
|
|
88497
90489
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonViewSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
88498
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: RibbonViewSectionComponent, isStandalone: true, selector: "pptx-ribbon-view-section", inputs: { canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openSorter: "openSorter", openReadingView: "openReadingView", openMasterView: "openMasterView", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
90490
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: RibbonViewSectionComponent, isStandalone: true, selector: "pptx-ribbon-view-section", inputs: { canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openSorter: "openSorter", openReadingView: "openReadingView", openOutlineView: "openOutlineView", openMasterView: "openMasterView", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
88499
90491
|
<!-- Presentation views -->
|
|
88500
90492
|
<button type="button" class="pptx-rb-pill" [title]="'pptx.view.normal' | translate">
|
|
88501
90493
|
{{ 'pptx.view.normal' | translate }}
|
|
@@ -88508,6 +90500,14 @@ class RibbonViewSectionComponent {
|
|
|
88508
90500
|
>
|
|
88509
90501
|
{{ 'pptx.slideSorter.title' | translate }}
|
|
88510
90502
|
</button>
|
|
90503
|
+
<button
|
|
90504
|
+
type="button"
|
|
90505
|
+
class="pptx-rb-pill"
|
|
90506
|
+
[title]="'pptx.view.outlineViewTooltip' | translate"
|
|
90507
|
+
(click)="openOutlineView.emit()"
|
|
90508
|
+
>
|
|
90509
|
+
{{ 'pptx.view.outlineView' | translate }}
|
|
90510
|
+
</button>
|
|
88511
90511
|
<button
|
|
88512
90512
|
type="button"
|
|
88513
90513
|
class="pptx-rb-pill"
|
|
@@ -88669,6 +90669,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
88669
90669
|
>
|
|
88670
90670
|
{{ 'pptx.slideSorter.title' | translate }}
|
|
88671
90671
|
</button>
|
|
90672
|
+
<button
|
|
90673
|
+
type="button"
|
|
90674
|
+
class="pptx-rb-pill"
|
|
90675
|
+
[title]="'pptx.view.outlineViewTooltip' | translate"
|
|
90676
|
+
(click)="openOutlineView.emit()"
|
|
90677
|
+
>
|
|
90678
|
+
{{ 'pptx.view.outlineView' | translate }}
|
|
90679
|
+
</button>
|
|
88672
90680
|
<button
|
|
88673
90681
|
type="button"
|
|
88674
90682
|
class="pptx-rb-pill"
|
|
@@ -88809,7 +90817,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
88809
90817
|
</button>
|
|
88810
90818
|
`,
|
|
88811
90819
|
}]
|
|
88812
|
-
}], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }] } });
|
|
90820
|
+
}], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openOutlineView: [{ type: i0.Output, args: ["openOutlineView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }] } });
|
|
88813
90821
|
|
|
88814
90822
|
/**
|
|
88815
90823
|
* ribbon-content-secondary.component.ts: the ribbon's Slide Show/Review/View/
|
|
@@ -88880,6 +90888,7 @@ class RibbonContentSecondaryComponent {
|
|
|
88880
90888
|
openSorter = output();
|
|
88881
90889
|
/** View tab > Reading View: the deck full-window, not the slide show. */
|
|
88882
90890
|
openReadingView = output();
|
|
90891
|
+
openOutlineView = output();
|
|
88883
90892
|
openMasterView = output();
|
|
88884
90893
|
toggleNotes = output();
|
|
88885
90894
|
toggleInspector = output();
|
|
@@ -88918,7 +90927,7 @@ class RibbonContentSecondaryComponent {
|
|
|
88918
90927
|
this.drawToolChange.emit(state);
|
|
88919
90928
|
}
|
|
88920
90929
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonContentSecondaryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
88921
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: RibbonContentSecondaryComponent, isStandalone: true, selector: "pptx-ribbon-content-secondary", inputs: { activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: true, transformFunction: null }, slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, selectedElement: { classPropertyName: "selectedElement", publicName: "selectedElement", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null }, themeGalleryOpen: { classPropertyName: "themeGalleryOpen", publicName: "themeGalleryOpen", isSignal: true, isRequired: false, transformFunction: null }, spellCheckEnabled: { classPropertyName: "spellCheckEnabled", publicName: "spellCheckEnabled", isSignal: true, isRequired: false, transformFunction: null }, showSubtitles: { classPropertyName: "showSubtitles", publicName: "showSubtitles", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { present: "present", presenter: "presenter", record: "record", presentFromBeginning: "presentFromBeginning", rehearseTimings: "rehearseTimings", toggleSubtitles: "toggleSubtitles", openSubtitleSettings: "openSubtitleSettings", recordFromBeginning: "recordFromBeginning", recordFromCurrent: "recordFromCurrent", spellCheckChange: "spellCheckChange", broadcast: "broadcast", info: "info", print: "print", comments: "comments", a11y: "a11y", link: "link", openSorter: "openSorter", openReadingView: "openReadingView", openMasterView: "openMasterView", toggleNotes: "toggleNotes", toggleInspector: "toggleInspector", drawToolChange: "drawToolChange", toggleThemeGallery: "toggleThemeGallery", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", openCustomShows: "openCustomShows", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper", openSetUpSlideShow: "openSetUpSlideShow", openCompare: "openCompare", openShortcuts: "openShortcuts", openSettings: "openSettings" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
90930
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: RibbonContentSecondaryComponent, isStandalone: true, selector: "pptx-ribbon-content-secondary", inputs: { activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: true, transformFunction: null }, slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, selectedElement: { classPropertyName: "selectedElement", publicName: "selectedElement", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null }, themeGalleryOpen: { classPropertyName: "themeGalleryOpen", publicName: "themeGalleryOpen", isSignal: true, isRequired: false, transformFunction: null }, spellCheckEnabled: { classPropertyName: "spellCheckEnabled", publicName: "spellCheckEnabled", isSignal: true, isRequired: false, transformFunction: null }, showSubtitles: { classPropertyName: "showSubtitles", publicName: "showSubtitles", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { present: "present", presenter: "presenter", record: "record", presentFromBeginning: "presentFromBeginning", rehearseTimings: "rehearseTimings", toggleSubtitles: "toggleSubtitles", openSubtitleSettings: "openSubtitleSettings", recordFromBeginning: "recordFromBeginning", recordFromCurrent: "recordFromCurrent", spellCheckChange: "spellCheckChange", broadcast: "broadcast", info: "info", print: "print", comments: "comments", a11y: "a11y", link: "link", openSorter: "openSorter", openReadingView: "openReadingView", openOutlineView: "openOutlineView", openMasterView: "openMasterView", toggleNotes: "toggleNotes", toggleInspector: "toggleInspector", drawToolChange: "drawToolChange", toggleThemeGallery: "toggleThemeGallery", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", openCustomShows: "openCustomShows", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper", openSetUpSlideShow: "openSetUpSlideShow", openCompare: "openCompare", openShortcuts: "openShortcuts", openSettings: "openSettings" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
88922
90931
|
@switch (activeTab()) {
|
|
88923
90932
|
@case ('slideShow') {
|
|
88924
90933
|
<pptx-ribbon-slideshow-section
|
|
@@ -88960,6 +90969,7 @@ class RibbonContentSecondaryComponent {
|
|
|
88960
90969
|
[eyedropperActive]="eyedropperActive()"
|
|
88961
90970
|
(openSorter)="openSorter.emit()"
|
|
88962
90971
|
(openReadingView)="openReadingView.emit()"
|
|
90972
|
+
(openOutlineView)="openOutlineView.emit()"
|
|
88963
90973
|
(openMasterView)="openMasterView.emit()"
|
|
88964
90974
|
(toggleGrid)="toggleGrid.emit()"
|
|
88965
90975
|
(toggleRulers)="toggleRulers.emit()"
|
|
@@ -89026,7 +91036,7 @@ class RibbonContentSecondaryComponent {
|
|
|
89026
91036
|
/>
|
|
89027
91037
|
}
|
|
89028
91038
|
}
|
|
89029
|
-
`, isInline: true, dependencies: [{ kind: "component", type: RibbonSlideshowSectionComponent, selector: "pptx-ribbon-slideshow-section", inputs: ["slideCount", "showSubtitles", "hiddenActions"], outputs: ["presentFromBeginning", "presentFromCurrent", "presenter", "broadcast", "openCustomShows", "openSetUpSlideShow", "rehearseTimings", "record", "toggleSubtitles", "openSubtitleSettings"] }, { kind: "component", type: RibbonReviewSectionComponent, selector: "pptx-ribbon-review-section", inputs: ["spellCheckEnabled", "canEdit"], outputs: ["comments", "spellCheckChange", "a11y", "openCompare", "language", "link"] }, { kind: "component", type: RibbonViewSectionComponent, selector: "pptx-ribbon-view-section", inputs: ["canEdit", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive"], outputs: ["openSorter", "openReadingView", "openMasterView", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper"] }, { kind: "component", type: RibbonDrawSectionComponent, selector: "pptx-ribbon-draw-section", inputs: ["activeTool", "drawingColor", "drawingWidth"], outputs: ["drawToolChange"] }, { kind: "component", type: RibbonDesignSectionComponent, selector: "pptx-ribbon-design-section", inputs: ["themeGalleryOpen"], outputs: ["toggleThemeGallery", "info", "toggleInspector"] }, { kind: "component", type: RibbonTransitionsSectionComponent, selector: "pptx-ribbon-transitions-section", inputs: ["slideIndex", "selectedTransition", "transitionDurationSec"], outputs: ["present", "toggleInspector", "transitionChange", "durationChange"] }, { kind: "component", type: RibbonAnimationsSectionComponent, selector: "pptx-ribbon-animations-section", inputs: ["slideIndex", "selectedElement", "canEdit"], outputs: ["present", "toggleInspector"] }, { kind: "component", type: RibbonRecordSectionComponent, selector: "pptx-ribbon-record-section", outputs: ["recordFromBeginning", "recordFromCurrent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
91039
|
+
`, isInline: true, dependencies: [{ kind: "component", type: RibbonSlideshowSectionComponent, selector: "pptx-ribbon-slideshow-section", inputs: ["slideCount", "showSubtitles", "hiddenActions"], outputs: ["presentFromBeginning", "presentFromCurrent", "presenter", "broadcast", "openCustomShows", "openSetUpSlideShow", "rehearseTimings", "record", "toggleSubtitles", "openSubtitleSettings"] }, { kind: "component", type: RibbonReviewSectionComponent, selector: "pptx-ribbon-review-section", inputs: ["spellCheckEnabled", "canEdit"], outputs: ["comments", "spellCheckChange", "a11y", "openCompare", "language", "link"] }, { kind: "component", type: RibbonViewSectionComponent, selector: "pptx-ribbon-view-section", inputs: ["canEdit", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive"], outputs: ["openSorter", "openReadingView", "openOutlineView", "openMasterView", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper"] }, { kind: "component", type: RibbonDrawSectionComponent, selector: "pptx-ribbon-draw-section", inputs: ["activeTool", "drawingColor", "drawingWidth"], outputs: ["drawToolChange"] }, { kind: "component", type: RibbonDesignSectionComponent, selector: "pptx-ribbon-design-section", inputs: ["themeGalleryOpen"], outputs: ["toggleThemeGallery", "info", "toggleInspector"] }, { kind: "component", type: RibbonTransitionsSectionComponent, selector: "pptx-ribbon-transitions-section", inputs: ["slideIndex", "selectedTransition", "transitionDurationSec"], outputs: ["present", "toggleInspector", "transitionChange", "durationChange"] }, { kind: "component", type: RibbonAnimationsSectionComponent, selector: "pptx-ribbon-animations-section", inputs: ["slideIndex", "selectedElement", "canEdit"], outputs: ["present", "toggleInspector"] }, { kind: "component", type: RibbonRecordSectionComponent, selector: "pptx-ribbon-record-section", outputs: ["recordFromBeginning", "recordFromCurrent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
89030
91040
|
}
|
|
89031
91041
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonContentSecondaryComponent, decorators: [{
|
|
89032
91042
|
type: Component,
|
|
@@ -89088,6 +91098,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
89088
91098
|
[eyedropperActive]="eyedropperActive()"
|
|
89089
91099
|
(openSorter)="openSorter.emit()"
|
|
89090
91100
|
(openReadingView)="openReadingView.emit()"
|
|
91101
|
+
(openOutlineView)="openOutlineView.emit()"
|
|
89091
91102
|
(openMasterView)="openMasterView.emit()"
|
|
89092
91103
|
(toggleGrid)="toggleGrid.emit()"
|
|
89093
91104
|
(toggleRulers)="toggleRulers.emit()"
|
|
@@ -89156,7 +91167,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
89156
91167
|
}
|
|
89157
91168
|
`,
|
|
89158
91169
|
}]
|
|
89159
|
-
}], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], themeGalleryOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeGalleryOpen", required: false }] }], spellCheckEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheckEnabled", required: false }] }], showSubtitles: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubtitles", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], record: [{ type: i0.Output, args: ["record"] }], presentFromBeginning: [{ type: i0.Output, args: ["presentFromBeginning"] }], rehearseTimings: [{ type: i0.Output, args: ["rehearseTimings"] }], toggleSubtitles: [{ type: i0.Output, args: ["toggleSubtitles"] }], openSubtitleSettings: [{ type: i0.Output, args: ["openSubtitleSettings"] }], recordFromBeginning: [{ type: i0.Output, args: ["recordFromBeginning"] }], recordFromCurrent: [{ type: i0.Output, args: ["recordFromCurrent"] }], spellCheckChange: [{ type: i0.Output, args: ["spellCheckChange"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], info: [{ type: i0.Output, args: ["info"] }], print: [{ type: i0.Output, args: ["print"] }], comments: [{ type: i0.Output, args: ["comments"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], link: [{ type: i0.Output, args: ["link"] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleNotes: [{ type: i0.Output, args: ["toggleNotes"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], drawToolChange: [{ type: i0.Output, args: ["drawToolChange"] }], toggleThemeGallery: [{ type: i0.Output, args: ["toggleThemeGallery"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }], openSetUpSlideShow: [{ type: i0.Output, args: ["openSetUpSlideShow"] }], openCompare: [{ type: i0.Output, args: ["openCompare"] }], openShortcuts: [{ type: i0.Output, args: ["openShortcuts"] }], openSettings: [{ type: i0.Output, args: ["openSettings"] }] } });
|
|
91170
|
+
}], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], themeGalleryOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeGalleryOpen", required: false }] }], spellCheckEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheckEnabled", required: false }] }], showSubtitles: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubtitles", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], record: [{ type: i0.Output, args: ["record"] }], presentFromBeginning: [{ type: i0.Output, args: ["presentFromBeginning"] }], rehearseTimings: [{ type: i0.Output, args: ["rehearseTimings"] }], toggleSubtitles: [{ type: i0.Output, args: ["toggleSubtitles"] }], openSubtitleSettings: [{ type: i0.Output, args: ["openSubtitleSettings"] }], recordFromBeginning: [{ type: i0.Output, args: ["recordFromBeginning"] }], recordFromCurrent: [{ type: i0.Output, args: ["recordFromCurrent"] }], spellCheckChange: [{ type: i0.Output, args: ["spellCheckChange"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], info: [{ type: i0.Output, args: ["info"] }], print: [{ type: i0.Output, args: ["print"] }], comments: [{ type: i0.Output, args: ["comments"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], link: [{ type: i0.Output, args: ["link"] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openOutlineView: [{ type: i0.Output, args: ["openOutlineView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleNotes: [{ type: i0.Output, args: ["toggleNotes"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], drawToolChange: [{ type: i0.Output, args: ["drawToolChange"] }], toggleThemeGallery: [{ type: i0.Output, args: ["toggleThemeGallery"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }], openSetUpSlideShow: [{ type: i0.Output, args: ["openSetUpSlideShow"] }], openCompare: [{ type: i0.Output, args: ["openCompare"] }], openShortcuts: [{ type: i0.Output, args: ["openShortcuts"] }], openSettings: [{ type: i0.Output, args: ["openSettings"] }] } });
|
|
89160
91171
|
|
|
89161
91172
|
/**
|
|
89162
91173
|
* ribbon-shape-extras.component.ts: the Arrange group's shape-level extras
|
|
@@ -90069,7 +92080,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
90069
92080
|
}], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }] } });
|
|
90070
92081
|
|
|
90071
92082
|
// Generated by scripts/inline-shared.mjs from package.json. Do not edit.
|
|
90072
|
-
const PPTX_ANGULAR_VIEWER_VERSION = "2.
|
|
92083
|
+
const PPTX_ANGULAR_VIEWER_VERSION = "2.10.0";
|
|
90073
92084
|
|
|
90074
92085
|
/**
|
|
90075
92086
|
* account-page.component.ts: File > Account content.
|
|
@@ -94132,6 +96143,7 @@ class RibbonComponent {
|
|
|
94132
96143
|
openSorter = output();
|
|
94133
96144
|
/** View tab > Reading View: the deck full-window, not the slide show. */
|
|
94134
96145
|
openReadingView = output();
|
|
96146
|
+
openOutlineView = output();
|
|
94135
96147
|
openMasterView = output();
|
|
94136
96148
|
toggleNotes = output();
|
|
94137
96149
|
toggleFormatPainter = output();
|
|
@@ -94196,7 +96208,7 @@ class RibbonComponent {
|
|
|
94196
96208
|
this.spellCheckChange.emit(enabled);
|
|
94197
96209
|
}
|
|
94198
96210
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
94199
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: RibbonComponent, isStandalone: true, selector: "pptx-ribbon", inputs: { slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, selectedElement: { classPropertyName: "selectedElement", publicName: "selectedElement", isSignal: true, isRequired: false, transformFunction: null }, zoomPercent: { classPropertyName: "zoomPercent", publicName: "zoomPercent", isSignal: true, isRequired: false, transformFunction: null }, formatPainterActive: { classPropertyName: "formatPainterActive", publicName: "formatPainterActive", isSignal: true, isRequired: false, transformFunction: null }, canActivateFormatPainter: { classPropertyName: "canActivateFormatPainter", publicName: "canActivateFormatPainter", isSignal: true, isRequired: false, transformFunction: null }, exporting: { classPropertyName: "exporting", publicName: "exporting", isSignal: true, isRequired: false, transformFunction: null }, hasMacros: { classPropertyName: "hasMacros", publicName: "hasMacros", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null }, themeGalleryOpen: { classPropertyName: "themeGalleryOpen", publicName: "themeGalleryOpen", isSignal: true, isRequired: false, transformFunction: null }, sidebarCollapsed: { classPropertyName: "sidebarCollapsed", publicName: "sidebarCollapsed", isSignal: true, isRequired: false, transformFunction: null }, inspectorOpen: { classPropertyName: "inspectorOpen", publicName: "inspectorOpen", isSignal: true, isRequired: false, transformFunction: null }, commentsOpen: { classPropertyName: "commentsOpen", publicName: "commentsOpen", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null }, findOpen: { classPropertyName: "findOpen", publicName: "findOpen", isSignal: true, isRequired: false, transformFunction: null }, collabConnected: { classPropertyName: "collabConnected", publicName: "collabConnected", isSignal: true, isRequired: false, transformFunction: null }, connectedCount: { classPropertyName: "connectedCount", publicName: "connectedCount", isSignal: true, isRequired: false, transformFunction: null }, spellCheckEnabled: { classPropertyName: "spellCheckEnabled", publicName: "spellCheckEnabled", isSignal: true, isRequired: false, transformFunction: null }, showSubtitles: { classPropertyName: "showSubtitles", publicName: "showSubtitles", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, aiEnabled: { classPropertyName: "aiEnabled", publicName: "aiEnabled", isSignal: true, isRequired: false, transformFunction: null }, aiPanelOpen: { classPropertyName: "aiPanelOpen", publicName: "aiPanelOpen", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { prev: "prev", next: "next", zoomIn: "zoomIn", zoomOut: "zoomOut", zoomReset: "zoomReset", find: "find", present: "present", presenter: "presenter", record: "record", presentFromBeginning: "presentFromBeginning", rehearseTimings: "rehearseTimings", toggleSubtitles: "toggleSubtitles", openSubtitleSettings: "openSubtitleSettings", recordFromBeginning: "recordFromBeginning", recordFromCurrent: "recordFromCurrent", spellCheckChange: "spellCheckChange", share: "share", broadcast: "broadcast", openFile: "openFile", openRecentFile: "openRecentFile", createPresentation: "createPresentation", save: "save", savePpsx: "savePpsx", savePptm: "savePptm", packageForSharing: "packageForSharing", toggleSidebar: "toggleSidebar", toggleAiPanel: "toggleAiPanel", signatures: "signatures", info: "info", print: "print", comments: "comments", a11y: "a11y", link: "link", openSorter: "openSorter", openReadingView: "openReadingView", openMasterView: "openMasterView", toggleNotes: "toggleNotes", toggleFormatPainter: "toggleFormatPainter", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", copySlideAsImage: "copySlideAsImage", replace: "replace", toggleInspector: "toggleInspector", drawToolChange: "drawToolChange", toggleThemeGallery: "toggleThemeGallery", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", openCustomShows: "openCustomShows", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper", openSmartArtDialog: "openSmartArtDialog", openEquationDialog: "openEquationDialog", openSetUpSlideShow: "openSetUpSlideShow", openCompare: "openCompare", openPassword: "openPassword", openFontEmbedding: "openFontEmbedding", openVersionHistory: "openVersionHistory", openShortcuts: "openShortcuts", openSettings: "openSettings" }, ngImport: i0, template: `
|
|
96211
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: RibbonComponent, isStandalone: true, selector: "pptx-ribbon", inputs: { slideIndex: { classPropertyName: "slideIndex", publicName: "slideIndex", isSignal: true, isRequired: false, transformFunction: null }, slideCount: { classPropertyName: "slideCount", publicName: "slideCount", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, selectedElement: { classPropertyName: "selectedElement", publicName: "selectedElement", isSignal: true, isRequired: false, transformFunction: null }, zoomPercent: { classPropertyName: "zoomPercent", publicName: "zoomPercent", isSignal: true, isRequired: false, transformFunction: null }, formatPainterActive: { classPropertyName: "formatPainterActive", publicName: "formatPainterActive", isSignal: true, isRequired: false, transformFunction: null }, canActivateFormatPainter: { classPropertyName: "canActivateFormatPainter", publicName: "canActivateFormatPainter", isSignal: true, isRequired: false, transformFunction: null }, exporting: { classPropertyName: "exporting", publicName: "exporting", isSignal: true, isRequired: false, transformFunction: null }, hasMacros: { classPropertyName: "hasMacros", publicName: "hasMacros", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showRulers: { classPropertyName: "showRulers", publicName: "showRulers", isSignal: true, isRequired: false, transformFunction: null }, showGuides: { classPropertyName: "showGuides", publicName: "showGuides", isSignal: true, isRequired: false, transformFunction: null }, snapToGrid: { classPropertyName: "snapToGrid", publicName: "snapToGrid", isSignal: true, isRequired: false, transformFunction: null }, snapToShape: { classPropertyName: "snapToShape", publicName: "snapToShape", isSignal: true, isRequired: false, transformFunction: null }, eyedropperActive: { classPropertyName: "eyedropperActive", publicName: "eyedropperActive", isSignal: true, isRequired: false, transformFunction: null }, themeGalleryOpen: { classPropertyName: "themeGalleryOpen", publicName: "themeGalleryOpen", isSignal: true, isRequired: false, transformFunction: null }, sidebarCollapsed: { classPropertyName: "sidebarCollapsed", publicName: "sidebarCollapsed", isSignal: true, isRequired: false, transformFunction: null }, inspectorOpen: { classPropertyName: "inspectorOpen", publicName: "inspectorOpen", isSignal: true, isRequired: false, transformFunction: null }, commentsOpen: { classPropertyName: "commentsOpen", publicName: "commentsOpen", isSignal: true, isRequired: false, transformFunction: null }, commentCount: { classPropertyName: "commentCount", publicName: "commentCount", isSignal: true, isRequired: false, transformFunction: null }, findOpen: { classPropertyName: "findOpen", publicName: "findOpen", isSignal: true, isRequired: false, transformFunction: null }, collabConnected: { classPropertyName: "collabConnected", publicName: "collabConnected", isSignal: true, isRequired: false, transformFunction: null }, connectedCount: { classPropertyName: "connectedCount", publicName: "connectedCount", isSignal: true, isRequired: false, transformFunction: null }, spellCheckEnabled: { classPropertyName: "spellCheckEnabled", publicName: "spellCheckEnabled", isSignal: true, isRequired: false, transformFunction: null }, showSubtitles: { classPropertyName: "showSubtitles", publicName: "showSubtitles", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, aiEnabled: { classPropertyName: "aiEnabled", publicName: "aiEnabled", isSignal: true, isRequired: false, transformFunction: null }, aiPanelOpen: { classPropertyName: "aiPanelOpen", publicName: "aiPanelOpen", isSignal: true, isRequired: false, transformFunction: null }, accountAuth: { classPropertyName: "accountAuth", publicName: "accountAuth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { prev: "prev", next: "next", zoomIn: "zoomIn", zoomOut: "zoomOut", zoomReset: "zoomReset", find: "find", present: "present", presenter: "presenter", record: "record", presentFromBeginning: "presentFromBeginning", rehearseTimings: "rehearseTimings", toggleSubtitles: "toggleSubtitles", openSubtitleSettings: "openSubtitleSettings", recordFromBeginning: "recordFromBeginning", recordFromCurrent: "recordFromCurrent", spellCheckChange: "spellCheckChange", share: "share", broadcast: "broadcast", openFile: "openFile", openRecentFile: "openRecentFile", createPresentation: "createPresentation", save: "save", savePpsx: "savePpsx", savePptm: "savePptm", packageForSharing: "packageForSharing", toggleSidebar: "toggleSidebar", toggleAiPanel: "toggleAiPanel", signatures: "signatures", info: "info", print: "print", comments: "comments", a11y: "a11y", link: "link", openSorter: "openSorter", openReadingView: "openReadingView", openOutlineView: "openOutlineView", openMasterView: "openMasterView", toggleNotes: "toggleNotes", toggleFormatPainter: "toggleFormatPainter", exportPng: "exportPng", exportPdf: "exportPdf", exportGif: "exportGif", exportVideo: "exportVideo", copySlideAsImage: "copySlideAsImage", replace: "replace", toggleInspector: "toggleInspector", drawToolChange: "drawToolChange", toggleThemeGallery: "toggleThemeGallery", toggleGrid: "toggleGrid", toggleRulers: "toggleRulers", toggleGuides: "toggleGuides", toggleSelectionPane: "toggleSelectionPane", openCustomShows: "openCustomShows", toggleSnapToGrid: "toggleSnapToGrid", toggleSnapToShape: "toggleSnapToShape", addGuide: "addGuide", zoomToFit: "zoomToFit", toggleEyedropper: "toggleEyedropper", openSmartArtDialog: "openSmartArtDialog", openEquationDialog: "openEquationDialog", openSetUpSlideShow: "openSetUpSlideShow", openCompare: "openCompare", openPassword: "openPassword", openFontEmbedding: "openFontEmbedding", openVersionHistory: "openVersionHistory", openShortcuts: "openShortcuts", openSettings: "openSettings" }, ngImport: i0, template: `
|
|
94200
96212
|
<div
|
|
94201
96213
|
role="toolbar"
|
|
94202
96214
|
[attr.aria-label]="'pptx.toolbar.presentationToolbarAria' | translate"
|
|
@@ -94321,6 +96333,7 @@ class RibbonComponent {
|
|
|
94321
96333
|
(link)="link.emit()"
|
|
94322
96334
|
(openSorter)="openSorter.emit()"
|
|
94323
96335
|
(openReadingView)="openReadingView.emit()"
|
|
96336
|
+
(openOutlineView)="openOutlineView.emit()"
|
|
94324
96337
|
(openMasterView)="openMasterView.emit()"
|
|
94325
96338
|
(toggleNotes)="toggleNotes.emit()"
|
|
94326
96339
|
(toggleInspector)="toggleInspector.emit()"
|
|
@@ -94343,7 +96356,7 @@ class RibbonComponent {
|
|
|
94343
96356
|
/>
|
|
94344
96357
|
</div>
|
|
94345
96358
|
</div>
|
|
94346
|
-
`, isInline: true, dependencies: [{ kind: "component", type: RibbonPrimaryRowComponent, selector: "pptx-ribbon-primary-row", inputs: ["slideCount", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "hiddenActions", "aiEnabled", "aiPanelOpen"], outputs: ["toggleSidebar", "toggleAiPanel", "toggleComments", "present", "presenter", "broadcast", "openCustomShows", "toggleInspector", "openSettings", "exportPng", "exportPdf", "exportGif", "exportVideo", "print", "info", "a11y", "save"] }, { kind: "component", type: RibbonTabListComponent, selector: "pptx-ribbon-tab-list", inputs: ["activeTab", "canEdit", "collabConnected", "connectedCount", "ribbonExpanded", "hiddenActions"], outputs: ["selectTab", "record", "share", "toggleRibbonExpanded"] }, { kind: "component", type: RibbonContentComponent, selector: "pptx-ribbon-content", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "hiddenActions", "accountAuth"], outputs: ["selectTab", "find", "share", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "signatures", "info", "print", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "openSmartArtDialog", "openEquationDialog", "link", "openPassword", "openFontEmbedding", "openVersionHistory", "openSettings"] }, { kind: "component", type: RibbonContentSecondaryComponent, selector: "pptx-ribbon-content-secondary", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "spellCheckEnabled", "showSubtitles", "hiddenActions"], outputs: ["present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "broadcast", "info", "print", "comments", "a11y", "link", "openSorter", "openReadingView", "openMasterView", "toggleNotes", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSetUpSlideShow", "openCompare", "openShortcuts", "openSettings"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
96359
|
+
`, isInline: true, dependencies: [{ kind: "component", type: RibbonPrimaryRowComponent, selector: "pptx-ribbon-primary-row", inputs: ["slideCount", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "hiddenActions", "aiEnabled", "aiPanelOpen"], outputs: ["toggleSidebar", "toggleAiPanel", "toggleComments", "present", "presenter", "broadcast", "openCustomShows", "toggleInspector", "openSettings", "exportPng", "exportPdf", "exportGif", "exportVideo", "print", "info", "a11y", "save"] }, { kind: "component", type: RibbonTabListComponent, selector: "pptx-ribbon-tab-list", inputs: ["activeTab", "canEdit", "collabConnected", "connectedCount", "ribbonExpanded", "hiddenActions"], outputs: ["selectTab", "record", "share", "toggleRibbonExpanded"] }, { kind: "component", type: RibbonContentComponent, selector: "pptx-ribbon-content", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "hiddenActions", "accountAuth"], outputs: ["selectTab", "find", "share", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "signatures", "info", "print", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "openSmartArtDialog", "openEquationDialog", "link", "openPassword", "openFontEmbedding", "openVersionHistory", "openSettings"] }, { kind: "component", type: RibbonContentSecondaryComponent, selector: "pptx-ribbon-content-secondary", inputs: ["activeTab", "slideIndex", "slideCount", "canEdit", "selectedElement", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "spellCheckEnabled", "showSubtitles", "hiddenActions"], outputs: ["present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "broadcast", "info", "print", "comments", "a11y", "link", "openSorter", "openReadingView", "openOutlineView", "openMasterView", "toggleNotes", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSetUpSlideShow", "openCompare", "openShortcuts", "openSettings"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
94347
96360
|
}
|
|
94348
96361
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: RibbonComponent, decorators: [{
|
|
94349
96362
|
type: Component,
|
|
@@ -94483,6 +96496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
94483
96496
|
(link)="link.emit()"
|
|
94484
96497
|
(openSorter)="openSorter.emit()"
|
|
94485
96498
|
(openReadingView)="openReadingView.emit()"
|
|
96499
|
+
(openOutlineView)="openOutlineView.emit()"
|
|
94486
96500
|
(openMasterView)="openMasterView.emit()"
|
|
94487
96501
|
(toggleNotes)="toggleNotes.emit()"
|
|
94488
96502
|
(toggleInspector)="toggleInspector.emit()"
|
|
@@ -94507,7 +96521,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
94507
96521
|
</div>
|
|
94508
96522
|
`,
|
|
94509
96523
|
}]
|
|
94510
|
-
}], propDecorators: { slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }], zoomPercent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoomPercent", required: false }] }], formatPainterActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatPainterActive", required: false }] }], canActivateFormatPainter: [{ type: i0.Input, args: [{ isSignal: true, alias: "canActivateFormatPainter", required: false }] }], exporting: [{ type: i0.Input, args: [{ isSignal: true, alias: "exporting", required: false }] }], hasMacros: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMacros", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], themeGalleryOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeGalleryOpen", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], inspectorOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "inspectorOpen", required: false }] }], commentsOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentsOpen", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], findOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "findOpen", required: false }] }], collabConnected: [{ type: i0.Input, args: [{ isSignal: true, alias: "collabConnected", required: false }] }], connectedCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedCount", required: false }] }], spellCheckEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheckEnabled", required: false }] }], showSubtitles: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubtitles", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], aiEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiEnabled", required: false }] }], aiPanelOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiPanelOpen", required: false }] }], accountAuth: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountAuth", required: false }] }], prev: [{ type: i0.Output, args: ["prev"] }], next: [{ type: i0.Output, args: ["next"] }], zoomIn: [{ type: i0.Output, args: ["zoomIn"] }], zoomOut: [{ type: i0.Output, args: ["zoomOut"] }], zoomReset: [{ type: i0.Output, args: ["zoomReset"] }], find: [{ type: i0.Output, args: ["find"] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], record: [{ type: i0.Output, args: ["record"] }], presentFromBeginning: [{ type: i0.Output, args: ["presentFromBeginning"] }], rehearseTimings: [{ type: i0.Output, args: ["rehearseTimings"] }], toggleSubtitles: [{ type: i0.Output, args: ["toggleSubtitles"] }], openSubtitleSettings: [{ type: i0.Output, args: ["openSubtitleSettings"] }], recordFromBeginning: [{ type: i0.Output, args: ["recordFromBeginning"] }], recordFromCurrent: [{ type: i0.Output, args: ["recordFromCurrent"] }], spellCheckChange: [{ type: i0.Output, args: ["spellCheckChange"] }], share: [{ type: i0.Output, args: ["share"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], openFile: [{ type: i0.Output, args: ["openFile"] }], openRecentFile: [{ type: i0.Output, args: ["openRecentFile"] }], createPresentation: [{ type: i0.Output, args: ["createPresentation"] }], save: [{ type: i0.Output, args: ["save"] }], savePpsx: [{ type: i0.Output, args: ["savePpsx"] }], savePptm: [{ type: i0.Output, args: ["savePptm"] }], packageForSharing: [{ type: i0.Output, args: ["packageForSharing"] }], toggleSidebar: [{ type: i0.Output, args: ["toggleSidebar"] }], toggleAiPanel: [{ type: i0.Output, args: ["toggleAiPanel"] }], signatures: [{ type: i0.Output, args: ["signatures"] }], info: [{ type: i0.Output, args: ["info"] }], print: [{ type: i0.Output, args: ["print"] }], comments: [{ type: i0.Output, args: ["comments"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], link: [{ type: i0.Output, args: ["link"] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleNotes: [{ type: i0.Output, args: ["toggleNotes"] }], toggleFormatPainter: [{ type: i0.Output, args: ["toggleFormatPainter"] }], exportPng: [{ type: i0.Output, args: ["exportPng"] }], exportPdf: [{ type: i0.Output, args: ["exportPdf"] }], exportGif: [{ type: i0.Output, args: ["exportGif"] }], exportVideo: [{ type: i0.Output, args: ["exportVideo"] }], copySlideAsImage: [{ type: i0.Output, args: ["copySlideAsImage"] }], replace: [{ type: i0.Output, args: ["replace"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], drawToolChange: [{ type: i0.Output, args: ["drawToolChange"] }], toggleThemeGallery: [{ type: i0.Output, args: ["toggleThemeGallery"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }], openSmartArtDialog: [{ type: i0.Output, args: ["openSmartArtDialog"] }], openEquationDialog: [{ type: i0.Output, args: ["openEquationDialog"] }], openSetUpSlideShow: [{ type: i0.Output, args: ["openSetUpSlideShow"] }], openCompare: [{ type: i0.Output, args: ["openCompare"] }], openPassword: [{ type: i0.Output, args: ["openPassword"] }], openFontEmbedding: [{ type: i0.Output, args: ["openFontEmbedding"] }], openVersionHistory: [{ type: i0.Output, args: ["openVersionHistory"] }], openShortcuts: [{ type: i0.Output, args: ["openShortcuts"] }], openSettings: [{ type: i0.Output, args: ["openSettings"] }] } });
|
|
96524
|
+
}], propDecorators: { slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }], zoomPercent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoomPercent", required: false }] }], formatPainterActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatPainterActive", required: false }] }], canActivateFormatPainter: [{ type: i0.Input, args: [{ isSignal: true, alias: "canActivateFormatPainter", required: false }] }], exporting: [{ type: i0.Input, args: [{ isSignal: true, alias: "exporting", required: false }] }], hasMacros: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMacros", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showRulers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRulers", required: false }] }], showGuides: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGuides", required: false }] }], snapToGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToGrid", required: false }] }], snapToShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapToShape", required: false }] }], eyedropperActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyedropperActive", required: false }] }], themeGalleryOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeGalleryOpen", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], inspectorOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "inspectorOpen", required: false }] }], commentsOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentsOpen", required: false }] }], commentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "commentCount", required: false }] }], findOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "findOpen", required: false }] }], collabConnected: [{ type: i0.Input, args: [{ isSignal: true, alias: "collabConnected", required: false }] }], connectedCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedCount", required: false }] }], spellCheckEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellCheckEnabled", required: false }] }], showSubtitles: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubtitles", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], aiEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiEnabled", required: false }] }], aiPanelOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "aiPanelOpen", required: false }] }], accountAuth: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountAuth", required: false }] }], prev: [{ type: i0.Output, args: ["prev"] }], next: [{ type: i0.Output, args: ["next"] }], zoomIn: [{ type: i0.Output, args: ["zoomIn"] }], zoomOut: [{ type: i0.Output, args: ["zoomOut"] }], zoomReset: [{ type: i0.Output, args: ["zoomReset"] }], find: [{ type: i0.Output, args: ["find"] }], present: [{ type: i0.Output, args: ["present"] }], presenter: [{ type: i0.Output, args: ["presenter"] }], record: [{ type: i0.Output, args: ["record"] }], presentFromBeginning: [{ type: i0.Output, args: ["presentFromBeginning"] }], rehearseTimings: [{ type: i0.Output, args: ["rehearseTimings"] }], toggleSubtitles: [{ type: i0.Output, args: ["toggleSubtitles"] }], openSubtitleSettings: [{ type: i0.Output, args: ["openSubtitleSettings"] }], recordFromBeginning: [{ type: i0.Output, args: ["recordFromBeginning"] }], recordFromCurrent: [{ type: i0.Output, args: ["recordFromCurrent"] }], spellCheckChange: [{ type: i0.Output, args: ["spellCheckChange"] }], share: [{ type: i0.Output, args: ["share"] }], broadcast: [{ type: i0.Output, args: ["broadcast"] }], openFile: [{ type: i0.Output, args: ["openFile"] }], openRecentFile: [{ type: i0.Output, args: ["openRecentFile"] }], createPresentation: [{ type: i0.Output, args: ["createPresentation"] }], save: [{ type: i0.Output, args: ["save"] }], savePpsx: [{ type: i0.Output, args: ["savePpsx"] }], savePptm: [{ type: i0.Output, args: ["savePptm"] }], packageForSharing: [{ type: i0.Output, args: ["packageForSharing"] }], toggleSidebar: [{ type: i0.Output, args: ["toggleSidebar"] }], toggleAiPanel: [{ type: i0.Output, args: ["toggleAiPanel"] }], signatures: [{ type: i0.Output, args: ["signatures"] }], info: [{ type: i0.Output, args: ["info"] }], print: [{ type: i0.Output, args: ["print"] }], comments: [{ type: i0.Output, args: ["comments"] }], a11y: [{ type: i0.Output, args: ["a11y"] }], link: [{ type: i0.Output, args: ["link"] }], openSorter: [{ type: i0.Output, args: ["openSorter"] }], openReadingView: [{ type: i0.Output, args: ["openReadingView"] }], openOutlineView: [{ type: i0.Output, args: ["openOutlineView"] }], openMasterView: [{ type: i0.Output, args: ["openMasterView"] }], toggleNotes: [{ type: i0.Output, args: ["toggleNotes"] }], toggleFormatPainter: [{ type: i0.Output, args: ["toggleFormatPainter"] }], exportPng: [{ type: i0.Output, args: ["exportPng"] }], exportPdf: [{ type: i0.Output, args: ["exportPdf"] }], exportGif: [{ type: i0.Output, args: ["exportGif"] }], exportVideo: [{ type: i0.Output, args: ["exportVideo"] }], copySlideAsImage: [{ type: i0.Output, args: ["copySlideAsImage"] }], replace: [{ type: i0.Output, args: ["replace"] }], toggleInspector: [{ type: i0.Output, args: ["toggleInspector"] }], drawToolChange: [{ type: i0.Output, args: ["drawToolChange"] }], toggleThemeGallery: [{ type: i0.Output, args: ["toggleThemeGallery"] }], toggleGrid: [{ type: i0.Output, args: ["toggleGrid"] }], toggleRulers: [{ type: i0.Output, args: ["toggleRulers"] }], toggleGuides: [{ type: i0.Output, args: ["toggleGuides"] }], toggleSelectionPane: [{ type: i0.Output, args: ["toggleSelectionPane"] }], openCustomShows: [{ type: i0.Output, args: ["openCustomShows"] }], toggleSnapToGrid: [{ type: i0.Output, args: ["toggleSnapToGrid"] }], toggleSnapToShape: [{ type: i0.Output, args: ["toggleSnapToShape"] }], addGuide: [{ type: i0.Output, args: ["addGuide"] }], zoomToFit: [{ type: i0.Output, args: ["zoomToFit"] }], toggleEyedropper: [{ type: i0.Output, args: ["toggleEyedropper"] }], openSmartArtDialog: [{ type: i0.Output, args: ["openSmartArtDialog"] }], openEquationDialog: [{ type: i0.Output, args: ["openEquationDialog"] }], openSetUpSlideShow: [{ type: i0.Output, args: ["openSetUpSlideShow"] }], openCompare: [{ type: i0.Output, args: ["openCompare"] }], openPassword: [{ type: i0.Output, args: ["openPassword"] }], openFontEmbedding: [{ type: i0.Output, args: ["openFontEmbedding"] }], openVersionHistory: [{ type: i0.Output, args: ["openVersionHistory"] }], openShortcuts: [{ type: i0.Output, args: ["openShortcuts"] }], openSettings: [{ type: i0.Output, args: ["openSettings"] }] } });
|
|
94511
96525
|
|
|
94512
96526
|
/**
|
|
94513
96527
|
* selection-pane.component.ts: Side panel listing all elements on the active slide.
|
|
@@ -95526,8 +97540,23 @@ function getAnimationElementLabel(element) {
|
|
|
95526
97540
|
}
|
|
95527
97541
|
|
|
95528
97542
|
let activePreview;
|
|
97543
|
+
/** Slide size assumed when the stage cannot be measured (detached preview). */
|
|
97544
|
+
const FALLBACK_SLIDE_WIDTH = 1280;
|
|
97545
|
+
const FALLBACK_SLIDE_HEIGHT = 720;
|
|
97546
|
+
/**
|
|
97547
|
+
* The element a preview should play on.
|
|
97548
|
+
*
|
|
97549
|
+
* The slides panel renders a thumbnail of the SAME element with the same
|
|
97550
|
+
* `data-element-id`, and it comes first in DOM order, so taking the first match
|
|
97551
|
+
* played every preview on a thumbnail the user is not looking at. For a motion
|
|
97552
|
+
* path that is worse than invisible: the travel is measured against the
|
|
97553
|
+
* thumbnail's own tiny stage, so it also plays at the wrong distance. Only the
|
|
97554
|
+
* interactive main canvas carries `data-pptx-viewport`, which is the neutral
|
|
97555
|
+
* marker every binding already agrees on.
|
|
97556
|
+
*/
|
|
95529
97557
|
function findElement(elementId) {
|
|
95530
|
-
|
|
97558
|
+
const matches = [...document.querySelectorAll('[data-element-id]')].filter((element) => element.dataset['elementId'] === elementId);
|
|
97559
|
+
return matches.find((element) => element.closest('[data-pptx-viewport]')) ?? matches[0];
|
|
95531
97560
|
}
|
|
95532
97561
|
function stopAngularAnimationPreview() {
|
|
95533
97562
|
if (!activePreview) {
|
|
@@ -95539,19 +97568,45 @@ function stopAngularAnimationPreview() {
|
|
|
95539
97568
|
activePreview.styleElement.remove();
|
|
95540
97569
|
activePreview = undefined;
|
|
95541
97570
|
}
|
|
95542
|
-
|
|
95543
|
-
|
|
97571
|
+
/**
|
|
97572
|
+
* Pick the descriptor an animation entry should play.
|
|
97573
|
+
*
|
|
97574
|
+
* A motion path WINS over the preset buckets: it is the effect being authored
|
|
97575
|
+
* on the canvas at that moment, and a fade or a spin would hide the travel
|
|
97576
|
+
* entirely. The slide size comes from the element's offset parent (the stage)
|
|
97577
|
+
* because path coordinates are fractions of the SLIDE, not of the element's own
|
|
97578
|
+
* box, and the stage is laid out in unscaled slide pixels.
|
|
97579
|
+
*/
|
|
97580
|
+
function buildAngularPreviewDescriptor(animation, element) {
|
|
97581
|
+
if (animation.motionPath) {
|
|
97582
|
+
const stage = element.offsetParent;
|
|
97583
|
+
return buildMotionPathPreview({
|
|
97584
|
+
path: animation.motionPath,
|
|
97585
|
+
slideWidth: stage?.offsetWidth || FALLBACK_SLIDE_WIDTH,
|
|
97586
|
+
slideHeight: stage?.offsetHeight || FALLBACK_SLIDE_HEIGHT,
|
|
97587
|
+
durationMs: animation.durationMs,
|
|
97588
|
+
delayMs: animation.delayMs,
|
|
97589
|
+
timingCurve: animation.timingCurve,
|
|
97590
|
+
});
|
|
97591
|
+
}
|
|
95544
97592
|
const preset = animation.entrance ?? animation.emphasis ?? animation.exit;
|
|
95545
97593
|
if (!preset || preset === 'none') {
|
|
95546
|
-
return
|
|
97594
|
+
return undefined;
|
|
95547
97595
|
}
|
|
95548
|
-
|
|
97596
|
+
return buildPreviewAnimation(preset, {
|
|
95549
97597
|
direction: animation.direction,
|
|
95550
97598
|
durationMs: animation.durationMs ?? 500,
|
|
95551
97599
|
timingCurve: animation.timingCurve,
|
|
95552
97600
|
});
|
|
95553
|
-
|
|
95554
|
-
|
|
97601
|
+
}
|
|
97602
|
+
function previewAngularAnimation(animation) {
|
|
97603
|
+
stopAngularAnimationPreview();
|
|
97604
|
+
const element = findElement(animation.elementId);
|
|
97605
|
+
if (!element) {
|
|
97606
|
+
return false;
|
|
97607
|
+
}
|
|
97608
|
+
const descriptor = buildAngularPreviewDescriptor(animation, element);
|
|
97609
|
+
if (!descriptor) {
|
|
95555
97610
|
return false;
|
|
95556
97611
|
}
|
|
95557
97612
|
const styleElement = document.createElement('style');
|
|
@@ -95726,6 +97781,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
95726
97781
|
`, styles: [".timeline{display:grid;gap:6px;padding:8px 0;border-top:1px solid var(--pptx-inspector-border, #333)}h4{margin:0;color:var(--pptx-inspector-muted, #888);font-size:10px;text-transform:uppercase}.bar{position:relative;height:22px;overflow:hidden;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:var(--pptx-inspector-input-bg, #2d2d2d)}.bar span{position:absolute;top:3px;bottom:3px;min-width:2%;border-radius:2px;background:#6b9a68}.bar span.selected{outline:1px solid var(--pptx-primary, #4c9ffe)}.list{display:grid;gap:3px;max-height:160px;overflow-y:auto}.item{display:flex;align-items:center;gap:4px;min-width:0;padding:4px;border:1px solid transparent;border-radius:3px;background:var(--pptx-inspector-input-bg, #2d2d2d);cursor:grab;font-size:10px}.item.selected{border-color:var(--pptx-primary, #4c9ffe)}.item.drag-over{border-top:2px solid var(--pptx-primary, #4c9ffe)}.grip,.order{color:var(--pptx-inspector-muted, #888)}.name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.effect{color:var(--pptx-inspector-muted, #aaa)}\n"] }]
|
|
95727
97782
|
}], propDecorators: { animations: [{ type: i0.Input, args: [{ isSignal: true, alias: "animations", required: true }] }], elements: [{ type: i0.Input, args: [{ isSignal: true, alias: "elements", required: false }] }], selectedElementId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElementId", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], animationsChange: [{ type: i0.Output, args: ["animationsChange"] }] } });
|
|
95728
97783
|
|
|
97784
|
+
/**
|
|
97785
|
+
* motion-path-row.component.ts: the animation panel's motion-path row.
|
|
97786
|
+
*
|
|
97787
|
+
* Selector: `pptx-motion-path-row`
|
|
97788
|
+
*
|
|
97789
|
+
* Its own component rather than more markup inside
|
|
97790
|
+
* {@link AnimationAuthorPanelComponent} because that file already sits just
|
|
97791
|
+
* under this repo's 300-LOC cap, and the row carries a catalogue-sized
|
|
97792
|
+
* `<select>` of its own.
|
|
97793
|
+
*
|
|
97794
|
+
* WHY a "Custom Path" option exists: dragging the end handle on the canvas
|
|
97795
|
+
* produces a path that no longer matches any catalogue entry. Without a slot
|
|
97796
|
+
* to show that in, the select would snap back to the preset the user started
|
|
97797
|
+
* from and misreport what will actually play. The option is therefore rendered
|
|
97798
|
+
* only while the applied path is unrecognised, and re-picking it is a no-op
|
|
97799
|
+
* (the panel refuses to translate "custom" back into some catalogue geometry).
|
|
97800
|
+
*
|
|
97801
|
+
* Reference binding: packages/react/src/viewer/components/inspector/MotionPathRow.tsx
|
|
97802
|
+
*
|
|
97803
|
+
* @module viewer/motion-path-row
|
|
97804
|
+
*/
|
|
97805
|
+
/** The select value standing for "this path was hand-dragged". */
|
|
97806
|
+
const CUSTOM_MOTION_PATH_VALUE = 'custom';
|
|
97807
|
+
/** The select value standing for "no path at all". */
|
|
97808
|
+
const NO_MOTION_PATH_VALUE = 'none';
|
|
97809
|
+
/**
|
|
97810
|
+
* Which option the select should show for an applied path.
|
|
97811
|
+
*
|
|
97812
|
+
* Pure so the branch that used to be a template ternary can be asserted
|
|
97813
|
+
* directly: `none` when nothing is applied, the catalogue id when the geometry
|
|
97814
|
+
* is recognised, `custom` when it is not.
|
|
97815
|
+
*/
|
|
97816
|
+
function motionPathSelectValue(motionPath) {
|
|
97817
|
+
if (!motionPath) {
|
|
97818
|
+
return NO_MOTION_PATH_VALUE;
|
|
97819
|
+
}
|
|
97820
|
+
return motionPathPresetIdForPath(motionPath) ?? CUSTOM_MOTION_PATH_VALUE;
|
|
97821
|
+
}
|
|
97822
|
+
class MotionPathRowComponent {
|
|
97823
|
+
/** The path currently applied to the selected element, if any. */
|
|
97824
|
+
motionPath = input(undefined, /* @ts-ignore */
|
|
97825
|
+
...(ngDevMode ? [{ debugName: "motionPath" }] : /* istanbul ignore next */ []));
|
|
97826
|
+
/** Whether the select is live. */
|
|
97827
|
+
canEdit = input(true, /* @ts-ignore */
|
|
97828
|
+
...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
97829
|
+
/**
|
|
97830
|
+
* Emits a catalogue preset id, or `'none'` to clear the path. `'custom'` is
|
|
97831
|
+
* never emitted: re-picking the marker changes nothing.
|
|
97832
|
+
*/
|
|
97833
|
+
presetChange = output();
|
|
97834
|
+
columns = MOTION_PATH_COLUMNS;
|
|
97835
|
+
/** The option the select shows: `none`, a catalogue id, or `custom`. */
|
|
97836
|
+
selectedValue = computed(() => motionPathSelectValue(this.motionPath()), /* @ts-ignore */
|
|
97837
|
+
...(ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []));
|
|
97838
|
+
/** True while the applied path matches no catalogue entry. */
|
|
97839
|
+
isCustom = computed(() => this.selectedValue() === CUSTOM_MOTION_PATH_VALUE, /* @ts-ignore */
|
|
97840
|
+
...(ngDevMode ? [{ debugName: "isCustom" }] : /* istanbul ignore next */ []));
|
|
97841
|
+
onSelect(event) {
|
|
97842
|
+
const target = event.target;
|
|
97843
|
+
if (!(target instanceof HTMLSelectElement)) {
|
|
97844
|
+
return;
|
|
97845
|
+
}
|
|
97846
|
+
// The custom marker is read-only: it describes a dragged path, and there is
|
|
97847
|
+
// no catalogue geometry to restore it to.
|
|
97848
|
+
if (target.value === CUSTOM_MOTION_PATH_VALUE) {
|
|
97849
|
+
return;
|
|
97850
|
+
}
|
|
97851
|
+
this.presetChange.emit(target.value);
|
|
97852
|
+
}
|
|
97853
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MotionPathRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
97854
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MotionPathRowComponent, isStandalone: true, selector: "pptx-motion-path-row", inputs: { motionPath: { classPropertyName: "motionPath", publicName: "motionPath", isSignal: true, isRequired: false, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { presetChange: "presetChange" }, ngImport: i0, template: `
|
|
97855
|
+
<label class="pptx-ng-anim__section pptx-ng-motion-path">
|
|
97856
|
+
<span class="pptx-ng-anim__label">
|
|
97857
|
+
{{ 'pptx.animation.motionPath.label' | translate }}
|
|
97858
|
+
</span>
|
|
97859
|
+
<!--
|
|
97860
|
+
Selection is expressed with [selected] on each option rather than
|
|
97861
|
+
[value] on the select: Angular applies an element's own property
|
|
97862
|
+
bindings before the @for blocks below it have produced any options, so
|
|
97863
|
+
a [value] naming a catalogue id would be assigned to an empty select
|
|
97864
|
+
and silently drop back to the first entry on first render.
|
|
97865
|
+
-->
|
|
97866
|
+
<select class="pptx-ng-anim__select" [disabled]="!canEdit()" (change)="onSelect($event)">
|
|
97867
|
+
<option value="none" [selected]="selectedValue() === 'none'">
|
|
97868
|
+
{{ 'pptx.animation.motionPath.none' | translate }}
|
|
97869
|
+
</option>
|
|
97870
|
+
@if (isCustom()) {
|
|
97871
|
+
<option value="custom" selected>
|
|
97872
|
+
{{ 'pptx.animation.motionPath.custom' | translate }}
|
|
97873
|
+
</option>
|
|
97874
|
+
}
|
|
97875
|
+
@for (column of columns; track column.family) {
|
|
97876
|
+
<optgroup [label]="column.labelKey | translate">
|
|
97877
|
+
@for (preset of column.presets; track preset.id) {
|
|
97878
|
+
<option [value]="preset.id" [selected]="selectedValue() === preset.id">
|
|
97879
|
+
{{ preset.labelKey | translate }}
|
|
97880
|
+
</option>
|
|
97881
|
+
}
|
|
97882
|
+
</optgroup>
|
|
97883
|
+
}
|
|
97884
|
+
</select>
|
|
97885
|
+
@if (motionPath()) {
|
|
97886
|
+
<span class="pptx-ng-motion-path__hint">
|
|
97887
|
+
{{ 'pptx.animation.motionPath.editHint' | translate }}
|
|
97888
|
+
</span>
|
|
97889
|
+
}
|
|
97890
|
+
</label>
|
|
97891
|
+
`, isInline: true, styles: [".pptx-ng-motion-path{display:block}.pptx-ng-motion-path__hint{display:block;margin-top:.2rem;font-size:10px;color:var(--pptx-inspector-muted, #888)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
97892
|
+
}
|
|
97893
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MotionPathRowComponent, decorators: [{
|
|
97894
|
+
type: Component,
|
|
97895
|
+
args: [{ selector: 'pptx-motion-path-row', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: `
|
|
97896
|
+
<label class="pptx-ng-anim__section pptx-ng-motion-path">
|
|
97897
|
+
<span class="pptx-ng-anim__label">
|
|
97898
|
+
{{ 'pptx.animation.motionPath.label' | translate }}
|
|
97899
|
+
</span>
|
|
97900
|
+
<!--
|
|
97901
|
+
Selection is expressed with [selected] on each option rather than
|
|
97902
|
+
[value] on the select: Angular applies an element's own property
|
|
97903
|
+
bindings before the @for blocks below it have produced any options, so
|
|
97904
|
+
a [value] naming a catalogue id would be assigned to an empty select
|
|
97905
|
+
and silently drop back to the first entry on first render.
|
|
97906
|
+
-->
|
|
97907
|
+
<select class="pptx-ng-anim__select" [disabled]="!canEdit()" (change)="onSelect($event)">
|
|
97908
|
+
<option value="none" [selected]="selectedValue() === 'none'">
|
|
97909
|
+
{{ 'pptx.animation.motionPath.none' | translate }}
|
|
97910
|
+
</option>
|
|
97911
|
+
@if (isCustom()) {
|
|
97912
|
+
<option value="custom" selected>
|
|
97913
|
+
{{ 'pptx.animation.motionPath.custom' | translate }}
|
|
97914
|
+
</option>
|
|
97915
|
+
}
|
|
97916
|
+
@for (column of columns; track column.family) {
|
|
97917
|
+
<optgroup [label]="column.labelKey | translate">
|
|
97918
|
+
@for (preset of column.presets; track preset.id) {
|
|
97919
|
+
<option [value]="preset.id" [selected]="selectedValue() === preset.id">
|
|
97920
|
+
{{ preset.labelKey | translate }}
|
|
97921
|
+
</option>
|
|
97922
|
+
}
|
|
97923
|
+
</optgroup>
|
|
97924
|
+
}
|
|
97925
|
+
</select>
|
|
97926
|
+
@if (motionPath()) {
|
|
97927
|
+
<span class="pptx-ng-motion-path__hint">
|
|
97928
|
+
{{ 'pptx.animation.motionPath.editHint' | translate }}
|
|
97929
|
+
</span>
|
|
97930
|
+
}
|
|
97931
|
+
</label>
|
|
97932
|
+
`, styles: [".pptx-ng-motion-path{display:block}.pptx-ng-motion-path__hint{display:block;margin-top:.2rem;font-size:10px;color:var(--pptx-inspector-muted, #888)}\n"] }]
|
|
97933
|
+
}], propDecorators: { motionPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "motionPath", required: false }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], presetChange: [{ type: i0.Output, args: ["presetChange"] }] } });
|
|
97934
|
+
|
|
95729
97935
|
/**
|
|
95730
97936
|
* animation-author-panel.component.ts: Animation authoring inspector sub-panel.
|
|
95731
97937
|
*
|
|
@@ -95881,6 +98087,22 @@ class AnimationAuthorPanelComponent {
|
|
|
95881
98087
|
}
|
|
95882
98088
|
this.emit(setAnimationEmphasis(this.animations(), this.element().id, value));
|
|
95883
98089
|
}
|
|
98090
|
+
// ── Motion path ───────────────────────────────────────────────────────────
|
|
98091
|
+
/**
|
|
98092
|
+
* Apply or clear the element's motion path.
|
|
98093
|
+
*
|
|
98094
|
+
* The path lives on the SAME animation entry as the preset buckets, so this
|
|
98095
|
+
* deliberately does not go through the preset setters: applying a path must
|
|
98096
|
+
* leave an existing entrance alone, and clearing one must drop the entry only
|
|
98097
|
+
* when nothing else is left on it. Both rules live in the shared helpers.
|
|
98098
|
+
*/
|
|
98099
|
+
onMotionPathChange(presetId) {
|
|
98100
|
+
const animations = this.animations();
|
|
98101
|
+
const elementId = this.element().id;
|
|
98102
|
+
this.emit(presetId === 'none'
|
|
98103
|
+
? clearMotionPath(animations, elementId)
|
|
98104
|
+
: applyMotionPathPreset(animations, elementId, presetId));
|
|
98105
|
+
}
|
|
95884
98106
|
// ── Trigger handlers ─────────────────────────────────────────────────────
|
|
95885
98107
|
onTriggerChange(event) {
|
|
95886
98108
|
const value = stringFromSelect(event);
|
|
@@ -96037,6 +98259,15 @@ class AnimationAuthorPanelComponent {
|
|
|
96037
98259
|
</select>
|
|
96038
98260
|
</section>
|
|
96039
98261
|
|
|
98262
|
+
<!-- ── Motion path: geometry, not a preset, so it gets its own row ─ -->
|
|
98263
|
+
<section class="pptx-ng-anim__section">
|
|
98264
|
+
<pptx-motion-path-row
|
|
98265
|
+
[motionPath]="current()?.motionPath"
|
|
98266
|
+
[canEdit]="canEdit()"
|
|
98267
|
+
(presetChange)="onMotionPathChange($event)"
|
|
98268
|
+
/>
|
|
98269
|
+
</section>
|
|
98270
|
+
|
|
96040
98271
|
<!-- ── Effect options: only shown when an animation is set ─────── -->
|
|
96041
98272
|
@if (currentHasAnimation()) {
|
|
96042
98273
|
<!-- ── Direction picker (directional presets only) ──────────── -->
|
|
@@ -96264,11 +98495,18 @@ class AnimationAuthorPanelComponent {
|
|
|
96264
98495
|
}
|
|
96265
98496
|
<!-- end @if (currentHasAnimation()) -->
|
|
96266
98497
|
</aside>
|
|
96267
|
-
`, isInline: true, styles: [".pptx-ng-anim{display:flex;flex-direction:column;gap:0;padding:.5rem;background:var(--pptx-inspector-bg, #1e1e1e);color:var(--pptx-inspector-fg, #e0e0e0);font-size:12px;min-width:220px;overflow-y:auto}.pptx-ng-anim__header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.4rem;border-bottom:1px solid var(--pptx-inspector-border, #333);margin-bottom:.35rem}.pptx-ng-anim__title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888)}.pptx-ng-anim__header-actions{display:flex;align-items:center;gap:4px}.pptx-ng-anim__preview-btn{padding:2px 6px;border:1px solid var(--pptx-primary, #4c9ffe);border-radius:3px;background:transparent;color:var(--pptx-primary, #4c9ffe);cursor:pointer;font-size:10px}.pptx-ng-anim__subheading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);padding:.4rem 0 .2rem;border-top:1px solid var(--pptx-inspector-border, #333);margin-top:.2rem}.pptx-ng-anim__section{padding:.25rem 0;border-bottom:1px solid var(--pptx-inspector-border, #2a2a2a)}.pptx-ng-anim__section:last-child{border-bottom:none}.pptx-ng-anim__label{display:block;font-size:10px;color:var(--pptx-inspector-muted, #888);margin-bottom:.2rem}.pptx-ng-anim__select,.pptx-ng-anim__input{width:100%;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;padding:3px 6px;font-size:12px;box-sizing:border-box}.pptx-ng-anim__select:disabled,.pptx-ng-anim__input:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__direction-grid{display:flex;flex-wrap:wrap;gap:.25rem}.pptx-ng-anim__dir-btn{width:30px;height:30px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center}.pptx-ng-anim__dir-btn.is-active{background:var(--pptx-inspector-active, #0078d4);border-color:var(--pptx-inspector-active, #0078d4);color:#fff}.pptx-ng-anim__dir-btn:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__row{display:flex;gap:.35rem}.pptx-ng-anim__order-btn{flex:1;padding:3px 6px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;cursor:pointer;font-size:11px;white-space:nowrap}.pptx-ng-anim__order-btn:hover:not(:disabled){background:var(--pptx-inspector-hover, #3a3a3a)}.pptx-ng-anim__order-btn:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__remove-btn{padding:2px 6px;background:transparent;border:1px solid var(--pptx-inspector-danger-border, #6b2a2a);color:var(--pptx-inspector-danger, #f47c7c);border-radius:3px;cursor:pointer;font-size:10px}.pptx-ng-anim__remove-btn:hover{background:var(--pptx-inspector-danger-hover, #4a1a1a)}@media(pointer:coarse),(max-width:640px){.pptx-ng-anim{width:100%;min-width:0;box-sizing:border-box;font-size:14px}.pptx-ng-anim__select,.pptx-ng-anim__input{min-height:40px;font-size:16px;padding:6px 8px}.pptx-ng-anim__dir-btn{width:40px;height:40px}.pptx-ng-anim__order-btn{min-height:40px;font-size:13px}}\n"], dependencies: [{ kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideArrowUp, selector: "svg[lucideArrowUp]" }, { kind: "component", type: LucideArrowDown, selector: "svg[lucideArrowDown]" }, { kind: "component", type: AnimationTimelineComponent, selector: "pptx-animation-timeline", inputs: ["animations", "elements", "selectedElementId", "canEdit"], outputs: ["animationsChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
98498
|
+
`, isInline: true, styles: [".pptx-ng-anim{display:flex;flex-direction:column;gap:0;padding:.5rem;background:var(--pptx-inspector-bg, #1e1e1e);color:var(--pptx-inspector-fg, #e0e0e0);font-size:12px;min-width:220px;overflow-y:auto}.pptx-ng-anim__header{display:flex;align-items:center;justify-content:space-between;padding-bottom:.4rem;border-bottom:1px solid var(--pptx-inspector-border, #333);margin-bottom:.35rem}.pptx-ng-anim__title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888)}.pptx-ng-anim__header-actions{display:flex;align-items:center;gap:4px}.pptx-ng-anim__preview-btn{padding:2px 6px;border:1px solid var(--pptx-primary, #4c9ffe);border-radius:3px;background:transparent;color:var(--pptx-primary, #4c9ffe);cursor:pointer;font-size:10px}.pptx-ng-anim__subheading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);padding:.4rem 0 .2rem;border-top:1px solid var(--pptx-inspector-border, #333);margin-top:.2rem}.pptx-ng-anim__section{padding:.25rem 0;border-bottom:1px solid var(--pptx-inspector-border, #2a2a2a)}.pptx-ng-anim__section:last-child{border-bottom:none}.pptx-ng-anim__label{display:block;font-size:10px;color:var(--pptx-inspector-muted, #888);margin-bottom:.2rem}.pptx-ng-anim__select,.pptx-ng-anim__input{width:100%;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;padding:3px 6px;font-size:12px;box-sizing:border-box}.pptx-ng-anim__select:disabled,.pptx-ng-anim__input:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__direction-grid{display:flex;flex-wrap:wrap;gap:.25rem}.pptx-ng-anim__dir-btn{width:30px;height:30px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;cursor:pointer;font-size:14px;display:flex;align-items:center;justify-content:center}.pptx-ng-anim__dir-btn.is-active{background:var(--pptx-inspector-active, #0078d4);border-color:var(--pptx-inspector-active, #0078d4);color:#fff}.pptx-ng-anim__dir-btn:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__row{display:flex;gap:.35rem}.pptx-ng-anim__order-btn{flex:1;padding:3px 6px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);color:inherit;border-radius:3px;cursor:pointer;font-size:11px;white-space:nowrap}.pptx-ng-anim__order-btn:hover:not(:disabled){background:var(--pptx-inspector-hover, #3a3a3a)}.pptx-ng-anim__order-btn:disabled{opacity:.5;cursor:not-allowed}.pptx-ng-anim__remove-btn{padding:2px 6px;background:transparent;border:1px solid var(--pptx-inspector-danger-border, #6b2a2a);color:var(--pptx-inspector-danger, #f47c7c);border-radius:3px;cursor:pointer;font-size:10px}.pptx-ng-anim__remove-btn:hover{background:var(--pptx-inspector-danger-hover, #4a1a1a)}@media(pointer:coarse),(max-width:640px){.pptx-ng-anim{width:100%;min-width:0;box-sizing:border-box;font-size:14px}.pptx-ng-anim__select,.pptx-ng-anim__input{min-height:40px;font-size:16px;padding:6px 8px}.pptx-ng-anim__dir-btn{width:40px;height:40px}.pptx-ng-anim__order-btn{min-height:40px;font-size:13px}}\n"], dependencies: [{ kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideArrowUp, selector: "svg[lucideArrowUp]" }, { kind: "component", type: LucideArrowDown, selector: "svg[lucideArrowDown]" }, { kind: "component", type: AnimationTimelineComponent, selector: "pptx-animation-timeline", inputs: ["animations", "elements", "selectedElementId", "canEdit"], outputs: ["animationsChange"] }, { kind: "component", type: MotionPathRowComponent, selector: "pptx-motion-path-row", inputs: ["motionPath", "canEdit"], outputs: ["presetChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
96268
98499
|
}
|
|
96269
98500
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AnimationAuthorPanelComponent, decorators: [{
|
|
96270
98501
|
type: Component,
|
|
96271
|
-
args: [{ selector: 'pptx-animation-author-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
98502
|
+
args: [{ selector: 'pptx-animation-author-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
98503
|
+
TranslatePipe,
|
|
98504
|
+
LucideX,
|
|
98505
|
+
LucideArrowUp,
|
|
98506
|
+
LucideArrowDown,
|
|
98507
|
+
AnimationTimelineComponent,
|
|
98508
|
+
MotionPathRowComponent,
|
|
98509
|
+
], template: `
|
|
96272
98510
|
<aside class="pptx-ng-anim" [attr.aria-label]="'pptx.animations.propertiesLabel' | translate">
|
|
96273
98511
|
<!-- ── Header ───────────────────────────────────────────────────── -->
|
|
96274
98512
|
<div class="pptx-ng-anim__header">
|
|
@@ -96353,6 +98591,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
96353
98591
|
</select>
|
|
96354
98592
|
</section>
|
|
96355
98593
|
|
|
98594
|
+
<!-- ── Motion path: geometry, not a preset, so it gets its own row ─ -->
|
|
98595
|
+
<section class="pptx-ng-anim__section">
|
|
98596
|
+
<pptx-motion-path-row
|
|
98597
|
+
[motionPath]="current()?.motionPath"
|
|
98598
|
+
[canEdit]="canEdit()"
|
|
98599
|
+
(presetChange)="onMotionPathChange($event)"
|
|
98600
|
+
/>
|
|
98601
|
+
</section>
|
|
98602
|
+
|
|
96356
98603
|
<!-- ── Effect options: only shown when an animation is set ─────── -->
|
|
96357
98604
|
@if (currentHasAnimation()) {
|
|
96358
98605
|
<!-- ── Direction picker (directional presets only) ──────────── -->
|
|
@@ -97229,6 +99476,13 @@ function setSeriesChartType(element, seriesIndex, seriesType) {
|
|
|
97229
99476
|
function setDataPointFill(element, seriesIndex, pointIndex, color) {
|
|
97230
99477
|
return withClonedChart(element, (el) => setChartDataPointFill(el, seriesIndex, pointIndex, color));
|
|
97231
99478
|
}
|
|
99479
|
+
/**
|
|
99480
|
+
* Set or clear a per-data-point marker override (`c:dPt/c:marker`), which
|
|
99481
|
+
* replaces the series marker for that one point.
|
|
99482
|
+
*/
|
|
99483
|
+
function setDataPointMarker(element, seriesIndex, pointIndex, marker) {
|
|
99484
|
+
return withClonedChart(element, (el) => setChartDataPointMarker(el, seriesIndex, pointIndex, marker));
|
|
99485
|
+
}
|
|
97232
99486
|
/** Set or clear a per-data-point pie/doughnut slice explosion. */
|
|
97233
99487
|
function setDataPointExplosion(element, seriesIndex, pointIndex, explosion) {
|
|
97234
99488
|
return withClonedChart(element, (el) => setChartDataPointExplosion(el, seriesIndex, pointIndex, explosion));
|
|
@@ -98068,6 +100322,242 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
98068
100322
|
`, styles: [".pptx-chart-card{display:flex;flex-direction:column;gap:.35rem;padding:.5rem 0;border-top:1px solid var(--pptx-inspector-border, #333)}.pptx-chart-card__heading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);margin:0}.pptx-chart-card__group{display:flex;flex-direction:column;gap:.3rem}.pptx-chart-card__group--indent{margin-left:.5rem}.pptx-chart-card__subhead{font-size:11px;font-weight:600}.pptx-chart-card__row{display:flex;align-items:center;gap:.4rem;font-size:11px}.pptx-chart-card__label{flex:0 0 auto;width:5rem;color:var(--pptx-inspector-muted, #888)}.pptx-chart-card__label--wide{width:6.5rem}.pptx-chart-card__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-chart-card__check{display:flex;align-items:center;gap:.35rem;font-size:11px;cursor:pointer}.pptx-chart-card__input{flex:1 1 auto;min-width:0;box-sizing:border-box;padding:2px 4px;font-size:11px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;color:inherit;outline:none}.pptx-chart-card__input--num{flex:0 0 auto;width:4rem;text-align:right}.pptx-chart-card__input:focus{border-color:var(--pptx-inspector-active, #0078d4)}.pptx-chart-card__input:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__color{flex:0 0 auto;width:26px;height:20px;padding:0;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:transparent;cursor:pointer}.pptx-chart-card__color:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__clear{flex:0 0 auto;padding:0 2px;font-size:12px;line-height:1;background:none;border:none;color:var(--pptx-inspector-muted, #888);cursor:pointer}.pptx-chart-card__clear:hover{color:var(--pptx-inspector-danger, #f47c7c)}.pptx-chart-card__input--num::-webkit-outer-spin-button,.pptx-chart-card__input--num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
|
|
98069
100323
|
}], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], elementChange: [{ type: i0.Output, args: ["elementChange"] }] } });
|
|
98070
100324
|
|
|
100325
|
+
/**
|
|
100326
|
+
* chart-datapoint-marker-options.component.ts: Per-data-point marker overrides.
|
|
100327
|
+
*
|
|
100328
|
+
* Selector: `pptx-chart-datapoint-marker-options`
|
|
100329
|
+
*
|
|
100330
|
+
* Mirrors React's `ChartDataPointMarkerOptions.tsx`, the one advanced chart
|
|
100331
|
+
* control Angular had never been given: `pptx-chart-datapoint-options` covers a
|
|
100332
|
+
* point's fill and slice explosion, but a `c:dPt` can also carry its own
|
|
100333
|
+
* `c:marker`, which replaces the series marker for that point alone (the usual
|
|
100334
|
+
* use is calling out a single outlier on an otherwise uniform line).
|
|
100335
|
+
*
|
|
100336
|
+
* The checkbox is the presence of the override, not a value: ticking it seeds a
|
|
100337
|
+
* circle, clearing it removes the whole `c:dPt/c:marker`. Edits route through
|
|
100338
|
+
* `setDataPointMarker`, which wraps core's headless op, so the `c:dPt`
|
|
100339
|
+
* bookkeeping matches React, Vue, Svelte and Vanilla exactly.
|
|
100340
|
+
*
|
|
100341
|
+
* @module angular-viewer/chart-datapoint-marker-options
|
|
100342
|
+
*/
|
|
100343
|
+
/** Concrete symbols only; '' is the "series default" sentinel, which the
|
|
100344
|
+
* presence checkbox already expresses. */
|
|
100345
|
+
const SYMBOL_OPTIONS = MARKER_SYMBOL_OPTIONS.filter((option) => option.value !== '');
|
|
100346
|
+
class ChartDatapointMarkerOptionsComponent {
|
|
100347
|
+
element = input.required(/* @ts-ignore */
|
|
100348
|
+
...(ngDevMode ? [{ debugName: "element" }] : /* istanbul ignore next */ []));
|
|
100349
|
+
canEdit = input(true, /* @ts-ignore */
|
|
100350
|
+
...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
|
|
100351
|
+
elementChange = output();
|
|
100352
|
+
symbolOptions = SYMBOL_OPTIONS;
|
|
100353
|
+
seriesIndex = signal(0, /* @ts-ignore */
|
|
100354
|
+
...(ngDevMode ? [{ debugName: "seriesIndex" }] : /* istanbul ignore next */ []));
|
|
100355
|
+
series = computed(() => this.element().chartData?.series ?? [], /* @ts-ignore */
|
|
100356
|
+
...(ngDevMode ? [{ debugName: "series" }] : /* istanbul ignore next */ []));
|
|
100357
|
+
categories = computed(() => this.element().chartData?.categories ?? [], /* @ts-ignore */
|
|
100358
|
+
...(ngDevMode ? [{ debugName: "categories" }] : /* istanbul ignore next */ []));
|
|
100359
|
+
/** Clamp the picker: removing a series must not strand the index past the end. */
|
|
100360
|
+
activeIndex = computed(() => Math.min(this.seriesIndex(), Math.max(0, this.series().length - 1)), /* @ts-ignore */
|
|
100361
|
+
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
100362
|
+
supported = computed(() => {
|
|
100363
|
+
const type = this.element().chartData?.chartType;
|
|
100364
|
+
return (type !== undefined &&
|
|
100365
|
+
MARKER_SUPPORTED_TYPES.has(type) &&
|
|
100366
|
+
this.series().length > 0 &&
|
|
100367
|
+
this.categories().length > 0);
|
|
100368
|
+
}, /* @ts-ignore */
|
|
100369
|
+
...(ngDevMode ? [{ debugName: "supported" }] : /* istanbul ignore next */ []));
|
|
100370
|
+
markerAt(pointIndex) {
|
|
100371
|
+
return this.series()[this.activeIndex()]?.dataPoints?.find((p) => p.idx === pointIndex)?.marker;
|
|
100372
|
+
}
|
|
100373
|
+
onSeries(event) {
|
|
100374
|
+
const value = selectValue$2(event);
|
|
100375
|
+
if (value === null) {
|
|
100376
|
+
return;
|
|
100377
|
+
}
|
|
100378
|
+
const num = Number.parseInt(value, 10);
|
|
100379
|
+
if (Number.isFinite(num)) {
|
|
100380
|
+
this.seriesIndex.set(num);
|
|
100381
|
+
}
|
|
100382
|
+
}
|
|
100383
|
+
onToggle(pointIndex, event) {
|
|
100384
|
+
this.emit(pointIndex, boolFromEvent(event) ? { symbol: 'circle' } : null);
|
|
100385
|
+
}
|
|
100386
|
+
onSymbol(pointIndex, event) {
|
|
100387
|
+
const value = selectValue$2(event);
|
|
100388
|
+
if (value === null) {
|
|
100389
|
+
return;
|
|
100390
|
+
}
|
|
100391
|
+
this.emit(pointIndex, { symbol: value });
|
|
100392
|
+
}
|
|
100393
|
+
onSize(pointIndex, event) {
|
|
100394
|
+
const num = numFromEvent(event);
|
|
100395
|
+
this.emit(pointIndex, { size: typeof num === 'number' ? num : undefined });
|
|
100396
|
+
}
|
|
100397
|
+
onFill(pointIndex, event) {
|
|
100398
|
+
const value = stringFromEvent$5(event);
|
|
100399
|
+
if (value === null) {
|
|
100400
|
+
return;
|
|
100401
|
+
}
|
|
100402
|
+
this.emit(pointIndex, { fillColor: value });
|
|
100403
|
+
}
|
|
100404
|
+
emit(pointIndex, marker) {
|
|
100405
|
+
this.elementChange.emit(setDataPointMarker(this.element(), this.activeIndex(), pointIndex, marker));
|
|
100406
|
+
}
|
|
100407
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ChartDatapointMarkerOptionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
100408
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: ChartDatapointMarkerOptionsComponent, isStandalone: true, selector: "pptx-chart-datapoint-marker-options", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { elementChange: "elementChange" }, ngImport: i0, template: `
|
|
100409
|
+
@if (supported()) {
|
|
100410
|
+
<section class="pptx-chart-card" [attr.aria-label]="'pptx.chart.pointMarkers' | translate">
|
|
100411
|
+
<h4 class="pptx-chart-card__heading">{{ 'pptx.chart.pointMarkers' | translate }}</h4>
|
|
100412
|
+
|
|
100413
|
+
@if (series().length > 1) {
|
|
100414
|
+
<label class="pptx-chart-card__row">
|
|
100415
|
+
<span class="pptx-chart-card__label">{{ 'pptx.chart.series' | translate }}</span>
|
|
100416
|
+
<select
|
|
100417
|
+
class="pptx-chart-card__input"
|
|
100418
|
+
[disabled]="!canEdit()"
|
|
100419
|
+
[value]="activeIndex()"
|
|
100420
|
+
(change)="onSeries($event)"
|
|
100421
|
+
>
|
|
100422
|
+
@for (s of series(); track $index; let i = $index) {
|
|
100423
|
+
<option [value]="i">{{ s.name }}</option>
|
|
100424
|
+
}
|
|
100425
|
+
</select>
|
|
100426
|
+
</label>
|
|
100427
|
+
}
|
|
100428
|
+
|
|
100429
|
+
<div class="pptx-chart-card__group">
|
|
100430
|
+
@for (cat of categories(); track $index; let ci = $index) {
|
|
100431
|
+
<div class="pptx-chart-card__row">
|
|
100432
|
+
<span class="pptx-chart-card__name" [title]="cat">{{ cat }}</span>
|
|
100433
|
+
<label class="pptx-chart-card__check">
|
|
100434
|
+
<input
|
|
100435
|
+
type="checkbox"
|
|
100436
|
+
[disabled]="!canEdit()"
|
|
100437
|
+
[checked]="markerAt(ci) !== undefined"
|
|
100438
|
+
(change)="onToggle(ci, $event)"
|
|
100439
|
+
/>
|
|
100440
|
+
{{ 'pptx.chart.markerOverride' | translate }}
|
|
100441
|
+
</label>
|
|
100442
|
+
</div>
|
|
100443
|
+
|
|
100444
|
+
@if (markerAt(ci); as marker) {
|
|
100445
|
+
<div class="pptx-chart-card__row pptx-chart-card__group--indent">
|
|
100446
|
+
<select
|
|
100447
|
+
class="pptx-chart-card__input"
|
|
100448
|
+
[disabled]="!canEdit()"
|
|
100449
|
+
[value]="marker.symbol"
|
|
100450
|
+
(change)="onSymbol(ci, $event)"
|
|
100451
|
+
>
|
|
100452
|
+
@for (opt of symbolOptions; track opt.value) {
|
|
100453
|
+
<option [value]="opt.value">{{ opt.labelKey | translate }}</option>
|
|
100454
|
+
}
|
|
100455
|
+
</select>
|
|
100456
|
+
<input
|
|
100457
|
+
type="number"
|
|
100458
|
+
min="1"
|
|
100459
|
+
max="20"
|
|
100460
|
+
class="pptx-chart-card__input pptx-chart-card__input--num"
|
|
100461
|
+
[title]="'pptx.chart.markerSize' | translate"
|
|
100462
|
+
[placeholder]="'pptx.chart.auto' | translate"
|
|
100463
|
+
[disabled]="!canEdit()"
|
|
100464
|
+
[value]="marker.size ?? ''"
|
|
100465
|
+
(change)="onSize(ci, $event)"
|
|
100466
|
+
/>
|
|
100467
|
+
<input
|
|
100468
|
+
type="color"
|
|
100469
|
+
class="pptx-chart-card__color"
|
|
100470
|
+
[title]="'pptx.chart.markerFill' | translate"
|
|
100471
|
+
[disabled]="!canEdit()"
|
|
100472
|
+
[value]="marker.spPr?.fillColor ?? '#4472c4'"
|
|
100473
|
+
(input)="onFill(ci, $event)"
|
|
100474
|
+
/>
|
|
100475
|
+
</div>
|
|
100476
|
+
}
|
|
100477
|
+
}
|
|
100478
|
+
</div>
|
|
100479
|
+
</section>
|
|
100480
|
+
}
|
|
100481
|
+
`, isInline: true, styles: [".pptx-chart-card{display:flex;flex-direction:column;gap:.35rem;padding:.5rem 0;border-top:1px solid var(--pptx-inspector-border, #333)}.pptx-chart-card__heading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);margin:0}.pptx-chart-card__group{display:flex;flex-direction:column;gap:.3rem}.pptx-chart-card__group--indent{margin-left:.5rem}.pptx-chart-card__subhead{font-size:11px;font-weight:600}.pptx-chart-card__row{display:flex;align-items:center;gap:.4rem;font-size:11px}.pptx-chart-card__label{flex:0 0 auto;width:5rem;color:var(--pptx-inspector-muted, #888)}.pptx-chart-card__label--wide{width:6.5rem}.pptx-chart-card__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-chart-card__check{display:flex;align-items:center;gap:.35rem;font-size:11px;cursor:pointer}.pptx-chart-card__input{flex:1 1 auto;min-width:0;box-sizing:border-box;padding:2px 4px;font-size:11px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;color:inherit;outline:none}.pptx-chart-card__input--num{flex:0 0 auto;width:4rem;text-align:right}.pptx-chart-card__input:focus{border-color:var(--pptx-inspector-active, #0078d4)}.pptx-chart-card__input:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__color{flex:0 0 auto;width:26px;height:20px;padding:0;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:transparent;cursor:pointer}.pptx-chart-card__color:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__clear{flex:0 0 auto;padding:0 2px;font-size:12px;line-height:1;background:none;border:none;color:var(--pptx-inspector-muted, #888);cursor:pointer}.pptx-chart-card__clear:hover{color:var(--pptx-inspector-danger, #f47c7c)}.pptx-chart-card__input--num::-webkit-outer-spin-button,.pptx-chart-card__input--num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
100482
|
+
}
|
|
100483
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ChartDatapointMarkerOptionsComponent, decorators: [{
|
|
100484
|
+
type: Component,
|
|
100485
|
+
args: [{ selector: 'pptx-chart-datapoint-marker-options', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: `
|
|
100486
|
+
@if (supported()) {
|
|
100487
|
+
<section class="pptx-chart-card" [attr.aria-label]="'pptx.chart.pointMarkers' | translate">
|
|
100488
|
+
<h4 class="pptx-chart-card__heading">{{ 'pptx.chart.pointMarkers' | translate }}</h4>
|
|
100489
|
+
|
|
100490
|
+
@if (series().length > 1) {
|
|
100491
|
+
<label class="pptx-chart-card__row">
|
|
100492
|
+
<span class="pptx-chart-card__label">{{ 'pptx.chart.series' | translate }}</span>
|
|
100493
|
+
<select
|
|
100494
|
+
class="pptx-chart-card__input"
|
|
100495
|
+
[disabled]="!canEdit()"
|
|
100496
|
+
[value]="activeIndex()"
|
|
100497
|
+
(change)="onSeries($event)"
|
|
100498
|
+
>
|
|
100499
|
+
@for (s of series(); track $index; let i = $index) {
|
|
100500
|
+
<option [value]="i">{{ s.name }}</option>
|
|
100501
|
+
}
|
|
100502
|
+
</select>
|
|
100503
|
+
</label>
|
|
100504
|
+
}
|
|
100505
|
+
|
|
100506
|
+
<div class="pptx-chart-card__group">
|
|
100507
|
+
@for (cat of categories(); track $index; let ci = $index) {
|
|
100508
|
+
<div class="pptx-chart-card__row">
|
|
100509
|
+
<span class="pptx-chart-card__name" [title]="cat">{{ cat }}</span>
|
|
100510
|
+
<label class="pptx-chart-card__check">
|
|
100511
|
+
<input
|
|
100512
|
+
type="checkbox"
|
|
100513
|
+
[disabled]="!canEdit()"
|
|
100514
|
+
[checked]="markerAt(ci) !== undefined"
|
|
100515
|
+
(change)="onToggle(ci, $event)"
|
|
100516
|
+
/>
|
|
100517
|
+
{{ 'pptx.chart.markerOverride' | translate }}
|
|
100518
|
+
</label>
|
|
100519
|
+
</div>
|
|
100520
|
+
|
|
100521
|
+
@if (markerAt(ci); as marker) {
|
|
100522
|
+
<div class="pptx-chart-card__row pptx-chart-card__group--indent">
|
|
100523
|
+
<select
|
|
100524
|
+
class="pptx-chart-card__input"
|
|
100525
|
+
[disabled]="!canEdit()"
|
|
100526
|
+
[value]="marker.symbol"
|
|
100527
|
+
(change)="onSymbol(ci, $event)"
|
|
100528
|
+
>
|
|
100529
|
+
@for (opt of symbolOptions; track opt.value) {
|
|
100530
|
+
<option [value]="opt.value">{{ opt.labelKey | translate }}</option>
|
|
100531
|
+
}
|
|
100532
|
+
</select>
|
|
100533
|
+
<input
|
|
100534
|
+
type="number"
|
|
100535
|
+
min="1"
|
|
100536
|
+
max="20"
|
|
100537
|
+
class="pptx-chart-card__input pptx-chart-card__input--num"
|
|
100538
|
+
[title]="'pptx.chart.markerSize' | translate"
|
|
100539
|
+
[placeholder]="'pptx.chart.auto' | translate"
|
|
100540
|
+
[disabled]="!canEdit()"
|
|
100541
|
+
[value]="marker.size ?? ''"
|
|
100542
|
+
(change)="onSize(ci, $event)"
|
|
100543
|
+
/>
|
|
100544
|
+
<input
|
|
100545
|
+
type="color"
|
|
100546
|
+
class="pptx-chart-card__color"
|
|
100547
|
+
[title]="'pptx.chart.markerFill' | translate"
|
|
100548
|
+
[disabled]="!canEdit()"
|
|
100549
|
+
[value]="marker.spPr?.fillColor ?? '#4472c4'"
|
|
100550
|
+
(input)="onFill(ci, $event)"
|
|
100551
|
+
/>
|
|
100552
|
+
</div>
|
|
100553
|
+
}
|
|
100554
|
+
}
|
|
100555
|
+
</div>
|
|
100556
|
+
</section>
|
|
100557
|
+
}
|
|
100558
|
+
`, styles: [".pptx-chart-card{display:flex;flex-direction:column;gap:.35rem;padding:.5rem 0;border-top:1px solid var(--pptx-inspector-border, #333)}.pptx-chart-card__heading{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--pptx-inspector-muted, #888);margin:0}.pptx-chart-card__group{display:flex;flex-direction:column;gap:.3rem}.pptx-chart-card__group--indent{margin-left:.5rem}.pptx-chart-card__subhead{font-size:11px;font-weight:600}.pptx-chart-card__row{display:flex;align-items:center;gap:.4rem;font-size:11px}.pptx-chart-card__label{flex:0 0 auto;width:5rem;color:var(--pptx-inspector-muted, #888)}.pptx-chart-card__label--wide{width:6.5rem}.pptx-chart-card__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-chart-card__check{display:flex;align-items:center;gap:.35rem;font-size:11px;cursor:pointer}.pptx-chart-card__input{flex:1 1 auto;min-width:0;box-sizing:border-box;padding:2px 4px;font-size:11px;background:var(--pptx-inspector-input-bg, #2d2d2d);border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;color:inherit;outline:none}.pptx-chart-card__input--num{flex:0 0 auto;width:4rem;text-align:right}.pptx-chart-card__input:focus{border-color:var(--pptx-inspector-active, #0078d4)}.pptx-chart-card__input:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__color{flex:0 0 auto;width:26px;height:20px;padding:0;border:1px solid var(--pptx-inspector-border, #444);border-radius:3px;background:transparent;cursor:pointer}.pptx-chart-card__color:disabled{opacity:.6;cursor:not-allowed}.pptx-chart-card__clear{flex:0 0 auto;padding:0 2px;font-size:12px;line-height:1;background:none;border:none;color:var(--pptx-inspector-muted, #888);cursor:pointer}.pptx-chart-card__clear:hover{color:var(--pptx-inspector-danger, #f47c7c)}.pptx-chart-card__input--num::-webkit-outer-spin-button,.pptx-chart-card__input--num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
|
|
100559
|
+
}], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], elementChange: [{ type: i0.Output, args: ["elementChange"] }] } });
|
|
100560
|
+
|
|
98071
100561
|
/**
|
|
98072
100562
|
* chart-datapoint-options.component.ts: Per-data-point fill + slice explosion.
|
|
98073
100563
|
*
|
|
@@ -98979,6 +101469,11 @@ class AdvancedChartEditorComponent {
|
|
|
98979
101469
|
[canEdit]="canEdit()"
|
|
98980
101470
|
(elementChange)="elementChange.emit($event)"
|
|
98981
101471
|
/>
|
|
101472
|
+
<pptx-chart-datapoint-marker-options
|
|
101473
|
+
[element]="element()"
|
|
101474
|
+
[canEdit]="canEdit()"
|
|
101475
|
+
(elementChange)="elementChange.emit($event)"
|
|
101476
|
+
/>
|
|
98982
101477
|
<pptx-chart-trendline-options
|
|
98983
101478
|
[element]="element()"
|
|
98984
101479
|
[canEdit]="canEdit()"
|
|
@@ -98990,7 +101485,7 @@ class AdvancedChartEditorComponent {
|
|
|
98990
101485
|
(elementChange)="elementChange.emit($event)"
|
|
98991
101486
|
/>
|
|
98992
101487
|
</div>
|
|
98993
|
-
`, isInline: true, styles: [".pptx-advanced-chart{display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: ChartDisplayOptionsComponent, selector: "pptx-chart-display-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartDataLabelOptionsComponent, selector: "pptx-chart-data-label-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartAxisOptionsComponent, selector: "pptx-chart-axis-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartAxisStyleOptionsComponent, selector: "pptx-chart-axis-style-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartMarkerOptionsComponent, selector: "pptx-chart-marker-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartComboTypeOptionsComponent, selector: "pptx-chart-combo-type-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartDatapointOptionsComponent, selector: "pptx-chart-datapoint-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartTrendlineOptionsComponent, selector: "pptx-chart-trendline-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartErrorBarOptionsComponent, selector: "pptx-chart-error-bar-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
101488
|
+
`, isInline: true, styles: [".pptx-advanced-chart{display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: ChartDisplayOptionsComponent, selector: "pptx-chart-display-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartDataLabelOptionsComponent, selector: "pptx-chart-data-label-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartAxisOptionsComponent, selector: "pptx-chart-axis-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartAxisStyleOptionsComponent, selector: "pptx-chart-axis-style-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartMarkerOptionsComponent, selector: "pptx-chart-marker-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartComboTypeOptionsComponent, selector: "pptx-chart-combo-type-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartDatapointOptionsComponent, selector: "pptx-chart-datapoint-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartDatapointMarkerOptionsComponent, selector: "pptx-chart-datapoint-marker-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartTrendlineOptionsComponent, selector: "pptx-chart-trendline-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }, { kind: "component", type: ChartErrorBarOptionsComponent, selector: "pptx-chart-error-bar-options", inputs: ["element", "canEdit"], outputs: ["elementChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
98994
101489
|
}
|
|
98995
101490
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AdvancedChartEditorComponent, decorators: [{
|
|
98996
101491
|
type: Component,
|
|
@@ -99002,6 +101497,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
99002
101497
|
ChartMarkerOptionsComponent,
|
|
99003
101498
|
ChartComboTypeOptionsComponent,
|
|
99004
101499
|
ChartDatapointOptionsComponent,
|
|
101500
|
+
ChartDatapointMarkerOptionsComponent,
|
|
99005
101501
|
ChartTrendlineOptionsComponent,
|
|
99006
101502
|
ChartErrorBarOptionsComponent,
|
|
99007
101503
|
], template: `
|
|
@@ -99041,6 +101537,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
99041
101537
|
[canEdit]="canEdit()"
|
|
99042
101538
|
(elementChange)="elementChange.emit($event)"
|
|
99043
101539
|
/>
|
|
101540
|
+
<pptx-chart-datapoint-marker-options
|
|
101541
|
+
[element]="element()"
|
|
101542
|
+
[canEdit]="canEdit()"
|
|
101543
|
+
(elementChange)="elementChange.emit($event)"
|
|
101544
|
+
/>
|
|
99044
101545
|
<pptx-chart-trendline-options
|
|
99045
101546
|
[element]="element()"
|
|
99046
101547
|
[canEdit]="canEdit()"
|
|
@@ -116440,6 +118941,8 @@ class PowerPointViewerComponent {
|
|
|
116440
118941
|
*/
|
|
116441
118942
|
showReadingView = signal(false, /* @ts-ignore */
|
|
116442
118943
|
...(ngDevMode ? [{ debugName: "showReadingView" }] : /* istanbul ignore next */ []));
|
|
118944
|
+
showOutlineView = signal(false, /* @ts-ignore */
|
|
118945
|
+
...(ngDevMode ? [{ debugName: "showOutlineView" }] : /* istanbul ignore next */ []));
|
|
116443
118946
|
/** Full-canvas master editor visibility and active target. */
|
|
116444
118947
|
showMasterView = signal(false, /* @ts-ignore */
|
|
116445
118948
|
...(ngDevMode ? [{ debugName: "showMasterView" }] : /* istanbul ignore next */ []));
|
|
@@ -117111,6 +119614,17 @@ class PowerPointViewerComponent {
|
|
|
117111
119614
|
this.showReadingView.set(false);
|
|
117112
119615
|
this.goTo(slideIndex);
|
|
117113
119616
|
}
|
|
119617
|
+
/**
|
|
119618
|
+
* Commit an outline edit as ONE undoable entry.
|
|
119619
|
+
*
|
|
119620
|
+
* `applyReplacement` rather than `setSlides`: the latter resets the undo
|
|
119621
|
+
* stack and the selection, which would make every keystroke in the outline
|
|
119622
|
+
* throw away the user's history.
|
|
119623
|
+
*/
|
|
119624
|
+
onOutlineCommit(commit) {
|
|
119625
|
+
this.editor.applyReplacement(commit.slides);
|
|
119626
|
+
this.goTo(commit.activeSlideIndex);
|
|
119627
|
+
}
|
|
117114
119628
|
goPrev() {
|
|
117115
119629
|
this.goTo(this.activeSlideIndex() - 1);
|
|
117116
119630
|
}
|
|
@@ -117260,6 +119774,23 @@ class PowerPointViewerComponent {
|
|
|
117260
119774
|
}
|
|
117261
119775
|
this.canvasEditing.onElementSelect(event);
|
|
117262
119776
|
}
|
|
119777
|
+
/**
|
|
119778
|
+
* Commit a motion path dragged on the canvas.
|
|
119779
|
+
*
|
|
119780
|
+
* `setMotionPath` rather than a preset apply: the dragged geometry no longer
|
|
119781
|
+
* matches any catalogue entry, and it is written onto the SAME animation
|
|
119782
|
+
* entry the preset buckets use, so the element's entrance survives the edit.
|
|
119783
|
+
*/
|
|
119784
|
+
onMotionPathChange(path) {
|
|
119785
|
+
const element = this.selectedElement();
|
|
119786
|
+
const slide = this.activeSlide();
|
|
119787
|
+
if (!this.canEdit() || !element || !slide) {
|
|
119788
|
+
return;
|
|
119789
|
+
}
|
|
119790
|
+
this.editor.updateSlide(this.activeSlideIndex(), {
|
|
119791
|
+
animations: setMotionPath(slide.animations ?? [], element.id, path),
|
|
119792
|
+
});
|
|
119793
|
+
}
|
|
117263
119794
|
/** Context-menu "Ask AI about this": scope + open the assistant, empty composer. */
|
|
117264
119795
|
onContextMenuAskAi() {
|
|
117265
119796
|
this.aiPanelStore.askAboutSelection();
|
|
@@ -117730,6 +120261,7 @@ class PowerPointViewerComponent {
|
|
|
117730
120261
|
(link)="docProperties.showHyperlink.set(true)"
|
|
117731
120262
|
(openSorter)="showSorter.set(true)"
|
|
117732
120263
|
(openReadingView)="showReadingView.set(true)"
|
|
120264
|
+
(openOutlineView)="showOutlineView.set(true)"
|
|
117733
120265
|
(toggleNotes)="mobileSheetSvc.toggleNotes()"
|
|
117734
120266
|
(toggleFormatPainter)="formatPainter.toggle()"
|
|
117735
120267
|
(exportPng)="xport.exportPng()"
|
|
@@ -117881,6 +120413,19 @@ class PowerPointViewerComponent {
|
|
|
117881
120413
|
[activeSlideIndex]="activeSlideIndex()"
|
|
117882
120414
|
/>
|
|
117883
120415
|
}
|
|
120416
|
+
<!--
|
|
120417
|
+
Motion path of the selected element: projected for the same
|
|
120418
|
+
reason the collaboration overlays are, and authored in raw
|
|
120419
|
+
slide coordinates. It draws nothing unless the deck is
|
|
120420
|
+
editable and the selection actually carries a path.
|
|
120421
|
+
-->
|
|
120422
|
+
<pptx-motion-path-overlay
|
|
120423
|
+
[element]="selectedElement()"
|
|
120424
|
+
[animations]="activeSlide()?.animations ?? []"
|
|
120425
|
+
[canvasSize]="loader.canvasSize()"
|
|
120426
|
+
[canEdit]="canEdit()"
|
|
120427
|
+
(pathChange)="onMotionPathChange($event)"
|
|
120428
|
+
/>
|
|
117884
120429
|
</pptx-slide-canvas>
|
|
117885
120430
|
@if (collab.active() && collab.presence().length > 0) {
|
|
117886
120431
|
<div class="pptx-ng-collab-follow">
|
|
@@ -118085,6 +120630,21 @@ class PowerPointViewerComponent {
|
|
|
118085
120630
|
/>
|
|
118086
120631
|
}
|
|
118087
120632
|
|
|
120633
|
+
@if (showOutlineView()) {
|
|
120634
|
+
<!--
|
|
120635
|
+
The EDITABLE deck, not the merged display deck: the merged one has
|
|
120636
|
+
each slide's inherited master/layout elements folded in, and
|
|
120637
|
+
committing that back would bake the template layer into the slides.
|
|
120638
|
+
-->
|
|
120639
|
+
<pptx-outline-view-overlay
|
|
120640
|
+
[slides]="editor.slides()"
|
|
120641
|
+
[canvasSize]="loader.canvasSize()"
|
|
120642
|
+
[canEdit]="canEdit()"
|
|
120643
|
+
(commit)="onOutlineCommit($event)"
|
|
120644
|
+
(closed)="showOutlineView.set(false)"
|
|
120645
|
+
/>
|
|
120646
|
+
}
|
|
120647
|
+
|
|
118088
120648
|
@if (showReadingView()) {
|
|
118089
120649
|
<!--
|
|
118090
120650
|
The merged deck, so each slide carries its own inherited template
|
|
@@ -118391,7 +120951,7 @@ class PowerPointViewerComponent {
|
|
|
118391
120951
|
/>
|
|
118392
120952
|
}
|
|
118393
120953
|
</div>
|
|
118394
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationOverlayComponent, selector: "pptx-presentation-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "startIndex", "showWithAnimation", "useTimings", "subtitlesVisible", "sessionEnded"], outputs: ["indexChange", "closed", "subtitlesChange", "annotationsExit"] }, { kind: "component", type: PresenterViewComponent, selector: "pptx-presenter-view", inputs: ["slides", "currentSlideIndex", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime", "isAudienceWindowOpen"], outputs: ["movePresentationSlide", "exit", "openAudienceWindow", "closeAudienceWindow", "navigateToSlide"] }, { kind: "component", type: MobilePresenterViewComponent, selector: "pptx-mobile-presenter-view", inputs: ["slides", "currentSlideIndex", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime"], outputs: ["movePresentationSlide", "exit"] }, { kind: "component", type: SlideSorterOverlayComponent, selector: "pptx-slide-sorter-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select", "closed"] }, { kind: "component", type: ReadingViewOverlayComponent, selector: "pptx-reading-view-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeSlideIndex"], outputs: ["exit"] }, { kind: "component", type: SlideDefaultInspectorComponent, selector: "pptx-slide-default-inspector", inputs: ["slideIndex", "canEdit", "selectedElement", "comments"], outputs: ["commentAdd", "commentRemove", "commentResolve"] }, { kind: "component", type: FindBarComponent, selector: "pptx-find-bar", inputs: ["slides"], outputs: ["navigate", "closed"] }, { kind: "component", type: FindReplaceBarComponent, selector: "pptx-find-replace-bar", inputs: ["matchCount", "matchIndex"], outputs: ["find", "navigate", "replaceOne", "replaceAll", "close"] }, { kind: "component", type: SlidesPanelComponent, selector: "pptx-slides-panel", inputs: ["canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select"] }, { kind: "component", type: StatusBarComponent, selector: "pptx-status-bar", inputs: ["slideIndex", "slideCount", "canEdit", "dirty", "autosaveStatus", "notesOpen", "zoomPercent", "sorterActive", "presenting", "hiddenActions"], outputs: ["toggleNotes", "normalView", "openSorter", "slideShow", "zoomIn", "zoomOut", "zoomReset"] }, { kind: "component", type: EditorContextMenuComponent, selector: "pptx-editor-context-menu", inputs: ["x", "y", "slideIndex", "showAiActions"], outputs: ["closed", "askAi", "fixAi", "editHyperlink", "addComment"] }, { kind: "component", type: ExportProgressModalComponent, selector: "pptx-export-progress-modal", inputs: ["open", "title", "progress", "statusMessage"], outputs: ["cancel"] }, { kind: "component", type: CommentsPanelComponent, selector: "pptx-comments-panel", inputs: ["comments", "authorName"], outputs: ["add", "remove", "resolve"] }, { kind: "component", type: SignaturesPanelComponent, selector: "pptx-signatures-panel", inputs: ["signatures"] }, { kind: "component", type: AccessibilityPanelComponent, selector: "pptx-accessibility-panel", inputs: ["issues"], outputs: ["selectSlide"] }, { kind: "component", type: CollaborationCursorsComponent, selector: "pptx-collaboration-cursors", inputs: ["cursors", "zoom"] }, { kind: "component", type: RemoteSelectionOverlayComponent, selector: "pptx-remote-selection-overlay", inputs: ["presences", "elements", "activeSlideIndex", "zoom"] }, { kind: "component", type: FollowModeBarComponent, selector: "pptx-follow-mode-bar", inputs: ["presences", "followedClientId"], outputs: ["follow"] }, { kind: "component", type: PropertiesDialogComponent, selector: "pptx-properties-dialog", inputs: ["open", "properties"], outputs: ["save", "close"] }, { kind: "component", type: HyperlinkDialogComponent, selector: "pptx-hyperlink-dialog", inputs: ["open", "element"], outputs: ["save", "close"] }, { kind: "component", type: PrintDialogComponent, selector: "pptx-print-dialog", inputs: ["slides", "activeSlideIndex", "defaultSlidesPerPage", "defaultFrameSlides"], outputs: ["print", "cancel"] }, { kind: "component", type: ShareDialogComponent, selector: "pptx-share-dialog", inputs: ["open", "defaults", "active", "connected", "userCount", "shareUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: BroadcastDialogComponent, selector: "pptx-broadcast-dialog", inputs: ["open", "defaults", "active", "connected", "viewerCount", "viewerUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: MobileBottomBarComponent, selector: "pptx-mobile-bottom-bar", inputs: ["slideCount", "commentCount", "activeSheet"], outputs: ["openSlides", "insert", "openFormat", "openComments", "notes"] }, { kind: "component", type: MobileMenuSheetComponent, selector: "pptx-mobile-menu-sheet", inputs: ["open", "slideCount", "exporting", "showNotes", "canEdit", "hiddenActions"], outputs: ["closed", "openFind", "openSorter", "toggleNotes", "insertText", "present", "openFile", "savePptx", "exportPng", "exportPdf", "exportGif", "exportVideo", "print"] }, { kind: "component", type: MobileSlidesSheetComponent, selector: "pptx-mobile-slides-sheet", inputs: ["open", "slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["closed", "jumpToSlide"] }, { kind: "component", type: MobileToolbarComponent, selector: "pptx-mobile-toolbar", inputs: ["canUndo", "canRedo", "canPresent", "canEdit", "menuOpen", "aiEnabled", "aiPanelOpen", "hiddenActions"], outputs: ["toggleMenu", "toggleAiPanel", "undo", "redo", "share", "save", "present"] }, { kind: "component", type: MasterViewCanvasComponent, selector: "pptx-master-view-canvas", inputs: ["tab", "slideMasters", "activeMasterIndex", "activeLayoutIndex", "notesMaster", "handoutMaster", "canvasSize", "notesCanvasSize", "mediaDataUrls", "editable"], outputs: ["notesMasterChange", "handoutMasterChange"] }, { kind: "component", type: MasterViewSidebarComponent, selector: "pptx-master-view-sidebar", inputs: ["tab", "slideMasters", "notesMaster", "handoutMaster", "activeMasterIndex", "activeLayoutIndex", "handoutSlidesPerPage"], outputs: ["tabChange", "selectMaster", "selectLayout", "slidesPerPageChange", "backgroundChange", "close"] }, { kind: "component", type: NotesPanelComponent, selector: "pptx-notes-panel", inputs: ["slide", "expanded"], outputs: ["update", "notesToggle"] }, { kind: "component", type: RibbonComponent, selector: "pptx-ribbon", inputs: ["slideIndex", "slideCount", "canEdit", "selectedElement", "zoomPercent", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "findOpen", "collabConnected", "connectedCount", "spellCheckEnabled", "showSubtitles", "hiddenActions", "aiEnabled", "aiPanelOpen", "accountAuth"], outputs: ["prev", "next", "zoomIn", "zoomOut", "zoomReset", "find", "present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "share", "broadcast", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "toggleSidebar", "toggleAiPanel", "signatures", "info", "print", "comments", "a11y", "link", "openSorter", "openReadingView", "openMasterView", "toggleNotes", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSmartArtDialog", "openEquationDialog", "openSetUpSlideShow", "openCompare", "openPassword", "openFontEmbedding", "openVersionHistory", "openShortcuts", "openSettings"] }, { kind: "component", type: TitleBarComponent, selector: "pptx-title-bar", inputs: ["canEdit", "fileName", "isDirty", "autosaveStatus", "autosaveEnabled", "canUndo", "canRedo", "undoLabel", "redoLabel", "findReplaceOpen", "hiddenActions", "quickAccess"], outputs: ["toggleAutosave", "save", "undo", "redo", "quickCommand", "toggleFindReplace", "commandSearch"] }, { kind: "component", type: ThemeGalleryComponent, selector: "pptx-theme-gallery", inputs: ["open", "activeName", "theme"], outputs: ["applyTheme", "applyCustomTheme", "close"] }, { kind: "component", type: SelectionPaneComponent, selector: "pptx-selection-pane", inputs: ["elements", "selectedIds"], outputs: ["selectElement", "bringForward", "sendBackward", "toggleHidden"] }, { kind: "component", type: CustomShowsComponent, selector: "pptx-custom-shows", inputs: ["open", "slides", "customShows", "activeCustomShowId"], outputs: ["create", "remove", "update", "setActive", "close"] }, { kind: "component", type: InsertSmartArtDialogComponent, selector: "pptx-insert-smart-art-dialog", inputs: ["open"], outputs: ["close", "insert"] }, { kind: "component", type: ViewerExtraDialogsComponent, selector: "pptx-viewer-extra-dialogs", inputs: ["activeSlideIndex", "selectedElementId", "filePath", "customShows", "themeKey", "availableThemes", "localeCode", "availableLocales", "aiExportVisible"], outputs: ["restoreContent", "themeKeySelect", "localeSelect"] }, { kind: "component", type: RehearseTimingsComponent, selector: "pptx-rehearse-timings", inputs: ["summary", "paused", "slideStartedAt", "presentationStartedAt", "timings"], outputs: ["togglePause", "save", "discard"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [/* @ts-ignore */
|
|
120954
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationOverlayComponent, selector: "pptx-presentation-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "startIndex", "showWithAnimation", "useTimings", "subtitlesVisible", "sessionEnded"], outputs: ["indexChange", "closed", "subtitlesChange", "annotationsExit"] }, { kind: "component", type: PresenterViewComponent, selector: "pptx-presenter-view", inputs: ["slides", "currentSlideIndex", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime", "isAudienceWindowOpen"], outputs: ["movePresentationSlide", "exit", "openAudienceWindow", "closeAudienceWindow", "navigateToSlide"] }, { kind: "component", type: MobilePresenterViewComponent, selector: "pptx-mobile-presenter-view", inputs: ["slides", "currentSlideIndex", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime"], outputs: ["movePresentationSlide", "exit"] }, { kind: "component", type: SlideSorterOverlayComponent, selector: "pptx-slide-sorter-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select", "closed"] }, { kind: "component", type: OutlineViewOverlayComponent, selector: "pptx-outline-view-overlay", inputs: ["slides", "canvasSize", "canEdit"], outputs: ["commit", "closed"] }, { kind: "component", type: ReadingViewOverlayComponent, selector: "pptx-reading-view-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeSlideIndex"], outputs: ["exit"] }, { kind: "component", type: SlideDefaultInspectorComponent, selector: "pptx-slide-default-inspector", inputs: ["slideIndex", "canEdit", "selectedElement", "comments"], outputs: ["commentAdd", "commentRemove", "commentResolve"] }, { kind: "component", type: FindBarComponent, selector: "pptx-find-bar", inputs: ["slides"], outputs: ["navigate", "closed"] }, { kind: "component", type: FindReplaceBarComponent, selector: "pptx-find-replace-bar", inputs: ["matchCount", "matchIndex"], outputs: ["find", "navigate", "replaceOne", "replaceAll", "close"] }, { kind: "component", type: SlidesPanelComponent, selector: "pptx-slides-panel", inputs: ["canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select"] }, { kind: "component", type: StatusBarComponent, selector: "pptx-status-bar", inputs: ["slideIndex", "slideCount", "canEdit", "dirty", "autosaveStatus", "notesOpen", "zoomPercent", "sorterActive", "presenting", "hiddenActions"], outputs: ["toggleNotes", "normalView", "openSorter", "slideShow", "zoomIn", "zoomOut", "zoomReset"] }, { kind: "component", type: EditorContextMenuComponent, selector: "pptx-editor-context-menu", inputs: ["x", "y", "slideIndex", "showAiActions"], outputs: ["closed", "askAi", "fixAi", "editHyperlink", "addComment"] }, { kind: "component", type: ExportProgressModalComponent, selector: "pptx-export-progress-modal", inputs: ["open", "title", "progress", "statusMessage"], outputs: ["cancel"] }, { kind: "component", type: CommentsPanelComponent, selector: "pptx-comments-panel", inputs: ["comments", "authorName"], outputs: ["add", "remove", "resolve"] }, { kind: "component", type: SignaturesPanelComponent, selector: "pptx-signatures-panel", inputs: ["signatures"] }, { kind: "component", type: AccessibilityPanelComponent, selector: "pptx-accessibility-panel", inputs: ["issues"], outputs: ["selectSlide"] }, { kind: "component", type: CollaborationCursorsComponent, selector: "pptx-collaboration-cursors", inputs: ["cursors", "zoom"] }, { kind: "component", type: RemoteSelectionOverlayComponent, selector: "pptx-remote-selection-overlay", inputs: ["presences", "elements", "activeSlideIndex", "zoom"] }, { kind: "component", type: MotionPathOverlayComponent, selector: "pptx-motion-path-overlay", inputs: ["element", "animations", "canvasSize", "canEdit"], outputs: ["pathChange"] }, { kind: "component", type: FollowModeBarComponent, selector: "pptx-follow-mode-bar", inputs: ["presences", "followedClientId"], outputs: ["follow"] }, { kind: "component", type: PropertiesDialogComponent, selector: "pptx-properties-dialog", inputs: ["open", "properties"], outputs: ["save", "close"] }, { kind: "component", type: HyperlinkDialogComponent, selector: "pptx-hyperlink-dialog", inputs: ["open", "element"], outputs: ["save", "close"] }, { kind: "component", type: PrintDialogComponent, selector: "pptx-print-dialog", inputs: ["slides", "activeSlideIndex", "defaultSlidesPerPage", "defaultFrameSlides"], outputs: ["print", "cancel"] }, { kind: "component", type: ShareDialogComponent, selector: "pptx-share-dialog", inputs: ["open", "defaults", "active", "connected", "userCount", "shareUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: BroadcastDialogComponent, selector: "pptx-broadcast-dialog", inputs: ["open", "defaults", "active", "connected", "viewerCount", "viewerUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: MobileBottomBarComponent, selector: "pptx-mobile-bottom-bar", inputs: ["slideCount", "commentCount", "activeSheet"], outputs: ["openSlides", "insert", "openFormat", "openComments", "notes"] }, { kind: "component", type: MobileMenuSheetComponent, selector: "pptx-mobile-menu-sheet", inputs: ["open", "slideCount", "exporting", "showNotes", "canEdit", "hiddenActions"], outputs: ["closed", "openFind", "openSorter", "toggleNotes", "insertText", "present", "openFile", "savePptx", "exportPng", "exportPdf", "exportGif", "exportVideo", "print"] }, { kind: "component", type: MobileSlidesSheetComponent, selector: "pptx-mobile-slides-sheet", inputs: ["open", "slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["closed", "jumpToSlide"] }, { kind: "component", type: MobileToolbarComponent, selector: "pptx-mobile-toolbar", inputs: ["canUndo", "canRedo", "canPresent", "canEdit", "menuOpen", "aiEnabled", "aiPanelOpen", "hiddenActions"], outputs: ["toggleMenu", "toggleAiPanel", "undo", "redo", "share", "save", "present"] }, { kind: "component", type: MasterViewCanvasComponent, selector: "pptx-master-view-canvas", inputs: ["tab", "slideMasters", "activeMasterIndex", "activeLayoutIndex", "notesMaster", "handoutMaster", "canvasSize", "notesCanvasSize", "mediaDataUrls", "editable"], outputs: ["notesMasterChange", "handoutMasterChange"] }, { kind: "component", type: MasterViewSidebarComponent, selector: "pptx-master-view-sidebar", inputs: ["tab", "slideMasters", "notesMaster", "handoutMaster", "activeMasterIndex", "activeLayoutIndex", "handoutSlidesPerPage"], outputs: ["tabChange", "selectMaster", "selectLayout", "slidesPerPageChange", "backgroundChange", "close"] }, { kind: "component", type: NotesPanelComponent, selector: "pptx-notes-panel", inputs: ["slide", "expanded"], outputs: ["update", "notesToggle"] }, { kind: "component", type: RibbonComponent, selector: "pptx-ribbon", inputs: ["slideIndex", "slideCount", "canEdit", "selectedElement", "zoomPercent", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "findOpen", "collabConnected", "connectedCount", "spellCheckEnabled", "showSubtitles", "hiddenActions", "aiEnabled", "aiPanelOpen", "accountAuth"], outputs: ["prev", "next", "zoomIn", "zoomOut", "zoomReset", "find", "present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "share", "broadcast", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "packageForSharing", "toggleSidebar", "toggleAiPanel", "signatures", "info", "print", "comments", "a11y", "link", "openSorter", "openReadingView", "openOutlineView", "openMasterView", "toggleNotes", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "copySlideAsImage", "replace", "toggleInspector", "drawToolChange", "toggleThemeGallery", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSmartArtDialog", "openEquationDialog", "openSetUpSlideShow", "openCompare", "openPassword", "openFontEmbedding", "openVersionHistory", "openShortcuts", "openSettings"] }, { kind: "component", type: TitleBarComponent, selector: "pptx-title-bar", inputs: ["canEdit", "fileName", "isDirty", "autosaveStatus", "autosaveEnabled", "canUndo", "canRedo", "undoLabel", "redoLabel", "findReplaceOpen", "hiddenActions", "quickAccess"], outputs: ["toggleAutosave", "save", "undo", "redo", "quickCommand", "toggleFindReplace", "commandSearch"] }, { kind: "component", type: ThemeGalleryComponent, selector: "pptx-theme-gallery", inputs: ["open", "activeName", "theme"], outputs: ["applyTheme", "applyCustomTheme", "close"] }, { kind: "component", type: SelectionPaneComponent, selector: "pptx-selection-pane", inputs: ["elements", "selectedIds"], outputs: ["selectElement", "bringForward", "sendBackward", "toggleHidden"] }, { kind: "component", type: CustomShowsComponent, selector: "pptx-custom-shows", inputs: ["open", "slides", "customShows", "activeCustomShowId"], outputs: ["create", "remove", "update", "setActive", "close"] }, { kind: "component", type: InsertSmartArtDialogComponent, selector: "pptx-insert-smart-art-dialog", inputs: ["open"], outputs: ["close", "insert"] }, { kind: "component", type: ViewerExtraDialogsComponent, selector: "pptx-viewer-extra-dialogs", inputs: ["activeSlideIndex", "selectedElementId", "filePath", "customShows", "themeKey", "availableThemes", "localeCode", "availableLocales", "aiExportVisible"], outputs: ["restoreContent", "themeKeySelect", "localeSelect"] }, { kind: "component", type: RehearseTimingsComponent, selector: "pptx-rehearse-timings", inputs: ["summary", "paused", "slideStartedAt", "presentationStartedAt", "timings"], outputs: ["togglePause", "save", "discard"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [/* @ts-ignore */
|
|
118395
120955
|
Promise.resolve().then(function () { return aiChatPanel_component; }).then(m => m.AiChatPanelComponent)]] });
|
|
118396
120956
|
}
|
|
118397
120957
|
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ngImport: i0, type: PowerPointViewerComponent, resolveDeferredDeps: () => [/* @ts-ignore */
|
|
@@ -118410,6 +120970,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ng
|
|
|
118410
120970
|
PresenterViewComponent,
|
|
118411
120971
|
MobilePresenterViewComponent,
|
|
118412
120972
|
SlideSorterOverlayComponent,
|
|
120973
|
+
OutlineViewOverlayComponent,
|
|
118413
120974
|
ReadingViewOverlayComponent,
|
|
118414
120975
|
SlideDefaultInspectorComponent,
|
|
118415
120976
|
FindBarComponent,
|
|
@@ -118424,6 +120985,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ng
|
|
|
118424
120985
|
AccessibilityPanelComponent,
|
|
118425
120986
|
CollaborationCursorsComponent,
|
|
118426
120987
|
RemoteSelectionOverlayComponent,
|
|
120988
|
+
MotionPathOverlayComponent,
|
|
118427
120989
|
FollowModeBarComponent,
|
|
118428
120990
|
PropertiesDialogComponent,
|
|
118429
120991
|
HyperlinkDialogComponent,
|
|
@@ -118546,6 +121108,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ng
|
|
|
118546
121108
|
(link)="docProperties.showHyperlink.set(true)"
|
|
118547
121109
|
(openSorter)="showSorter.set(true)"
|
|
118548
121110
|
(openReadingView)="showReadingView.set(true)"
|
|
121111
|
+
(openOutlineView)="showOutlineView.set(true)"
|
|
118549
121112
|
(toggleNotes)="mobileSheetSvc.toggleNotes()"
|
|
118550
121113
|
(toggleFormatPainter)="formatPainter.toggle()"
|
|
118551
121114
|
(exportPng)="xport.exportPng()"
|
|
@@ -118697,6 +121260,19 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ng
|
|
|
118697
121260
|
[activeSlideIndex]="activeSlideIndex()"
|
|
118698
121261
|
/>
|
|
118699
121262
|
}
|
|
121263
|
+
<!--
|
|
121264
|
+
Motion path of the selected element: projected for the same
|
|
121265
|
+
reason the collaboration overlays are, and authored in raw
|
|
121266
|
+
slide coordinates. It draws nothing unless the deck is
|
|
121267
|
+
editable and the selection actually carries a path.
|
|
121268
|
+
-->
|
|
121269
|
+
<pptx-motion-path-overlay
|
|
121270
|
+
[element]="selectedElement()"
|
|
121271
|
+
[animations]="activeSlide()?.animations ?? []"
|
|
121272
|
+
[canvasSize]="loader.canvasSize()"
|
|
121273
|
+
[canEdit]="canEdit()"
|
|
121274
|
+
(pathChange)="onMotionPathChange($event)"
|
|
121275
|
+
/>
|
|
118700
121276
|
</pptx-slide-canvas>
|
|
118701
121277
|
@if (collab.active() && collab.presence().length > 0) {
|
|
118702
121278
|
<div class="pptx-ng-collab-follow">
|
|
@@ -118901,6 +121477,21 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.0.8", ng
|
|
|
118901
121477
|
/>
|
|
118902
121478
|
}
|
|
118903
121479
|
|
|
121480
|
+
@if (showOutlineView()) {
|
|
121481
|
+
<!--
|
|
121482
|
+
The EDITABLE deck, not the merged display deck: the merged one has
|
|
121483
|
+
each slide's inherited master/layout elements folded in, and
|
|
121484
|
+
committing that back would bake the template layer into the slides.
|
|
121485
|
+
-->
|
|
121486
|
+
<pptx-outline-view-overlay
|
|
121487
|
+
[slides]="editor.slides()"
|
|
121488
|
+
[canvasSize]="loader.canvasSize()"
|
|
121489
|
+
[canEdit]="canEdit()"
|
|
121490
|
+
(commit)="onOutlineCommit($event)"
|
|
121491
|
+
(closed)="showOutlineView.set(false)"
|
|
121492
|
+
/>
|
|
121493
|
+
}
|
|
121494
|
+
|
|
118904
121495
|
@if (showReadingView()) {
|
|
118905
121496
|
<!--
|
|
118906
121497
|
The merged deck, so each slide carries its own inherited template
|
|
@@ -121100,5 +123691,5 @@ function cn(...values) {
|
|
|
121100
123691
|
* Generated bundle index. Do not edit.
|
|
121101
123692
|
*/
|
|
121102
123693
|
|
|
121103
|
-
export { DATA_TABLE_HEADER_H as $, ALIGN_OPTIONS as A, BroadcastDialogComponent as B, CHART_EDITOR_STYLES as C, CanvasFitService as D, ChartAxisOptionsComponent as E, ChartAxisStyleOptionsComponent as F, ChartComboTypeOptionsComponent as G, ChartDataEditorComponent as H, ChartDataLabelOptionsComponent as I, ChartDatapointOptionsComponent as J, ChartDisplayOptionsComponent as K, ChartElementViewComponent as L, ChartErrorBarOptionsComponent as M, ChartMarkerOptionsComponent as N, ChartPartSelectionService as O, ChartPrimitivesComponent as P, ChartRendererComponent as Q, ChartTrendlineOptionsComponent as R, CollaborationCursorsComponent as S, CollaborationService as T, ColorChangedImageComponent as U, CommentsPanelComponent as V, CommentsService as W, ComparePanelComponent as X, ConnectorRendererComponent as Y, ConnectorTextOverlayComponent as Z, CustomShowsComponent as _, ANIMATION_PRESET_CATEGORIES as a, MAX_ZOOM_SCALE as a$, DATA_TABLE_KEY_W as a0, DATA_TABLE_PADDING as a1, DATA_TABLE_ROW_H as a2, DEFAULT_BOUNDS as a3, DEFAULT_BROADCAST_SERVER_URL as a4, DEFAULT_CANVAS_HEIGHT as a5, DEFAULT_CANVAS_WIDTH as a6, DEFAULT_COLOR_SCHEME as a7, DEFAULT_FILL_COLOR as a8, DEFAULT_LAYOUT as a9, EquationTemplateGalleryComponent as aA, ExportProgressModalComponent as aB, ExportService as aC, FieldContextService as aD, FindBarComponent as aE, FindReplaceBarComponent as aF, FollowModeBarComponent as aG, FontEmbeddingListComponent as aH, FontEmbeddingPanelComponent as aI, GALLERY_THEME_PRESETS as aJ, GradientPickerComponent as aK, HANDOUT_OPTIONS as aL, HeaderFooterDialogComponent as aM, HyperlinkDialogComponent as aN, ImagePropertiesPanelComponent as aO, InkDrawingService as aP, InkRendererComponent as aQ, InsertSmartArtDialogComponent as aR, InspectorPaneHeaderComponent as aS, InspectorPanelComponent as aT, IsMobileService as aU, KeepAnnotationsDialogComponent as aV, LOCALE_CATALOG as aW, LONG_PRESS_DURATION_MS as aX, LONG_PRESS_MOVE_TOLERANCE_PX as aY, LoadContentService as aZ, LocalPresencePublisher as a_, DEFAULT_PALETTE$1 as aa, DEFAULT_PRINT_SETTINGS as ab, DEFAULT_SLIDE_BACKGROUND as ac, DEFAULT_STROKE_COLOR as ad, DEFAULT_STYLE as ae, DEFAULT_TABLE_ROW_HEIGHT as af, DEFAULT_TEXT_COLOR$1 as ag, DEFAULT_VIEWER_PROFILE as ah, DIRECTIONAL_PRESETS as ai, DIRECTION_OPTIONS as aj, DocumentPropertiesCardComponent as ak, EMBEDDED_FONTS_STYLE_ID as al, EMPHASIS_PRESETS as am, ENTRANCE_PRESETS as an, TEMPLATES as ao, EXIT_PRESETS as ap, EditorContextMenuComponent as aq, EditorHistory as ar, EditorStateService as as, EditorToolbarComponent as at, EffectsPanelComponent as au, ElementRendererComponent as av, EmbeddedFontsService as aw, EncryptedFileDialogComponent as ax, EquationEditorDialogComponent as ay, EquationRendererComponent as az, AUDIENCE_HASH as b, RibbonSlideshowSectionComponent as b$, MIN_ZOOM_SCALE as b0, MediaPreviewComponent as b1, MediaPropertiesPanelComponent as b2, MediaRendererComponent as b3, MediaTrimTimelineComponent as b4, MobileBottomBarComponent as b5, MobileMenuSheetComponent as b6, MobilePresenterViewComponent as b7, MobileSheetComponent as b8, MobileSlidesSheetComponent as b9, PrintSettingsPanelComponent as bA, PropertiesDialogComponent as bB, REPEAT_MODE_OPTIONS as bC, RESIZE_HANDLES as bD, RULER_FONT_SIZE as bE, RULER_THICKNESS as bF, ReadingViewOverlayComponent as bG, RemoteSelectionOverlayComponent as bH, RibbonAnimationGalleryComponent as bI, RibbonAnimationsSectionComponent as bJ, RibbonArrangeSectionComponent as bK, RibbonColorPopoverComponent as bL, RibbonComponent as bM, RibbonDesignSectionComponent as bN, RibbonDrawSectionComponent as bO, RibbonDrawingGroupComponent as bP, RibbonEditingSectionComponent as bQ, RibbonFileSectionComponent as bR, RibbonFontControlsComponent as bS, RibbonHomeSectionComponent as bT, RibbonHyperlinkButtonComponent as bU, RibbonInsertFieldsComponent as bV, RibbonInsertSectionComponent as bW, RibbonParagraphControlsComponent as bX, RibbonPrimaryRowComponent as bY, RibbonReviewSectionComponent as bZ, RibbonShapeExtrasComponent as b_, MobileToolbarComponent as ba, ModalDialogComponent as bb, Model3DRendererComponent as bc, NotesHandoutCardComponent as bd, NotesPanelComponent as be, NotesToolbarComponent as bf, OleRendererComponent as bg, POWER_POINT_VIEWER_PROVIDERS as bh, PRESENTER_CHANNEL_NAME as bi, PRESENTER_MSG_ORIGIN as bj, PX_PER_CM as bk, PX_PER_INCH as bl, PasswordProtectionDialogComponent as bm, PasswordStrengthMeterComponent as bn, PowerPointViewerComponent as bo, PresentationAnnotationOverlayComponent as bp, PresentationAnnotationsService as bq, PresentationOverlayComponent as br, PresentationPropertiesPanelComponent as bs, PresentationSettingsCardComponent as bt, PresentationSubtitleBarComponent as bu, PresentationTransitionOverlayComponent as bv, PresenterViewComponent as bw, PresenterWindowService as bx, PrintDialogComponent as by, PrintService as bz, AUDIENCE_NONCE_KEY as c, TextAdvancedPanelComponent as c$, RibbonTransitionsSectionComponent as c0, RibbonViewSectionComponent as c1, RulerGuidesService as c2, SEQUENCE_OPTIONS as c3, SEVERITY_GROUPS as c4, SEVERITY_LABELS as c5, SHORTCUT_REFERENCE_ITEMS as c6, SLIDE_TRANSITION_KEYFRAMES as c7, DEFAULT_PALETTE as c8, PALETTES$1 as c9, SlideThemeOverridePanelComponent as cA, SlideTransitionCardComponent as cB, SlidesPanelComponent as cC, SmartArt3DRendererComponent as cD, SmartArt3DService as cE, SmartArtPreviewComponent as cF, SmartArtPropertiesComponent as cG, SmartArtRendererComponent as cH, StatusBarComponent as cI, TABLE_STRUCTURE_TOGGLES as cJ, TEXT_3D_BOTTOM_BEVEL_KEYS as cK, TEXT_3D_TOP_BEVEL_KEYS as cL, TEXT_DIRECTION_OPTIONS$1 as cM, THEME_CATALOG as cN, TIMING_CURVE_OPTIONS as cO, TRIGGER_OPTIONS as cP, TYPE_LABELS as cQ, TableCellAdvancedFillComponent as cR, TableCellFormattingComponent as cS, TableDataEditorComponent as cT, TablePropertiesComponent as cU, TableRendererComponent as cV, TableResizeOverlayComponent as cW, TableSelectionService as cX, TagsCardComponent as cY, Text3DBevelSectionComponent as cZ, Text3DPanelComponent as c_, SMART_ART_COLOR_SCHEMES as ca, SMART_ART_STYLE_OPTIONS as cb, SUB_ITEM_LABEL as cc, SVG_WARP_PRESETS as cd, SWIPE_MAX_VERTICAL_PX as ce, SWIPE_THRESHOLD_PX as cf, SelectionPaneComponent as cg, SetUpSlideShowDialogComponent as ch, SettingsAppearanceTabComponent as ci, SettingsDialogComponent as cj, SettingsLanguageTabComponent as ck, ShareDialogComponent as cl, ShortcutPanelComponent as cm, ShowOptionsFieldsetComponent as cn, ShowSlidesFieldsetComponent as co, SignatureStrippedDialogComponent as cp, SignaturesPanelComponent as cq, SignaturesService as cr, SlideBackgroundCardComponent as cs, SlideCanvasComponent as ct, SlideDefaultInspectorComponent as cu, SlideDiffChangesComponent as cv, SlideDiffRowComponent as cw, SlideDiffThumbnailsComponent as cx, SlideSizeCardComponent as cy, SlideSorterOverlayComponent as cz, AVATAR_COLOR_SWATCHES as d, buildBroadcastViewerUrl as d$, ThemeEditorFieldsComponent as d0, ThemeGalleryComponent as d1, ThemeSelectorCardComponent as d2, TitleBarComponent as d3, TransitionDirectionPickerComponent as d4, TransitionPreviewComponent as d5, VALIGN_OPTIONS as d6, VIEWER_THEME as d7, VersionHistoryPanelComponent as d8, ViewerCanvasEditingService as d9, addGradientStopPatch as dA, addItem as dB, addSeries as dC, addSubItem as dD, advanceStep as dE, aiToggleVisible as dF, alignPatch as dG, animationFor as dH, animationPresetLabelKey as dI, annotationMapToInkInserts as dJ, applyAcceptedDiff as dK, applyAnimationPreset as dL, applyFindReplacements as dM, applyFormatToElement as dN, applyMove as dO, applyResize as dP, applyTableStylePreset as dQ, asMediaElement as dR, assignUserColor as dS, attachTouchGestures as dT, beginNodeEdit as dU, bevelSizePatch as dV, boolFromEvent as dW, bringForward as dX, bringToFront as dY, buildBarActions as dZ, buildBroadcastConfig as d_, ViewerCollabCursorService as da, ViewerCollaborationSessionService as db, ViewerCompareService as dc, ViewerCustomShowsService as dd, ViewerDialogsService as de, ViewerDocumentPropertiesService as df, ViewerExportService as dg, ViewerExtraDialogsComponent as dh, ViewerFileIOService as di, ViewerFindReplaceService as dj, ViewerFormatPainterService as dk, ViewerInspectorPanelService as dl, ViewerKeyboardService as dm, ViewerMobileSheetService as dn, ViewerPresentationModeService as dp, ViewerThemeGalleryService as dq, ViewerTouchGesturesService as dr, ViewerZoomService as ds, WEBM_MIME_CANDIDATES as dt, WriteBackScheduler as du, ZoomNavigationService as dv, ZoomRendererComponent as dw, ZoomTargetService as dx, addCategory as dy, addCommentToList as dz, AccessibilityPanelComponent as e, clampCursorPosition as e$, buildCategoryLabels as e0, buildCellParagraphs as e1, buildChartViewModel as e2, buildChatLogExport as e3, buildChatLogMarkdown as e4, buildChromeStyle as e5, buildClearHyperlinkPatch as e6, buildClickGroups as e7, buildColStyles as e8, buildCollaborationConfig as e9, buildSmartArtNodes as eA, buildStockViewModel as eB, buildSurfaceViewModel as eC, buildTableViewModel as eD, buildTreemapViewModel as eE, buildTrimFragment as eF, buildWaterfallViewModel as eG, buildZeroLine as eH, buildZoomContainerStyle as eI, buildZoomViewModel as eJ, bulletIndentPx as eK, canAddTopLevelNode as eL, canGroupSelection as eM, canRemoveTopLevelNode as eN, canSetStrokeWidth as eO, canStartBroadcast as eP, canStartShare as eQ, canUngroupSelection as eR, canUseClipboard as eS, captionDisplayText as eT, cellRunStyle as eU, cellStyleToStyleMap as eV, cellTdStyle as eW, changeCountLabel as eX, changeIcon as eY, characterSpacingPatch as eZ, checkFontAvailable as e_, buildComboViewModel as ea, buildCssGradientFromShapeStyle as eb, buildDuotoneFilter as ec, buildDuotoneFilterId as ed, buildEmbeddedFontStyles as ee, buildEquationElement as ef, buildEquationSegment as eg, buildFallbackViewModel as eh, buildFontFaceRule as ei, buildGradientFillCss as ej, buildGridlinesAndLabels as ek, buildHyperlinkPatch as el, buildInkContainerStyle as em, buildInkStrokes as en, buildLegend as eo, buildModel3DContainerStyle as ep, buildModel3DViewModel as eq, buildOleActionModel as er, buildOleInfoRows as es, buildPatternFillCss as et, buildPrintHtmlDocument as eu, buildPropertiesPatch as ev, buildRegionMapViewModel as ew, buildSaveSlides as ex, buildShareUrl as ey, buildSmartArtInsertElement as ez, AccessibilityService as f, defaultRadius as f$, clampGifDimensions as f0, clampIndex as f1, clampNotesFontSize as f2, clampScale as f3, clampStep as f4, clearAllLocalViewerData as f5, clearAudienceContent as f6, cn as f7, collectAccessibilityIssues as f8, collectElementText as f9, computeRSquared as fA, computeRadarPoints as fB, computeScatterDots as fC, computeSelectionBoxes as fD, computeSingleSelected as fE, computeSlideIndices as fF, computeSnap as fG, computeStackedBarRects as fH, computeStackedValueRange as fI, computeTextLines as fJ, computeTimerProgress as fK, computeTrendlinePrimitives as fL, computeValueRange as fM, convertOmmlToMathMl as fN, copyFormatFromElement as fO, countAccessibilityIssues as fP, countAnnotationStrokes as fQ, createAngularAiBridge as fR, createCustomShow as fS, createSwipeDismissDrag as fT, createWebrtcBundle as fU, createWebsocketBundle as fV, cssObjectToStyleMap as fW, currentColorScheme as fX, currentLayout as fY, currentStyle as fZ, defaultCssVars as f_, collectSlideText as fa, collectStoredChats as fb, collectUsedFontFamilies as fc, columnWidthStyle as fd, commitNodeText as fe, computeAlign as ff, computeAxisTitlePrimitives as fg, computeBarRects as fh, computeBubbleRadius as fi, computeCornerHandle as fj, computeDataTablePrimitives as fk, computeDistribute as fl, computeDrawingViewBox as fm, computeErrorBarPrimitives as fn, computeFocusTargets as fo, computeHandleBoxes as fp, computeHandoutLayout as fq, computeIsMobile as fr, computeIsTablet as fs, computeLinePoints as ft, computeLinearRegression as fu, computePageCount as fv, computePieLayout as fw, computePieSlicePath as fx, computePieSlices as fy, computePlotLayout as fz, AccountPageComponent as g, getPatternSvg as g$, defaultThemeColors as g0, deleteElementsByIds as g1, deleteVersion as g2, demoteNode as g3, deriveModel3DBlobUrl as g4, derivePresenceList as g5, describeSmartArtBounds as g6, disableGlowPatch as g7, disableInnerShadowPatch as g8, disableOuterShadowPatch as g9, fontSizeOf as gA, formatAutoNumber as gB, formatAxisValue as gC, formatBytes as gD, formatCursorLabel as gE, formatElapsed as gF, formatFileSize as gG, formatPropertyDate as gH, formatTime as gI, fpsToFrameIntervalMs as gJ, generateBroadcastRoomId as gK, generateCommentId as gL, generateCustomShowId as gM, generatePressureCircles as gN, generateTicks as gO, getClrChangeParams as gP, getContainerStyle as gQ, getDuotoneFilterDef as gR, getImageSrc as gS, getLocalStorageUsageSummary as gT, getOleAriaLabel as gU, getOleBadgeLabel as gV, getOleDisplayName as gW, getOleDownloadFileName as gX, getOleTypeColor as gY, getOleTypeLabel as gZ, getPasswordStrength as g_, disableReflectionPatch as ga, disableSoftEdgePatch as gb, duplicateElementById as gc, durationOf as gd, effectsStateOf as ge, enableGlowPatch as gf, enableInnerShadowPatch as gg, enableOuterShadowPatch as gh, enableReflectionPatch as gi, enableSoftEdgePatch as gj, encodeGif as gk, estimatePageCount as gl, evenColumnWidths as gm, evenRowHeights as gn, exitPresentationFullscreen as go, exportAiChatLogs as gp, extractPathPoints as gq, eyedropperAvailable as gr, fillColorOf as gs, findInSlides as gt, findOwningSlideIndex as gu, findSlideIndexByElementId as gv, fitPolynomial as gw, fitZoom as gx, focusTargetChips as gy, fontMimeForFormat as gz, ActionSettingsPanelComponent as h, moveNodeUp as h$, getPlaceholderStyle as h0, getVersions as h1, getResolvedShapeClipPath as h2, getResolvedShapeClipPathFor as h3, getShapeFillStrokeStyle as h4, getSlideBackgroundStyle as h5, getSlideTransitionAnimations as h6, getSmartArtNodeBounds as h7, getSpeechRecognitionCtor as h8, getTextBlockStyle as h9, isChildNode as hA, isElementInteractive as hB, isInjectableUrl as hC, isItalic as hD, isPpactionUrl as hE, isPresenterMessage as hF, isSigned as hG, isTextElement as hH, isTwoTableFocus as hI, isUnderline as hJ, isUrlSafe as hK, isValidRoomId as hL, isViewportBackgroundPressTarget as hM, isZoomActivationKey as hN, issueTrackKey as hO, issueTypeLabel as hP, keyToLabel as hQ, latexToMathml as hR, linePointsToSvgString as hS, lineSpacingPatch as hT, loadAudienceContent as hU, mergeCaptionResults as hV, mergeDown as hW, mergeRight as hX, mergeSelection as hY, moveElementBy as hZ, moveNodeDown as h_, getTextWarp as ha, getTouchDistance as hb, getWarpCategory as hc, getWarpPath as hd, gradientStateFromStyle as he, gradientStateOf as hf, gradientStatePatch as hg, gridColumns as hh, groupElements as hi, groupIssuesBySeverity as hj, hasAnimation as hk, hasCopyableFormat as hl, hasExistingLink as hm, hasExitedFullscreen as hn, hasGradientFill as ho, hasPressureVariation as hp, hasVisibleSlideAfter as hq, headerLabel as hr, imageDimensions as hs, inkViewBox as ht, insertTableElementColumn as hu, insertTableElementRow as hv, interpolateWidth as hw, isAudienceTab as hx, isBold as hy, isBrowserOpenableMime as hz, AdvancedChartEditorComponent as i, removeNode as i$, msToFrameDelayCs as i0, narrowToCircle as i1, narrowToPolygon as i2, narrowToRect as i3, newChartElement as i4, newEquationElement as i5, newPresetShapeElement as i6, newShapeElement as i7, newSmartArtElement as i8, newTableElement as i9, patchTextStyle as iA, pendingElementStyles as iB, pickColorByClickFallback as iC, pickFile as iD, pickSupportedMimeType as iE, planGifFrames as iF, planVideoSegments as iG, pointsToSvgPathD as iH, presenceToCursors as iI, presetByLayout as iJ, presetsForCategory as iK, pressuresToWidths as iL, prevVisibleIndex as iM, projectDrawingShapes as iN, promoteNode as iO, provideViewerTheme as iP, radarAngle as iQ, radarRingPoints as iR, readAsDataUrl as iS, recordWebm as iT, redistributeColumnWidth as iU, removeAnimation as iV, removeCategory as iW, removeTableElementColumn as iX, removeCommentFromList as iY, removeElementAnimation as iZ, removeGradientStopPatch as i_, newTextElement as ia, nextVisibleIndex as ib, nodeBold as ic, nodeEditBox as id, nodeFillColor as ie, nodeFontColor as ig, nodeIdFromKey as ih, nodeItalic as ii, nodeStyle as ij, normalizeFontFormat as ik, normalizeSlidesPerPage as il, normalizeValue as im, numFromEvent as io, ommlToMathml as ip, ooxmlDashToCssBorderStyle as iq, openNativeEyeDropper as ir, overallStatus as is, paletteColor as it, parseAudienceNonce as iu, parseNodeTextarea as iv, partitionSlides as iw, patchChartData as ix, patchChartStyle as iy, patchTableData as iz, AiChangeOverlayComponent as j, setDuration as j$, removeTableElementRow as j0, removeSeries as j1, renderToCanvas as j2, reorderAnimationDown as j3, reorderAnimationUp as j4, replaceInSlides as j5, replaceMatch as j6, requestPresentationFullscreen as j7, resizeElement as j8, resolveCaptionTracks as j9, searchSlides as jA, seedBroadcastFields as jB, seedHyperlinkDraft as jC, seedPropertiesDraft as jD, seedShareFields as jE, segmentFrameCount as jF, selectValue$2 as jG, sendBackward as jH, sendToBack as jI, sequentialColorScale as jJ, serializeWriteBack as jK, seriesColor as jL, setAnimationEmphasis as jM, setAnimationEntrance as jN, setAnimationExit as jO, setAxis as jP, setAxisLogScale as jQ, setAxisTitleStyle as jR, setCategoryLabel as jS, setCellText as jT, setColorScheme as jU, setDataLabels as jV, setDataPointExplosion as jW, setDataPointFill as jX, setDataPointLabel as jY, setDelay as jZ, setDirection as j_, resolveChartKind as ja, resolveFontVariant as jb, resolveHyperlinkHref as jc, resolveInteractiveElementId as jd, resolveMediaSrc as je, resolveOleType as jf, resolveParagraphBullet as jg, resolvePresenterNotes as jh, resolveProfileInitial as ji, resolveRegionCode as jj, resolveSlideAutoAdvanceMs as jk, resolvePalette as jl, resolveThemeCatalogEntry as jm, resolveTransitionDuration as jn, revealedElementStyles as jo, routeOrthogonalConnector as jp, rowStyle as jq, rulerDragToGuidePosition as jr, rulerHighlight as js, rulerStripTicks as jt, sampleColorFromSlide as ju, sanitizeColor as jv, sanitizeSlideIndex as jw, sanitizeUserName as jx, saveViewerProfile as jy, scanAvailableFonts as jz, AiChatPanelComponent as k, translationsEn as k$, setElementPosition as k0, setGridlineStyle as k1, setLayout as k2, setLegend as k3, setNodeStyle as k4, setNodeText as k5, setRepeatCount as k6, setRepeatMode as k7, setSequence as k8, setSeriesChartType as k9, splitCursorCell as kA, splitMergedCell as kB, statusKind as kC, statusLabel$1 as kD, storeAudienceContent as kE, stringFromEvent$5 as kF, strokeColorOf as kG, strokeToInkElement as kH, strokeWidthOf as kI, styleShadowFilter as kJ, textAdvancedPatch as kK, textAdvancedStateFromStyle as kL, textAdvancedStateOf as kM, textColorOf as kN, textDirectionPatch as kO, textStyleOf as kP, textStylePatch as kQ, themeStyle as kR, themeToCssVars as kS, thumbnailHeight as kT, thumbnailZoom as kU, toggleCommentResolvedInList as kV, toggleNodeBold as kW, toggleNodeItalic as kX, toggleSheet as kY, topLevelNodeCount as kZ, transformSelectedTextCase as k_, setSeriesColor as ka, setSeriesErrorBars as kb, setSeriesMarker as kc, setSeriesName as kd, setSeriesTrendline as ke, setSeriesValue as kf, setStyle as kg, setTimingCurve as kh, setTitle as ki, setTrigger as kj, setTriggerShapeId as kk, shapeStylePatch as kl, sheetAfterNavigate as km, shouldBlockClickAdvance as kn, shouldUseSvgWarp as ko, showDirectionPicker as kp, showsTemplateAffordance as kq, signatureCountLabel as kr, signatureKey as ks, signatureTimestamp as kt, signerName as ku, statusLabel as kv, slideNumberOf as kw, smartArtNodes as kx, paletteColour as ky, snapToGridStep as kz, AiChatService as l, ungroupElements as l0, updateElementById as l1, updateGlowPatch as l2, updateGradientStopPatch as l3, updateInnerShadowPatch as l4, updateOuterShadowPatch as l5, updateReflectionPatch as l6, vAlignPatch as l7, validatePassword as l8, validatePrintSettings as l9, validateRoomId as la, valueToY as lb, vermilionDarkColors as lc, vermilionDarkTheme as ld, vermilionLightColors as le, vermilionLightTheme as lf, vermilionRadius as lg, waypointsToPathD as lh, worstStatus as li, zoomTargetSlideIndex as lj, AiComposerComponent as m, AiFocusBarComponent as n, AiFocusHighlightOverlayComponent as o, AiMessageListComponent as p, AiPanelStore as q, AiProposalCardComponent as r, AiSettingsSectionComponent as s, toChatSummary as t, AiToolCallCardComponent as u, AnimationAuthorPanelComponent as v, AnimationPanelComponent as w, AnimationPlaybackService as x, AutosaveService as y, CURSOR_PALETTE as z };
|
|
121104
|
-
//# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-
|
|
123694
|
+
export { CustomShowsComponent as $, ALIGN_OPTIONS as A, BroadcastDialogComponent as B, CHART_EDITOR_STYLES as C, CanvasFitService as D, ChartAxisOptionsComponent as E, ChartAxisStyleOptionsComponent as F, ChartComboTypeOptionsComponent as G, ChartDataEditorComponent as H, ChartDataLabelOptionsComponent as I, ChartDatapointMarkerOptionsComponent as J, ChartDatapointOptionsComponent as K, ChartDisplayOptionsComponent as L, ChartElementViewComponent as M, ChartErrorBarOptionsComponent as N, ChartMarkerOptionsComponent as O, ChartPartSelectionService as P, ChartPrimitivesComponent as Q, ChartRendererComponent as R, ChartTrendlineOptionsComponent as S, CollaborationCursorsComponent as T, CollaborationService as U, ColorChangedImageComponent as V, CommentsPanelComponent as W, CommentsService as X, ComparePanelComponent as Y, ConnectorRendererComponent as Z, ConnectorTextOverlayComponent as _, ANIMATION_PRESET_CATEGORIES as a, LocalPresencePublisher as a$, DATA_TABLE_HEADER_H as a0, DATA_TABLE_KEY_W as a1, DATA_TABLE_PADDING as a2, DATA_TABLE_ROW_H as a3, DEFAULT_BOUNDS as a4, DEFAULT_BROADCAST_SERVER_URL as a5, DEFAULT_CANVAS_HEIGHT as a6, DEFAULT_CANVAS_WIDTH as a7, DEFAULT_COLOR_SCHEME as a8, DEFAULT_FILL_COLOR as a9, EquationRendererComponent as aA, EquationTemplateGalleryComponent as aB, ExportProgressModalComponent as aC, ExportService as aD, FieldContextService as aE, FindBarComponent as aF, FindReplaceBarComponent as aG, FollowModeBarComponent as aH, FontEmbeddingListComponent as aI, FontEmbeddingPanelComponent as aJ, GALLERY_THEME_PRESETS as aK, GradientPickerComponent as aL, HANDOUT_OPTIONS as aM, HeaderFooterDialogComponent as aN, HyperlinkDialogComponent as aO, ImagePropertiesPanelComponent as aP, InkDrawingService as aQ, InkRendererComponent as aR, InsertSmartArtDialogComponent as aS, InspectorPaneHeaderComponent as aT, InspectorPanelComponent as aU, IsMobileService as aV, KeepAnnotationsDialogComponent as aW, LOCALE_CATALOG as aX, LONG_PRESS_DURATION_MS as aY, LONG_PRESS_MOVE_TOLERANCE_PX as aZ, LoadContentService as a_, DEFAULT_LAYOUT as aa, DEFAULT_PALETTE$1 as ab, DEFAULT_PRINT_SETTINGS as ac, DEFAULT_SLIDE_BACKGROUND as ad, DEFAULT_STROKE_COLOR as ae, DEFAULT_STYLE as af, DEFAULT_TABLE_ROW_HEIGHT as ag, DEFAULT_TEXT_COLOR$1 as ah, DEFAULT_VIEWER_PROFILE as ai, DIRECTIONAL_PRESETS as aj, DIRECTION_OPTIONS as ak, DocumentPropertiesCardComponent as al, EMBEDDED_FONTS_STYLE_ID as am, EMPHASIS_PRESETS as an, ENTRANCE_PRESETS as ao, TEMPLATES as ap, EXIT_PRESETS as aq, EditorContextMenuComponent as ar, EditorHistory as as, EditorStateService as at, EditorToolbarComponent as au, EffectsPanelComponent as av, ElementRendererComponent as aw, EmbeddedFontsService as ax, EncryptedFileDialogComponent as ay, EquationEditorDialogComponent as az, AUDIENCE_HASH as b, RibbonParagraphControlsComponent as b$, MAX_ZOOM_SCALE as b0, MIN_ZOOM_SCALE as b1, MOTION_PATH_COLUMNS as b2, MediaPreviewComponent as b3, MediaPropertiesPanelComponent as b4, MediaRendererComponent as b5, MediaTrimTimelineComponent as b6, MobileBottomBarComponent as b7, MobileMenuSheetComponent as b8, MobilePresenterViewComponent as b9, PresenterWindowService as bA, PrintDialogComponent as bB, PrintService as bC, PrintSettingsPanelComponent as bD, PropertiesDialogComponent as bE, REPEAT_MODE_OPTIONS as bF, RESIZE_HANDLES as bG, RULER_FONT_SIZE as bH, RULER_THICKNESS as bI, ReadingViewOverlayComponent as bJ, RemoteSelectionOverlayComponent as bK, RibbonAnimationGalleryComponent as bL, RibbonAnimationsSectionComponent as bM, RibbonArrangeSectionComponent as bN, RibbonColorPopoverComponent as bO, RibbonComponent as bP, RibbonDesignSectionComponent as bQ, RibbonDrawSectionComponent as bR, RibbonDrawingGroupComponent as bS, RibbonEditingSectionComponent as bT, RibbonFileSectionComponent as bU, RibbonFontControlsComponent as bV, RibbonHomeSectionComponent as bW, RibbonHyperlinkButtonComponent as bX, RibbonInsertFieldsComponent as bY, RibbonInsertSectionComponent as bZ, RibbonMotionPathGalleryComponent as b_, MobileSheetComponent as ba, MobileSlidesSheetComponent as bb, MobileToolbarComponent as bc, ModalDialogComponent as bd, Model3DRendererComponent as be, NotesHandoutCardComponent as bf, NotesPanelComponent as bg, NotesToolbarComponent as bh, OleRendererComponent as bi, OutlineViewOverlayComponent as bj, POWER_POINT_VIEWER_PROVIDERS as bk, PRESENTER_CHANNEL_NAME as bl, PRESENTER_MSG_ORIGIN as bm, PX_PER_CM as bn, PX_PER_INCH as bo, PasswordProtectionDialogComponent as bp, PasswordStrengthMeterComponent as bq, PowerPointViewerComponent as br, PresentationAnnotationOverlayComponent as bs, PresentationAnnotationsService as bt, PresentationOverlayComponent as bu, PresentationPropertiesPanelComponent as bv, PresentationSettingsCardComponent as bw, PresentationSubtitleBarComponent as bx, PresentationTransitionOverlayComponent as by, PresenterViewComponent as bz, AUDIENCE_NONCE_KEY as c, TableSelectionService as c$, RibbonPrimaryRowComponent as c0, RibbonReviewSectionComponent as c1, RibbonShapeExtrasComponent as c2, RibbonSlideshowSectionComponent as c3, RibbonTransitionsSectionComponent as c4, RibbonViewSectionComponent as c5, RulerGuidesService as c6, SEQUENCE_OPTIONS as c7, SEVERITY_GROUPS as c8, SEVERITY_LABELS as c9, SlideDiffRowComponent as cA, SlideDiffThumbnailsComponent as cB, SlideSizeCardComponent as cC, SlideSorterOverlayComponent as cD, SlideThemeOverridePanelComponent as cE, SlideTransitionCardComponent as cF, SlidesPanelComponent as cG, SmartArt3DRendererComponent as cH, SmartArt3DService as cI, SmartArtPreviewComponent as cJ, SmartArtPropertiesComponent as cK, SmartArtRendererComponent as cL, StatusBarComponent as cM, TABLE_STRUCTURE_TOGGLES as cN, TEXT_3D_BOTTOM_BEVEL_KEYS as cO, TEXT_3D_TOP_BEVEL_KEYS as cP, TEXT_DIRECTION_OPTIONS$1 as cQ, THEME_CATALOG as cR, TIMING_CURVE_OPTIONS as cS, TRIGGER_OPTIONS as cT, TYPE_LABELS as cU, TableCellAdvancedFillComponent as cV, TableCellFormattingComponent as cW, TableDataEditorComponent as cX, TablePropertiesComponent as cY, TableRendererComponent as cZ, TableResizeOverlayComponent as c_, SHORTCUT_REFERENCE_ITEMS as ca, SLIDE_TRANSITION_KEYFRAMES as cb, DEFAULT_PALETTE as cc, PALETTES$1 as cd, SMART_ART_COLOR_SCHEMES as ce, SMART_ART_STYLE_OPTIONS as cf, SUB_ITEM_LABEL as cg, SVG_WARP_PRESETS as ch, SWIPE_MAX_VERTICAL_PX as ci, SWIPE_THRESHOLD_PX as cj, SelectionPaneComponent as ck, SetUpSlideShowDialogComponent as cl, SettingsAppearanceTabComponent as cm, SettingsDialogComponent as cn, SettingsLanguageTabComponent as co, ShareDialogComponent as cp, ShortcutPanelComponent as cq, ShowOptionsFieldsetComponent as cr, ShowSlidesFieldsetComponent as cs, SignatureStrippedDialogComponent as ct, SignaturesPanelComponent as cu, SignaturesService as cv, SlideBackgroundCardComponent as cw, SlideCanvasComponent as cx, SlideDefaultInspectorComponent as cy, SlideDiffChangesComponent as cz, AVATAR_COLOR_SWATCHES as d, bringForward as d$, TagsCardComponent as d0, Text3DBevelSectionComponent as d1, Text3DPanelComponent as d2, TextAdvancedPanelComponent as d3, ThemeEditorFieldsComponent as d4, ThemeGalleryComponent as d5, ThemeSelectorCardComponent as d6, TitleBarComponent as d7, TransitionDirectionPickerComponent as d8, TransitionPreviewComponent as d9, ZoomRendererComponent as dA, ZoomTargetService as dB, addCategory as dC, addCommentToList as dD, addGradientStopPatch as dE, addItem as dF, addSeries as dG, addSubItem as dH, advanceStep as dI, aiToggleVisible as dJ, alignPatch as dK, animationFor as dL, animationPresetLabelKey as dM, annotationMapToInkInserts as dN, applyAcceptedDiff as dO, applyAnimationPreset as dP, applyFindReplacements as dQ, applyFormatToElement as dR, applyMove as dS, applyResize as dT, applyTableStylePreset as dU, asMediaElement as dV, assignUserColor as dW, attachTouchGestures as dX, beginNodeEdit as dY, bevelSizePatch as dZ, boolFromEvent as d_, VALIGN_OPTIONS as da, VIEWER_THEME as db, VersionHistoryPanelComponent as dc, ViewerCanvasEditingService as dd, ViewerCollabCursorService as de, ViewerCollaborationSessionService as df, ViewerCompareService as dg, ViewerCustomShowsService as dh, ViewerDialogsService as di, ViewerDocumentPropertiesService as dj, ViewerExportService as dk, ViewerExtraDialogsComponent as dl, ViewerFileIOService as dm, ViewerFindReplaceService as dn, 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, WriteBackScheduler as dy, ZoomNavigationService as dz, AccessibilityPanelComponent as e, changeCountLabel as e$, bringToFront as e0, buildBarActions as e1, buildBroadcastConfig as e2, buildBroadcastViewerUrl as e3, buildCategoryLabels as e4, buildCellParagraphs as e5, buildChartViewModel as e6, buildChatLogExport as e7, buildChatLogMarkdown as e8, buildChromeStyle as e9, buildRegionMapViewModel as eA, buildSaveSlides as eB, buildShareUrl as eC, buildSmartArtInsertElement as eD, buildSmartArtNodes as eE, buildStockViewModel as eF, buildSurfaceViewModel as eG, buildTableViewModel as eH, buildTreemapViewModel as eI, buildTrimFragment as eJ, buildWaterfallViewModel as eK, buildZeroLine as eL, buildZoomContainerStyle as eM, buildZoomViewModel as eN, bulletIndentPx as eO, canAddTopLevelNode as eP, canGroupSelection as eQ, canRemoveTopLevelNode as eR, canSetStrokeWidth as eS, canStartBroadcast as eT, canStartShare as eU, canUngroupSelection as eV, canUseClipboard as eW, captionDisplayText as eX, cellRunStyle as eY, cellStyleToStyleMap as eZ, cellTdStyle as e_, buildClearHyperlinkPatch as ea, buildClickGroups as eb, buildColStyles as ec, buildCollaborationConfig as ed, buildComboViewModel as ee, buildCssGradientFromShapeStyle as ef, buildDuotoneFilter as eg, buildDuotoneFilterId as eh, buildEmbeddedFontStyles as ei, buildEquationElement as ej, buildEquationSegment as ek, buildFallbackViewModel as el, buildFontFaceRule as em, buildGradientFillCss as en, buildGridlinesAndLabels as eo, buildHyperlinkPatch as ep, buildInkContainerStyle as eq, buildInkStrokes as er, buildLegend as es, buildModel3DContainerStyle as et, buildModel3DViewModel as eu, buildOleActionModel as ev, buildOleInfoRows as ew, buildPatternFillCss as ex, buildPrintHtmlDocument as ey, buildPropertiesPatch as ez, AccessibilityService as f, currentColorScheme as f$, changeIcon as f0, characterSpacingPatch as f1, checkFontAvailable as f2, clampCursorPosition as f3, clampGifDimensions as f4, clampIndex as f5, clampNotesFontSize as f6, clampScale as f7, clampStep as f8, clearAllLocalViewerData as f9, computePieLayout as fA, computePieSlicePath as fB, computePieSlices as fC, computePlotLayout as fD, computeRSquared as fE, computeRadarPoints as fF, computeScatterDots as fG, computeSelectionBoxes as fH, computeSingleSelected as fI, computeSlideIndices as fJ, computeSnap as fK, computeStackedBarRects as fL, computeStackedValueRange as fM, computeTextLines as fN, computeTimerProgress as fO, computeTrendlinePrimitives as fP, computeValueRange as fQ, convertOmmlToMathMl as fR, copyFormatFromElement as fS, countAccessibilityIssues as fT, countAnnotationStrokes as fU, createAngularAiBridge as fV, createCustomShow as fW, createSwipeDismissDrag as fX, createWebrtcBundle as fY, createWebsocketBundle as fZ, cssObjectToStyleMap as f_, clearAudienceContent as fa, cn as fb, collectAccessibilityIssues as fc, collectElementText as fd, collectSlideText as fe, collectStoredChats as ff, collectUsedFontFamilies as fg, columnWidthStyle as fh, commitNodeText as fi, computeAlign as fj, computeAxisTitlePrimitives as fk, computeBarRects as fl, computeBubbleRadius as fm, computeCornerHandle as fn, computeDataTablePrimitives as fo, computeDistribute as fp, computeDrawingViewBox as fq, computeErrorBarPrimitives as fr, computeFocusTargets as fs, computeHandleBoxes as ft, computeHandoutLayout as fu, computeIsMobile as fv, computeIsTablet as fw, computeLinePoints as fx, computeLinearRegression as fy, computePageCount as fz, AccountPageComponent as g, getOleDownloadFileName as g$, currentLayout as g0, currentStyle as g1, defaultCssVars as g2, defaultRadius as g3, defaultThemeColors as g4, deleteElementsByIds as g5, deleteVersion as g6, demoteNode as g7, deriveModel3DBlobUrl as g8, derivePresenceList as g9, fitPolynomial as gA, fitZoom as gB, focusTargetChips as gC, fontMimeForFormat as gD, fontSizeOf as gE, formatAutoNumber as gF, formatAxisValue as gG, formatBytes as gH, formatCursorLabel as gI, formatElapsed as gJ, formatFileSize as gK, formatPropertyDate as gL, formatTime as gM, fpsToFrameIntervalMs as gN, generateBroadcastRoomId as gO, generateCommentId as gP, generateCustomShowId as gQ, generatePressureCircles as gR, generateTicks as gS, getClrChangeParams as gT, getContainerStyle as gU, getDuotoneFilterDef as gV, getImageSrc as gW, getLocalStorageUsageSummary as gX, getOleAriaLabel as gY, getOleBadgeLabel as gZ, getOleDisplayName as g_, describeSmartArtBounds as ga, disableGlowPatch as gb, disableInnerShadowPatch as gc, disableOuterShadowPatch as gd, disableReflectionPatch as ge, disableSoftEdgePatch as gf, duplicateElementById as gg, durationOf as gh, effectsStateOf as gi, enableGlowPatch as gj, enableInnerShadowPatch as gk, enableOuterShadowPatch as gl, enableReflectionPatch as gm, enableSoftEdgePatch as gn, encodeGif as go, estimatePageCount as gp, evenColumnWidths as gq, evenRowHeights as gr, exitPresentationFullscreen as gs, exportAiChatLogs as gt, extractPathPoints as gu, eyedropperAvailable as gv, fillColorOf as gw, findInSlides as gx, findOwningSlideIndex as gy, findSlideIndexByElementId as gz, ActionSettingsPanelComponent as h, mergeRight as h$, getOleTypeColor as h0, getOleTypeLabel as h1, getPasswordStrength as h2, getPatternSvg as h3, getPlaceholderStyle as h4, getVersions as h5, getResolvedShapeClipPath as h6, getResolvedShapeClipPathFor as h7, getShapeFillStrokeStyle as h8, getSlideBackgroundStyle as h9, interpolateWidth as hA, isAudienceTab as hB, isBold as hC, isBrowserOpenableMime as hD, isChildNode as hE, isElementInteractive as hF, isInjectableUrl as hG, isItalic as hH, isPpactionUrl as hI, isPresenterMessage as hJ, isSigned as hK, isTextElement as hL, isTwoTableFocus as hM, isUnderline as hN, isUrlSafe as hO, isValidRoomId as hP, isViewportBackgroundPressTarget as hQ, isZoomActivationKey as hR, issueTrackKey as hS, issueTypeLabel as hT, keyToLabel as hU, latexToMathml as hV, linePointsToSvgString as hW, lineSpacingPatch as hX, loadAudienceContent as hY, mergeCaptionResults as hZ, mergeDown as h_, getSlideTransitionAnimations as ha, getSmartArtNodeBounds as hb, getSpeechRecognitionCtor as hc, getTextBlockStyle as hd, getTextWarp as he, getTouchDistance as hf, getWarpCategory as hg, getWarpPath as hh, gradientStateFromStyle as hi, gradientStateOf as hj, gradientStatePatch as hk, gridColumns as hl, groupElements as hm, groupIssuesBySeverity as hn, hasAnimation as ho, hasCopyableFormat as hp, hasExistingLink as hq, hasExitedFullscreen as hr, hasGradientFill as hs, hasPressureVariation as ht, hasVisibleSlideAfter as hu, headerLabel as hv, imageDimensions as hw, inkViewBox as hx, insertTableElementColumn as hy, insertTableElementRow as hz, AdvancedChartEditorComponent as i, removeTableElementColumn as i$, mergeSelection as i0, moveElementBy as i1, moveNodeDown as i2, moveNodeUp as i3, msToFrameDelayCs as i4, narrowToCircle as i5, narrowToPolygon as i6, narrowToRect as i7, newChartElement as i8, newEquationElement as i9, partitionSlides as iA, patchChartData as iB, patchChartStyle as iC, patchTableData as iD, patchTextStyle as iE, pendingElementStyles as iF, pickColorByClickFallback as iG, pickFile as iH, pickSupportedMimeType as iI, planGifFrames as iJ, planVideoSegments as iK, pointsToSvgPathD as iL, presenceToCursors as iM, presetByLayout as iN, presetsForCategory as iO, pressuresToWidths as iP, prevVisibleIndex as iQ, projectDrawingShapes as iR, promoteNode as iS, provideViewerTheme as iT, radarAngle as iU, radarRingPoints as iV, readAsDataUrl as iW, recordWebm as iX, redistributeColumnWidth as iY, removeAnimation as iZ, removeCategory as i_, newPresetShapeElement as ia, newShapeElement as ib, newSmartArtElement as ic, newTableElement as id, newTextElement as ie, nextVisibleIndex as ig, nodeBold as ih, nodeEditBox as ii, nodeFillColor as ij, nodeFontColor as ik, nodeIdFromKey as il, nodeItalic as im, nodeStyle as io, normalizeFontFormat as ip, normalizeSlidesPerPage as iq, normalizeValue as ir, numFromEvent as is, ommlToMathml as it, ooxmlDashToCssBorderStyle as iu, openNativeEyeDropper as iv, overallStatus as iw, paletteColor as ix, parseAudienceNonce as iy, parseNodeTextarea as iz, AiChangeOverlayComponent as j, setDataPointFill as j$, removeCommentFromList as j0, removeElementAnimation as j1, removeGradientStopPatch as j2, removeNode as j3, removeTableElementRow as j4, removeSeries as j5, renderToCanvas as j6, reorderAnimationDown as j7, reorderAnimationUp as j8, replaceInSlides as j9, sanitizeSlideIndex as jA, sanitizeUserName as jB, saveViewerProfile as jC, scanAvailableFonts as jD, searchSlides as jE, seedBroadcastFields as jF, seedHyperlinkDraft as jG, seedPropertiesDraft as jH, seedShareFields as jI, segmentFrameCount as jJ, selectValue$2 as jK, sendBackward as jL, sendToBack as jM, sequentialColorScale as jN, serializeWriteBack as jO, seriesColor as jP, setAnimationEmphasis as jQ, setAnimationEntrance as jR, setAnimationExit as jS, setAxis as jT, setAxisLogScale as jU, setAxisTitleStyle as jV, setCategoryLabel as jW, setCellText as jX, setColorScheme as jY, setDataLabels as jZ, setDataPointExplosion as j_, replaceMatch as ja, requestPresentationFullscreen as jb, resizeElement as jc, resolveCaptionTracks as jd, resolveChartKind as je, resolveFontVariant as jf, resolveHyperlinkHref as jg, resolveInteractiveElementId as jh, resolveMediaSrc as ji, resolveOleType as jj, resolveParagraphBullet as jk, resolvePresenterNotes as jl, resolveProfileInitial as jm, resolveRegionCode as jn, resolveSlideAutoAdvanceMs as jo, resolvePalette as jp, resolveThemeCatalogEntry as jq, resolveTransitionDuration as jr, revealedElementStyles as js, routeOrthogonalConnector as jt, rowStyle as ju, rulerDragToGuidePosition as jv, rulerHighlight as jw, rulerStripTicks as jx, sampleColorFromSlide as jy, sanitizeColor as jz, AiChatPanelComponent as k, toggleNodeBold as k$, setDataPointLabel as k0, setDataPointMarker as k1, setDelay as k2, setDirection as k3, setDuration as k4, setElementPosition as k5, setGridlineStyle as k6, setLayout as k7, setLegend as k8, setNodeStyle as k9, statusLabel as kA, slideNumberOf as kB, smartArtNodes as kC, paletteColour as kD, snapToGridStep as kE, splitCursorCell as kF, splitMergedCell as kG, statusKind as kH, statusLabel$1 as kI, storeAudienceContent as kJ, stringFromEvent$5 as kK, strokeColorOf as kL, strokeToInkElement as kM, strokeWidthOf as kN, styleShadowFilter as kO, textAdvancedPatch as kP, textAdvancedStateFromStyle as kQ, textAdvancedStateOf as kR, textColorOf as kS, textDirectionPatch as kT, textStyleOf as kU, textStylePatch as kV, themeStyle as kW, themeToCssVars as kX, thumbnailHeight as kY, thumbnailZoom as kZ, toggleCommentResolvedInList as k_, setNodeText as ka, setRepeatCount as kb, setRepeatMode as kc, setSequence as kd, setSeriesChartType as ke, setSeriesColor as kf, setSeriesErrorBars as kg, setSeriesMarker as kh, setSeriesName as ki, setSeriesTrendline as kj, setSeriesValue as kk, setStyle as kl, setTimingCurve as km, setTitle as kn, setTrigger as ko, setTriggerShapeId as kp, shapeStylePatch as kq, sheetAfterNavigate as kr, shouldBlockClickAdvance as ks, shouldUseSvgWarp as kt, showDirectionPicker as ku, showsTemplateAffordance as kv, signatureCountLabel as kw, signatureKey as kx, signatureTimestamp as ky, signerName as kz, AiChatService as l, toggleNodeItalic as l0, toggleSheet as l1, topLevelNodeCount as l2, transformSelectedTextCase as l3, translationsEn as l4, ungroupElements as l5, updateElementById as l6, updateGlowPatch as l7, updateGradientStopPatch as l8, updateInnerShadowPatch as l9, updateOuterShadowPatch as la, updateReflectionPatch as lb, vAlignPatch as lc, validatePassword as ld, validatePrintSettings as le, validateRoomId as lf, valueToY as lg, vermilionDarkColors as lh, vermilionDarkTheme as li, vermilionLightColors as lj, vermilionLightTheme as lk, vermilionRadius as ll, waypointsToPathD as lm, worstStatus as ln, zoomTargetSlideIndex as lo, AiComposerComponent as m, AiFocusBarComponent as n, AiFocusHighlightOverlayComponent as o, AiMessageListComponent as p, AiPanelStore as q, AiProposalCardComponent as r, AiSettingsSectionComponent as s, toChatSummary as t, AiToolCallCardComponent as u, AnimationAuthorPanelComponent as v, AnimationPanelComponent as w, AnimationPlaybackService as x, AutosaveService as y, CURSOR_PALETTE as z };
|
|
123695
|
+
//# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-DS2J9zVf.mjs.map
|