pptx-angular-viewer 1.1.61 → 1.1.63
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 +6 -0
- package/README.md +1 -2
- package/fesm2022/pptx-angular-viewer.mjs +207 -36
- package/fesm2022/pptx-angular-viewer.mjs.map +1 -1
- package/package.json +1 -1
- package/types/pptx-angular-viewer.d.ts +17 -21
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
|
|
5
5
|
by [git-cliff](https://git-cliff.org); do not edit it by hand.
|
|
6
6
|
|
|
7
|
+
## [1.1.62](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.1.62) - 2026-07-03
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
- **vue,angular:** Correct stale parity-tracker claims (by @ChristopherVR) ([54c4f05](https://github.com/ChristopherVR/pptx-viewer/commit/54c4f0540e33692d82f961c96d8a1818c8678751))
|
|
12
|
+
|
|
7
13
|
## [1.1.59](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@1.1.59) - 2026-07-03
|
|
8
14
|
|
|
9
15
|
### Features
|
package/README.md
CHANGED
|
@@ -194,8 +194,7 @@ polish/cosmetic, not behavioural gaps:
|
|
|
194
194
|
image otherwise (the same as the React package).
|
|
195
195
|
|
|
196
196
|
The `pptx-viewer-core` engine parses all element data, so you can access it from
|
|
197
|
-
the model even where the UI does not expose it yet.
|
|
198
|
-
in [`PORTING.md`](./PORTING.md).
|
|
197
|
+
the model even where the UI does not expose it yet.
|
|
199
198
|
|
|
200
199
|
## Build (contributing)
|
|
201
200
|
|
|
@@ -4946,15 +4946,15 @@ function convertOmmlToLatex(omml) {
|
|
|
4946
4946
|
}
|
|
4947
4947
|
|
|
4948
4948
|
/**
|
|
4949
|
-
* Framework-agnostic chart helpers
|
|
4949
|
+
* Framework-agnostic chart helpers, a focused Vue port of the React package's
|
|
4950
4950
|
* `viewer/utils/chart-helpers.ts`, `chart-layout.ts`, and
|
|
4951
4951
|
* `chart-style-palettes.ts`.
|
|
4952
4952
|
*
|
|
4953
|
-
*
|
|
4954
|
-
* area / pie / doughnut) and the shared chrome
|
|
4955
|
-
* features (log axes, secondary axes, display units,
|
|
4956
|
-
*
|
|
4957
|
-
* `
|
|
4953
|
+
* This module only covers the common-type renderers (bar / column / stacked /
|
|
4954
|
+
* line / area / pie / doughnut) and the shared chrome. Advanced axis/overlay
|
|
4955
|
+
* features (log axes, secondary axes, display units, trendlines, error bars,
|
|
4956
|
+
* data tables) live in `chart-axis.ts` / `chart-axis-render.ts` /
|
|
4957
|
+
* `chart-cartesian.ts` and are consumed via `chart/ChartViewModelSvg.vue`.
|
|
4958
4958
|
*
|
|
4959
4959
|
* These small pure helpers are an extraction candidate: long-term they (and
|
|
4960
4960
|
* their React counterparts) should live in a shared, framework-agnostic
|
|
@@ -21862,7 +21862,7 @@ function connectorBendFraction(element) {
|
|
|
21862
21862
|
* for straight connectors (which render as a `<line>`). Endpoints are already
|
|
21863
21863
|
* flip-adjusted by the caller.
|
|
21864
21864
|
*
|
|
21865
|
-
* Viewer-first approximation (full A* routing is a TODO
|
|
21865
|
+
* Viewer-first approximation (full A* routing is a TODO):
|
|
21866
21866
|
* - **bent**: orthogonal elbow polyline. `bentConnector2` is a single L-bend;
|
|
21867
21867
|
* `bentConnector3..5` route through a vertical mid-axis at `bend`.
|
|
21868
21868
|
* - **curved**: `curvedConnector2` is a quadratic Bezier; `curvedConnector3..5`
|
|
@@ -22992,6 +22992,164 @@ function observeYDocSlides(ydoc, onChange) {
|
|
|
22992
22992
|
return () => arr.unobserveDeep(onChange);
|
|
22993
22993
|
}
|
|
22994
22994
|
|
|
22995
|
+
/**
|
|
22996
|
+
* collaboration-text-merge.ts: character-level in-place merging of a desired
|
|
22997
|
+
* text state into a live Y.Text.
|
|
22998
|
+
*
|
|
22999
|
+
* `reconcileTextBody` used to replace the whole Y.Text whenever the canonical
|
|
23000
|
+
* decoded form differed, which made concurrent edits to the SAME text element
|
|
23001
|
+
* collide at element granularity (last writer wins). This module instead
|
|
23002
|
+
* applies a minimal edit script to the existing Y.Text:
|
|
23003
|
+
*
|
|
23004
|
+
* - plain-text diff via common prefix/suffix (surrogate-pair safe): one
|
|
23005
|
+
* delete + attributed inserts for the changed middle span
|
|
23006
|
+
* - attribute reconcile: walk the current and desired attribute runs by
|
|
23007
|
+
* position and `format()` only the ranges whose attributes differ
|
|
23008
|
+
*
|
|
23009
|
+
* Because each peer submits a minimal delta, Yjs merges concurrent edits to
|
|
23010
|
+
* the same run at character granularity (e.g. one peer prepends while another
|
|
23011
|
+
* appends, both survive).
|
|
23012
|
+
*/
|
|
23013
|
+
function isYTextEditable(value) {
|
|
23014
|
+
return (isYTextLike(value) &&
|
|
23015
|
+
typeof value.delete === 'function' &&
|
|
23016
|
+
typeof value.format === 'function');
|
|
23017
|
+
}
|
|
23018
|
+
const isHighSurrogate = (code) => code >= 0xd800 && code <= 0xdbff;
|
|
23019
|
+
const isLowSurrogate = (code) => code >= 0xdc00 && code <= 0xdfff;
|
|
23020
|
+
function opsText(ops) {
|
|
23021
|
+
let text = '';
|
|
23022
|
+
for (const op of ops) {
|
|
23023
|
+
if (typeof op.insert === 'string') {
|
|
23024
|
+
text += op.insert;
|
|
23025
|
+
}
|
|
23026
|
+
}
|
|
23027
|
+
return text;
|
|
23028
|
+
}
|
|
23029
|
+
function commonPrefixLength(a, b) {
|
|
23030
|
+
const max = Math.min(a.length, b.length);
|
|
23031
|
+
let i = 0;
|
|
23032
|
+
while (i < max && a.charCodeAt(i) === b.charCodeAt(i)) {
|
|
23033
|
+
i++;
|
|
23034
|
+
}
|
|
23035
|
+
// Never cut between a surrogate pair.
|
|
23036
|
+
if (i > 0 && isHighSurrogate(a.charCodeAt(i - 1))) {
|
|
23037
|
+
i--;
|
|
23038
|
+
}
|
|
23039
|
+
return i;
|
|
23040
|
+
}
|
|
23041
|
+
function commonSuffixLength(a, b, prefix) {
|
|
23042
|
+
const max = Math.min(a.length, b.length) - prefix;
|
|
23043
|
+
let i = 0;
|
|
23044
|
+
while (i < max && a.charCodeAt(a.length - i - 1) === b.charCodeAt(b.length - i - 1)) {
|
|
23045
|
+
i++;
|
|
23046
|
+
}
|
|
23047
|
+
if (i > 0 && isLowSurrogate(a.charCodeAt(a.length - i))) {
|
|
23048
|
+
i--;
|
|
23049
|
+
}
|
|
23050
|
+
return i;
|
|
23051
|
+
}
|
|
23052
|
+
/**
|
|
23053
|
+
* Insert the desired-text span [from, to) into `ytext`, carrying each desired
|
|
23054
|
+
* op's attributes so no character inherits formatting from its neighbour.
|
|
23055
|
+
*/
|
|
23056
|
+
function insertSpanWithAttrs(ytext, desiredOps, from, to) {
|
|
23057
|
+
let opStart = 0;
|
|
23058
|
+
let index = from;
|
|
23059
|
+
for (const op of desiredOps) {
|
|
23060
|
+
if (typeof op.insert !== 'string') {
|
|
23061
|
+
continue;
|
|
23062
|
+
}
|
|
23063
|
+
const opEnd = opStart + op.insert.length;
|
|
23064
|
+
const start = Math.max(opStart, from);
|
|
23065
|
+
const end = Math.min(opEnd, to);
|
|
23066
|
+
if (start < end) {
|
|
23067
|
+
const chunk = op.insert.slice(start - opStart, end - opStart);
|
|
23068
|
+
// Explicit attrs always: attribute-less inserts inherit the previous
|
|
23069
|
+
// character's formatting in Yjs (the style-bleed bug).
|
|
23070
|
+
ytext.insert(index, chunk, (op.attributes ?? {}));
|
|
23071
|
+
index += chunk.length;
|
|
23072
|
+
}
|
|
23073
|
+
opStart = opEnd;
|
|
23074
|
+
}
|
|
23075
|
+
}
|
|
23076
|
+
function attrsEqual(a, b) {
|
|
23077
|
+
const aKeys = Object.keys(a);
|
|
23078
|
+
if (aKeys.length !== Object.keys(b).length) {
|
|
23079
|
+
return false;
|
|
23080
|
+
}
|
|
23081
|
+
return aKeys.every((k) => a[k] === b[k]);
|
|
23082
|
+
}
|
|
23083
|
+
/**
|
|
23084
|
+
* Bring the attribute runs of `ytext` (whose plain text already matches the
|
|
23085
|
+
* desired ops) in line with the desired attributes, formatting only the
|
|
23086
|
+
* ranges that differ.
|
|
23087
|
+
*/
|
|
23088
|
+
function reconcileAttributeRuns(ytext, desiredOps) {
|
|
23089
|
+
const currentOps = ytext.toDelta().filter((op) => typeof op.insert === 'string');
|
|
23090
|
+
let ci = 0;
|
|
23091
|
+
let cOff = 0;
|
|
23092
|
+
let pos = 0;
|
|
23093
|
+
for (const dop of desiredOps) {
|
|
23094
|
+
if (typeof dop.insert !== 'string') {
|
|
23095
|
+
continue;
|
|
23096
|
+
}
|
|
23097
|
+
const dAttrs = (dop.attributes ?? {});
|
|
23098
|
+
let remaining = dop.insert.length;
|
|
23099
|
+
while (remaining > 0 && ci < currentOps.length) {
|
|
23100
|
+
const cText = currentOps[ci].insert;
|
|
23101
|
+
const len = Math.min(cText.length - cOff, remaining);
|
|
23102
|
+
const cAttrs = (currentOps[ci].attributes ?? {});
|
|
23103
|
+
if (!attrsEqual(cAttrs, dAttrs)) {
|
|
23104
|
+
const patch = {};
|
|
23105
|
+
for (const key of Object.keys(dAttrs)) {
|
|
23106
|
+
if (cAttrs[key] !== dAttrs[key]) {
|
|
23107
|
+
patch[key] = dAttrs[key];
|
|
23108
|
+
}
|
|
23109
|
+
}
|
|
23110
|
+
for (const key of Object.keys(cAttrs)) {
|
|
23111
|
+
if (!(key in dAttrs)) {
|
|
23112
|
+
patch[key] = null;
|
|
23113
|
+
}
|
|
23114
|
+
}
|
|
23115
|
+
ytext.format(pos, len, patch);
|
|
23116
|
+
}
|
|
23117
|
+
pos += len;
|
|
23118
|
+
remaining -= len;
|
|
23119
|
+
cOff += len;
|
|
23120
|
+
if (cOff >= cText.length) {
|
|
23121
|
+
ci++;
|
|
23122
|
+
cOff = 0;
|
|
23123
|
+
}
|
|
23124
|
+
}
|
|
23125
|
+
}
|
|
23126
|
+
}
|
|
23127
|
+
/**
|
|
23128
|
+
* Apply the minimal edit script that turns the live `ytext` into the state
|
|
23129
|
+
* described by `desiredOps`. Returns false (leaving the caller to fall back
|
|
23130
|
+
* to wholesale replacement) if the text diff did not converge.
|
|
23131
|
+
*
|
|
23132
|
+
* Must be called inside a Y.Doc transaction when the text is integrated.
|
|
23133
|
+
*/
|
|
23134
|
+
function mergeDeltaIntoYText(ytext, desiredOps) {
|
|
23135
|
+
const currentText = opsText(ytext.toDelta());
|
|
23136
|
+
const desiredText = opsText(desiredOps);
|
|
23137
|
+
if (currentText !== desiredText) {
|
|
23138
|
+
const prefix = commonPrefixLength(currentText, desiredText);
|
|
23139
|
+
const suffix = commonSuffixLength(currentText, desiredText, prefix);
|
|
23140
|
+
const deleteLen = currentText.length - prefix - suffix;
|
|
23141
|
+
if (deleteLen > 0) {
|
|
23142
|
+
ytext.delete(prefix, deleteLen);
|
|
23143
|
+
}
|
|
23144
|
+
insertSpanWithAttrs(ytext, desiredOps, prefix, desiredText.length - suffix);
|
|
23145
|
+
if (opsText(ytext.toDelta()) !== desiredText) {
|
|
23146
|
+
return false;
|
|
23147
|
+
}
|
|
23148
|
+
}
|
|
23149
|
+
reconcileAttributeRuns(ytext, desiredOps);
|
|
23150
|
+
return true;
|
|
23151
|
+
}
|
|
23152
|
+
|
|
22995
23153
|
/**
|
|
22996
23154
|
* collaboration-reconcile.ts: Granular Y.Doc reconciliation for collaborative
|
|
22997
23155
|
* editing.
|
|
@@ -23004,7 +23162,9 @@ function observeYDocSlides(ydoc, onChange) {
|
|
|
23004
23162
|
* - slides and elements are matched by `id`; unchanged ones keep their Y.Map
|
|
23005
23163
|
* instance so concurrent field edits merge via Yjs
|
|
23006
23164
|
* - scalar / complex fields are compared and only set when different
|
|
23007
|
-
* - textBody is
|
|
23165
|
+
* - textBody is edited in place (minimal char-level diff via
|
|
23166
|
+
* collaboration-text-merge.ts) when its canonical decoded form differs;
|
|
23167
|
+
* wholesale replacement is only a fallback
|
|
23008
23168
|
* - removed items are deleted, new ones inserted at their position; moves
|
|
23009
23169
|
* are delete+reinsert (Yjs has no move primitive)
|
|
23010
23170
|
*
|
|
@@ -23053,11 +23213,17 @@ function reconcileTextBody(ymap, rec, factories) {
|
|
|
23053
23213
|
}
|
|
23054
23214
|
return;
|
|
23055
23215
|
}
|
|
23056
|
-
const
|
|
23216
|
+
const desiredDelta = encodeSegmentsToDelta(segments);
|
|
23217
|
+
const desired = decodeDelta(desiredDelta);
|
|
23057
23218
|
const existing = isYTextLike(current) ? decodeDelta(current.toDelta()) : undefined;
|
|
23058
23219
|
if (existing !== undefined && jsonEqual(existing, desired)) {
|
|
23059
23220
|
return;
|
|
23060
23221
|
}
|
|
23222
|
+
// Prefer an in-place minimal edit so concurrent edits to the same text
|
|
23223
|
+
// element merge at character granularity instead of element-level LWW.
|
|
23224
|
+
if (isYTextEditable(current) && mergeDeltaIntoYText(current, desiredDelta)) {
|
|
23225
|
+
return;
|
|
23226
|
+
}
|
|
23061
23227
|
const ytext = factories.createText();
|
|
23062
23228
|
encodeTextBody(segments, ytext);
|
|
23063
23229
|
ymap.set('textBody', ytext);
|
|
@@ -34423,10 +34589,9 @@ function segmentFrameCount(durationMs, fps) {
|
|
|
34423
34589
|
* - loader: load-pipeline helpers (media/image collection, guides).
|
|
34424
34590
|
* - types: CanvasSize, CollaborationConfig, CollaborationRole.
|
|
34425
34591
|
* - constants: scalar viewer defaults (canvas size, fallback colours).
|
|
34426
|
-
*
|
|
34427
|
-
*
|
|
34428
|
-
*
|
|
34429
|
-
* timeline engine, table-merge math, morph matching, export data helpers.
|
|
34592
|
+
* - render: the bulk of the shared logic (colour/geometry/connector/
|
|
34593
|
+
* animation/table/chart/text/effects/collaboration/i18n).
|
|
34594
|
+
* - export: export data helpers.
|
|
34430
34595
|
*/
|
|
34431
34596
|
|
|
34432
34597
|
/**
|
|
@@ -39301,10 +39466,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
39301
39466
|
* Provide it at the component level so its lifetime tracks the host viewer:
|
|
39302
39467
|
* `@Component({ providers: [LoadContentService] })`.
|
|
39303
39468
|
*
|
|
39304
|
-
*
|
|
39305
|
-
*
|
|
39306
|
-
*
|
|
39307
|
-
* the corresponding features are ported.
|
|
39469
|
+
* Originally the viewer-first subset of the React hook; the extra pieces of
|
|
39470
|
+
* presentation metadata (sections, custom shows, embedded fonts, digital
|
|
39471
|
+
* signatures, …) were added alongside the corresponding features.
|
|
39308
39472
|
*/
|
|
39309
39473
|
class LoadContentService {
|
|
39310
39474
|
/** Parsed slides (with image Blob URLs patched in). */
|
|
@@ -40715,7 +40879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
40715
40879
|
* building the SmartArt element payload from a chosen preset, hierarchy
|
|
40716
40880
|
* parenting) is delegated to the pure functions below so they can be unit-tested
|
|
40717
40881
|
* in plain vitest (the Angular package's vitest setup has no Angular compiler,
|
|
40718
|
-
* so component / TestBed tests are not available
|
|
40882
|
+
* so component / TestBed tests are not available).
|
|
40719
40883
|
*
|
|
40720
40884
|
* The preset catalogue itself is the framework-agnostic, vendored
|
|
40721
40885
|
* `pptx-viewer-shared` source of truth (`render/smart-art-presets`), consumed
|
|
@@ -46514,7 +46678,7 @@ function describeSmartArtBounds(layout) {
|
|
|
46514
46678
|
* `editor-insert.ts` (sourced from `pptx-viewer-core`). Keeping this logic out of
|
|
46515
46679
|
* the component lets it be unit-tested in plain vitest (the Angular package's
|
|
46516
46680
|
* vitest setup has no Angular compiler, so TestBed component tests are not
|
|
46517
|
-
* available
|
|
46681
|
+
* available).
|
|
46518
46682
|
*
|
|
46519
46683
|
* Mirrors the React inspector:
|
|
46520
46684
|
* packages/react/src/viewer/components/inspector/SmartArtPropertiesPanel.tsx
|
|
@@ -52203,7 +52367,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
52203
52367
|
* Compound (double/triple) lines render as parallel strands and line caps map
|
|
52204
52368
|
* from `a:ln/@cap`; both derive from the shared connector geometry.
|
|
52205
52369
|
*
|
|
52206
|
-
* Not yet ported (TODO
|
|
52370
|
+
* Not yet ported (TODO): line shadows/glow.
|
|
52207
52371
|
*/
|
|
52208
52372
|
class ConnectorRendererComponent {
|
|
52209
52373
|
element = input.required(/* @ts-ignore */
|
|
@@ -52630,7 +52794,8 @@ function buildDuotoneFilter(element) {
|
|
|
52630
52794
|
* and paint text boxes, basic preset shapes, images, and image/gradient fills
|
|
52631
52795
|
* (the latter via the parser's prebuilt CSS gradient string). Advanced visuals
|
|
52632
52796
|
* (the structured gradient builder, pattern fills, custom geometry clip-paths,
|
|
52633
|
-
* shadows, 3D, image effects, text warp) are
|
|
52797
|
+
* shadows, 3D, image effects, text warp) are handled by the shared render
|
|
52798
|
+
* modules (`pptx-viewer-shared`) consumed from the renderer components.
|
|
52634
52799
|
*
|
|
52635
52800
|
* Long term the *logic* here is a shared-extraction candidate; only the
|
|
52636
52801
|
* return type (CSS map shape) differs per framework, so a future refactor
|
|
@@ -53068,7 +53233,7 @@ function buildInkContainerStyle(element, zIndex) {
|
|
|
53068
53233
|
* radii follow the per-point pressure, matching React's `renderInk`. Strokes
|
|
53069
53234
|
* without pressure variation degrade to a plain constant-width `<path>`.
|
|
53070
53235
|
*
|
|
53071
|
-
* Not ported (TODO
|
|
53236
|
+
* Not ported (TODO): ink replay animation and the
|
|
53072
53237
|
* highlighter/eraser tool blend modes.
|
|
53073
53238
|
*
|
|
53074
53239
|
* All non-trivial pure computation lives in `ink-renderer-helpers.ts` (no
|
|
@@ -54463,7 +54628,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
54463
54628
|
* its text directly on the diagram. Everything that can be expressed as a pure
|
|
54464
54629
|
* function lives here so it can be unit-tested in plain vitest (the Angular
|
|
54465
54630
|
* package's vitest setup has no Angular compiler, so component/TestBed tests are
|
|
54466
|
-
* not available
|
|
54631
|
+
* not available). The component
|
|
54467
54632
|
* (`smart-art-renderer.component.ts`) stays thin: it owns only the edit-state
|
|
54468
54633
|
* signal, the positioned `<textarea>`, and the call into the existing commit
|
|
54469
54634
|
* path (`EditorStateService.updateElement`, the same channel the inspector's
|
|
@@ -57128,8 +57293,7 @@ function runStyleFromSegment(seg) {
|
|
|
57128
57293
|
* ElementRendererComponent: Angular port of the React `ElementRenderer.tsx`
|
|
57129
57294
|
* and the Vue `ElementRenderer.vue`.
|
|
57130
57295
|
*
|
|
57131
|
-
* Renders a single slide element by its `type` discriminant
|
|
57132
|
-
* subset):
|
|
57296
|
+
* Renders a single slide element by its `type` discriminant:
|
|
57133
57297
|
* - `text` / `shape` → positioned box with fill/stroke + rich text + effects
|
|
57134
57298
|
* - `connector` → SVG straight/bent/curved connector
|
|
57135
57299
|
* - `chart` → inline-SVG chart (bar/line/area/pie/scatter)
|
|
@@ -57137,14 +57301,13 @@ function runStyleFromSegment(seg) {
|
|
|
57137
57301
|
* - `smartArt` → SVG drawing-shapes / node-text fallback
|
|
57138
57302
|
* - `ink` → SVG ink strokes
|
|
57139
57303
|
* - `ole` → embedded-object preview / icon
|
|
57140
|
-
* - `model3d` →
|
|
57304
|
+
* - `model3d` → interactive three.js scene when the optional
|
|
57305
|
+
* `three` peer is present, else poster / placeholder
|
|
57141
57306
|
* - `zoom` → slide/section zoom thumbnail
|
|
57142
57307
|
* - `picture` / `image` → `<img>`
|
|
57143
57308
|
* - `media` → native `<video>`/`<audio>` playback, poster fallback
|
|
57144
57309
|
* - `group` → recursive children (self-referencing selector)
|
|
57145
|
-
* - everything else → labelled placeholder (
|
|
57146
|
-
*
|
|
57147
|
-
* Interaction (selection, resize, inline editing) is not yet ported.
|
|
57310
|
+
* - everything else → labelled placeholder (defensive fallback)
|
|
57148
57311
|
*/
|
|
57149
57312
|
class ElementRendererComponent {
|
|
57150
57313
|
element = input.required(/* @ts-ignore */
|
|
@@ -58030,8 +58193,8 @@ function plainText(el) {
|
|
|
58030
58193
|
* Renders the active slide as a fixed-size stage scaled by `zoom`, with each
|
|
58031
58194
|
* element absolutely positioned. When `editable`, supports click-to-select
|
|
58032
58195
|
* (event delegation), selection outlines, and pointer drag-to-move / resize
|
|
58033
|
-
* handles
|
|
58034
|
-
*
|
|
58196
|
+
* handles, plus the rulers, grid, guides, marquee, and collaboration
|
|
58197
|
+
* overlays.
|
|
58035
58198
|
*/
|
|
58036
58199
|
class SlideCanvasComponent {
|
|
58037
58200
|
slide = input(undefined, /* @ts-ignore */
|
|
@@ -71265,7 +71428,6 @@ const GRID_GAP = 16;
|
|
|
71265
71428
|
* Escape or clicking the ✕ button emits `closed`.
|
|
71266
71429
|
*
|
|
71267
71430
|
* Viewer-first scope: no drag-reorder, no context menu, no section grouping.
|
|
71268
|
-
* Those features are tracked in PORTING.md.
|
|
71269
71431
|
*
|
|
71270
71432
|
* Usage:
|
|
71271
71433
|
* ```html
|
|
@@ -76833,10 +76995,9 @@ const ZOOM_MAX = 3;
|
|
|
76833
76995
|
* and Vue `PowerPointViewer.vue`.
|
|
76834
76996
|
*
|
|
76835
76997
|
* Top-level orchestrator that loads `.pptx` bytes and renders the slides with
|
|
76836
|
-
* navigation and zoom
|
|
76837
|
-
*
|
|
76838
|
-
*
|
|
76839
|
-
* per-area status live in `packages/angular/PORTING.md`.
|
|
76998
|
+
* navigation and zoom, composing the full editor (toolbar, inspector panels,
|
|
76999
|
+
* dialogs, presentation mode, collaboration, export) like its React and Vue
|
|
77000
|
+
* counterparts.
|
|
76840
77001
|
*
|
|
76841
77002
|
* Conventions vs. React/Vue:
|
|
76842
77003
|
* - React `forwardRef` handle / Vue `defineExpose` → public {@link getContent}
|
|
@@ -80258,6 +80419,8 @@ const translationsEn = {
|
|
|
80258
80419
|
'pptx.inspector.fill': 'Fill',
|
|
80259
80420
|
'pptx.inspector.line': 'Line',
|
|
80260
80421
|
'pptx.inspector.effects': 'Effects',
|
|
80422
|
+
'pptx.inspector.softEdge': 'Soft Edge',
|
|
80423
|
+
'pptx.inspector.softEdgeRadius': 'Soft Edge Radius',
|
|
80261
80424
|
'pptx.arrange.positionSize': 'Position & Size',
|
|
80262
80425
|
'pptx.arrange.lockElement': 'Lock element',
|
|
80263
80426
|
'pptx.arrange.unlockElement': 'Unlock element',
|
|
@@ -80279,6 +80442,9 @@ const translationsEn = {
|
|
|
80279
80442
|
'pptx.media.trimEndTime': 'End (mm:ss)',
|
|
80280
80443
|
'pptx.media.trimmedDuration': 'Trimmed duration',
|
|
80281
80444
|
'pptx.media.resetTrim': 'Reset trim',
|
|
80445
|
+
'pptx.media.trimErrorNegative': 'Trim times cannot be negative.',
|
|
80446
|
+
'pptx.media.trimErrorStartAfterEnd': 'Trim start must be before trim end.',
|
|
80447
|
+
'pptx.media.trimErrorBeyondDuration': 'Trim times cannot exceed the clip duration.',
|
|
80282
80448
|
'pptx.media.playback': 'Playback',
|
|
80283
80449
|
'pptx.media.volume': 'Volume',
|
|
80284
80450
|
'pptx.media.speed': 'Speed',
|
|
@@ -81513,13 +81679,18 @@ const translationsEn = {
|
|
|
81513
81679
|
'pptx.documentProperties.custom.typeNumber': 'Number',
|
|
81514
81680
|
'pptx.documentProperties.custom.typeText': 'Text',
|
|
81515
81681
|
'pptx.documentProperties.custom.typeYesNo': 'Yes or No',
|
|
81682
|
+
'pptx.documentProperties.statistics.application': 'Application',
|
|
81683
|
+
'pptx.documentProperties.statistics.appVersion': 'Application Version',
|
|
81516
81684
|
'pptx.documentProperties.statistics.elements': 'Elements',
|
|
81517
81685
|
'pptx.documentProperties.statistics.hiddenSlides': 'Hidden Slides',
|
|
81518
81686
|
'pptx.documentProperties.statistics.lastModifiedBy': 'Last Modified By',
|
|
81519
81687
|
'pptx.documentProperties.statistics.notes': 'Notes',
|
|
81520
81688
|
'pptx.documentProperties.statistics.paragraphs': 'Paragraphs',
|
|
81689
|
+
'pptx.documentProperties.statistics.presentationFormat': 'Presentation Format',
|
|
81521
81690
|
'pptx.documentProperties.statistics.revision': 'Revision',
|
|
81522
81691
|
'pptx.documentProperties.statistics.slides': 'Slides',
|
|
81692
|
+
'pptx.documentProperties.statistics.template': 'Template',
|
|
81693
|
+
'pptx.documentProperties.statistics.totalTime': 'Total Editing Time',
|
|
81523
81694
|
'pptx.documentProperties.statistics.words': 'Words',
|
|
81524
81695
|
'pptx.documentProperties.summary.category': 'Category',
|
|
81525
81696
|
'pptx.documentProperties.summary.description': 'Description',
|