pptx-angular-viewer 0.1.0 → 1.1.11
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/fesm2022/pptx-angular-viewer.mjs +16970 -463
- package/fesm2022/pptx-angular-viewer.mjs.map +1 -1
- package/package.json +49 -47
- package/pptx-angular-viewer.css +270 -0
- package/types/pptx-angular-viewer.d.ts +2044 -19
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as pptx_viewer_core from 'pptx-viewer-core';
|
|
2
|
-
import { PptxSlide, PptxTheme, PptxSlideMaster,
|
|
2
|
+
import { PptxSlide, PptxElement, PptxTheme, PptxSlideMaster, PptxTableCell, Model3DPptxElement, ZoomPptxElement, TextSegment, XmlObject, ShapeStyle } from 'pptx-viewer-core';
|
|
3
3
|
import * as _angular_core from '@angular/core';
|
|
4
|
-
import { InjectionToken, Provider } from '@angular/core';
|
|
4
|
+
import { OnInit, OnDestroy, InjectionToken, Provider } from '@angular/core';
|
|
5
|
+
import { Options } from 'html2canvas-pro';
|
|
6
|
+
import { SafeHtml } from '@angular/platform-browser';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Theme configuration types for the PowerPoint viewer.
|
|
@@ -164,6 +166,108 @@ declare const DEFAULT_FILL_COLOR = "#3b82f6";
|
|
|
164
166
|
/** Fallback shape stroke colour. */
|
|
165
167
|
declare const DEFAULT_STROKE_COLOR = "#1f2937";
|
|
166
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Pure geometry helpers for aligning and distributing selected editor elements.
|
|
171
|
+
*
|
|
172
|
+
* No Angular imports, no DOM, no side effects — only data in, data out.
|
|
173
|
+
* All inputs are treated as immutable.
|
|
174
|
+
*/
|
|
175
|
+
/** Horizontal or vertical alignment mode. */
|
|
176
|
+
type AlignMode = 'left' | 'centerH' | 'right' | 'top' | 'middle' | 'bottom';
|
|
177
|
+
/** Axis along which to distribute spacing evenly. */
|
|
178
|
+
type DistributeMode = 'horizontal' | 'vertical';
|
|
179
|
+
|
|
180
|
+
declare class EditorStateService {
|
|
181
|
+
private readonly history;
|
|
182
|
+
/** The editable slide deck (a clone of the loaded presentation). */
|
|
183
|
+
readonly slides: _angular_core.WritableSignal<readonly PptxSlide[]>;
|
|
184
|
+
/** Ids of the currently selected elements (on the active slide). */
|
|
185
|
+
readonly selectedIds: _angular_core.WritableSignal<readonly string[]>;
|
|
186
|
+
/** Whether the deck has unsaved edits. */
|
|
187
|
+
readonly dirty: _angular_core.WritableSignal<boolean>;
|
|
188
|
+
readonly canUndo: _angular_core.WritableSignal<boolean>;
|
|
189
|
+
readonly canRedo: _angular_core.WritableSignal<boolean>;
|
|
190
|
+
readonly undoLabel: _angular_core.WritableSignal<string | undefined>;
|
|
191
|
+
readonly redoLabel: _angular_core.WritableSignal<string | undefined>;
|
|
192
|
+
readonly hasSelection: _angular_core.Signal<boolean>;
|
|
193
|
+
/** Replace the editable deck (clones the source); resets selection + history. */
|
|
194
|
+
setSlides(slides: readonly PptxSlide[]): void;
|
|
195
|
+
/** Current editable slides as a fresh (cloned) array. */
|
|
196
|
+
snapshot(): readonly PptxSlide[];
|
|
197
|
+
select(ids: readonly string[]): void;
|
|
198
|
+
toggleSelect(id: string, additive: boolean): void;
|
|
199
|
+
clearSelection(): void;
|
|
200
|
+
/** Select every element on a slide. */
|
|
201
|
+
selectAll(slideIndex: number): void;
|
|
202
|
+
isSelected(id: string): boolean;
|
|
203
|
+
moveSelectedBy(slideIndex: number, dx: number, dy: number): void;
|
|
204
|
+
nudgeSelected(slideIndex: number, dirX: number, dirY: number): void;
|
|
205
|
+
setPosition(slideIndex: number, id: string, x: number, y: number): void;
|
|
206
|
+
resize(slideIndex: number, id: string, width: number, height: number): void;
|
|
207
|
+
updateElement(slideIndex: number, id: string, patch: Partial<PptxElement>): void;
|
|
208
|
+
deleteSelected(slideIndex: number): void;
|
|
209
|
+
duplicateSelected(slideIndex: number): void;
|
|
210
|
+
bringSelectedToFront(slideIndex: number): void;
|
|
211
|
+
sendSelectedToBack(slideIndex: number): void;
|
|
212
|
+
bringSelectedForward(slideIndex: number): void;
|
|
213
|
+
sendSelectedBackward(slideIndex: number): void;
|
|
214
|
+
/** Record a single history snapshot at the start of a drag/resize gesture. */
|
|
215
|
+
beginTransform(label: string): void;
|
|
216
|
+
/**
|
|
217
|
+
* Apply a live transform during a gesture WITHOUT recording history (the
|
|
218
|
+
* gesture's snapshot was taken in {@link beginTransform}). Accepts any subset
|
|
219
|
+
* of x/y/width/height.
|
|
220
|
+
*/
|
|
221
|
+
applyTransform(slideIndex: number, id: string, box: {
|
|
222
|
+
x?: number;
|
|
223
|
+
y?: number;
|
|
224
|
+
width?: number;
|
|
225
|
+
height?: number;
|
|
226
|
+
rotation?: number;
|
|
227
|
+
}): void;
|
|
228
|
+
undo(): void;
|
|
229
|
+
redo(): void;
|
|
230
|
+
/** Align the selected elements within their group bounds (one history entry). */
|
|
231
|
+
alignSelected(slideIndex: number, mode: AlignMode): void;
|
|
232
|
+
/** Evenly distribute the selected elements along an axis (one history entry). */
|
|
233
|
+
distributeSelected(slideIndex: number, mode: DistributeMode): void;
|
|
234
|
+
private applyPositionMap;
|
|
235
|
+
/** Group the selected elements into a single group element. */
|
|
236
|
+
groupSelected(slideIndex: number): void;
|
|
237
|
+
/** Ungroup the single selected group back into its children. */
|
|
238
|
+
ungroupSelected(slideIndex: number): void;
|
|
239
|
+
private clipboard;
|
|
240
|
+
/** Whether the clipboard holds copied elements (enables paste). */
|
|
241
|
+
readonly hasClipboard: _angular_core.WritableSignal<boolean>;
|
|
242
|
+
/** Copy the selected elements to the in-memory clipboard. */
|
|
243
|
+
copySelected(slideIndex: number): void;
|
|
244
|
+
/** Copy then delete the selected elements. */
|
|
245
|
+
cutSelected(slideIndex: number): void;
|
|
246
|
+
/** Paste clipboard elements onto a slide (offset + fresh ids) and select them. */
|
|
247
|
+
paste(slideIndex: number): void;
|
|
248
|
+
/** Append a new element to a slide (records history) and select it. */
|
|
249
|
+
addElement(slideIndex: number, element: PptxElement): void;
|
|
250
|
+
/** Patch slide-level properties (background, notes, …); one history entry. */
|
|
251
|
+
updateSlide(slideIndex: number, patch: Partial<PptxSlide>): void;
|
|
252
|
+
/** Insert a blank slide after `afterIndex` (records history). */
|
|
253
|
+
addSlide(afterIndex: number): void;
|
|
254
|
+
/** Delete a slide (keeps at least one; records history). */
|
|
255
|
+
deleteSlide(index: number): void;
|
|
256
|
+
/** Duplicate a slide, inserting the copy after it (records history). */
|
|
257
|
+
duplicateSlide(index: number): void;
|
|
258
|
+
/** Reorder a slide from `from` to `to` (records history). */
|
|
259
|
+
moveSlide(from: number, to: number): void;
|
|
260
|
+
private renumber;
|
|
261
|
+
private zOrder;
|
|
262
|
+
private commit;
|
|
263
|
+
private syncHistory;
|
|
264
|
+
private clone;
|
|
265
|
+
private newId;
|
|
266
|
+
private idCounter;
|
|
267
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorStateService, never>;
|
|
268
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EditorStateService>;
|
|
269
|
+
}
|
|
270
|
+
|
|
167
271
|
/**
|
|
168
272
|
* `LoadContentService` — Angular port of the React `useLoadContent` hook and
|
|
169
273
|
* the Vue `useLoadContent` composable.
|
|
@@ -205,8 +309,13 @@ declare class LoadContentService {
|
|
|
205
309
|
private renderToken;
|
|
206
310
|
private activeBlobUrls;
|
|
207
311
|
constructor();
|
|
208
|
-
/** Serialise the current presentation back to `.pptx` bytes. */
|
|
312
|
+
/** Serialise the current (loaded) presentation back to `.pptx` bytes. */
|
|
209
313
|
getContent(): Promise<Uint8Array>;
|
|
314
|
+
/**
|
|
315
|
+
* Serialise an explicit set of slides back to `.pptx` bytes (e.g. the
|
|
316
|
+
* editor's edited deck) using the loaded presentation's handler.
|
|
317
|
+
*/
|
|
318
|
+
saveSlides(slides: readonly PptxSlide[]): Promise<Uint8Array>;
|
|
210
319
|
/** Parse the supplied `.pptx` bytes into the reactive signals. */
|
|
211
320
|
load(raw: Uint8Array | ArrayBuffer | null | undefined): Promise<void>;
|
|
212
321
|
private disposeHandler;
|
|
@@ -250,34 +359,160 @@ declare class PowerPointViewerComponent {
|
|
|
250
359
|
/** Fired when the in-memory content changes after edits. (Editing not yet ported.) */
|
|
251
360
|
readonly contentChange: _angular_core.OutputEmitterRef<Uint8Array<ArrayBufferLike>>;
|
|
252
361
|
protected readonly loader: LoadContentService;
|
|
362
|
+
private readonly exportSvc;
|
|
363
|
+
protected readonly editor: EditorStateService;
|
|
364
|
+
/** The `<main>` host; used to locate the live `.pptx-ng-canvas-stage`. */
|
|
365
|
+
private readonly mainEl;
|
|
366
|
+
/** True while a PNG/PDF export is in progress (disables the buttons). */
|
|
367
|
+
protected readonly exporting: _angular_core.WritableSignal<boolean>;
|
|
253
368
|
protected readonly activeSlideIndex: _angular_core.WritableSignal<number>;
|
|
369
|
+
/** Slides to display: the editable deck when `canEdit`, else the loaded deck. */
|
|
370
|
+
protected readonly displaySlides: _angular_core.Signal<readonly pptx_viewer_core.PptxSlide[]>;
|
|
254
371
|
protected readonly slideCount: _angular_core.Signal<number>;
|
|
255
372
|
protected readonly activeSlide: _angular_core.Signal<pptx_viewer_core.PptxSlide>;
|
|
256
373
|
protected readonly rootStyle: _angular_core.Signal<Record<string, string>>;
|
|
257
374
|
protected readonly zoom: _angular_core.WritableSignal<number>;
|
|
258
375
|
protected readonly zoomPercent: _angular_core.Signal<number>;
|
|
376
|
+
/** Fullscreen presentation-mode overlay visibility. */
|
|
377
|
+
protected readonly presenting: _angular_core.WritableSignal<boolean>;
|
|
378
|
+
/** Slide-sorter grid overlay visibility. */
|
|
379
|
+
protected readonly showSorter: _angular_core.WritableSignal<boolean>;
|
|
380
|
+
/** Speaker-notes strip visibility. */
|
|
381
|
+
protected readonly showNotes: _angular_core.WritableSignal<boolean>;
|
|
382
|
+
/** Find-in-slides bar visibility. */
|
|
383
|
+
protected readonly showFind: _angular_core.WritableSignal<boolean>;
|
|
384
|
+
/** Open editor context-menu position (client coords), or null. */
|
|
385
|
+
protected readonly contextMenuPos: _angular_core.WritableSignal<{
|
|
386
|
+
x: number;
|
|
387
|
+
y: number;
|
|
388
|
+
} | null>;
|
|
389
|
+
/** Id of the element being inline text-edited, or null. */
|
|
390
|
+
protected readonly editingId: _angular_core.WritableSignal<string | null>;
|
|
391
|
+
/** Notes for the active slide, if any. */
|
|
392
|
+
protected readonly activeNotes: _angular_core.Signal<string>;
|
|
393
|
+
/**
|
|
394
|
+
* Stable, always-truthy key for the slide-properties form. Changes only when
|
|
395
|
+
* the active slide changes, so the `@if` recreates (and reseeds) the
|
|
396
|
+
* uncontrolled notes/background inputs on navigation — but never mid-typing.
|
|
397
|
+
* String-prefixed so slide index 0 stays truthy under `@if (…; as key)`.
|
|
398
|
+
*/
|
|
399
|
+
protected readonly slidePropsKey: _angular_core.Signal<string>;
|
|
400
|
+
/** The single selected element on the active slide (for the inspector). */
|
|
401
|
+
protected readonly selectedElement: _angular_core.Signal<PptxElement | null>;
|
|
259
402
|
constructor();
|
|
260
|
-
/**
|
|
403
|
+
/**
|
|
404
|
+
* Serialise the current presentation to `.pptx` bytes (imperative handle).
|
|
405
|
+
* When editing, this serialises the editor's edited deck so changes persist.
|
|
406
|
+
*/
|
|
261
407
|
getContent(): Promise<Uint8Array>;
|
|
262
408
|
goTo(index: number): void;
|
|
263
409
|
goPrev(): void;
|
|
264
410
|
goNext(): void;
|
|
411
|
+
/** Horizontal-swipe tracking start coordinates (touch begins on the canvas). */
|
|
412
|
+
private swipeStartX;
|
|
413
|
+
private swipeStartY;
|
|
414
|
+
/**
|
|
415
|
+
* Begin tracking a horizontal swipe for slide navigation.
|
|
416
|
+
*
|
|
417
|
+
* To disambiguate a navigation swipe from an element drag, swipe-nav is only
|
|
418
|
+
* armed when editing is off (`!canEdit()`). When `canEdit()` is true,
|
|
419
|
+
* pointer/touch gestures belong to element manipulation (move/resize/rotate),
|
|
420
|
+
* so we never hijack them. The large ‹ › buttons remain available in all
|
|
421
|
+
* modes for explicit navigation.
|
|
422
|
+
*/
|
|
423
|
+
onMainTouchStart(event: TouchEvent): void;
|
|
424
|
+
/**
|
|
425
|
+
* Complete a swipe: a predominantly horizontal drag of at least the threshold
|
|
426
|
+
* navigates to the previous (swipe right) or next (swipe left) slide.
|
|
427
|
+
*/
|
|
428
|
+
onMainTouchEnd(event: TouchEvent): void;
|
|
265
429
|
zoomIn(): void;
|
|
266
430
|
zoomOut(): void;
|
|
267
431
|
zoomReset(): void;
|
|
432
|
+
/** Open the fullscreen presentation overlay from the current slide. */
|
|
433
|
+
present(): void;
|
|
434
|
+
/** Toggle the speaker-notes strip. */
|
|
435
|
+
toggleNotes(): void;
|
|
436
|
+
/**
|
|
437
|
+
* Handle an element press from the canvas. Additive (Shift/Ctrl) toggles
|
|
438
|
+
* membership; a plain press selects the element (keeping it selected if it
|
|
439
|
+
* already was, so a subsequent drag works).
|
|
440
|
+
*/
|
|
441
|
+
onElementSelect(event: {
|
|
442
|
+
id: string;
|
|
443
|
+
additive: boolean;
|
|
444
|
+
}): void;
|
|
445
|
+
/** Right-click: select the element under the cursor and open the menu. */
|
|
446
|
+
onContextMenu(event: {
|
|
447
|
+
id: string | null;
|
|
448
|
+
x: number;
|
|
449
|
+
y: number;
|
|
450
|
+
}): void;
|
|
451
|
+
/** Update the active slide's background colour. */
|
|
452
|
+
onSlideBackground(event: Event): void;
|
|
453
|
+
/** Update the active slide's speaker notes. */
|
|
454
|
+
onSlideNotes(event: Event): void;
|
|
455
|
+
/** Commit an inline text edit: replace the element's text (one history entry). */
|
|
456
|
+
onTextCommit(event: {
|
|
457
|
+
id: string;
|
|
458
|
+
text: string;
|
|
459
|
+
}): void;
|
|
460
|
+
/**
|
|
461
|
+
* Editing keyboard shortcuts (only when `canEdit` and not typing in a
|
|
462
|
+
* field or presenting): Delete, Ctrl/Cmd+Z/Y undo/redo, Ctrl/Cmd+D
|
|
463
|
+
* duplicate, arrow-key nudge (Shift = ×10).
|
|
464
|
+
*/
|
|
465
|
+
onKeyDown(event: KeyboardEvent): void;
|
|
466
|
+
/** Resolve the live slide-stage element within `<main>`. */
|
|
467
|
+
private stageElement;
|
|
468
|
+
/** Export the current slide as a PNG download. */
|
|
469
|
+
exportPng(): Promise<void>;
|
|
470
|
+
/**
|
|
471
|
+
* Export every slide to a multi-page PDF. Each slide is made the live stage,
|
|
472
|
+
* given a render tick to settle, captured to a canvas, then the original
|
|
473
|
+
* slide is restored.
|
|
474
|
+
*/
|
|
475
|
+
exportPdf(): Promise<void>;
|
|
268
476
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PowerPointViewerComponent, never>;
|
|
269
477
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PowerPointViewerComponent, "pptx-viewer", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "canEdit": { "alias": "canEdit"; "required": false; "isSignal": true; }; "class": { "alias": "class"; "required": false; "isSignal": true; }; "theme": { "alias": "theme"; "required": false; "isSignal": true; }; "collaboration": { "alias": "collaboration"; "required": false; "isSignal": true; }; }, { "activeSlideChange": "activeSlideChange"; "dirtyChange": "dirtyChange"; "contentChange": "contentChange"; }, never, never, true, never>;
|
|
270
478
|
}
|
|
271
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Pure geometry for interactive element drag/resize.
|
|
482
|
+
*
|
|
483
|
+
* Stage-space deltas in, a new bounding box out — no DOM, no framework, so the
|
|
484
|
+
* SlideCanvas pointer wiring stays thin and the maths is unit-testable.
|
|
485
|
+
*/
|
|
486
|
+
/** The eight resize-handle positions around a selection box. */
|
|
487
|
+
type ResizeHandle = 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w';
|
|
488
|
+
/** An axis-aligned box in stage (slide) coordinates. */
|
|
489
|
+
interface Box {
|
|
490
|
+
x: number;
|
|
491
|
+
y: number;
|
|
492
|
+
width: number;
|
|
493
|
+
height: number;
|
|
494
|
+
}
|
|
495
|
+
/** All handles, in render order (corners + edge midpoints). */
|
|
496
|
+
declare const RESIZE_HANDLES: readonly ResizeHandle[];
|
|
497
|
+
/** Translate a box by a stage-space delta. */
|
|
498
|
+
declare function applyMove(start: Box, dx: number, dy: number): Box;
|
|
499
|
+
/**
|
|
500
|
+
* Resize `start` by dragging `handle` with a stage-space delta, clamping to
|
|
501
|
+
* `min`. When clamping at the min size, the edge opposite the dragged handle
|
|
502
|
+
* stays fixed.
|
|
503
|
+
*/
|
|
504
|
+
declare function applyResize(start: Box, handle: ResizeHandle, dx: number, dy: number, min?: number): Box;
|
|
505
|
+
|
|
272
506
|
/**
|
|
273
507
|
* Basic, framework-agnostic style computation for slide elements, returning
|
|
274
508
|
* `[ngStyle]`-compatible maps.
|
|
275
509
|
*
|
|
276
510
|
* This mirrors the Vue package's `element-style.ts` (and a deliberately small
|
|
277
511
|
* subset of the React `viewer/utils/*` style layer). It is enough to position
|
|
278
|
-
* and paint text boxes, basic preset shapes, and
|
|
279
|
-
* (
|
|
280
|
-
*
|
|
512
|
+
* and paint text boxes, basic preset shapes, images, and image/gradient fills
|
|
513
|
+
* (the latter via the parser's prebuilt CSS gradient string). Advanced visuals
|
|
514
|
+
* (the structured gradient builder, pattern fills, custom geometry clip-paths,
|
|
515
|
+
* shadows, 3D, image effects, text warp) are tracked in PORTING.md.
|
|
281
516
|
*
|
|
282
517
|
* Long term the *logic* here is a shared-extraction candidate — only the
|
|
283
518
|
* return type (CSS map shape) differs per framework — so a future refactor
|
|
@@ -303,30 +538,174 @@ declare function getTextBlockStyle(el: PptxElement): StyleMap;
|
|
|
303
538
|
/** Resolve a displayable image source for picture/image/media poster frames. */
|
|
304
539
|
declare function getImageSrc(el: PptxElement, mediaDataUrls: Map<string, string>): string | undefined;
|
|
305
540
|
|
|
541
|
+
/**
|
|
542
|
+
* A single guide line to draw.
|
|
543
|
+
*
|
|
544
|
+
* `axis: 'x'` → a vertical line at x = `pos`, spanning y ∈ [start, end].
|
|
545
|
+
* `axis: 'y'` → a horizontal line at y = `pos`, spanning x ∈ [start, end].
|
|
546
|
+
*/
|
|
547
|
+
interface SnapGuide {
|
|
548
|
+
axis: 'x' | 'y';
|
|
549
|
+
/** The fixed coordinate of the line on its own axis. */
|
|
550
|
+
pos: number;
|
|
551
|
+
/** Start of the line along the perpendicular axis. */
|
|
552
|
+
start: number;
|
|
553
|
+
/** End of the line along the perpendicular axis. */
|
|
554
|
+
end: number;
|
|
555
|
+
}
|
|
556
|
+
|
|
306
557
|
/**
|
|
307
558
|
* SlideCanvasComponent — Angular port of the React `SlideCanvas.tsx` and Vue
|
|
308
|
-
* `SlideCanvas.vue
|
|
559
|
+
* `SlideCanvas.vue`.
|
|
309
560
|
*
|
|
310
561
|
* Renders the active slide as a fixed-size stage scaled by `zoom`, with each
|
|
311
|
-
* element absolutely positioned.
|
|
312
|
-
*
|
|
313
|
-
*
|
|
562
|
+
* element absolutely positioned. When `editable`, supports click-to-select
|
|
563
|
+
* (event delegation), selection outlines, and pointer drag-to-move / resize
|
|
564
|
+
* handles. Rulers, grid, guides, marquee, and collaboration overlays are
|
|
565
|
+
* tracked in PORTING.md.
|
|
314
566
|
*/
|
|
315
567
|
declare class SlideCanvasComponent {
|
|
316
568
|
readonly slide: _angular_core.InputSignal<PptxSlide | undefined>;
|
|
317
569
|
readonly canvasSize: _angular_core.InputSignal<CanvasSize>;
|
|
318
570
|
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
319
571
|
readonly zoom: _angular_core.InputSignal<number>;
|
|
320
|
-
|
|
572
|
+
/** When true, elements are selectable and drag/resize handles are shown. */
|
|
573
|
+
readonly editable: _angular_core.InputSignal<boolean>;
|
|
574
|
+
/** Ids of currently-selected elements (drawn with a selection outline). */
|
|
575
|
+
readonly selectedIds: _angular_core.InputSignal<readonly string[]>;
|
|
576
|
+
/** Id of the element currently being text-edited inline (or null). */
|
|
577
|
+
readonly editingId: _angular_core.InputSignal<string | null>;
|
|
578
|
+
/** Emitted when an element is pointer-pressed (with the additive modifier). */
|
|
579
|
+
readonly elementSelect: _angular_core.OutputEmitterRef<{
|
|
580
|
+
id: string;
|
|
581
|
+
additive: boolean;
|
|
582
|
+
}>;
|
|
583
|
+
/** Emitted when empty stage space is pressed (deselect). */
|
|
584
|
+
readonly backgroundClick: _angular_core.OutputEmitterRef<void>;
|
|
585
|
+
/** Emitted once when a drag/resize gesture actually starts moving. */
|
|
586
|
+
readonly transformStart: _angular_core.OutputEmitterRef<{
|
|
587
|
+
id: string;
|
|
588
|
+
label: string;
|
|
589
|
+
}>;
|
|
590
|
+
/** Emitted on each pointer move during a gesture with the new box. */
|
|
591
|
+
readonly transformUpdate: _angular_core.OutputEmitterRef<{
|
|
592
|
+
id: string;
|
|
593
|
+
box: Box;
|
|
594
|
+
}>;
|
|
595
|
+
/** Emitted on right-click with the element under the cursor (or null). */
|
|
596
|
+
readonly contextMenu: _angular_core.OutputEmitterRef<{
|
|
597
|
+
id: string | null;
|
|
598
|
+
x: number;
|
|
599
|
+
y: number;
|
|
600
|
+
}>;
|
|
601
|
+
/** Emitted on double-click of a text-bearing element to begin inline edit. */
|
|
602
|
+
readonly textEditStart: _angular_core.OutputEmitterRef<{
|
|
603
|
+
id: string;
|
|
604
|
+
}>;
|
|
605
|
+
/** Emitted with the new text when an inline edit commits. */
|
|
606
|
+
readonly textCommit: _angular_core.OutputEmitterRef<{
|
|
607
|
+
id: string;
|
|
608
|
+
text: string;
|
|
609
|
+
}>;
|
|
610
|
+
/** Emitted when an inline edit is cancelled (Escape). */
|
|
611
|
+
readonly textCancel: _angular_core.OutputEmitterRef<void>;
|
|
612
|
+
/** Emitted during a rotate gesture with the new rotation (degrees). */
|
|
613
|
+
readonly rotateUpdate: _angular_core.OutputEmitterRef<{
|
|
614
|
+
id: string;
|
|
615
|
+
rotation: number;
|
|
616
|
+
}>;
|
|
617
|
+
/** Emitted on marquee release with the ids of enclosed/overlapping elements. */
|
|
618
|
+
readonly marqueeSelect: _angular_core.OutputEmitterRef<string[]>;
|
|
619
|
+
private drag;
|
|
620
|
+
private editCancelled;
|
|
621
|
+
private marquee;
|
|
622
|
+
/** Live marquee rectangle (stage coords) while rubber-band selecting. */
|
|
623
|
+
readonly marqueeRect: _angular_core.WritableSignal<{
|
|
624
|
+
x: number;
|
|
625
|
+
y: number;
|
|
626
|
+
width: number;
|
|
627
|
+
height: number;
|
|
628
|
+
} | null>;
|
|
629
|
+
/** Live alignment-snap guide lines (stage coords) during a move. */
|
|
630
|
+
readonly snapGuides: _angular_core.WritableSignal<readonly SnapGuide[]>;
|
|
631
|
+
private readonly textEditor;
|
|
632
|
+
private readonly stageRef;
|
|
633
|
+
/** The editing id we've already initialised the textarea for, to avoid re-seeding its value mid-edit. */
|
|
634
|
+
private seededEditId;
|
|
635
|
+
/** Last-tap timestamp + element id, for synthetic double-tap detection on touch. */
|
|
636
|
+
private lastTap;
|
|
637
|
+
constructor();
|
|
638
|
+
readonly elements: _angular_core.Signal<PptxElement[]>;
|
|
639
|
+
/** Bounding boxes (stage coords) for the selected elements. */
|
|
640
|
+
readonly selectionBoxes: _angular_core.Signal<{
|
|
641
|
+
id: string;
|
|
642
|
+
x: number;
|
|
643
|
+
y: number;
|
|
644
|
+
width: number;
|
|
645
|
+
height: number;
|
|
646
|
+
}[]>;
|
|
647
|
+
/** The single selected element's box, or null when 0 or >1 are selected. */
|
|
648
|
+
readonly singleSelected: _angular_core.Signal<(Box & {
|
|
649
|
+
id: string;
|
|
650
|
+
}) | null>;
|
|
651
|
+
/** Resize-handle render boxes (stage coords) for the single selection. */
|
|
652
|
+
readonly handleBoxes: _angular_core.Signal<{
|
|
653
|
+
handle: ResizeHandle;
|
|
654
|
+
left: number;
|
|
655
|
+
top: number;
|
|
656
|
+
size: number;
|
|
657
|
+
cursor: string;
|
|
658
|
+
}[]>;
|
|
659
|
+
/** Rotation-handle box (stage coords) above the single selection, or null. */
|
|
660
|
+
readonly rotateHandle: _angular_core.Signal<{
|
|
661
|
+
left: number;
|
|
662
|
+
top: number;
|
|
663
|
+
size: number;
|
|
664
|
+
} | null>;
|
|
665
|
+
onStagePointerDown(event: PointerEvent): void;
|
|
666
|
+
/** Box + current plain text for the element under inline edit, or null. */
|
|
667
|
+
readonly editingBox: _angular_core.Signal<{
|
|
668
|
+
id: string;
|
|
669
|
+
x: number;
|
|
670
|
+
y: number;
|
|
671
|
+
width: number;
|
|
672
|
+
height: number;
|
|
673
|
+
text: string;
|
|
674
|
+
} | null>;
|
|
675
|
+
onDblClick(event: MouseEvent): void;
|
|
676
|
+
onEditorKeydown(event: KeyboardEvent): void;
|
|
677
|
+
commitText(event: Event, id: string): void;
|
|
678
|
+
onContextMenu(event: MouseEvent): void;
|
|
679
|
+
onHandlePointerDown(event: PointerEvent, handle: ResizeHandle): void;
|
|
680
|
+
onRotatePointerDown(event: PointerEvent): void;
|
|
681
|
+
onPointerMove(event: PointerEvent): void;
|
|
682
|
+
onPointerUp(): void;
|
|
321
683
|
readonly wrapperStyle: _angular_core.Signal<StyleMap>;
|
|
322
684
|
readonly stageStyle: _angular_core.Signal<StyleMap>;
|
|
323
685
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SlideCanvasComponent, never>;
|
|
324
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlideCanvasComponent, "pptx-slide-canvas", never, { "slide": { "alias": "slide"; "required": false; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
686
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlideCanvasComponent, "pptx-slide-canvas", never, { "slide": { "alias": "slide"; "required": false; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "selectedIds": { "alias": "selectedIds"; "required": false; "isSignal": true; }; "editingId": { "alias": "editingId"; "required": false; "isSignal": true; }; }, { "elementSelect": "elementSelect"; "backgroundClick": "backgroundClick"; "transformStart": "transformStart"; "transformUpdate": "transformUpdate"; "contextMenu": "contextMenu"; "textEditStart": "textEditStart"; "textCommit": "textCommit"; "textCancel": "textCancel"; "rotateUpdate": "rotateUpdate"; "marqueeSelect": "marqueeSelect"; }, never, never, true, never>;
|
|
325
687
|
}
|
|
326
688
|
|
|
327
689
|
interface TextRun {
|
|
328
690
|
text: string;
|
|
329
691
|
style: StyleMap;
|
|
692
|
+
/** Safe `href` when this run carries a renderable hyperlink. */
|
|
693
|
+
href?: string;
|
|
694
|
+
/** Hyperlink tooltip / title text. */
|
|
695
|
+
tooltip?: string;
|
|
696
|
+
/** Parsed OMML for an inline equation run (rendered as MathML). */
|
|
697
|
+
equationXml?: Record<string, unknown>;
|
|
698
|
+
/** Optional equation number for numbered equations. */
|
|
699
|
+
equationNumber?: string;
|
|
700
|
+
}
|
|
701
|
+
interface Paragraph {
|
|
702
|
+
runs: TextRun[];
|
|
703
|
+
/** Bullet / number marker text, when this paragraph is a list item. */
|
|
704
|
+
bulletMarker?: string;
|
|
705
|
+
/** `[ngStyle]` map for the bullet marker (colour / font). */
|
|
706
|
+
bulletStyle: StyleMap;
|
|
707
|
+
/** Left indent in px derived from the paragraph outline level. */
|
|
708
|
+
indentPx: number;
|
|
330
709
|
}
|
|
331
710
|
/**
|
|
332
711
|
* ElementRendererComponent — Angular port of the React `ElementRenderer.tsx`
|
|
@@ -334,14 +713,21 @@ interface TextRun {
|
|
|
334
713
|
*
|
|
335
714
|
* Renders a single slide element by its `type` discriminant (viewer-first
|
|
336
715
|
* subset):
|
|
337
|
-
* - `text` / `shape` → positioned box with fill/stroke + rich text
|
|
716
|
+
* - `text` / `shape` → positioned box with fill/stroke + rich text + effects
|
|
717
|
+
* - `connector` → SVG straight/bent/curved connector
|
|
718
|
+
* - `chart` → inline-SVG chart (bar/line/area/pie/scatter)
|
|
719
|
+
* - `table` → HTML `<table>`
|
|
720
|
+
* - `smartArt` → SVG drawing-shapes / node-text fallback
|
|
721
|
+
* - `ink` → SVG ink strokes
|
|
722
|
+
* - `ole` → embedded-object preview / icon
|
|
723
|
+
* - `model3d` → poster / placeholder (no three.js)
|
|
724
|
+
* - `zoom` → slide/section zoom thumbnail
|
|
338
725
|
* - `picture` / `image` → `<img>`
|
|
339
726
|
* - `media` → poster frame (`<img>`) — playback TODO
|
|
340
727
|
* - `group` → recursive children (self-referencing selector)
|
|
341
728
|
* - everything else → labelled placeholder (TODO, see PORTING.md)
|
|
342
729
|
*
|
|
343
|
-
* Interaction (selection, resize, inline editing)
|
|
344
|
-
* SmartArt, ink, OLE, and 3D are not yet ported.
|
|
730
|
+
* Interaction (selection, resize, inline editing) is not yet ported.
|
|
345
731
|
*/
|
|
346
732
|
declare class ElementRendererComponent {
|
|
347
733
|
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
@@ -354,7 +740,7 @@ declare class ElementRendererComponent {
|
|
|
354
740
|
readonly children: _angular_core.Signal<PptxElement[]>;
|
|
355
741
|
readonly isShapeLike: _angular_core.Signal<boolean>;
|
|
356
742
|
readonly isImageLike: _angular_core.Signal<boolean>;
|
|
357
|
-
readonly paragraphs: _angular_core.Signal<
|
|
743
|
+
readonly paragraphs: _angular_core.Signal<Paragraph[]>;
|
|
358
744
|
readonly hasText: _angular_core.Signal<boolean>;
|
|
359
745
|
readonly placeholderLabel: _angular_core.Signal<string>;
|
|
360
746
|
private segmentStyle;
|
|
@@ -362,6 +748,1645 @@ declare class ElementRendererComponent {
|
|
|
362
748
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ElementRendererComponent, "pptx-element-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
363
749
|
}
|
|
364
750
|
|
|
751
|
+
/**
|
|
752
|
+
* Pure, framework-agnostic helpers for rendering connector elements.
|
|
753
|
+
*
|
|
754
|
+
* These are extracted from the component so they can be unit-tested without
|
|
755
|
+
* the Angular compiler or TestBed (the vitest setup for this package is
|
|
756
|
+
* plain happy-dom, no Analog plugin yet — see PORTING.md).
|
|
757
|
+
*
|
|
758
|
+
* Mirror of the Vue `ConnectorRenderer.vue` helpers and the React
|
|
759
|
+
* `ConnectorElementRenderer` path logic (basic straight-line subset).
|
|
760
|
+
*/
|
|
761
|
+
|
|
762
|
+
/** Shape description for a SVG `<marker>` element (viewBox 0 0 10 10). */
|
|
763
|
+
interface MarkerShape {
|
|
764
|
+
shape: 'path' | 'circle';
|
|
765
|
+
d?: string;
|
|
766
|
+
}
|
|
767
|
+
/** All derived connector rendering values, computed from a `PptxElement`. */
|
|
768
|
+
interface ConnectorGeometry {
|
|
769
|
+
strokeWidth: number;
|
|
770
|
+
strokeColor: string;
|
|
771
|
+
strokeOpacity: number;
|
|
772
|
+
dashArray: string | undefined;
|
|
773
|
+
/** SVG width (clamped to at least 1). */
|
|
774
|
+
svgW: number;
|
|
775
|
+
/** SVG height (clamped to at least 1). */
|
|
776
|
+
svgH: number;
|
|
777
|
+
x1: number;
|
|
778
|
+
y1: number;
|
|
779
|
+
x2: number;
|
|
780
|
+
y2: number;
|
|
781
|
+
/**
|
|
782
|
+
* SVG `path` data for bent / curved connectors. `undefined` for straight
|
|
783
|
+
* connectors, in which case the component renders a `<line>` from
|
|
784
|
+
* `(x1,y1)` to `(x2,y2)` instead.
|
|
785
|
+
*/
|
|
786
|
+
pathD: string | undefined;
|
|
787
|
+
startMarkerId: string;
|
|
788
|
+
endMarkerId: string;
|
|
789
|
+
startMarker: MarkerShape | null;
|
|
790
|
+
endMarker: MarkerShape | null;
|
|
791
|
+
startMarkerRef: string | null;
|
|
792
|
+
endMarkerRef: string | null;
|
|
793
|
+
/** Inline `style` string for the wrapper `<div>`. */
|
|
794
|
+
wrapperStyle: string;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* ConnectorRendererComponent — Angular port of the Vue `ConnectorRenderer.vue`
|
|
799
|
+
* (and the React `ConnectorElementRenderer`, basic subset).
|
|
800
|
+
*
|
|
801
|
+
* Renders straight connectors/lines as an inline SVG spanning the element's
|
|
802
|
+
* bounding box, with stroke colour/width/dash and start/end arrowheads. Flip
|
|
803
|
+
* is baked into the endpoints (not a CSS transform) so arrowheads point the
|
|
804
|
+
* right way.
|
|
805
|
+
*
|
|
806
|
+
* All path/style math lives in `connector-path.ts` (pure TS, no Angular
|
|
807
|
+
* dependency) so it can be unit-tested without TestBed.
|
|
808
|
+
*
|
|
809
|
+
* Not yet ported (TODO, see PORTING.md): bent/curved connector routing
|
|
810
|
+
* (`getConnectorPathGeometry`), compound lines, connector text overlay, line
|
|
811
|
+
* shadows/glow. Bent/curved connectors currently fall back to a straight line.
|
|
812
|
+
*/
|
|
813
|
+
declare class ConnectorRendererComponent {
|
|
814
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
815
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
816
|
+
/** All derived geometry, recomputed on every input change. */
|
|
817
|
+
readonly geo: _angular_core.Signal<ConnectorGeometry>;
|
|
818
|
+
readonly viewBox: _angular_core.Signal<string>;
|
|
819
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConnectorRendererComponent, never>;
|
|
820
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConnectorRendererComponent, "pptx-connector-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Pure, framework-agnostic helpers for table rendering.
|
|
825
|
+
*
|
|
826
|
+
* Ported from:
|
|
827
|
+
* - packages/react/src/viewer/utils/table-render-helpers.ts (cellStyleToCss,
|
|
828
|
+
* ooxmlDashToCssBorderStyle)
|
|
829
|
+
* - packages/react/src/viewer/utils/table-render-data.tsx (row / cell
|
|
830
|
+
* view-model projection)
|
|
831
|
+
*
|
|
832
|
+
* All functions are pure (no Angular dependencies) so they can be unit-tested
|
|
833
|
+
* with plain vitest without TestBed or the Angular compiler.
|
|
834
|
+
*/
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* A single styled text run inside a cell paragraph.
|
|
838
|
+
*
|
|
839
|
+
* The `style` map is an `[ngStyle]`-compatible object derived from the cell's
|
|
840
|
+
* `PptxTableCellStyle` (bold, italic, underline, color, fontSize). When the
|
|
841
|
+
* cell has no style the map is empty ({}) and CSS inherits.
|
|
842
|
+
*
|
|
843
|
+
* `isLineBreak` is true for soft line-break runs. The template renders them
|
|
844
|
+
* as `<br>`.
|
|
845
|
+
*/
|
|
846
|
+
interface CellTextRun {
|
|
847
|
+
text: string;
|
|
848
|
+
style: StyleMap;
|
|
849
|
+
isLineBreak?: true;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* A single paragraph inside a table cell, made up of one or more `CellTextRun`s.
|
|
853
|
+
*
|
|
854
|
+
* In the current implementation each paragraph has exactly one run (styled by
|
|
855
|
+
* the cell-level `PptxTableCellStyle`). When the core later exposes per-run
|
|
856
|
+
* segments on `PptxTableCell`, additional runs per paragraph will be populated.
|
|
857
|
+
*/
|
|
858
|
+
type CellParagraph = CellTextRun[];
|
|
859
|
+
/**
|
|
860
|
+
* A flattened cell descriptor ready for template iteration. Cells flagged
|
|
861
|
+
* `hMerge` or `vMerge` are excluded; the template produces no `<td>` for
|
|
862
|
+
* them (the origin cell's colspan/rowspan expands to cover the gap).
|
|
863
|
+
*/
|
|
864
|
+
interface TableCellViewModel {
|
|
865
|
+
cell: PptxTableCell;
|
|
866
|
+
/** Resolved colspan from `gridSpan` (>= 2) or undefined. */
|
|
867
|
+
colSpan: number | undefined;
|
|
868
|
+
/** Resolved rowspan from `rowSpan` (>= 2) or undefined. */
|
|
869
|
+
rowSpan: number | undefined;
|
|
870
|
+
/** Pre-computed `[ngStyle]` map for this cell's `<td>`. */
|
|
871
|
+
tdStyle: StyleMap;
|
|
872
|
+
/**
|
|
873
|
+
* Display text — non-breaking space when the cell is empty to keep the row
|
|
874
|
+
* height. Used as fallback when `paragraphs` is empty (no text AND no style).
|
|
875
|
+
*/
|
|
876
|
+
displayText: string;
|
|
877
|
+
/**
|
|
878
|
+
* Rich-text paragraphs built from the cell's text content and cell-level
|
|
879
|
+
* style. When non-empty the template renders this instead of `displayText`.
|
|
880
|
+
* Each entry is a paragraph (array of styled runs); runs with `isLineBreak`
|
|
881
|
+
* render as `<br>`.
|
|
882
|
+
*
|
|
883
|
+
* When this array is empty (cell is completely empty + unstyled) the template
|
|
884
|
+
* falls back to rendering `displayText` (a non-breaking space) so the row
|
|
885
|
+
* retains its height.
|
|
886
|
+
*/
|
|
887
|
+
paragraphs: CellParagraph[];
|
|
888
|
+
}
|
|
889
|
+
interface TableRowViewModel {
|
|
890
|
+
rowStyle: StyleMap;
|
|
891
|
+
cells: TableCellViewModel[];
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* TableRendererComponent — Angular port of the React `renderTableFromTableData`
|
|
896
|
+
* (packages/react/src/viewer/utils/table-render-data.tsx).
|
|
897
|
+
*
|
|
898
|
+
* Renders a `<table>` from the typed `PptxTableData` structure that the core
|
|
899
|
+
* parser populates on every `TablePptxElement`. This is the viewer-first path:
|
|
900
|
+
* editing, resize overlays, and inline cell input are not yet ported.
|
|
901
|
+
*
|
|
902
|
+
* Key behaviours:
|
|
903
|
+
* - Merged cells: cells with `hMerge`/`vMerge` are skipped; the origin cell
|
|
904
|
+
* receives `[attr.colspan]`/`[attr.rowspan]` from `gridSpan`/`rowSpan`.
|
|
905
|
+
* - Column widths: a `<colgroup>` drives proportional widths from
|
|
906
|
+
* `PptxTableData.columnWidths` (0–1 fractions).
|
|
907
|
+
* - Row heights: `[ngStyle]` on `<tr>` sets an explicit pixel height when
|
|
908
|
+
* `PptxTableRow.height` is present.
|
|
909
|
+
* - Cell fill: solid `backgroundColor` or the parser's pre-built
|
|
910
|
+
* `gradientFillCss` string (gradient). Pattern fills are deferred.
|
|
911
|
+
* - Cell borders: per-edge (top/bottom/left/right) width + colour.
|
|
912
|
+
* - Cell text: rich-text paragraphs of styled `<span>` runs when the cell
|
|
913
|
+
* carries text or formatting; falls back to a non-breaking-space placeholder
|
|
914
|
+
* for empty+unstyled cells (preserves row height).
|
|
915
|
+
*
|
|
916
|
+
* Pure helpers (view-model projection, style maps) live in
|
|
917
|
+
* `table-renderer-helpers.ts` so tests can exercise them without TestBed.
|
|
918
|
+
*/
|
|
919
|
+
declare class TableRendererComponent {
|
|
920
|
+
/** The table element to render. Must be `type === 'table'`. */
|
|
921
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
922
|
+
/** Pre-computed `<col>` styles for the colgroup. */
|
|
923
|
+
readonly colStyles: _angular_core.Signal<StyleMap[]>;
|
|
924
|
+
/** Projected view-model rows with merged-cell resolution applied. */
|
|
925
|
+
readonly rows: _angular_core.Signal<TableRowViewModel[]>;
|
|
926
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableRendererComponent, never>;
|
|
927
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableRendererComponent, "pptx-table-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Pure, framework-agnostic helpers for chart rendering.
|
|
932
|
+
*
|
|
933
|
+
* Ported from:
|
|
934
|
+
* packages/react/src/viewer/utils/chart-helpers.ts (value range, Y mapping, formatting, palette)
|
|
935
|
+
* packages/react/src/viewer/utils/chart-layout.ts (plot-area layout)
|
|
936
|
+
* packages/react/src/viewer/utils/chart-pie.tsx (pie/doughnut geometry)
|
|
937
|
+
* packages/react/src/viewer/utils/chart-bar.tsx (bar rect projection)
|
|
938
|
+
* packages/react/src/viewer/utils/chart-area-line.tsx (line/area point projection)
|
|
939
|
+
* packages/react/src/viewer/utils/chart-scatter-bubble.tsx (scatter point projection)
|
|
940
|
+
*
|
|
941
|
+
* All functions here are pure TypeScript with zero Angular dependencies.
|
|
942
|
+
* The component consumes a single `ChartViewModel` that is the projection
|
|
943
|
+
* of a `ChartPptxElement` -> SVG primitives.
|
|
944
|
+
*
|
|
945
|
+
* Supported chart kinds (viewer-first):
|
|
946
|
+
* bar / column (clustered, stacked, percentStacked) -> bar rects
|
|
947
|
+
* line / line3D -> polyline + dots
|
|
948
|
+
* area / area3D -> polygon fill + polyline
|
|
949
|
+
* pie / doughnut / pie3D / ofPie -> arc paths
|
|
950
|
+
* scatter -> circle dots
|
|
951
|
+
*
|
|
952
|
+
* Deferred (fallback box rendered instead):
|
|
953
|
+
* bubble, radar, stock, waterfall, combo, surface, treemap, sunburst,
|
|
954
|
+
* funnel, boxWhisker, histogram, regionMap, bar3D (complex 3-D shading),
|
|
955
|
+
* error bars, trendlines, secondary axes, data tables.
|
|
956
|
+
*
|
|
957
|
+
* @module chart-renderer-helpers
|
|
958
|
+
*/
|
|
959
|
+
|
|
960
|
+
interface SvgRect {
|
|
961
|
+
kind: 'rect';
|
|
962
|
+
x: number;
|
|
963
|
+
y: number;
|
|
964
|
+
w: number;
|
|
965
|
+
h: number;
|
|
966
|
+
fill: string;
|
|
967
|
+
rx?: number;
|
|
968
|
+
opacity?: number;
|
|
969
|
+
}
|
|
970
|
+
interface SvgPath {
|
|
971
|
+
kind: 'path';
|
|
972
|
+
d: string;
|
|
973
|
+
fill: string;
|
|
974
|
+
stroke?: string;
|
|
975
|
+
strokeWidth?: number;
|
|
976
|
+
}
|
|
977
|
+
interface SvgPolyline {
|
|
978
|
+
kind: 'polyline';
|
|
979
|
+
points: string;
|
|
980
|
+
stroke: string;
|
|
981
|
+
strokeWidth: number;
|
|
982
|
+
fill: string;
|
|
983
|
+
opacity?: number;
|
|
984
|
+
}
|
|
985
|
+
interface SvgCircle {
|
|
986
|
+
kind: 'circle';
|
|
987
|
+
cx: number;
|
|
988
|
+
cy: number;
|
|
989
|
+
r: number;
|
|
990
|
+
fill: string;
|
|
991
|
+
opacity?: number;
|
|
992
|
+
}
|
|
993
|
+
interface SvgLine {
|
|
994
|
+
kind: 'line';
|
|
995
|
+
x1: number;
|
|
996
|
+
y1: number;
|
|
997
|
+
x2: number;
|
|
998
|
+
y2: number;
|
|
999
|
+
stroke: string;
|
|
1000
|
+
strokeWidth: number;
|
|
1001
|
+
dashArray?: string;
|
|
1002
|
+
opacity?: number;
|
|
1003
|
+
}
|
|
1004
|
+
interface SvgText {
|
|
1005
|
+
kind: 'text';
|
|
1006
|
+
x: number;
|
|
1007
|
+
y: number;
|
|
1008
|
+
text: string;
|
|
1009
|
+
fontSize: number;
|
|
1010
|
+
fill: string;
|
|
1011
|
+
textAnchor: 'start' | 'middle' | 'end';
|
|
1012
|
+
fontWeight?: 'normal' | 'bold';
|
|
1013
|
+
dominantBaseline?: string;
|
|
1014
|
+
opacity?: number;
|
|
1015
|
+
}
|
|
1016
|
+
interface SvgAreaGradient {
|
|
1017
|
+
kind: 'areaGradient';
|
|
1018
|
+
id: string;
|
|
1019
|
+
color: string;
|
|
1020
|
+
}
|
|
1021
|
+
type SvgPrimitive = SvgRect | SvgPath | SvgPolyline | SvgCircle | SvgLine | SvgText | SvgAreaGradient;
|
|
1022
|
+
interface LegendEntry {
|
|
1023
|
+
color: string;
|
|
1024
|
+
label: string;
|
|
1025
|
+
}
|
|
1026
|
+
interface ChartViewModel {
|
|
1027
|
+
svgWidth: number;
|
|
1028
|
+
svgHeight: number;
|
|
1029
|
+
title: string | undefined;
|
|
1030
|
+
titleX: number;
|
|
1031
|
+
titleY: number;
|
|
1032
|
+
gridlines: SvgLine[];
|
|
1033
|
+
axisLabels: SvgText[];
|
|
1034
|
+
zeroLine: SvgLine | undefined;
|
|
1035
|
+
categoryLabels: SvgText[];
|
|
1036
|
+
primitives: SvgPrimitive[];
|
|
1037
|
+
dataLabels: SvgText[];
|
|
1038
|
+
legend: LegendEntry[];
|
|
1039
|
+
legendX: number;
|
|
1040
|
+
legendY: number;
|
|
1041
|
+
legendAnchor: 'start' | 'middle' | 'end';
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
declare class ChartRendererComponent {
|
|
1045
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1046
|
+
readonly vm: _angular_core.Signal<ChartViewModel>;
|
|
1047
|
+
readonly viewBox: _angular_core.Signal<string>;
|
|
1048
|
+
readonly swatchSize = 10;
|
|
1049
|
+
legendTransform(index: number): string;
|
|
1050
|
+
asRect(p: SvgPrimitive): SvgRect;
|
|
1051
|
+
asPath(p: SvgPrimitive): SvgPath;
|
|
1052
|
+
asPolyline(p: SvgPrimitive): SvgPolyline;
|
|
1053
|
+
asCircle(p: SvgPrimitive): SvgCircle;
|
|
1054
|
+
asLine(p: SvgPrimitive): SvgLine;
|
|
1055
|
+
asText(p: SvgPrimitive): SvgText;
|
|
1056
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ChartRendererComponent, never>;
|
|
1057
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ChartRendererComponent, "pptx-chart-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Pure TypeScript SmartArt family layout engines.
|
|
1062
|
+
*
|
|
1063
|
+
* Computes node box positions for the four core SmartArt families so the
|
|
1064
|
+
* Angular `SmartArtRendererComponent` can lay out nodes when no explicit
|
|
1065
|
+
* drawing-shapes are present.
|
|
1066
|
+
*
|
|
1067
|
+
* No Angular imports — all exports are plain TypeScript so they can be
|
|
1068
|
+
* unit-tested with vitest without TestBed or the Angular compiler.
|
|
1069
|
+
*
|
|
1070
|
+
* Geometry ported from the React renderers:
|
|
1071
|
+
* packages/react/src/viewer/components/elements/smartart-layout-renderers.tsx
|
|
1072
|
+
* packages/react/src/viewer/components/elements/smartart-renderer-hierarchy.tsx
|
|
1073
|
+
* packages/react/src/viewer/utils/smartart-helpers.tsx
|
|
1074
|
+
*/
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* A positioned node box ready to be rendered as `<rect>` + `<text>` in an SVG.
|
|
1078
|
+
*/
|
|
1079
|
+
interface PositionedNode {
|
|
1080
|
+
/** Original node id from `PptxSmartArtNode`. */
|
|
1081
|
+
id: string;
|
|
1082
|
+
/** Display text (may be truncated by the caller). */
|
|
1083
|
+
text: string;
|
|
1084
|
+
/** Left edge (SVG user units). */
|
|
1085
|
+
x: number;
|
|
1086
|
+
/** Top edge (SVG user units). */
|
|
1087
|
+
y: number;
|
|
1088
|
+
/** Box width (SVG user units). */
|
|
1089
|
+
w: number;
|
|
1090
|
+
/** Box height (SVG user units). */
|
|
1091
|
+
h: number;
|
|
1092
|
+
/**
|
|
1093
|
+
* Zero-based tree depth / band index.
|
|
1094
|
+
* For flat families (list, process, cycle) all nodes are at level 0.
|
|
1095
|
+
*/
|
|
1096
|
+
level: number;
|
|
1097
|
+
/**
|
|
1098
|
+
* Node radius — only set for cycle nodes (rendered as `<circle>`).
|
|
1099
|
+
* When defined the caller should render a circle at (x + r, y + r) instead
|
|
1100
|
+
* of a rect.
|
|
1101
|
+
*/
|
|
1102
|
+
r?: number;
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* A connector segment rendered as `<line x1 y1 x2 y2 />` or SVG `<path>`.
|
|
1106
|
+
*/
|
|
1107
|
+
interface ConnectorSegment {
|
|
1108
|
+
x1: number;
|
|
1109
|
+
y1: number;
|
|
1110
|
+
x2: number;
|
|
1111
|
+
y2: number;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Result returned by `layoutSmartArtNodes`.
|
|
1115
|
+
*/
|
|
1116
|
+
interface SmartArtLayoutResult {
|
|
1117
|
+
nodes: PositionedNode[];
|
|
1118
|
+
connectors: ConnectorSegment[];
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Pure, framework-agnostic helpers for SmartArt rendering.
|
|
1123
|
+
*
|
|
1124
|
+
* Ported from the Vue component
|
|
1125
|
+
* packages/vue/src/viewer/components/SmartArtRenderer.vue
|
|
1126
|
+
* (viewer-first subset — drawing-shapes path + stacked-block fallback).
|
|
1127
|
+
*
|
|
1128
|
+
* No Angular imports: all exports are plain TypeScript functions / types so
|
|
1129
|
+
* they can be unit-tested with vitest without TestBed or the Angular compiler.
|
|
1130
|
+
*/
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* Projected view-model for a single pre-computed drawing shape, ready for
|
|
1134
|
+
* direct use in an SVG `<g>` block.
|
|
1135
|
+
*/
|
|
1136
|
+
interface RenderedShape {
|
|
1137
|
+
/** Stable React-style key. */
|
|
1138
|
+
key: string;
|
|
1139
|
+
/** True → render `<ellipse>`, false → render `<rect>`. */
|
|
1140
|
+
isEllipse: boolean;
|
|
1141
|
+
/** Rect top-left (relative to the viewBox origin). */
|
|
1142
|
+
x: number;
|
|
1143
|
+
y: number;
|
|
1144
|
+
width: number;
|
|
1145
|
+
height: number;
|
|
1146
|
+
/** Border-radius for `<rect rx>` (roundRect shapes). */
|
|
1147
|
+
rx: number;
|
|
1148
|
+
/** Ellipse centre x. */
|
|
1149
|
+
cx: number;
|
|
1150
|
+
/** Ellipse centre y. */
|
|
1151
|
+
cy: number;
|
|
1152
|
+
fill: string;
|
|
1153
|
+
stroke: string;
|
|
1154
|
+
strokeWidth: number;
|
|
1155
|
+
/** SVG `transform` attribute, e.g. `rotate(30 50 40)`. */
|
|
1156
|
+
transform: string | undefined;
|
|
1157
|
+
/** Truncated text label (≤30 chars), or `undefined` when absent. */
|
|
1158
|
+
text: string | undefined;
|
|
1159
|
+
/** Text anchor x (centre of shape). */
|
|
1160
|
+
textX: number;
|
|
1161
|
+
/** Text anchor y (centre of shape). */
|
|
1162
|
+
textY: number;
|
|
1163
|
+
fontColor: string;
|
|
1164
|
+
fontSize: number;
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* SVG `viewBox` bounding-box derived from all drawing shapes.
|
|
1168
|
+
*
|
|
1169
|
+
* Returns the minimal bounding box plus `minX`/`minY` offsets used to
|
|
1170
|
+
* rebase each shape's position to (0, 0).
|
|
1171
|
+
*/
|
|
1172
|
+
interface DrawingViewBox {
|
|
1173
|
+
minX: number;
|
|
1174
|
+
minY: number;
|
|
1175
|
+
width: number;
|
|
1176
|
+
height: number;
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* A single coloured block in the stacked fallback list.
|
|
1180
|
+
*/
|
|
1181
|
+
interface FallbackBlock {
|
|
1182
|
+
/** Stable key for `@for` tracking. */
|
|
1183
|
+
key: string;
|
|
1184
|
+
text: string;
|
|
1185
|
+
fill: string;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* SmartArtRendererComponent — Angular port of the Vue `SmartArtRenderer.vue`
|
|
1190
|
+
* (packages/vue/src/viewer/components/SmartArtRenderer.vue).
|
|
1191
|
+
*
|
|
1192
|
+
* Viewer-first subset: renders from pre-computed drawing shapes
|
|
1193
|
+
* (`smartArtData.drawingShapes`) when present, otherwise falls back to a
|
|
1194
|
+
* stacked coloured block list of node text. When neither is available a small
|
|
1195
|
+
* "SmartArt" placeholder is shown.
|
|
1196
|
+
*
|
|
1197
|
+
* Editing, interaction, and the full family-specific layout renderers
|
|
1198
|
+
* (hierarchy / cycle / process / …) are out of scope — tracked in PORTING.md.
|
|
1199
|
+
*/
|
|
1200
|
+
declare class SmartArtRendererComponent {
|
|
1201
|
+
/** The smartArt element to render. Must be `type === 'smartArt'`. */
|
|
1202
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1203
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
1204
|
+
readonly containerStyle: _angular_core.Signal<StyleMap>;
|
|
1205
|
+
readonly chromeStyle: _angular_core.Signal<StyleMap>;
|
|
1206
|
+
readonly palette: _angular_core.Signal<string[]>;
|
|
1207
|
+
readonly artStyle: _angular_core.Signal<pptx_viewer_core.SmartArtStyle>;
|
|
1208
|
+
readonly nodes: _angular_core.Signal<pptx_viewer_core.PptxSmartArtNode[]>;
|
|
1209
|
+
readonly rawDrawingShapes: _angular_core.Signal<pptx_viewer_core.PptxSmartArtDrawingShape[]>;
|
|
1210
|
+
readonly hasDrawingShapes: _angular_core.Signal<boolean>;
|
|
1211
|
+
readonly viewBox: _angular_core.Signal<DrawingViewBox>;
|
|
1212
|
+
/** `viewBox` attribute string for the `<svg>` element. */
|
|
1213
|
+
readonly svgViewBox: _angular_core.Signal<string>;
|
|
1214
|
+
readonly renderedShapes: _angular_core.Signal<RenderedShape[]>;
|
|
1215
|
+
readonly shadowFilter: _angular_core.Signal<string | undefined>;
|
|
1216
|
+
readonly layoutResult: _angular_core.Signal<SmartArtLayoutResult>;
|
|
1217
|
+
readonly hasLayout: _angular_core.Signal<boolean>;
|
|
1218
|
+
readonly layoutViewBox: _angular_core.Signal<string>;
|
|
1219
|
+
/** Palette colour for a node at the given depth level. */
|
|
1220
|
+
nodeFill(level: number): string;
|
|
1221
|
+
readonly fallbackBlocks: _angular_core.Signal<FallbackBlock[]>;
|
|
1222
|
+
readonly isEmpty: _angular_core.Signal<boolean>;
|
|
1223
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SmartArtRendererComponent, never>;
|
|
1224
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SmartArtRendererComponent, "pptx-smart-art-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
* Pure helpers for `InkRendererComponent`.
|
|
1229
|
+
*
|
|
1230
|
+
* All functions are framework-agnostic (no Angular dependency) so they can be
|
|
1231
|
+
* unit-tested without TestBed, following the same pattern as
|
|
1232
|
+
* `connector-path.ts`.
|
|
1233
|
+
*/
|
|
1234
|
+
/** Resolved per-stroke data used to render a single `<path>`. */
|
|
1235
|
+
interface InkStroke {
|
|
1236
|
+
d: string;
|
|
1237
|
+
color: string;
|
|
1238
|
+
width: number;
|
|
1239
|
+
opacity: number;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* InkRendererComponent — Angular port of the Vue `InkRenderer.vue`
|
|
1244
|
+
* (and the React `renderInk` inside `InkGroupRenderers.tsx`), viewer-first
|
|
1245
|
+
* subset.
|
|
1246
|
+
*
|
|
1247
|
+
* Renders freehand ink strokes (`InkPptxElement.inkPaths`) as inline SVG
|
|
1248
|
+
* `<path>` elements inside the element's bounding box, with per-stroke colour,
|
|
1249
|
+
* width, and opacity resolved from the parallel `inkColors`/`inkWidths`/
|
|
1250
|
+
* `inkOpacities` arrays.
|
|
1251
|
+
*
|
|
1252
|
+
* Not ported (TODO, see PORTING.md): pressure-sensitive variable-width strokes
|
|
1253
|
+
* (`inkPointPressures`), ink replay animation, and the highlighter/eraser tool
|
|
1254
|
+
* blend modes. These all degrade gracefully to plain constant-width strokes.
|
|
1255
|
+
*
|
|
1256
|
+
* All non-trivial pure computation lives in `ink-renderer-helpers.ts` (no
|
|
1257
|
+
* Angular dependency) so it can be unit-tested without TestBed.
|
|
1258
|
+
*/
|
|
1259
|
+
declare class InkRendererComponent {
|
|
1260
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1261
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
1262
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1263
|
+
readonly containerStyle: _angular_core.Signal<StyleMap>;
|
|
1264
|
+
readonly strokes: _angular_core.Signal<InkStroke[]>;
|
|
1265
|
+
readonly viewBox: _angular_core.Signal<string>;
|
|
1266
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<InkRendererComponent, never>;
|
|
1267
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<InkRendererComponent, "pptx-ink-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Pure, framework-agnostic helpers for OLE renderer.
|
|
1272
|
+
*
|
|
1273
|
+
* Ported from:
|
|
1274
|
+
* - packages/react/src/viewer/components/elements/InkGroupRenderers.tsx
|
|
1275
|
+
* (resolveOleType, getOleTypeColor, getOleTypeLabel, getOleAriaLabel)
|
|
1276
|
+
* - packages/vue/src/viewer/components/OleRenderer.vue
|
|
1277
|
+
* (placeholder style, badge label, display name)
|
|
1278
|
+
*
|
|
1279
|
+
* All functions are pure (no Angular dependencies) so they can be unit-tested
|
|
1280
|
+
* with plain vitest without TestBed or the Angular compiler.
|
|
1281
|
+
*/
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Resolved OLE application type, narrowed from the raw `OleObjectType` union.
|
|
1285
|
+
*
|
|
1286
|
+
* `package` and `unknown` from the core type both collapse to `'unknown'` here
|
|
1287
|
+
* so that every branch is guaranteed to have a colour and label.
|
|
1288
|
+
*/
|
|
1289
|
+
type ResolvedOleType = 'excel' | 'word' | 'pdf' | 'visio' | 'mathtype' | 'unknown';
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* OleRendererComponent — Angular port of the React `renderOleElement`
|
|
1293
|
+
* (packages/react/src/viewer/components/elements/InkGroupRenderers.tsx) and
|
|
1294
|
+
* the Vue `OleRenderer.vue`.
|
|
1295
|
+
*
|
|
1296
|
+
* Renders an embedded OLE object (`OlePptxElement`). When a decoded preview
|
|
1297
|
+
* image is present (`previewImageData`) it is shown full-size with a small
|
|
1298
|
+
* type-badge overlay; otherwise a type-specific icon + label placeholder box
|
|
1299
|
+
* is drawn, mirroring the React / Vue fallback.
|
|
1300
|
+
*
|
|
1301
|
+
* Pure helpers (type resolution, colour / label maps, placeholder style) live
|
|
1302
|
+
* in `ole-renderer-helpers.ts` so they can be unit-tested without TestBed.
|
|
1303
|
+
*
|
|
1304
|
+
* Double-click-to-open and OLE extraction are not ported (viewer-only).
|
|
1305
|
+
*/
|
|
1306
|
+
declare class OleRendererComponent {
|
|
1307
|
+
/** The element to render. Must be `type === 'ole'`. */
|
|
1308
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1309
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
1310
|
+
/** Absolute container positioning + dimensions. */
|
|
1311
|
+
readonly containerStyle: _angular_core.Signal<StyleMap>;
|
|
1312
|
+
/** Narrowed OLE element — undefined when the input is not `type === 'ole'`. */
|
|
1313
|
+
private readonly ole;
|
|
1314
|
+
/** Resolved application type (excel / word / pdf / visio / mathtype / unknown). */
|
|
1315
|
+
readonly oleType: _angular_core.Signal<ResolvedOleType>;
|
|
1316
|
+
/** Brand hex colour for the resolved type. */
|
|
1317
|
+
readonly typeColor: _angular_core.Signal<string>;
|
|
1318
|
+
/** Human-readable type label (e.g. "Excel Spreadsheet"). */
|
|
1319
|
+
readonly typeLabel: _angular_core.Signal<string>;
|
|
1320
|
+
/** Short uppercase badge text shown over the preview image. */
|
|
1321
|
+
readonly badgeLabel: _angular_core.Signal<string>;
|
|
1322
|
+
/** Preview image data-URL, or undefined to show the placeholder. */
|
|
1323
|
+
readonly previewSrc: _angular_core.Signal<string | undefined>;
|
|
1324
|
+
/** Original file name, if present. */
|
|
1325
|
+
readonly fileName: _angular_core.Signal<string | undefined>;
|
|
1326
|
+
/** Primary display name: file name if present, otherwise the type label. */
|
|
1327
|
+
readonly displayName: _angular_core.Signal<string>;
|
|
1328
|
+
/** Accessible label for the role="img" wrapper. */
|
|
1329
|
+
readonly ariaLabel: _angular_core.Signal<string>;
|
|
1330
|
+
/** Border + background style for the placeholder box. */
|
|
1331
|
+
readonly placeholderStyle: _angular_core.Signal<StyleMap>;
|
|
1332
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OleRendererComponent, never>;
|
|
1333
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<OleRendererComponent, "pptx-ole-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/**
|
|
1337
|
+
* Pure helpers for `Model3DRendererComponent`.
|
|
1338
|
+
*
|
|
1339
|
+
* All functions are framework-agnostic (no Angular dependency) so they can be
|
|
1340
|
+
* unit-tested without TestBed, following the same pattern as
|
|
1341
|
+
* `connector-path.ts`.
|
|
1342
|
+
*/
|
|
1343
|
+
/** Narrowed view-model derived from a `Model3DPptxElement`. */
|
|
1344
|
+
interface Model3DViewModel {
|
|
1345
|
+
/** Resolved model element, or undefined when the element is not a model3d. */
|
|
1346
|
+
readonly model: Model3DPptxElement | undefined;
|
|
1347
|
+
/**
|
|
1348
|
+
* Poster image src: `posterImage` is preferred over the raster `imageData`
|
|
1349
|
+
* fallback (mirrors the React `PosterFallback` and the Vue port).
|
|
1350
|
+
*/
|
|
1351
|
+
readonly posterSrc: string | undefined;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
* Model3DRendererComponent — Angular port of the Vue `Model3DRenderer.vue`
|
|
1356
|
+
* (and the React `Model3DRenderer` / `PosterFallback`), poster-only subset.
|
|
1357
|
+
*
|
|
1358
|
+
* Interactive 3D rendering (three.js) is intentionally OUT OF SCOPE for the
|
|
1359
|
+
* Angular port — see PORTING.md. This component always renders the
|
|
1360
|
+
* poster/preview image (`posterImage`, falling back to `imageData`); when
|
|
1361
|
+
* neither exists it draws a labelled "3D Model" placeholder, exactly like the
|
|
1362
|
+
* React poster fallback.
|
|
1363
|
+
*
|
|
1364
|
+
* All non-trivial pure computation lives in `model3d-renderer-helpers.ts` (no
|
|
1365
|
+
* Angular dependency) so it can be unit-tested without TestBed.
|
|
1366
|
+
*/
|
|
1367
|
+
declare class Model3DRendererComponent {
|
|
1368
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1369
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
1370
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1371
|
+
readonly containerStyle: _angular_core.Signal<StyleMap>;
|
|
1372
|
+
readonly vm: _angular_core.Signal<Model3DViewModel>;
|
|
1373
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Model3DRendererComponent, never>;
|
|
1374
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<Model3DRendererComponent, "pptx-model3d-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* Pure helpers for `ZoomRendererComponent`.
|
|
1379
|
+
*
|
|
1380
|
+
* All functions are framework-agnostic (no Angular dependency) so they can be
|
|
1381
|
+
* unit-tested without TestBed, following the same pattern as
|
|
1382
|
+
* `connector-path.ts`.
|
|
1383
|
+
*/
|
|
1384
|
+
/** Narrowed view-model derived from a `ZoomPptxElement`. */
|
|
1385
|
+
interface ZoomViewModel {
|
|
1386
|
+
/** Resolved zoom element, or undefined when the element is not a zoom. */
|
|
1387
|
+
readonly zoom: ZoomPptxElement | undefined;
|
|
1388
|
+
/** Preview image src (the `imageData` embedded thumbnail). */
|
|
1389
|
+
readonly previewSrc: string | undefined;
|
|
1390
|
+
/** Zero-based target slide index. */
|
|
1391
|
+
readonly targetSlideIndex: number;
|
|
1392
|
+
/** Zoom type string used as the badge label source and data attribute. */
|
|
1393
|
+
readonly zoomType: 'slide' | 'section';
|
|
1394
|
+
/** Optional section identifier for section zooms. */
|
|
1395
|
+
readonly targetSectionId: string | undefined;
|
|
1396
|
+
/** Human-readable badge text ("Slide Zoom" / "Section Zoom"). */
|
|
1397
|
+
readonly badgeText: string;
|
|
1398
|
+
/** Human-readable slide label ("Slide N"). */
|
|
1399
|
+
readonly slideLabel: string;
|
|
1400
|
+
/** Accessible label for the element. */
|
|
1401
|
+
readonly ariaLabel: string;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* ZoomRendererComponent — Angular port of the Vue `ZoomRenderer.vue`
|
|
1406
|
+
* (and the React `ZoomElementRenderer`), static viewer-first subset.
|
|
1407
|
+
*
|
|
1408
|
+
* Renders a Slide-Zoom / Section-Zoom tile (`ZoomPptxElement`): the element's
|
|
1409
|
+
* own preview thumbnail (`imageData`) when available, otherwise a fallback tile
|
|
1410
|
+
* showing the target slide number. A small "Slide Zoom" / "Section Zoom" badge
|
|
1411
|
+
* is drawn in the corner.
|
|
1412
|
+
*
|
|
1413
|
+
* Navigation (click-to-jump in presentation mode) and live target-slide preview
|
|
1414
|
+
* rendering are NOT ported — this is a static link tile only (see PORTING.md).
|
|
1415
|
+
* The `slides` array is not threaded through, so the fallback uses the target
|
|
1416
|
+
* slide index rather than the real target background.
|
|
1417
|
+
*
|
|
1418
|
+
* All non-trivial pure computation lives in `zoom-renderer-helpers.ts` (no
|
|
1419
|
+
* Angular dependency) so it can be unit-tested without TestBed.
|
|
1420
|
+
*/
|
|
1421
|
+
declare class ZoomRendererComponent {
|
|
1422
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1423
|
+
readonly zIndex: _angular_core.InputSignal<number>;
|
|
1424
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1425
|
+
readonly containerStyle: _angular_core.Signal<StyleMap>;
|
|
1426
|
+
readonly vm: _angular_core.Signal<ZoomViewModel>;
|
|
1427
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZoomRendererComponent, never>;
|
|
1428
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZoomRendererComponent, "pptx-zoom-renderer", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* PresentationOverlayComponent — full-viewport black overlay that renders
|
|
1433
|
+
* slides in presentation (kiosk) mode.
|
|
1434
|
+
*
|
|
1435
|
+
* Selector: `pptx-presentation-overlay`
|
|
1436
|
+
*
|
|
1437
|
+
* Inputs:
|
|
1438
|
+
* - `slides` (required) — all slides in the deck
|
|
1439
|
+
* - `canvasSize` (required) — logical canvas dimensions in pixels
|
|
1440
|
+
* - `mediaDataUrls` — data-URL map for media assets (default: empty Map)
|
|
1441
|
+
* - `startIndex` — zero-based slide to show first (default: 0)
|
|
1442
|
+
*
|
|
1443
|
+
* Outputs:
|
|
1444
|
+
* - `indexChange` — emits the new index on every navigation
|
|
1445
|
+
* - `closed` — emits void when the overlay should be dismissed
|
|
1446
|
+
*
|
|
1447
|
+
* Keyboard bindings (document-level so no focusable element is required):
|
|
1448
|
+
* ArrowRight / Space / PageDown → next visible slide
|
|
1449
|
+
* ArrowLeft / PageUp → previous visible slide
|
|
1450
|
+
* Home → first slide
|
|
1451
|
+
* End → last slide
|
|
1452
|
+
* Escape → emit `closed`
|
|
1453
|
+
*
|
|
1454
|
+
* Touch bindings (mobile has no keyboard):
|
|
1455
|
+
* Always-visible ✕ button (top-right) → emit `closed`
|
|
1456
|
+
* ‹ / › edge buttons → previous / next visible slide
|
|
1457
|
+
* Horizontal swipe → left → next, right → previous
|
|
1458
|
+
*
|
|
1459
|
+
* Click on the overlay body → advance to next visible slide.
|
|
1460
|
+
*/
|
|
1461
|
+
declare class PresentationOverlayComponent implements OnInit, OnDestroy {
|
|
1462
|
+
readonly slides: _angular_core.InputSignal<PptxSlide[]>;
|
|
1463
|
+
readonly canvasSize: _angular_core.InputSignal<CanvasSize>;
|
|
1464
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1465
|
+
readonly startIndex: _angular_core.InputSignal<number>;
|
|
1466
|
+
readonly indexChange: _angular_core.OutputEmitterRef<number>;
|
|
1467
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
1468
|
+
/** Zero-based index into `slides()`. */
|
|
1469
|
+
protected readonly currentIndex: _angular_core.WritableSignal<number>;
|
|
1470
|
+
/** Viewport dimensions — updated on resize. */
|
|
1471
|
+
private readonly viewportW;
|
|
1472
|
+
private readonly viewportH;
|
|
1473
|
+
protected readonly currentSlide: _angular_core.Signal<PptxSlide | undefined>;
|
|
1474
|
+
/** Zoom level that fits the canvas into the current viewport. */
|
|
1475
|
+
protected readonly zoom: _angular_core.Signal<number>;
|
|
1476
|
+
/** Centre the scaled slide in the viewport. */
|
|
1477
|
+
protected readonly stageContainerStyle: _angular_core.Signal<Record<string, string>>;
|
|
1478
|
+
/** "3 / 12" label. */
|
|
1479
|
+
protected readonly counterLabel: _angular_core.Signal<string>;
|
|
1480
|
+
/**
|
|
1481
|
+
* Always-visible close button, fixed at the top-right and offset by the
|
|
1482
|
+
* device safe-area insets so it clears notches / rounded corners. Sits on a
|
|
1483
|
+
* higher z-index than the stage so taps never fall through to tap-advance.
|
|
1484
|
+
*/
|
|
1485
|
+
protected readonly closeButtonStyle: Record<string, string>;
|
|
1486
|
+
/** Shared geometry for the left/right edge navigation buttons. */
|
|
1487
|
+
private readonly navButtonBase;
|
|
1488
|
+
protected readonly prevButtonStyle: Record<string, string>;
|
|
1489
|
+
protected readonly nextButtonStyle: Record<string, string>;
|
|
1490
|
+
protected readonly counterStyle: Record<string, string>;
|
|
1491
|
+
/** Horizontal swipe distance (px) required to trigger navigation. */
|
|
1492
|
+
private static readonly SWIPE_THRESHOLD;
|
|
1493
|
+
/** X coordinate captured on touchstart, or null when no swipe is active. */
|
|
1494
|
+
private touchStartX;
|
|
1495
|
+
private touchStartY;
|
|
1496
|
+
ngOnInit(): void;
|
|
1497
|
+
ngOnDestroy(): void;
|
|
1498
|
+
onWindowResize(): void;
|
|
1499
|
+
private snapViewport;
|
|
1500
|
+
onKeyDown(event: KeyboardEvent): void;
|
|
1501
|
+
/** Left-click on the slide area advances to the next visible slide. */
|
|
1502
|
+
protected onBodyClick(event: MouseEvent): void;
|
|
1503
|
+
/** Close button click — stop propagation so it does not also advance. */
|
|
1504
|
+
protected onClose(event: MouseEvent): void;
|
|
1505
|
+
/**
|
|
1506
|
+
* Close button touch — stop propagation and prevent the synthesized click
|
|
1507
|
+
* so a tap exits without bubbling to the tap-advance handler.
|
|
1508
|
+
*/
|
|
1509
|
+
protected onCloseTouch(event: TouchEvent): void;
|
|
1510
|
+
/** Previous-edge button — stop propagation so the tap does not double-fire. */
|
|
1511
|
+
protected onPrev(event: MouseEvent): void;
|
|
1512
|
+
protected onPrevTouch(event: TouchEvent): void;
|
|
1513
|
+
/** Next-edge button — stop propagation so the tap does not double-fire. */
|
|
1514
|
+
protected onNext(event: MouseEvent): void;
|
|
1515
|
+
protected onNextTouch(event: TouchEvent): void;
|
|
1516
|
+
/** Record the initial touch position. */
|
|
1517
|
+
protected onTouchStart(event: TouchEvent): void;
|
|
1518
|
+
/**
|
|
1519
|
+
* On touchend, treat a predominantly horizontal drag past the threshold as a
|
|
1520
|
+
* swipe: left-swipe → next, right-swipe → prev.
|
|
1521
|
+
*/
|
|
1522
|
+
protected onTouchEnd(event: TouchEvent): void;
|
|
1523
|
+
private navigate;
|
|
1524
|
+
private emitClosed;
|
|
1525
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PresentationOverlayComponent, never>;
|
|
1526
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PresentationOverlayComponent, "pptx-presentation-overlay", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "startIndex": { "alias": "startIndex"; "required": false; "isSignal": true; }; }, { "indexChange": "indexChange"; "closed": "closed"; }, never, never, true, never>;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* SlideSorterOverlayComponent — Angular port of the React `SlideSorterOverlay`.
|
|
1531
|
+
*
|
|
1532
|
+
* Renders a fixed full-screen modal overlay containing a responsive grid of
|
|
1533
|
+
* scaled slide previews. Clicking a thumbnail emits `select(index)`; pressing
|
|
1534
|
+
* Escape or clicking the ✕ button emits `closed`.
|
|
1535
|
+
*
|
|
1536
|
+
* Viewer-first scope: no drag-reorder, no context menu, no section grouping.
|
|
1537
|
+
* Those features are tracked in PORTING.md.
|
|
1538
|
+
*
|
|
1539
|
+
* Usage:
|
|
1540
|
+
* ```html
|
|
1541
|
+
* <pptx-slide-sorter-overlay
|
|
1542
|
+
* [slides]="slides()"
|
|
1543
|
+
* [canvasSize]="canvasSize()"
|
|
1544
|
+
* [mediaDataUrls]="mediaDataUrls()"
|
|
1545
|
+
* [activeIndex]="activeSlideIndex()"
|
|
1546
|
+
* (select)="goTo($event)"
|
|
1547
|
+
* (closed)="showSorter.set(false)"
|
|
1548
|
+
* />
|
|
1549
|
+
* ```
|
|
1550
|
+
*/
|
|
1551
|
+
declare class SlideSorterOverlayComponent {
|
|
1552
|
+
/** Full list of slides to display. */
|
|
1553
|
+
readonly slides: _angular_core.InputSignal<PptxSlide[]>;
|
|
1554
|
+
/** Natural (100 %) canvas dimensions — passed through to SlideCanvasComponent. */
|
|
1555
|
+
readonly canvasSize: _angular_core.InputSignal<CanvasSize>;
|
|
1556
|
+
/** Media asset lookup table — forwarded to each SlideCanvasComponent. */
|
|
1557
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1558
|
+
/** Zero-based index of the currently active slide (highlighted in blue). */
|
|
1559
|
+
readonly activeIndex: _angular_core.InputSignal<number>;
|
|
1560
|
+
/** Emits the zero-based index of the thumbnail the user clicked. */
|
|
1561
|
+
readonly select: _angular_core.OutputEmitterRef<number>;
|
|
1562
|
+
/** Emits when the user closes the overlay (✕ button or Escape key). */
|
|
1563
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
1564
|
+
/** Zoom level that fits the full canvas width into THUMB_W pixels. */
|
|
1565
|
+
readonly thumbZoom: _angular_core.Signal<number>;
|
|
1566
|
+
/** Pixel height of the clipping box (aspect-correct). */
|
|
1567
|
+
readonly thumbH: _angular_core.Signal<number>;
|
|
1568
|
+
/** ngStyle object for the thumbnail clipping box. */
|
|
1569
|
+
readonly clipStyle: _angular_core.Signal<Record<string, string>>;
|
|
1570
|
+
/** ngStyle object for the grid: responsive auto-fill columns. */
|
|
1571
|
+
readonly gridStyle: _angular_core.Signal<Record<string, string>>;
|
|
1572
|
+
/** Keyboard handler: Escape closes the overlay. */
|
|
1573
|
+
onKeydown(event: KeyboardEvent): void;
|
|
1574
|
+
/** Clicking the backdrop (outside the panel) closes the overlay. */
|
|
1575
|
+
onBackdropClick(event: MouseEvent): void;
|
|
1576
|
+
/** Clicking a thumbnail selects the slide. */
|
|
1577
|
+
onThumbClick(index: number): void;
|
|
1578
|
+
/** Returns true when a slide has been marked as hidden in the presentation. */
|
|
1579
|
+
isHiddenSlide(slide: PptxSlide): boolean;
|
|
1580
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SlideSorterOverlayComponent, never>;
|
|
1581
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlideSorterOverlayComponent, "pptx-slide-sorter-overlay", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "activeIndex": { "alias": "activeIndex"; "required": false; "isSignal": true; }; }, { "select": "select"; "closed": "closed"; }, never, never, true, never>;
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* slide-search.ts — Pure text-search helpers for PPTX slides.
|
|
1586
|
+
*
|
|
1587
|
+
* No Angular imports; safe to use in web workers or server-side code.
|
|
1588
|
+
*
|
|
1589
|
+
* @module slide-search
|
|
1590
|
+
*/
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* A single slide that matched a text search query.
|
|
1594
|
+
*/
|
|
1595
|
+
interface SlideSearchMatch {
|
|
1596
|
+
/** Zero-based index of the matching slide in the slides array. */
|
|
1597
|
+
slideIndex: number;
|
|
1598
|
+
/** Number of (overlapping) occurrences of the query on this slide. */
|
|
1599
|
+
matchCount: number;
|
|
1600
|
+
/**
|
|
1601
|
+
* A short snippet of text surrounding the first match.
|
|
1602
|
+
* Includes a few characters of context on each side.
|
|
1603
|
+
*/
|
|
1604
|
+
snippet: string;
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Collect all visible text from a single {@link PptxElement}.
|
|
1608
|
+
*
|
|
1609
|
+
* - `text` / `shape` / `connector` — flat `text` field + `textSegments[].text`.
|
|
1610
|
+
* - `table` — iterates `tableData.rows[].cells[].text`.
|
|
1611
|
+
* - `smartArt` — recursively collects `smartArtData.nodes[].text`.
|
|
1612
|
+
* - `group` — recurses into `children`.
|
|
1613
|
+
* - All other element types produce an empty string.
|
|
1614
|
+
*/
|
|
1615
|
+
declare function collectElementText(element: PptxElement): string;
|
|
1616
|
+
/**
|
|
1617
|
+
* Collect all visible text from a {@link PptxSlide}, including speaker notes.
|
|
1618
|
+
*/
|
|
1619
|
+
declare function collectSlideText(slide: PptxSlide): string;
|
|
1620
|
+
/**
|
|
1621
|
+
* Search all slides for `query` (case-insensitive substring match).
|
|
1622
|
+
*
|
|
1623
|
+
* Returns an empty array when `query` is empty or whitespace-only.
|
|
1624
|
+
*/
|
|
1625
|
+
declare function searchSlides(slides: readonly PptxSlide[], query: string): SlideSearchMatch[];
|
|
1626
|
+
|
|
1627
|
+
declare class FindBarComponent {
|
|
1628
|
+
/** All slides in the current presentation. */
|
|
1629
|
+
readonly slides: _angular_core.InputSignal<PptxSlide[]>;
|
|
1630
|
+
/** Emits the zero-based slide index to navigate to. */
|
|
1631
|
+
readonly navigate: _angular_core.OutputEmitterRef<number>;
|
|
1632
|
+
/** Emits when the user closes the find bar (Escape or ✕). */
|
|
1633
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
1634
|
+
private readonly queryInputRef;
|
|
1635
|
+
/** Current text typed into the search input. */
|
|
1636
|
+
readonly query: _angular_core.WritableSignal<string>;
|
|
1637
|
+
/**
|
|
1638
|
+
* Zero-based index into the flat `matches` array tracking which result is
|
|
1639
|
+
* currently highlighted. Clamped whenever `matches` changes.
|
|
1640
|
+
*/
|
|
1641
|
+
readonly activeMatchIndex: _angular_core.WritableSignal<number>;
|
|
1642
|
+
/** Slides that contain at least one match for the current query. */
|
|
1643
|
+
readonly matches: _angular_core.Signal<SlideSearchMatch[]>;
|
|
1644
|
+
/** Total number of individual occurrences across all matching slides. */
|
|
1645
|
+
readonly totalMatches: _angular_core.Signal<number>;
|
|
1646
|
+
/**
|
|
1647
|
+
* 1-based display position (which slide-level result we're on).
|
|
1648
|
+
* Accounts for clamping when the match list shrinks.
|
|
1649
|
+
*/
|
|
1650
|
+
readonly activeMatchDisplay: _angular_core.Signal<number>;
|
|
1651
|
+
/** Snippet text for the currently active match. */
|
|
1652
|
+
readonly activeSnippet: _angular_core.Signal<string>;
|
|
1653
|
+
/**
|
|
1654
|
+
* Pressing Escape anywhere on the document closes the find bar.
|
|
1655
|
+
* (Enter inside the input already calls `next()` via `keydown.enter`.)
|
|
1656
|
+
*/
|
|
1657
|
+
onDocumentKeydown(event: KeyboardEvent): void;
|
|
1658
|
+
onInput(event: Event): void;
|
|
1659
|
+
next(): void;
|
|
1660
|
+
prev(): void;
|
|
1661
|
+
close(): void;
|
|
1662
|
+
private _emitCurrentSlide;
|
|
1663
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FindBarComponent, never>;
|
|
1664
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FindBarComponent, "pptx-find-bar", never, { "slides": { "alias": "slides"; "required": true; "isSignal": true; }; }, { "navigate": "navigate"; "closed": "closed"; }, never, never, true, never>;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
declare class InspectorPanelComponent {
|
|
1668
|
+
/** The single selected element whose properties are being edited. */
|
|
1669
|
+
readonly element: _angular_core.InputSignal<PptxElement>;
|
|
1670
|
+
/** Zero-based index of the active slide. */
|
|
1671
|
+
readonly slideIndex: _angular_core.InputSignal<number>;
|
|
1672
|
+
protected readonly editor: EditorStateService;
|
|
1673
|
+
/** Alias so the template can call el() without conflicting with Angular internals. */
|
|
1674
|
+
protected readonly el: _angular_core.Signal<PptxElement>;
|
|
1675
|
+
/**
|
|
1676
|
+
* Stable identity key for the selected element. Only changes when a
|
|
1677
|
+
* *different* element is selected. The seed signal below is keyed on this so
|
|
1678
|
+
* input [value] bindings never get rewritten while the user is typing into
|
|
1679
|
+
* the currently-selected element (caret-reset / keyboard-dismiss guard).
|
|
1680
|
+
*/
|
|
1681
|
+
protected readonly elementKey: _angular_core.Signal<string>;
|
|
1682
|
+
/**
|
|
1683
|
+
* One-shot seed of every editable field's initial display value, recomputed
|
|
1684
|
+
* only when `elementKey` changes (i.e. on selection change), NOT on every
|
|
1685
|
+
* edit commit. Bound to each <input>'s [value] so Angular re-evaluating the
|
|
1686
|
+
* binding during change-detection always yields the same value mid-edit and
|
|
1687
|
+
* therefore never rewrites the element's `.value` / resets the caret.
|
|
1688
|
+
*/
|
|
1689
|
+
protected readonly seed: _angular_core.Signal<{
|
|
1690
|
+
x: number;
|
|
1691
|
+
y: number;
|
|
1692
|
+
width: number;
|
|
1693
|
+
height: number;
|
|
1694
|
+
rotation: number;
|
|
1695
|
+
opacity: number;
|
|
1696
|
+
fillColor: string;
|
|
1697
|
+
strokeColor: string;
|
|
1698
|
+
textColor: string;
|
|
1699
|
+
fontSize: number;
|
|
1700
|
+
}>;
|
|
1701
|
+
/** Whether the element supports shape-style (fill/stroke) editing. */
|
|
1702
|
+
protected readonly hasShape: _angular_core.Signal<boolean>;
|
|
1703
|
+
/** Whether the element supports text-style editing. */
|
|
1704
|
+
protected readonly hasText: _angular_core.Signal<boolean>;
|
|
1705
|
+
protected readonly currentBold: _angular_core.Signal<boolean>;
|
|
1706
|
+
protected readonly currentItalic: _angular_core.Signal<boolean>;
|
|
1707
|
+
protected readonly currentUnderline: _angular_core.Signal<boolean>;
|
|
1708
|
+
protected onPositionChange(event: Event, axis: 'x' | 'y'): void;
|
|
1709
|
+
protected onSizeChange(event: Event, dim: 'width' | 'height'): void;
|
|
1710
|
+
protected onRotationChange(event: Event): void;
|
|
1711
|
+
protected onOpacityChange(event: Event): void;
|
|
1712
|
+
protected onFillColorChange(event: Event): void;
|
|
1713
|
+
protected onStrokeColorChange(event: Event): void;
|
|
1714
|
+
protected onTextColorChange(event: Event): void;
|
|
1715
|
+
protected onFontSizeChange(event: Event): void;
|
|
1716
|
+
protected onBoldToggle(): void;
|
|
1717
|
+
protected onItalicToggle(): void;
|
|
1718
|
+
protected onUnderlineToggle(): void;
|
|
1719
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<InspectorPanelComponent, never>;
|
|
1720
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<InspectorPanelComponent, "pptx-inspector-panel", never, { "element": { "alias": "element"; "required": true; "isSignal": true; }; "slideIndex": { "alias": "slideIndex"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/**
|
|
1724
|
+
* SlidesPanelComponent — vertical slide-strip for the editor sidebar.
|
|
1725
|
+
*
|
|
1726
|
+
* Renders the live editable deck (from {@link EditorStateService}) as a
|
|
1727
|
+
* scrollable vertical list of numbered thumbnail cards. Clicking a card emits
|
|
1728
|
+
* `select(index)`; the active card is highlighted. Per-card hover toolbar
|
|
1729
|
+
* provides Duplicate, Delete (disabled when only 1 slide), Move up, and Move
|
|
1730
|
+
* down. A footer "+ Add slide" button appends a blank slide after the current
|
|
1731
|
+
* `activeIndex`.
|
|
1732
|
+
*
|
|
1733
|
+
* Usage:
|
|
1734
|
+
* ```html
|
|
1735
|
+
* <pptx-slides-panel
|
|
1736
|
+
* [canvasSize]="loader.canvasSize()"
|
|
1737
|
+
* [mediaDataUrls]="loader.mediaDataUrls()"
|
|
1738
|
+
* [activeIndex]="activeSlideIndex()"
|
|
1739
|
+
* (select)="goTo($event)"
|
|
1740
|
+
* />
|
|
1741
|
+
* ```
|
|
1742
|
+
*/
|
|
1743
|
+
declare class SlidesPanelComponent {
|
|
1744
|
+
/** Natural (100 %) canvas dimensions — forwarded to each SlideCanvasComponent. */
|
|
1745
|
+
readonly canvasSize: _angular_core.InputSignal<CanvasSize>;
|
|
1746
|
+
/** Media asset lookup table — forwarded to each SlideCanvasComponent. */
|
|
1747
|
+
readonly mediaDataUrls: _angular_core.InputSignal<Map<string, string>>;
|
|
1748
|
+
/** Zero-based index of the currently active slide (highlighted in blue). */
|
|
1749
|
+
readonly activeIndex: _angular_core.InputSignal<number>;
|
|
1750
|
+
/** Emits the zero-based index of the card the user clicked. */
|
|
1751
|
+
readonly select: _angular_core.OutputEmitterRef<number>;
|
|
1752
|
+
protected readonly editor: EditorStateService;
|
|
1753
|
+
/** Zoom level that fits the full canvas width into THUMB_W pixels. */
|
|
1754
|
+
readonly thumbZoom: _angular_core.Signal<number>;
|
|
1755
|
+
/** Pixel height of the clipping box (aspect-correct). */
|
|
1756
|
+
readonly thumbH: _angular_core.Signal<number>;
|
|
1757
|
+
/** ngStyle object for the thumbnail clipping box. */
|
|
1758
|
+
readonly clipStyle: _angular_core.Signal<Record<string, string>>;
|
|
1759
|
+
onDuplicate(index: number): void;
|
|
1760
|
+
onDelete(index: number): void;
|
|
1761
|
+
onMoveUp(index: number): void;
|
|
1762
|
+
onMoveDown(index: number): void;
|
|
1763
|
+
onAddSlide(): void;
|
|
1764
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SlidesPanelComponent, never>;
|
|
1765
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SlidesPanelComponent, "pptx-slides-panel", never, { "canvasSize": { "alias": "canvasSize"; "required": true; "isSignal": true; }; "mediaDataUrls": { "alias": "mediaDataUrls"; "required": false; "isSignal": true; }; "activeIndex": { "alias": "activeIndex"; "required": false; "isSignal": true; }; }, { "select": "select"; }, never, never, true, never>;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
declare class EditorToolbarComponent {
|
|
1769
|
+
/** Zero-based index of the slide being edited. */
|
|
1770
|
+
readonly slideIndex: _angular_core.InputSignal<number>;
|
|
1771
|
+
protected readonly editor: EditorStateService;
|
|
1772
|
+
/** Align needs ≥2 selected elements; distribute needs ≥3. */
|
|
1773
|
+
protected readonly canAlign: _angular_core.Signal<boolean>;
|
|
1774
|
+
protected readonly canDistribute: _angular_core.Signal<boolean>;
|
|
1775
|
+
/** Group needs ≥2 selected; ungroup needs exactly one selected group. */
|
|
1776
|
+
protected readonly canGroup: _angular_core.Signal<boolean>;
|
|
1777
|
+
protected readonly canUngroup: _angular_core.Signal<boolean>;
|
|
1778
|
+
protected onInsertText(): void;
|
|
1779
|
+
protected onInsertShape(shapeType: 'rect' | 'ellipse' | 'line'): void;
|
|
1780
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorToolbarComponent, never>;
|
|
1781
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EditorToolbarComponent, "pptx-editor-toolbar", never, { "slideIndex": { "alias": "slideIndex"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
declare class EditorContextMenuComponent {
|
|
1785
|
+
/** Horizontal viewport coordinate (px) of the top-left corner of the menu. */
|
|
1786
|
+
readonly x: _angular_core.InputSignal<number>;
|
|
1787
|
+
/** Vertical viewport coordinate (px) of the top-left corner of the menu. */
|
|
1788
|
+
readonly y: _angular_core.InputSignal<number>;
|
|
1789
|
+
/** Zero-based index of the slide being edited. */
|
|
1790
|
+
readonly slideIndex: _angular_core.InputSignal<number>;
|
|
1791
|
+
/** Emitted when the menu should close (Escape or outside click). */
|
|
1792
|
+
readonly closed: _angular_core.OutputEmitterRef<void>;
|
|
1793
|
+
protected readonly editor: EditorStateService;
|
|
1794
|
+
private readonly host;
|
|
1795
|
+
onEscape(): void;
|
|
1796
|
+
onDocumentPointerDown(event: PointerEvent): void;
|
|
1797
|
+
protected onCut(): void;
|
|
1798
|
+
protected onCopy(): void;
|
|
1799
|
+
protected onPaste(): void;
|
|
1800
|
+
protected onDuplicate(): void;
|
|
1801
|
+
protected onDelete(): void;
|
|
1802
|
+
protected onBringToFront(): void;
|
|
1803
|
+
protected onSendToBack(): void;
|
|
1804
|
+
protected onBringForward(): void;
|
|
1805
|
+
protected onSendBackward(): void;
|
|
1806
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorContextMenuComponent, never>;
|
|
1807
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EditorContextMenuComponent, "pptx-editor-context-menu", never, { "x": { "alias": "x"; "required": true; "isSignal": true; }; "y": { "alias": "y"; "required": true; "isSignal": true; }; "slideIndex": { "alias": "slideIndex"; "required": true; "isSignal": true; }; }, { "closed": "closed"; }, never, never, true, never>;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
declare class ExportService {
|
|
1811
|
+
/**
|
|
1812
|
+
* Rasterize a single DOM element to PNG and trigger a browser download.
|
|
1813
|
+
*
|
|
1814
|
+
* @param el - The element to capture (e.g. the `.pptx-ng-canvas-stage`).
|
|
1815
|
+
* @param fileName - Suggested download file name (unsafe chars are stripped).
|
|
1816
|
+
* @param scale - Device-pixel ratio multiplier (default 2 for sharp output).
|
|
1817
|
+
*/
|
|
1818
|
+
exportElementToPng(el: HTMLElement, fileName: string, scale?: number): Promise<void>;
|
|
1819
|
+
/**
|
|
1820
|
+
* Rasterize a single element to a canvas (passthrough to html2canvas-pro).
|
|
1821
|
+
* Capture each slide's canvas *while that slide is the live DOM* — the
|
|
1822
|
+
* viewer reuses one stage node, so a deferred capture would yield the same
|
|
1823
|
+
* (last) slide for every page.
|
|
1824
|
+
*/
|
|
1825
|
+
renderElement(el: HTMLElement, scale?: number): Promise<HTMLCanvasElement>;
|
|
1826
|
+
/**
|
|
1827
|
+
* Assemble a multi-page PDF from pre-rendered slide canvases (one page per
|
|
1828
|
+
* canvas, sized to the slide aspect ratio in pt) and trigger a download.
|
|
1829
|
+
*
|
|
1830
|
+
* @param canvases - One canvas per slide, in order, each captured while
|
|
1831
|
+
* its slide was the live stage.
|
|
1832
|
+
* @param canvasWidth - Slide canvas width in pixels (for aspect ratio).
|
|
1833
|
+
* @param canvasHeight - Slide canvas height in pixels (for aspect ratio).
|
|
1834
|
+
* @param fileName - Suggested download file name (unsafe chars stripped).
|
|
1835
|
+
*/
|
|
1836
|
+
exportCanvasesToPdf(canvases: HTMLCanvasElement[], canvasWidth: number, canvasHeight: number, fileName: string): void;
|
|
1837
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ExportService, never>;
|
|
1838
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ExportService>;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
/**
|
|
1842
|
+
* A drop-in replacement for `html2canvas(element, options)` that first
|
|
1843
|
+
* resolves any oklch / oklab / lch / lab / color() values in the cloned
|
|
1844
|
+
* DOM to rgb()/hex, preventing parse errors in html2canvas ≤ 1.x.
|
|
1845
|
+
*
|
|
1846
|
+
* Three-pronged approach:
|
|
1847
|
+
* 1. Patch `<style>` elements to replace oklch in CSS custom properties.
|
|
1848
|
+
* 2. Resolve `:root` / `<body>` inline custom properties.
|
|
1849
|
+
* 3. Walk every element and convert computed colour values to sRGB.
|
|
1850
|
+
*
|
|
1851
|
+
* Usage:
|
|
1852
|
+
* ```ts
|
|
1853
|
+
* import { renderToCanvas } from '../lib/canvas-export';
|
|
1854
|
+
* const canvas = await renderToCanvas(element, { scale: 2 });
|
|
1855
|
+
* ```
|
|
1856
|
+
*/
|
|
1857
|
+
declare function renderToCanvas(element: HTMLElement, options?: Partial<Options>): Promise<HTMLCanvasElement>;
|
|
1858
|
+
|
|
1859
|
+
/**
|
|
1860
|
+
* editor-history.ts — Generic undo/redo history stack.
|
|
1861
|
+
*
|
|
1862
|
+
* Framework-agnostic: no Angular, React, or any other framework imports.
|
|
1863
|
+
* Designed to be consumed by an Angular service (e.g. EditorStateService).
|
|
1864
|
+
*
|
|
1865
|
+
* ## Snapshot semantics (PRE-mutation model)
|
|
1866
|
+
*
|
|
1867
|
+
* `record(snapshot, label)` must be called with the snapshot taken BEFORE the
|
|
1868
|
+
* caller applies its mutation. The class never deep-clones values: the caller
|
|
1869
|
+
* is responsible for passing already-cloned / immutable snapshots so that
|
|
1870
|
+
* mutations to the live state do not retroactively corrupt stored history
|
|
1871
|
+
* entries.
|
|
1872
|
+
*
|
|
1873
|
+
* ## Example usage inside EditorStateService
|
|
1874
|
+
*
|
|
1875
|
+
* // before mutating:
|
|
1876
|
+
* this.history.record(this.currentSnapshot(), 'Move element');
|
|
1877
|
+
* // apply mutation to the live signal …
|
|
1878
|
+
*
|
|
1879
|
+
* // undo:
|
|
1880
|
+
* const result = this.history.undo(this.currentSnapshot());
|
|
1881
|
+
* if (result) this.applySnapshot(result.snapshot);
|
|
1882
|
+
*
|
|
1883
|
+
* // redo:
|
|
1884
|
+
* const result = this.history.redo(this.currentSnapshot());
|
|
1885
|
+
* if (result) this.applySnapshot(result.snapshot);
|
|
1886
|
+
*/
|
|
1887
|
+
interface UndoRedoResult<T> {
|
|
1888
|
+
readonly snapshot: T;
|
|
1889
|
+
readonly label: string;
|
|
1890
|
+
}
|
|
1891
|
+
interface EditorHistoryOptions {
|
|
1892
|
+
/**
|
|
1893
|
+
* Maximum number of past entries kept on the undo stack.
|
|
1894
|
+
* When exceeded, the oldest entry is silently dropped.
|
|
1895
|
+
* @default 100
|
|
1896
|
+
*/
|
|
1897
|
+
maxDepth?: number;
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* Generic undo/redo history stack.
|
|
1901
|
+
*
|
|
1902
|
+
* `T` is the snapshot type; the caller decides what constitutes a snapshot
|
|
1903
|
+
* (e.g. `PptxSlide[]`, a plain state object, etc.).
|
|
1904
|
+
*
|
|
1905
|
+
* No deep-cloning is performed inside this class — the caller must pass
|
|
1906
|
+
* already-cloned snapshots.
|
|
1907
|
+
*/
|
|
1908
|
+
declare class EditorHistory<T> {
|
|
1909
|
+
private readonly _maxDepth;
|
|
1910
|
+
private readonly _past;
|
|
1911
|
+
private readonly _future;
|
|
1912
|
+
constructor(options?: EditorHistoryOptions);
|
|
1913
|
+
/** True when at least one undo step is available. */
|
|
1914
|
+
get canUndo(): boolean;
|
|
1915
|
+
/** True when at least one redo step is available. */
|
|
1916
|
+
get canRedo(): boolean;
|
|
1917
|
+
/**
|
|
1918
|
+
* Label of the most-recently recorded entry (the action that would be
|
|
1919
|
+
* undone on the next `undo()` call), or `undefined` when the stack is
|
|
1920
|
+
* empty.
|
|
1921
|
+
*/
|
|
1922
|
+
get undoLabel(): string | undefined;
|
|
1923
|
+
/**
|
|
1924
|
+
* Label of the most-recently undone entry (the action that would be
|
|
1925
|
+
* redone on the next `redo()` call), or `undefined` when the redo stack
|
|
1926
|
+
* is empty.
|
|
1927
|
+
*/
|
|
1928
|
+
get redoLabel(): string | undefined;
|
|
1929
|
+
/** Number of entries currently on the undo (past) stack. */
|
|
1930
|
+
get depth(): number;
|
|
1931
|
+
/**
|
|
1932
|
+
* Push `snapshot` (taken **before** the caller's mutation) onto the undo
|
|
1933
|
+
* stack with the given `label`, then clear the redo stack.
|
|
1934
|
+
*
|
|
1935
|
+
* When the stack length exceeds `maxDepth`, the oldest entry is dropped.
|
|
1936
|
+
*
|
|
1937
|
+
* The caller must pass an already-cloned snapshot — this method does NOT
|
|
1938
|
+
* deep-clone.
|
|
1939
|
+
*/
|
|
1940
|
+
record(snapshot: T, label: string): void;
|
|
1941
|
+
/**
|
|
1942
|
+
* Undo the last recorded action.
|
|
1943
|
+
*
|
|
1944
|
+
* Pops the top of the past stack, pushes `current` onto the future stack
|
|
1945
|
+
* (so it can be redone), and returns the popped entry so the caller can
|
|
1946
|
+
* restore it.
|
|
1947
|
+
*
|
|
1948
|
+
* Returns `undefined` when there is nothing to undo (`canUndo === false`).
|
|
1949
|
+
*
|
|
1950
|
+
* The caller must pass an already-cloned snapshot for `current` — this
|
|
1951
|
+
* method does NOT deep-clone.
|
|
1952
|
+
*/
|
|
1953
|
+
undo(current: T): UndoRedoResult<T> | undefined;
|
|
1954
|
+
/**
|
|
1955
|
+
* Redo the last undone action.
|
|
1956
|
+
*
|
|
1957
|
+
* Pops the top of the future stack, pushes `current` back onto the past
|
|
1958
|
+
* stack, and returns the popped entry so the caller can restore it.
|
|
1959
|
+
*
|
|
1960
|
+
* Returns `undefined` when there is nothing to redo (`canRedo === false`).
|
|
1961
|
+
*
|
|
1962
|
+
* The caller must pass an already-cloned snapshot for `current` — this
|
|
1963
|
+
* method does NOT deep-clone.
|
|
1964
|
+
*/
|
|
1965
|
+
redo(current: T): UndoRedoResult<T> | undefined;
|
|
1966
|
+
/**
|
|
1967
|
+
* Clear both the undo and redo stacks, resetting history to an empty
|
|
1968
|
+
* state.
|
|
1969
|
+
*/
|
|
1970
|
+
clear(): void;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
/**
|
|
1974
|
+
* element-operations — Pure array-transformation functions for slide elements.
|
|
1975
|
+
*
|
|
1976
|
+
* All functions are framework-agnostic (no Angular imports). Each takes a
|
|
1977
|
+
* `readonly PptxElement[]` representing the ordered element list for a slide
|
|
1978
|
+
* (array index 0 = back, last index = front/top in paint order) and returns a
|
|
1979
|
+
* NEW array — the input is never mutated.
|
|
1980
|
+
*
|
|
1981
|
+
* Callers supply a `newId` wherever a new element identity is needed, keeping
|
|
1982
|
+
* these functions deterministic and side-effect-free.
|
|
1983
|
+
*
|
|
1984
|
+
* Usage in an Angular service:
|
|
1985
|
+
* history.snapshot();
|
|
1986
|
+
* slides.update(s => replaceSlideElements(s, idx, ops(s[idx].elements, …)));
|
|
1987
|
+
*/
|
|
1988
|
+
|
|
1989
|
+
/**
|
|
1990
|
+
* Shallow-merge `patch` onto the element with `id`.
|
|
1991
|
+
* The discriminant `type` is always preserved from the original element.
|
|
1992
|
+
*
|
|
1993
|
+
* @example
|
|
1994
|
+
* updateElementById(elements, 'el1', { x: 50, hidden: true })
|
|
1995
|
+
*/
|
|
1996
|
+
declare function updateElementById(elements: readonly PptxElement[], id: string, patch: Partial<PptxElement>): PptxElement[];
|
|
1997
|
+
/**
|
|
1998
|
+
* Translate the element by `(dx, dy)` relative to its current position.
|
|
1999
|
+
*
|
|
2000
|
+
* @example
|
|
2001
|
+
* moveElementBy(elements, 'el1', 10, -5)
|
|
2002
|
+
*/
|
|
2003
|
+
declare function moveElementBy(elements: readonly PptxElement[], id: string, dx: number, dy: number): PptxElement[];
|
|
2004
|
+
/**
|
|
2005
|
+
* Set the absolute position of the element with `id`.
|
|
2006
|
+
*
|
|
2007
|
+
* @example
|
|
2008
|
+
* setElementPosition(elements, 'el1', 100, 200)
|
|
2009
|
+
*/
|
|
2010
|
+
declare function setElementPosition(elements: readonly PptxElement[], id: string, x: number, y: number): PptxElement[];
|
|
2011
|
+
/**
|
|
2012
|
+
* Set the size of the element with `id`, clamping both dimensions to at
|
|
2013
|
+
* least `MIN_ELEMENT_SIZE` (mirrors React's min-size guard).
|
|
2014
|
+
*
|
|
2015
|
+
* @example
|
|
2016
|
+
* resizeElement(elements, 'el1', 300, 150)
|
|
2017
|
+
*/
|
|
2018
|
+
declare function resizeElement(elements: readonly PptxElement[], id: string, width: number, height: number): PptxElement[];
|
|
2019
|
+
/**
|
|
2020
|
+
* Remove all elements whose `id` is contained in `ids`.
|
|
2021
|
+
* Elements not in `ids` are returned in their original order.
|
|
2022
|
+
*
|
|
2023
|
+
* @example
|
|
2024
|
+
* deleteElementsByIds(elements, ['el1', 'el3'])
|
|
2025
|
+
*/
|
|
2026
|
+
declare function deleteElementsByIds(elements: readonly PptxElement[], ids: readonly string[]): PptxElement[];
|
|
2027
|
+
/**
|
|
2028
|
+
* Insert a copy of the element with `id` at the end of the array, using
|
|
2029
|
+
* `newId` as the copy's identity. The copy is nudged by `offset` on both
|
|
2030
|
+
* axes so it does not exactly overlap the original.
|
|
2031
|
+
*
|
|
2032
|
+
* The caller is responsible for supplying a unique `newId` — keeping this
|
|
2033
|
+
* function pure and deterministic.
|
|
2034
|
+
*
|
|
2035
|
+
* @example
|
|
2036
|
+
* duplicateElementById(elements, 'el1', crypto.randomUUID(), 20)
|
|
2037
|
+
*/
|
|
2038
|
+
declare function duplicateElementById(elements: readonly PptxElement[], id: string, newId: string, offset?: number): PptxElement[];
|
|
2039
|
+
/**
|
|
2040
|
+
* Move the element with `id` to the end of the array (top/front in paint order).
|
|
2041
|
+
*
|
|
2042
|
+
* @example
|
|
2043
|
+
* bringToFront(elements, 'el1')
|
|
2044
|
+
*/
|
|
2045
|
+
declare function bringToFront(elements: readonly PptxElement[], id: string): PptxElement[];
|
|
2046
|
+
/**
|
|
2047
|
+
* Move the element with `id` to index 0 (bottom/back in paint order).
|
|
2048
|
+
*
|
|
2049
|
+
* @example
|
|
2050
|
+
* sendToBack(elements, 'el1')
|
|
2051
|
+
*/
|
|
2052
|
+
declare function sendToBack(elements: readonly PptxElement[], id: string): PptxElement[];
|
|
2053
|
+
/**
|
|
2054
|
+
* Swap the element with `id` with the element one position higher in the
|
|
2055
|
+
* array (one step toward the front/top). No-op if already at the top.
|
|
2056
|
+
*
|
|
2057
|
+
* @example
|
|
2058
|
+
* bringForward(elements, 'el1')
|
|
2059
|
+
*/
|
|
2060
|
+
declare function bringForward(elements: readonly PptxElement[], id: string): PptxElement[];
|
|
2061
|
+
/**
|
|
2062
|
+
* Swap the element with `id` with the element one position lower in the
|
|
2063
|
+
* array (one step toward the back/bottom). No-op if already at the bottom.
|
|
2064
|
+
*
|
|
2065
|
+
* @example
|
|
2066
|
+
* sendBackward(elements, 'el1')
|
|
2067
|
+
*/
|
|
2068
|
+
declare function sendBackward(elements: readonly PptxElement[], id: string): PptxElement[];
|
|
2069
|
+
|
|
2070
|
+
/**
|
|
2071
|
+
* Pure paragraph bullet / list-marker helpers for the Angular text renderer.
|
|
2072
|
+
*
|
|
2073
|
+
* No Angular imports — all exports are plain TypeScript functions suitable for
|
|
2074
|
+
* use inside computed signals or template helper calls.
|
|
2075
|
+
*
|
|
2076
|
+
* Numbering schemes follow the OOXML `ST_TextAutonumberScheme` enumeration
|
|
2077
|
+
* (ECMA-376 §20.1.10.81). The `autoNumType` strings come from
|
|
2078
|
+
* `BulletInfo.autoNumType` as parsed by `pptx-viewer-core`.
|
|
2079
|
+
*/
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* Render the n-th (1-based) marker for an OOXML auto-numbering scheme.
|
|
2083
|
+
*
|
|
2084
|
+
* Suffix conventions:
|
|
2085
|
+
* - `…Period` → `label.` (e.g. "1.", "a.", "i.")
|
|
2086
|
+
* - `…ParenR` → `label)` (e.g. "1)", "a)", "i)")
|
|
2087
|
+
* - `…ParenBoth` → `(label)` (e.g. "(1)", "(a)", "(i)")
|
|
2088
|
+
* - `…Plain` → `label` (bare numeral)
|
|
2089
|
+
*
|
|
2090
|
+
* Unrecognised schemes fall back to `"<n>."`.
|
|
2091
|
+
*
|
|
2092
|
+
* @param autoNumType - The OOXML auto-number type string (e.g. "arabicPeriod").
|
|
2093
|
+
* @param n - 1-based sequence number to format.
|
|
2094
|
+
*/
|
|
2095
|
+
declare function formatAutoNumber(autoNumType: string | undefined, n: number): string;
|
|
2096
|
+
/**
|
|
2097
|
+
* Resolved bullet marker for a single paragraph.
|
|
2098
|
+
*
|
|
2099
|
+
* `marker` — the text to prepend (e.g. "•", "1.", "a)").
|
|
2100
|
+
* `isNumbered` — true for auto-numbered lists; false for character bullets.
|
|
2101
|
+
* `color` — optional explicit bullet colour (hex string from `BulletInfo.color`).
|
|
2102
|
+
* `fontFamily` — optional explicit bullet font (from `BulletInfo.fontFamily`).
|
|
2103
|
+
*/
|
|
2104
|
+
interface ParagraphBulletResult {
|
|
2105
|
+
marker: string;
|
|
2106
|
+
isNumbered: boolean;
|
|
2107
|
+
color?: string;
|
|
2108
|
+
fontFamily?: string;
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* Resolve the bullet marker for the first segment of a paragraph.
|
|
2112
|
+
*
|
|
2113
|
+
* Returns `undefined` when:
|
|
2114
|
+
* - `firstSegment` is undefined or carries no `bulletInfo`.
|
|
2115
|
+
* - `bulletInfo.none` is `true` (`a:buNone` explicitly suppresses the bullet).
|
|
2116
|
+
* - The paragraph's `listType` is `'none'`.
|
|
2117
|
+
* - Neither `char` nor `autoNumType` is present.
|
|
2118
|
+
*
|
|
2119
|
+
* For auto-numbered bullets the 1-based sequence index is derived from
|
|
2120
|
+
* `bulletInfo.autoNumStartAt` (default 1) plus `bulletInfo.paragraphIndex`
|
|
2121
|
+
* (0-based paragraph position within the text body).
|
|
2122
|
+
*
|
|
2123
|
+
* @param firstSegment - The first `TextSegment` of the paragraph (carries `bulletInfo`).
|
|
2124
|
+
*/
|
|
2125
|
+
declare function resolveParagraphBullet(firstSegment: TextSegment | undefined): ParagraphBulletResult | undefined;
|
|
2126
|
+
/**
|
|
2127
|
+
* Return the left-indent in pixels for the given list nesting level.
|
|
2128
|
+
*
|
|
2129
|
+
* `level` is the 0-based `paragraphLevel` from `TextSegment` (matches
|
|
2130
|
+
* OOXML `a:p/@lvl`). `undefined` or negative values are treated as level 0.
|
|
2131
|
+
*
|
|
2132
|
+
* @example
|
|
2133
|
+
* bulletIndentPx(0) // 0
|
|
2134
|
+
* bulletIndentPx(1) // 18
|
|
2135
|
+
* bulletIndentPx(3) // 54
|
|
2136
|
+
* bulletIndentPx(undefined) // 0
|
|
2137
|
+
*/
|
|
2138
|
+
declare function bulletIndentPx(level: number | undefined): number;
|
|
2139
|
+
|
|
2140
|
+
/**
|
|
2141
|
+
* EquationRendererComponent — Angular port of the Vue `EquationRenderer.vue`
|
|
2142
|
+
* (single-equation variant).
|
|
2143
|
+
*
|
|
2144
|
+
* Renders one parsed OMML equation tree as inline MathML via Angular's
|
|
2145
|
+
* `DomSanitizer.bypassSecurityTrustHtml`, which is required because Angular's
|
|
2146
|
+
* default HTML sanitizer strips `<math>` namespace markup.
|
|
2147
|
+
*
|
|
2148
|
+
* The wrapper is an inline-block `<span>` so the component flows inside a text
|
|
2149
|
+
* paragraph in place of a regular text run. When an equation number is
|
|
2150
|
+
* supplied the layout mirrors the Vue numbered-equation row: centred equation
|
|
2151
|
+
* with the number right-aligned (flex row, width 100%).
|
|
2152
|
+
*
|
|
2153
|
+
* Pure conversion logic lives in `omml-to-mathml.ts` (Angular-free) so it can
|
|
2154
|
+
* be unit-tested without TestBed.
|
|
2155
|
+
*/
|
|
2156
|
+
declare class EquationRendererComponent {
|
|
2157
|
+
/** Parsed OMML equation tree (the `equationXml` field of a `TextSegment`). */
|
|
2158
|
+
readonly equationXml: _angular_core.InputSignal<Record<string, unknown>>;
|
|
2159
|
+
/** Optional equation number shown right-aligned, e.g. `"1"` → `(1)`. */
|
|
2160
|
+
readonly equationNumber: _angular_core.InputSignal<string | undefined>;
|
|
2161
|
+
private readonly sanitizer;
|
|
2162
|
+
/**
|
|
2163
|
+
* Converts the OMML input to MathML and wraps it in a `SafeHtml` value so
|
|
2164
|
+
* Angular's `[innerHTML]` binding renders the `<math>` markup instead of
|
|
2165
|
+
* stripping it.
|
|
2166
|
+
*/
|
|
2167
|
+
readonly safeMathml: _angular_core.Signal<SafeHtml>;
|
|
2168
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EquationRendererComponent, never>;
|
|
2169
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EquationRendererComponent, "pptx-equation-renderer", never, { "equationXml": { "alias": "equationXml"; "required": true; "isSignal": true; }; "equationNumber": { "alias": "equationNumber"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
/**
|
|
2173
|
+
* omml-to-mathml.ts — pure OMML → MathML conversion.
|
|
2174
|
+
*
|
|
2175
|
+
* Angular port of the Vue `viewer/composables/omml-to-mathml.ts`, consolidated
|
|
2176
|
+
* into a single self-contained, framework-agnostic module. No Angular/Vue/DOM
|
|
2177
|
+
* dependencies.
|
|
2178
|
+
*
|
|
2179
|
+
* Converts Office MathML (OMML) XML objects — as parsed by fast-xml-parser
|
|
2180
|
+
* during PPTX load (attributes prefixed with `@_`) — into standard MathML
|
|
2181
|
+
* markup strings (`<math>…</math>`) that browsers render natively.
|
|
2182
|
+
*
|
|
2183
|
+
* `pptx-viewer-core` does NOT ship an OMML→MathML converter (its
|
|
2184
|
+
* `OmmlLatexConverter` only does OMML↔LaTeX), so this logic is ported here.
|
|
2185
|
+
*/
|
|
2186
|
+
|
|
2187
|
+
/**
|
|
2188
|
+
* A parsed OMML node. Structurally a parsed-XML object: attributes live under
|
|
2189
|
+
* `@_`-prefixed keys, children under their (namespaced) tag name, text under
|
|
2190
|
+
* `#text` (or a collapsed bare string). Aliased to core's `XmlObject`.
|
|
2191
|
+
*/
|
|
2192
|
+
type OmmlNode = XmlObject;
|
|
2193
|
+
/**
|
|
2194
|
+
* Convert an OMML XML node (from fast-xml-parser) into a MathML string.
|
|
2195
|
+
*
|
|
2196
|
+
* Accepts the object at the `<a14:m>` / `<m:oMathPara>` level or directly at
|
|
2197
|
+
* `<m:oMath>`. Returns a `<math>` element string, or empty string if the input
|
|
2198
|
+
* is empty / unparseable.
|
|
2199
|
+
*/
|
|
2200
|
+
declare function convertOmmlToMathMl(ommlNode: OmmlNode): string;
|
|
2201
|
+
/**
|
|
2202
|
+
* Convenience wrapper used by the Angular viewer: `ommlToMathml(omml)`.
|
|
2203
|
+
*
|
|
2204
|
+
* Accepts the parsed OMML object (the shape stored on
|
|
2205
|
+
* {@link TextSegment.equationXml}) or a raw OMML markup string. String inputs
|
|
2206
|
+
* are not re-parsed here (no XML parser dependency in this pure module) — they
|
|
2207
|
+
* are returned wrapped so callers can still surface raw markup if needed.
|
|
2208
|
+
*/
|
|
2209
|
+
declare function ommlToMathml(omml: Record<string, unknown> | string | undefined): string;
|
|
2210
|
+
|
|
2211
|
+
/**
|
|
2212
|
+
* Shape-geometry clip-path helper.
|
|
2213
|
+
*
|
|
2214
|
+
* Wires the core geometry APIs into the Angular viewer's shape clipping
|
|
2215
|
+
* pipeline. Implements a priority cascade so renderers always pick the
|
|
2216
|
+
* highest-fidelity geometry available for a given element:
|
|
2217
|
+
*
|
|
2218
|
+
* 1. **Adjustment-aware** — if `shapeAdjustments` exist, consult
|
|
2219
|
+
* {@link getAdjustmentAwareShapeClipPath} so shapes like `pie`, `arc`,
|
|
2220
|
+
* `donut`, `blockArc`, and the wedge callouts respond to their
|
|
2221
|
+
* adjustment values.
|
|
2222
|
+
* 2. **Spec-correct preset evaluator** — {@link getShapeClipPathFromPreset}
|
|
2223
|
+
* uses the ECMA-376 `pathLst` evaluator to produce a `path('…')`
|
|
2224
|
+
* clip-path for any shape covered by the preset table.
|
|
2225
|
+
* 3. **Cloud Bezier path** — {@link getCloudPathForRendering} produces a
|
|
2226
|
+
* DPI-stable cubic-Bezier `path('…')` for `cloud` / `cloudCallout`.
|
|
2227
|
+
* 4. **Static polygon table** — {@link getShapeClipPath} (the core preset
|
|
2228
|
+
* table) is the final fallback for shapes none of the higher-fidelity
|
|
2229
|
+
* APIs cover.
|
|
2230
|
+
*
|
|
2231
|
+
* This module is a plain-TypeScript port of the React package's
|
|
2232
|
+
* `viewer/utils/resolved-shape-clip-path.ts`, with no framework imports.
|
|
2233
|
+
* It mirrors the Vue port's `viewer/composables/shape-geometry.ts` exactly
|
|
2234
|
+
* so the exported function names and signatures are drop-in compatible.
|
|
2235
|
+
*/
|
|
2236
|
+
|
|
2237
|
+
/**
|
|
2238
|
+
* Resolve the best available CSS `clip-path` value for a shape type at a
|
|
2239
|
+
* given pixel size. Implements the priority cascade described in the module
|
|
2240
|
+
* docstring.
|
|
2241
|
+
*
|
|
2242
|
+
* @param shapeType The OOXML preset geometry name (case-insensitive).
|
|
2243
|
+
* @param width Element width in pixels (must be > 0 for path output).
|
|
2244
|
+
* @param height Element height in pixels (must be > 0 for path output).
|
|
2245
|
+
* @param adjustments Optional `shapeAdjustments` record from the element.
|
|
2246
|
+
* @returns A CSS `clip-path` value (`polygon(...)`, `path('…')`, or `inset(...)`),
|
|
2247
|
+
* or `undefined` if no clipping is needed.
|
|
2248
|
+
*/
|
|
2249
|
+
declare function getResolvedShapeClipPathFor(shapeType: string | undefined, width: number, height: number, adjustments?: Record<string, number>): string | undefined;
|
|
2250
|
+
/**
|
|
2251
|
+
* Element-level convenience wrapper. Pulls `shapeType`, `width`, `height`,
|
|
2252
|
+
* and `shapeAdjustments` off a {@link PptxElement} and delegates to
|
|
2253
|
+
* {@link getResolvedShapeClipPathFor}.
|
|
2254
|
+
*
|
|
2255
|
+
* @param element The PPTX element to resolve a clip-path for.
|
|
2256
|
+
* @param width Optional width override (pixels). Defaults to `element.width`.
|
|
2257
|
+
* @param height Optional height override (pixels). Defaults to `element.height`.
|
|
2258
|
+
* @returns A CSS `clip-path` value, or `undefined`.
|
|
2259
|
+
*/
|
|
2260
|
+
declare function getResolvedShapeClipPath(element: PptxElement, width?: number, height?: number): string | undefined;
|
|
2261
|
+
|
|
2262
|
+
/**
|
|
2263
|
+
* Slide-background style resolution.
|
|
2264
|
+
*
|
|
2265
|
+
* Maps a `PptxSlide`'s background fields to a `[ngStyle]`-compatible map for
|
|
2266
|
+
* the slide stage. Mirrors the React `SlideCanvas` background handling and the
|
|
2267
|
+
* Vue port: the core parser resolves the theme/master chain onto the slide, so
|
|
2268
|
+
* here we only translate the already-resolved fields to CSS.
|
|
2269
|
+
*
|
|
2270
|
+
* Precedence (highest first): image fill → gradient → pattern → solid colour.
|
|
2271
|
+
* Pattern fills currently approximate to their background colour (the SVG
|
|
2272
|
+
* pattern preset renderer — `color-patterns.ts` in React — is a shared
|
|
2273
|
+
* extraction candidate; see PORTING.md).
|
|
2274
|
+
*/
|
|
2275
|
+
|
|
2276
|
+
/** Default slide stage colour when a slide carries no usable background. */
|
|
2277
|
+
declare const DEFAULT_SLIDE_BACKGROUND = "#ffffff";
|
|
2278
|
+
/**
|
|
2279
|
+
* Build the background portion of the slide stage style from a slide's
|
|
2280
|
+
* resolved background fields. Returns only `background-*` properties so the
|
|
2281
|
+
* caller can spread it into the rest of the stage style.
|
|
2282
|
+
*/
|
|
2283
|
+
declare function getSlideBackgroundStyle(slide: PptxSlide | undefined): StyleMap;
|
|
2284
|
+
|
|
2285
|
+
/**
|
|
2286
|
+
* Hyperlink resolution + URL safety for the viewer.
|
|
2287
|
+
*
|
|
2288
|
+
* Viewer-first subset of the React `hyperlink-security.ts`: enough to render
|
|
2289
|
+
* safe `<a href>` links on text runs. Internal PowerPoint actions
|
|
2290
|
+
* (`ppaction://…` slide jumps) and unsafe protocols are not turned into
|
|
2291
|
+
* navigable hrefs here — slide-jump wiring is a follow-up (see PORTING.md).
|
|
2292
|
+
*/
|
|
2293
|
+
/**
|
|
2294
|
+
* Whether a URL is safe to expose as an `href`. Blocks `javascript:`,
|
|
2295
|
+
* `data:`, `vbscript:`, and `mhtml:` (case- and whitespace-bypass resistant);
|
|
2296
|
+
* allows `http(s)`, `mailto:`, `tel:`, `ftp:`, and relative URLs.
|
|
2297
|
+
*/
|
|
2298
|
+
declare function isUrlSafe(url: string | undefined): boolean;
|
|
2299
|
+
/** Whether a URL is a PowerPoint internal action (`ppaction://…`). */
|
|
2300
|
+
declare function isPpactionUrl(url: string | undefined): boolean;
|
|
2301
|
+
/**
|
|
2302
|
+
* Resolve a raw hyperlink value to a renderable, safe `href`, or `undefined`
|
|
2303
|
+
* when it should not be a plain link (empty, unsafe, or an internal
|
|
2304
|
+
* `ppaction://` slide jump).
|
|
2305
|
+
*/
|
|
2306
|
+
declare function resolveHyperlinkHref(url: string | undefined): string | undefined;
|
|
2307
|
+
|
|
2308
|
+
/**
|
|
2309
|
+
* Gradient fill CSS builder — pure TypeScript, no Angular dependency.
|
|
2310
|
+
*
|
|
2311
|
+
* Ported from `packages/react/src/viewer/utils/color-gradient.ts`.
|
|
2312
|
+
*
|
|
2313
|
+
* Handles sanitization of gradient stop arrays and conversion to CSS gradient
|
|
2314
|
+
* strings. Gradient rendering follows ECMA-376 Part 1, §20.1.8.35 (gradFill)
|
|
2315
|
+
* and §20.1.8.49 (pathFill). The three path types — circle, rect, shape — each
|
|
2316
|
+
* have dedicated builders that approximate the OOXML behaviour as closely as
|
|
2317
|
+
* CSS radial-gradient permits.
|
|
2318
|
+
*
|
|
2319
|
+
* Pattern fill (`a:pattFill`) is intentionally NOT included here — it lives in
|
|
2320
|
+
* a separate module.
|
|
2321
|
+
*/
|
|
2322
|
+
|
|
2323
|
+
/**
|
|
2324
|
+
* Builds a complete CSS `linear-gradient()` or `radial-gradient()` string
|
|
2325
|
+
* from a ShapeStyle's gradient properties.
|
|
2326
|
+
*
|
|
2327
|
+
* For radial gradients, the rendering varies by `fillGradientPathType`:
|
|
2328
|
+
* - `"circle"` (default): Simple circular radial gradient at the focal point.
|
|
2329
|
+
* - `"rect"`: Elliptical radial gradient sized from the fillToRect rectangle,
|
|
2330
|
+
* approximating the OOXML rectangular path gradient.
|
|
2331
|
+
* - `"shape"`: Radial gradient using farthest-side sizing, approximating a
|
|
2332
|
+
* gradient that follows the shape boundary.
|
|
2333
|
+
*
|
|
2334
|
+
* Falls back to `style.fillGradient` if no valid stops are present.
|
|
2335
|
+
*
|
|
2336
|
+
* @param style - The shape style containing gradient configuration.
|
|
2337
|
+
* @returns A CSS gradient string, or `undefined` if not a gradient fill.
|
|
2338
|
+
*/
|
|
2339
|
+
declare function buildCssGradientFromShapeStyle(style: ShapeStyle | undefined): string | undefined;
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* SVG pattern generation for OOXML pattern fill presets.
|
|
2343
|
+
*
|
|
2344
|
+
* Each preset maps to a tiled inline SVG data URI that closely approximates
|
|
2345
|
+
* the corresponding ECMA-376 pattern (ST_PresetPatternVal). Patterns use
|
|
2346
|
+
* two colours: foreground (`fg`) drawn on top of a background (`bg`) fill.
|
|
2347
|
+
*
|
|
2348
|
+
* Tile sizes are kept small (4-16 px) for performance when used as CSS
|
|
2349
|
+
* `background-image` data URIs.
|
|
2350
|
+
*
|
|
2351
|
+
* Reference: ECMA-376 Part 1, section 20.1.10.33 (ST_PresetPatternVal)
|
|
2352
|
+
*
|
|
2353
|
+
* Ported from `packages/react/src/viewer/utils/color-patterns.ts`.
|
|
2354
|
+
* Pure TypeScript — no Angular, Vue, or React runtime imports.
|
|
2355
|
+
*/
|
|
2356
|
+
|
|
2357
|
+
/**
|
|
2358
|
+
* Generate an inline SVG string for an OOXML preset pattern fill.
|
|
2359
|
+
*
|
|
2360
|
+
* @param preset - DrawingML `ST_PresetPatternVal` string (e.g. `"pct5"`, `"horz"`).
|
|
2361
|
+
* @param fgColor - Foreground hex colour (e.g. `"#000000"`).
|
|
2362
|
+
* @param bgColor - Background hex colour (e.g. `"#ffffff"`).
|
|
2363
|
+
* @returns An SVG string for use as a tiled `background-image`, or `undefined`
|
|
2364
|
+
* when the preset is not implemented.
|
|
2365
|
+
*/
|
|
2366
|
+
declare function getPatternSvg(preset: string, fgColor: string, bgColor: string): string | undefined;
|
|
2367
|
+
/**
|
|
2368
|
+
* Build CSS `background-image` and `background-color` values for an OOXML
|
|
2369
|
+
* pattern fill (`a:pattFill`) from a resolved `ShapeStyle`.
|
|
2370
|
+
*
|
|
2371
|
+
* Returns `undefined` when:
|
|
2372
|
+
* - `style` is absent,
|
|
2373
|
+
* - `style.fillMode` is not `"pattern"`,
|
|
2374
|
+
* - `style.fillPatternPreset` is missing, or
|
|
2375
|
+
* - the preset is not implemented by `getPatternSvg`.
|
|
2376
|
+
*
|
|
2377
|
+
* Colour values are hex-normalised before being passed to `getPatternSvg` so
|
|
2378
|
+
* the SVG is always well-formed even when the parser emits bare colour strings
|
|
2379
|
+
* without a leading `#`.
|
|
2380
|
+
*
|
|
2381
|
+
* @param style - Resolved shape style from the core parser.
|
|
2382
|
+
* @returns `{ backgroundImage, backgroundColor }` ready for `[ngStyle]`, or
|
|
2383
|
+
* `undefined` when pattern rendering is not applicable.
|
|
2384
|
+
*/
|
|
2385
|
+
declare function buildPatternFillCss(style: ShapeStyle | undefined): {
|
|
2386
|
+
backgroundImage: string;
|
|
2387
|
+
backgroundColor: string;
|
|
2388
|
+
} | undefined;
|
|
2389
|
+
|
|
365
2390
|
/**
|
|
366
2391
|
* Theme system for the Angular PowerPoint viewer.
|
|
367
2392
|
*
|
|
@@ -402,5 +2427,5 @@ declare function themeStyle(theme: ViewerTheme | undefined): Record<string, stri
|
|
|
402
2427
|
type ClassValue = string | number | false | null | undefined;
|
|
403
2428
|
declare function cn(...values: ClassValue[]): string;
|
|
404
2429
|
|
|
405
|
-
export { DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, ElementRendererComponent, LoadContentService, PowerPointViewerComponent, SlideCanvasComponent, VIEWER_THEME, cn, defaultCssVars, defaultRadius, defaultThemeColors, getContainerStyle, getImageSrc, getShapeFillStrokeStyle, getTextBlockStyle, provideViewerTheme, themeStyle, themeToCssVars };
|
|
406
|
-
export type { CanvasSize, ClassValue, CollaborationConfig, CollaborationRole, StyleMap, ViewerTheme, ViewerThemeColors };
|
|
2430
|
+
export { ChartRendererComponent, ConnectorRendererComponent, DEFAULT_CANVAS_HEIGHT, DEFAULT_CANVAS_WIDTH, DEFAULT_FILL_COLOR, DEFAULT_SLIDE_BACKGROUND, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR, EditorContextMenuComponent, EditorHistory, EditorStateService, EditorToolbarComponent, ElementRendererComponent, EquationRendererComponent, ExportService, FindBarComponent, InkRendererComponent, InspectorPanelComponent, LoadContentService, Model3DRendererComponent, OleRendererComponent, PowerPointViewerComponent, PresentationOverlayComponent, RESIZE_HANDLES, SlideCanvasComponent, SlideSorterOverlayComponent, SlidesPanelComponent, SmartArtRendererComponent, TableRendererComponent, VIEWER_THEME, ZoomRendererComponent, applyMove, applyResize, bringForward, bringToFront, buildCssGradientFromShapeStyle, buildPatternFillCss, bulletIndentPx, cn, collectElementText, collectSlideText, convertOmmlToMathMl, defaultCssVars, defaultRadius, defaultThemeColors, deleteElementsByIds, duplicateElementById, formatAutoNumber, getContainerStyle, getImageSrc, getPatternSvg, getResolvedShapeClipPath, getResolvedShapeClipPathFor, getShapeFillStrokeStyle, getSlideBackgroundStyle, getTextBlockStyle, isPpactionUrl, isUrlSafe, moveElementBy, ommlToMathml, provideViewerTheme, renderToCanvas, resizeElement, resolveHyperlinkHref, resolveParagraphBullet, searchSlides, sendBackward, sendToBack, setElementPosition, themeStyle, themeToCssVars, updateElementById };
|
|
2431
|
+
export type { Box, CanvasSize, ClassValue, CollaborationConfig, CollaborationRole, ResizeHandle, StyleMap, ViewerTheme, ViewerThemeColors };
|