pptx-angular-viewer 4.10.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/fesm2022/{pptx-angular-viewer-chart-3d-view-scene-CkW1D-mg.mjs → pptx-angular-viewer-chart-3d-view-scene-Cfk7dMVK.mjs} +111 -24
- package/fesm2022/pptx-angular-viewer-chart-3d-view-scene-Cfk7dMVK.mjs.map +1 -0
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-BboVG09q.mjs → pptx-angular-viewer-chat-history-idb-BnV3ANp_.mjs} +2 -2
- package/fesm2022/{pptx-angular-viewer-chat-history-idb-BboVG09q.mjs.map → pptx-angular-viewer-chat-history-idb-BnV3ANp_.mjs.map} +1 -1
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-BWuuwItt.mjs → pptx-angular-viewer-pptx-angular-viewer-Dy62s3Dt.mjs} +160 -3136
- package/fesm2022/{pptx-angular-viewer-pptx-angular-viewer-BWuuwItt.mjs.map → pptx-angular-viewer-pptx-angular-viewer-Dy62s3Dt.mjs.map} +1 -1
- package/fesm2022/{pptx-angular-viewer-view-scene-BJXZicXV.mjs → pptx-angular-viewer-view-scene-CNlGt3WC.mjs} +3 -3
- package/fesm2022/{pptx-angular-viewer-view-scene-BJXZicXV.mjs.map → pptx-angular-viewer-view-scene-CNlGt3WC.mjs.map} +1 -1
- package/fesm2022/pptx-angular-viewer.mjs +1 -1
- package/package.json +2 -2
- package/types/pptx-angular-viewer.d.ts +18 -502
- package/types/pptx-angular-viewer.d.ts.map +1 -1
- package/fesm2022/pptx-angular-viewer-chart-3d-view-scene-CkW1D-mg.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,25 @@ A release listed with no entries carried no Conventional Commit in this package'
|
|
|
7
7
|
scope: scripts/release-plan.mjs re-releases a package whenever any of its files
|
|
8
8
|
change, not only on conventional ones.
|
|
9
9
|
|
|
10
|
+
## [4.10.1](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@4.10.1) - 2026-09-26
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **shared:** Fit SmartArt light rigs' key light under a scene camera (by @claude) ([91394b0](https://github.com/ChristopherVR/pptx-viewer/commit/91394b03ee8f68536e8099e15997465b0d257a95))
|
|
15
|
+
- **shared:** Keep a 3D view's scene across a move and a same-task re-attach (by @claude) ([5bc411c](https://github.com/ChristopherVR/pptx-viewer/commit/5bc411cb3ba2d0613bddb678be7c5eae3972d806))
|
|
16
|
+
|
|
17
|
+
## [4.10.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@4.10.0) - 2026-09-26
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- **core:** Style regenerated SmartArt shapes by their own style label (by @claude) ([67ea2fb](https://github.com/ChristopherVR/pptx-viewer/commit/67ea2fbe0efdded17cb3cfce73921dcef8712d85))
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
- **shared:** Page slides with Up, Down, PageUp and PageDown in the editor (by @claude) ([c0cc4dc](https://github.com/ChristopherVR/pptx-viewer/commit/c0cc4dcdff6525e06aac39f7091723aa3bb9d882))
|
|
26
|
+
- **core:** Draw a merged SmartArt text node's labels in its own colour (by @claude) ([7e6232d](https://github.com/ChristopherVR/pptx-viewer/commit/7e6232d6b8115f448c328db4a1a8478c2a934345))
|
|
27
|
+
- **shared:** Blend translucent SmartArt solids once and draw clear as glass (by @claude) ([52128d7](https://github.com/ChristopherVR/pptx-viewer/commit/52128d737ebf2b3b3c37ccd60edc4ccd5fa9ea20))
|
|
28
|
+
|
|
10
29
|
## [4.9.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-angular-viewer@4.9.0) - 2026-09-25
|
|
11
30
|
|
|
12
31
|
### Features
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as shade, c as createSvgEl, a as appendChartLegendSvg, r as renderChartLineSvg, b as renderChartTextSvg,
|
|
1
|
+
import { s as shade, c as createSvgEl, a as appendChartLegendSvg, r as renderChartLineSvg, b as renderChartTextSvg, d as buildBarChart3DHoverTooltip, i as isChartInteractionArmed, e as roundDragValue, o as obliqueBarTaper, p as perspBoxMatrix, D as DEFAULT_PALETTE, f as buildPerspCamera, g as perspToScreen, h as pieRimPoint, j as computePieChartLayout, k as perspScreenToPlaneY, l as resolvePieSliceShareValue, w as widenPieViewModel } from './pptx-angular-viewer-pptx-angular-viewer-Dy62s3Dt.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* chart-3d-shading.ts: PowerPoint's flat chart-space shading for a 3D chart's
|
|
@@ -383,6 +383,70 @@ function appendBoxLabels(doc, svg, vm, labels) {
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Minimum pointer travel (px) before a mark press becomes a value drag,
|
|
388
|
+
* mirroring {@link CHART_DRAG_THRESHOLD_PX} (`chart-canvas-drag.ts`): without
|
|
389
|
+
* a threshold, every click on a mark would commit a (tiny) value change, so a
|
|
390
|
+
* user could never select a mark without editing it.
|
|
391
|
+
*/
|
|
392
|
+
const CHART_3D_DRAG_THRESHOLD_PX = 3;
|
|
393
|
+
/** Emissive colour + intensity applied to a selected mark's material. */
|
|
394
|
+
const CHART_3D_SELECTED_EMISSIVE = '#3b82f6';
|
|
395
|
+
const CHART_3D_SELECTED_EMISSIVE_INTENSITY = 0.55;
|
|
396
|
+
/**
|
|
397
|
+
* Map a 3D raycast hit (or none) to the same selection descriptor the 2D
|
|
398
|
+
* chart-interaction model uses.
|
|
399
|
+
*/
|
|
400
|
+
function chart3DHitToPartRef(hit) {
|
|
401
|
+
if (!hit) {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
return { role: 'dataPoint', seriesIndex: hit.seriesIndex, pointIndex: hit.pointIndex };
|
|
405
|
+
}
|
|
406
|
+
/** Whether a mesh's own (series, point) reference is the currently-selected part. */
|
|
407
|
+
function chart3DMarkMatchesPart(mark, part) {
|
|
408
|
+
return (part !== null &&
|
|
409
|
+
part !== undefined &&
|
|
410
|
+
part.role === 'dataPoint' &&
|
|
411
|
+
part.seriesIndex === mark.seriesIndex &&
|
|
412
|
+
part.pointIndex === mark.pointIndex);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Calibrate a value axis from two already-projected screen points known to
|
|
416
|
+
* correspond to two distinct data values on the same mark (e.g. its
|
|
417
|
+
* value-zero base and its current top). Returns `null` when the two values
|
|
418
|
+
* coincide or the two screen points are (near) coincident (camera looking
|
|
419
|
+
* straight down the axis), since no calibration is possible.
|
|
420
|
+
*
|
|
421
|
+
* Order-independent: swapping `(screenAtValue0, value0)` with
|
|
422
|
+
* `(screenAtValue1, value1)` yields the same {@link chart3DPointerDeltaToValueDelta}
|
|
423
|
+
* result, since the direction vector and `pixelsPerUnit` sign flip together.
|
|
424
|
+
*/
|
|
425
|
+
function calibrateChart3DValueAxis(screenAtValue0, value0, screenAtValue1, value1) {
|
|
426
|
+
const valueSpan = value1 - value0;
|
|
427
|
+
const dx = screenAtValue1.x - screenAtValue0.x;
|
|
428
|
+
const dy = screenAtValue1.y - screenAtValue0.y;
|
|
429
|
+
const pixelSpan = Math.hypot(dx, dy);
|
|
430
|
+
if (valueSpan === 0 || pixelSpan < 1e-6 || !Number.isFinite(valueSpan)) {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
directionScreen: { x: dx / pixelSpan, y: dy / pixelSpan },
|
|
435
|
+
pixelsPerUnit: pixelSpan / valueSpan,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Convert a screen-space pointer delta (current position minus drag-start
|
|
440
|
+
* position, in CSS px) into a value delta, using a calibration taken at drag
|
|
441
|
+
* start. Add the result to the mark's value at drag start to get the live
|
|
442
|
+
* (or committed) dragged value.
|
|
443
|
+
*/
|
|
444
|
+
function chart3DPointerDeltaToValueDelta(calibration, pointerDeltaScreen) {
|
|
445
|
+
const dot = pointerDeltaScreen.x * calibration.directionScreen.x +
|
|
446
|
+
pointerDeltaScreen.y * calibration.directionScreen.y;
|
|
447
|
+
return dot / calibration.pixelsPerUnit;
|
|
448
|
+
}
|
|
449
|
+
|
|
386
450
|
function partOf(point) {
|
|
387
451
|
return point
|
|
388
452
|
? { role: 'dataPoint', seriesIndex: point.seriesIndex, pointIndex: point.pointIndex }
|
|
@@ -683,6 +747,7 @@ function buildPerspBarPrisms(chartData, layout, override) {
|
|
|
683
747
|
neg = to;
|
|
684
748
|
}
|
|
685
749
|
}
|
|
750
|
+
const shape = chartData.series[s]?.shape ?? chartData.barShape ?? 'box';
|
|
686
751
|
const slotIndex = layout.grouping === 'clustered' ? s : 0;
|
|
687
752
|
const row = layout.grouping === 'standard' ? s : 0;
|
|
688
753
|
const c0 = c * slot + (gapWidth * barW) / 2 + slotIndex * barW;
|
|
@@ -705,6 +770,9 @@ function buildPerspBarPrisms(chartData, layout, override) {
|
|
|
705
770
|
],
|
|
706
771
|
z0,
|
|
707
772
|
z1: z0 + depth,
|
|
773
|
+
shape,
|
|
774
|
+
taper: obliqueBarTaper(shape, v0, v1, (layout.range.max - layout.range.min) * layout.valueScale, raw),
|
|
775
|
+
horizontal: layout.horizontal,
|
|
708
776
|
});
|
|
709
777
|
}
|
|
710
778
|
}
|
|
@@ -797,6 +865,44 @@ function buildPerspPrisms(chartData, layout, override) {
|
|
|
797
865
|
return prisms;
|
|
798
866
|
}
|
|
799
867
|
|
|
868
|
+
/** Whether a prism is drawn as a shaped solid rather than an extrusion. */
|
|
869
|
+
function isShapedPerspPrism(prism) {
|
|
870
|
+
return prism.shape !== undefined && prism.shape !== 'box';
|
|
871
|
+
}
|
|
872
|
+
/** The prism's box-space bounding box: `[x0, x1, y0, y1]`. */
|
|
873
|
+
function outlineBounds(prism) {
|
|
874
|
+
const xs = prism.outline.map(([x]) => x);
|
|
875
|
+
const ys = prism.outline.map(([, y]) => y);
|
|
876
|
+
return [Math.min(...xs), Math.max(...xs), Math.min(...ys), Math.max(...ys)];
|
|
877
|
+
}
|
|
878
|
+
/** A shaped bar's geometry in box space, with shading baked into vertex colours. */
|
|
879
|
+
function buildShapedPrismGeometry(three, prism) {
|
|
880
|
+
const shape = prism.shape ?? 'box';
|
|
881
|
+
const unit = buildObliqueShapeGeometry(three, { shape, taper: prism.taper ?? { bottom: 1, top: 1 } }, Boolean(prism.horizontal));
|
|
882
|
+
const geometry = unit.index ? unit.toNonIndexed() : unit;
|
|
883
|
+
if (geometry !== unit) {
|
|
884
|
+
unit.dispose();
|
|
885
|
+
}
|
|
886
|
+
const [x0, x1, y0, y1] = outlineBounds(prism);
|
|
887
|
+
const sx = Math.max(x1 - x0, 1e-6);
|
|
888
|
+
const sy = Math.max(y1 - y0, 1e-6);
|
|
889
|
+
const sz = Math.max(prism.z1 - prism.z0, 1e-6);
|
|
890
|
+
geometry.scale(sx, sy, sz);
|
|
891
|
+
geometry.translate((x0 + x1) / 2, (y0 + y1) / 2, (prism.z0 + prism.z1) / 2);
|
|
892
|
+
geometry.computeVertexNormals();
|
|
893
|
+
const normals = geometry.getAttribute('normal');
|
|
894
|
+
const colors = new Float32Array(normals.count * 3);
|
|
895
|
+
const base = new three.Color(prism.color).getRGB(new three.Color(), three.SRGBColorSpace);
|
|
896
|
+
const out = new three.Color();
|
|
897
|
+
for (let i = 0; i < normals.count; i++) {
|
|
898
|
+
const f = chart3DNormalShade(shape, normals.getX(i), normals.getY(i), -normals.getZ(i));
|
|
899
|
+
out.setRGB(Math.min(1, base.r * f), Math.min(1, base.g * f), Math.min(1, base.b * f), three.SRGBColorSpace);
|
|
900
|
+
colors.set([out.r, out.g, out.b], i * 3);
|
|
901
|
+
}
|
|
902
|
+
geometry.setAttribute('color', new three.Float32BufferAttribute(colors, 3));
|
|
903
|
+
return geometry;
|
|
904
|
+
}
|
|
905
|
+
|
|
800
906
|
/** PowerPoint's default major gridline colour (tx1 at 15% tint, `#D9D9D9`). */
|
|
801
907
|
const GRIDLINE_COLOR = 0xd9d9d9;
|
|
802
908
|
/** Bake face shading into a geometry's vertex colours. */
|
|
@@ -817,6 +923,9 @@ function shadePerspGeometry(three, geometry, color) {
|
|
|
817
923
|
}
|
|
818
924
|
/** An extruded, shaded prism geometry in box space. */
|
|
819
925
|
function buildPrismGeometry(three, prism) {
|
|
926
|
+
if (isShapedPerspPrism(prism)) {
|
|
927
|
+
return buildShapedPrismGeometry(three, prism);
|
|
928
|
+
}
|
|
820
929
|
const shape = new three.Shape(prism.outline.map(([x, y]) => new three.Vector2(x, y)));
|
|
821
930
|
const extruded = new three.ExtrudeGeometry(shape, {
|
|
822
931
|
depth: Math.max(prism.z1 - prism.z0, 1e-6),
|
|
@@ -1612,25 +1721,6 @@ function buildObliqueCamera(three, svgWidth, svgHeight, shearX, shearY) {
|
|
|
1612
1721
|
camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
|
|
1613
1722
|
return camera;
|
|
1614
1723
|
}
|
|
1615
|
-
/** The hosted perspective scene for a spec whose oblique geometry is `null`. */
|
|
1616
|
-
function mountPerspectiveScene(perspective, ctx) {
|
|
1617
|
-
switch (perspective.kind) {
|
|
1618
|
-
case 'bar':
|
|
1619
|
-
return createBarChart3DScene(ctx, perspective.options);
|
|
1620
|
-
case 'line':
|
|
1621
|
-
return createLineChart3DScene(ctx, perspective.options);
|
|
1622
|
-
case 'area':
|
|
1623
|
-
return createAreaChart3DScene(ctx, perspective.options);
|
|
1624
|
-
case 'pie':
|
|
1625
|
-
return createPieChart3DScene(ctx, perspective.options);
|
|
1626
|
-
case 'surface':
|
|
1627
|
-
return createSurfaceChart3DScene(ctx, perspective.options);
|
|
1628
|
-
default: {
|
|
1629
|
-
const exhaustive = perspective;
|
|
1630
|
-
return exhaustive;
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
1724
|
async function mountChart3DView(spec, ctx) {
|
|
1635
1725
|
if (spec.geometry?.kind === 'pie') {
|
|
1636
1726
|
const chartData = spec.element.chartData;
|
|
@@ -1653,9 +1743,6 @@ async function mountChart3DView(spec, ctx) {
|
|
|
1653
1743
|
return mountPerspChartView({ vm: spec.vm, layout: spec.geometry.layout, chartData, categoryLabels: spec.categoryLabels }, ctx);
|
|
1654
1744
|
}
|
|
1655
1745
|
if (spec.projection.mode !== 'oblique' || spec.geometry?.kind !== 'oblique') {
|
|
1656
|
-
if (spec.perspective) {
|
|
1657
|
-
return mountPerspectiveScene(spec.perspective, ctx);
|
|
1658
|
-
}
|
|
1659
1746
|
throw new Error(`no 3D chart scene for chartType=${spec.chartType}`);
|
|
1660
1747
|
}
|
|
1661
1748
|
const three = ctx.three;
|
|
@@ -1714,4 +1801,4 @@ async function mountChart3DView(spec, ctx) {
|
|
|
1714
1801
|
}
|
|
1715
1802
|
|
|
1716
1803
|
export { buildObliqueCamera, mountChart3DView };
|
|
1717
|
-
//# sourceMappingURL=pptx-angular-viewer-chart-3d-view-scene-
|
|
1804
|
+
//# sourceMappingURL=pptx-angular-viewer-chart-3d-view-scene-Cfk7dMVK.mjs.map
|