@embedpdf/plugin-stage 3.0.0-next.10 → 3.0.0-next.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/dist/contract-BU33R4oL.cjs +13 -0
- package/dist/contract-BU33R4oL.cjs.map +1 -0
- package/dist/contract-CPSX8ANN.js +8 -0
- package/dist/contract-CPSX8ANN.js.map +1 -0
- package/dist/contract.cjs +10 -0
- package/dist/contract.d.cts +3 -0
- package/dist/contract.d.ts +3 -0
- package/dist/contract.js +2 -0
- package/dist/destination.cjs +147 -0
- package/dist/destination.cjs.map +1 -0
- package/dist/destination.d.cts +19 -0
- package/dist/destination.d.ts +19 -0
- package/dist/destination.js +146 -0
- package/dist/destination.js.map +1 -0
- package/dist/index.cjs +117 -158
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -657
- package/dist/index.d.ts +6 -657
- package/dist/index.js +117 -158
- package/dist/index.js.map +1 -1
- package/dist/types-CdIFKQnj.d.ts +656 -0
- package/dist/types-qdO_v-V-.d.cts +656 -0
- package/package.json +16 -6
package/dist/index.cjs
CHANGED
|
@@ -21,7 +21,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
+
const require_destination = require("./destination.cjs");
|
|
25
|
+
const require_contract = require("./contract-BU33R4oL.cjs");
|
|
24
26
|
let _embedpdf_core = require("@embedpdf/core");
|
|
27
|
+
let _embedpdf_plugin_actions_contract = require("@embedpdf/plugin-actions/contract");
|
|
28
|
+
let _embedpdf_plugin_actions_contract_host = require("@embedpdf/plugin-actions/contract/host");
|
|
25
29
|
let _embedpdf_core_stage = require("@embedpdf/core-stage");
|
|
26
30
|
_embedpdf_core_stage = __toESM(_embedpdf_core_stage, 1);
|
|
27
31
|
let _embedpdf_core_geometry = require("@embedpdf/core-geometry");
|
|
@@ -854,7 +858,16 @@ function createStageCapability(ctx, config = {}) {
|
|
|
854
858
|
if (isFitAll()) goToTarget(ctx.getState().cursor, { behavior: "instant" });
|
|
855
859
|
else applyAnchor(anchor, align);
|
|
856
860
|
};
|
|
861
|
+
/** Tag what drives the NEXT camera/cursor change — dispatched on flips
|
|
862
|
+
* only, read by the page-state feed (see StageState.motionCause). */
|
|
863
|
+
const markCause = (cause) => {
|
|
864
|
+
if (ctx.getState().motionCause !== cause) ctx.dispatch({
|
|
865
|
+
type: "MOTION_CAUSE",
|
|
866
|
+
cause
|
|
867
|
+
});
|
|
868
|
+
};
|
|
857
869
|
const goToTarget = (pageIndex, opts) => {
|
|
870
|
+
markCause("programmatic");
|
|
858
871
|
cancelAnim();
|
|
859
872
|
const doc = ctx.document();
|
|
860
873
|
if (!doc || doc.pageCount === 0) return;
|
|
@@ -1232,11 +1245,13 @@ function createStageCapability(ctx, config = {}) {
|
|
|
1232
1245
|
});
|
|
1233
1246
|
},
|
|
1234
1247
|
setCamera: (c) => {
|
|
1248
|
+
markCause("user");
|
|
1235
1249
|
cancelAnim();
|
|
1236
1250
|
setCam(c);
|
|
1237
1251
|
syncCursorFromCamera();
|
|
1238
1252
|
},
|
|
1239
1253
|
panBy: (dx, dy) => {
|
|
1254
|
+
markCause("user");
|
|
1240
1255
|
cancelAnim();
|
|
1241
1256
|
if (gestureDepth > 0 && gestureElastic) {
|
|
1242
1257
|
gestureRaw = _embedpdf_core_stage.panByScreen(gestureRaw ?? unrubberize(cam()), dx, dy);
|
|
@@ -1245,6 +1260,7 @@ function createStageCapability(ctx, config = {}) {
|
|
|
1245
1260
|
syncCursorFromCamera();
|
|
1246
1261
|
},
|
|
1247
1262
|
scrollTo: (opts) => {
|
|
1263
|
+
markCause("user");
|
|
1248
1264
|
cancelAnim();
|
|
1249
1265
|
if (!buildScene().itemCount) return;
|
|
1250
1266
|
const next = _embedpdf_core_stage.cameraFromScroll(cam(), stayBounds(), vp(), pad(), opts);
|
|
@@ -1347,6 +1363,7 @@ function createStageCapability(ctx, config = {}) {
|
|
|
1347
1363
|
},
|
|
1348
1364
|
goToPage: (pageIndex, opts) => goToTarget(pageIndex, opts),
|
|
1349
1365
|
reveal: (pageIndex, opts) => {
|
|
1366
|
+
markCause("programmatic");
|
|
1350
1367
|
const doc = ctx.document();
|
|
1351
1368
|
if (!doc || doc.pageCount === 0) return;
|
|
1352
1369
|
const target = Math.max(0, Math.min(pageIndex, doc.pageCount - 1));
|
|
@@ -1488,22 +1505,51 @@ function createStageCapability(ctx, config = {}) {
|
|
|
1488
1505
|
//#endregion
|
|
1489
1506
|
//#region src/effects.ts
|
|
1490
1507
|
/**
|
|
1491
|
-
*
|
|
1492
|
-
* (rotate/move/delete bump `DocumentMeta.revision`), the page geometry under
|
|
1493
|
-
* this lens just changed, so re-fit — re-resolve the active zoom intent and
|
|
1494
|
-
* re-place against the new footprint.
|
|
1508
|
+
* Stage lens effects.
|
|
1495
1509
|
*
|
|
1496
|
-
*
|
|
1497
|
-
*
|
|
1498
|
-
*
|
|
1499
|
-
* only
|
|
1510
|
+
* 1. Re-fit on page-registry mutations: when rotate/move/delete bump
|
|
1511
|
+
* `DocumentMeta.revision`, the page geometry under this lens changed, so
|
|
1512
|
+
* re-resolve the active zoom intent and re-place against the new
|
|
1513
|
+
* footprint. Steady-state only — it reacts to revision CHANGES, never the
|
|
1514
|
+
* initial value, so it can't race the capability's level-triggered
|
|
1515
|
+
* initial placement.
|
|
1500
1516
|
*
|
|
1501
|
-
*
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1517
|
+
* 2. The page-state feed (main lens only, actions plugin present): stage is
|
|
1518
|
+
* AUTHORITATIVE for what page the viewer is on; the action engine's
|
|
1519
|
+
* lifecycle coordinator owns WHEN page-lifecycle triggers fire. This feed
|
|
1520
|
+
* pushes `{ currentPon, visiblePons, placed, cause }` snapshots — pons,
|
|
1521
|
+
* not indexes (reorder-safe) — on placement and on every change; the
|
|
1522
|
+
* coordinator buffers them behind the document-open barrier and diffs
|
|
1523
|
+
* against its last-emitted state, so this side stays a dumb reporter.
|
|
1504
1524
|
*/
|
|
1505
|
-
function registerStageEffects(ctx, token) {
|
|
1525
|
+
function registerStageEffects(ctx, token, feedActions = false) {
|
|
1506
1526
|
ctx.watch(() => ctx.document()?.revision ?? 0, () => ctx.get(token).refit());
|
|
1527
|
+
if (!feedActions) return;
|
|
1528
|
+
const actions = ctx.tryGet(_embedpdf_plugin_actions_contract_host.ActionsToken);
|
|
1529
|
+
if (!actions) return;
|
|
1530
|
+
const snapshot = () => {
|
|
1531
|
+
const state = ctx.getState();
|
|
1532
|
+
if (!state.placed) return null;
|
|
1533
|
+
const stage = ctx.get(token);
|
|
1534
|
+
return {
|
|
1535
|
+
currentPon: stage.pages()[state.cursor]?.pon ?? null,
|
|
1536
|
+
visiblePons: stage.visiblePages().map((page) => page.pon),
|
|
1537
|
+
cause: state.motionCause
|
|
1538
|
+
};
|
|
1539
|
+
};
|
|
1540
|
+
ctx.watch(() => {
|
|
1541
|
+
const s = snapshot();
|
|
1542
|
+
return s === null ? "unplaced" : `${s.currentPon ?? -1}|${[...s.visiblePons].sort((a, b) => a - b).join(",")}`;
|
|
1543
|
+
}, () => {
|
|
1544
|
+
const s = snapshot();
|
|
1545
|
+
if (s === null) return;
|
|
1546
|
+
actions.reportPageState({
|
|
1547
|
+
currentPon: s.currentPon,
|
|
1548
|
+
visiblePons: s.visiblePons,
|
|
1549
|
+
placed: true,
|
|
1550
|
+
cause: s.cause
|
|
1551
|
+
});
|
|
1552
|
+
});
|
|
1507
1553
|
}
|
|
1508
1554
|
//#endregion
|
|
1509
1555
|
//#region src/reducer.ts
|
|
@@ -1523,6 +1569,7 @@ const initialStageState = (config) => {
|
|
|
1523
1569
|
},
|
|
1524
1570
|
dpr: 1,
|
|
1525
1571
|
cursor: 0,
|
|
1572
|
+
motionCause: "user",
|
|
1526
1573
|
activeRules: [],
|
|
1527
1574
|
...DEFAULT_SETTINGS,
|
|
1528
1575
|
...overrides
|
|
@@ -1569,6 +1616,10 @@ const stageReducer = (state, a) => {
|
|
|
1569
1616
|
...state,
|
|
1570
1617
|
cursor: a.cursor
|
|
1571
1618
|
};
|
|
1619
|
+
case "MOTION_CAUSE": return {
|
|
1620
|
+
...state,
|
|
1621
|
+
motionCause: a.cause
|
|
1622
|
+
};
|
|
1572
1623
|
case "PATCH": return applyPatch(state, a.patch);
|
|
1573
1624
|
case "RESPONSIVE": return {
|
|
1574
1625
|
...state,
|
|
@@ -1578,9 +1629,6 @@ const stageReducer = (state, a) => {
|
|
|
1578
1629
|
}
|
|
1579
1630
|
};
|
|
1580
1631
|
//#endregion
|
|
1581
|
-
//#region src/types.ts
|
|
1582
|
-
const StageToken = (0, _embedpdf_core.createCapabilityToken)("stage");
|
|
1583
|
-
//#endregion
|
|
1584
1632
|
//#region src/stage.plugin.ts
|
|
1585
1633
|
/**
|
|
1586
1634
|
* Wires the parts into a kernel plugin. This file is the "manifest": it says what
|
|
@@ -1588,159 +1636,70 @@ const StageToken = (0, _embedpdf_core.createCapabilityToken)("stage");
|
|
|
1588
1636
|
* sibling files.
|
|
1589
1637
|
*/
|
|
1590
1638
|
const stagePlugin = (options = {}) => {
|
|
1591
|
-
const { id = "stage", token = StageToken, ...config } = options;
|
|
1639
|
+
const { id = "stage", token = require_contract.StageToken, ...config } = options;
|
|
1592
1640
|
return (0, _embedpdf_core.definePlugin)({
|
|
1593
1641
|
id,
|
|
1594
1642
|
token,
|
|
1595
1643
|
scope: "document",
|
|
1644
|
+
optional: [_embedpdf_plugin_actions_contract.ActionsToken],
|
|
1596
1645
|
initialState: () => initialStageState(config),
|
|
1597
1646
|
reduce: stageReducer,
|
|
1598
1647
|
capability: (ctx) => createStageCapability(ctx, config),
|
|
1599
|
-
effects: (ctx) => registerStageEffects(ctx, token)
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
* resolve (engine-side) to an explicit `PdfDestination`; this maps it onto
|
|
1609
|
-
* ONE `reveal(pageIndex, options)` call — no destination-specific camera
|
|
1610
|
-
* code exists anywhere else.
|
|
1611
|
-
*
|
|
1612
|
-
* The whole protocol collapses onto three knobs:
|
|
1613
|
-
* rect — what to look at (a point for /XYZ, a rect for /FitR, the
|
|
1614
|
-
* page for /Fit, the content bounding box for /FitB*)
|
|
1615
|
-
* zoom — 'keep' | {level} | 'fit' | 'fit-width' | 'fit-height'
|
|
1616
|
-
* anchor — where it lands; 'keep' encodes the spec's null-means-retain
|
|
1617
|
-
*
|
|
1618
|
-
* Coordinates convert PDF user space (y-up, absolute) → content space
|
|
1619
|
-
* (y-down, crop-relative) through the SAME `pdfToContent` matrix selection
|
|
1620
|
-
* and search use, so a destination and an overlay can never disagree.
|
|
1621
|
-
*/
|
|
1622
|
-
/**
|
|
1623
|
-
* Translate one explicit destination against its target page's layout.
|
|
1624
|
-
* `bbox` is the page's content BOUNDING box in CONTENT space, for the
|
|
1625
|
-
* `/FitB*` kinds — pass it when known; the crop box is the spec-tolerated
|
|
1626
|
-
* fallback until the engine exposes it.
|
|
1627
|
-
*/
|
|
1628
|
-
function destinationToReveal(dest, layout, bbox) {
|
|
1629
|
-
const geo = (0, _embedpdf_core_geometry.pageGeometry)({
|
|
1630
|
-
crop: layout.boxes.crop,
|
|
1631
|
-
rotation: layout.rotation,
|
|
1632
|
-
userUnit: layout.userUnit
|
|
1633
|
-
}, 1);
|
|
1634
|
-
const crop = layout.boxes.crop;
|
|
1635
|
-
const toContent = (x, y) => (0, _embedpdf_core_geometry.applyPoint)(geo.pdfToContent, {
|
|
1636
|
-
x,
|
|
1637
|
-
y
|
|
1638
|
-
});
|
|
1639
|
-
const page = {
|
|
1640
|
-
x: 0,
|
|
1641
|
-
y: 0,
|
|
1642
|
-
width: layout.size.width,
|
|
1643
|
-
height: layout.size.height
|
|
1644
|
-
};
|
|
1645
|
-
const box = bbox ?? page;
|
|
1646
|
-
const options = (() => {
|
|
1647
|
-
switch (dest.kind) {
|
|
1648
|
-
case "xyz": {
|
|
1649
|
-
const hasLeft = dest.left != null;
|
|
1650
|
-
const hasTop = dest.top != null;
|
|
1651
|
-
const p = toContent(dest.left ?? crop.left, dest.top ?? crop.top);
|
|
1652
|
-
return {
|
|
1653
|
-
rect: {
|
|
1654
|
-
x: p.x,
|
|
1655
|
-
y: p.y,
|
|
1656
|
-
width: 0,
|
|
1657
|
-
height: 0
|
|
1658
|
-
},
|
|
1659
|
-
anchor: {
|
|
1660
|
-
x: hasLeft ? "start" : "keep",
|
|
1661
|
-
y: hasTop ? "start" : "keep"
|
|
1662
|
-
},
|
|
1663
|
-
zoom: dest.zoom != null && dest.zoom !== 0 ? { level: dest.zoom } : "keep"
|
|
1648
|
+
effects: (ctx) => registerStageEffects(ctx, token, id === "stage"),
|
|
1649
|
+
init: (ctx) => {
|
|
1650
|
+
if (id !== "stage") return;
|
|
1651
|
+
const actions = ctx.tryGet(_embedpdf_plugin_actions_contract_host.ActionsToken);
|
|
1652
|
+
if (!actions) return;
|
|
1653
|
+
ctx.cleanup(actions.registerExecutor("goto", (node) => {
|
|
1654
|
+
if (node.type !== "goto") return {
|
|
1655
|
+
status: "inert",
|
|
1656
|
+
reason: "not a goto node"
|
|
1664
1657
|
};
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
rect: {
|
|
1671
|
-
x: 0,
|
|
1672
|
-
y: hasTop ? toContent(crop.left, dest.top).y : 0,
|
|
1673
|
-
width: page.width,
|
|
1674
|
-
height: 0
|
|
1675
|
-
},
|
|
1676
|
-
zoom: "fit-width",
|
|
1677
|
-
anchor: { y: hasTop ? "start" : "keep" }
|
|
1658
|
+
const stage = ctx.tryGet(token);
|
|
1659
|
+
const layout = ctx.document()?.pages.find((p) => p.pageObjectNumber === node.destination.pageObjectNumber);
|
|
1660
|
+
if (!stage || !layout) return {
|
|
1661
|
+
status: "failed",
|
|
1662
|
+
error: "no stage or destination page available"
|
|
1678
1663
|
};
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
anchor: { x: hasLeft ? "start" : "keep" }
|
|
1691
|
-
};
|
|
1692
|
-
}
|
|
1693
|
-
case "fitR": {
|
|
1694
|
-
const tl = toContent(dest.left, dest.top);
|
|
1695
|
-
const br = toContent(dest.right, dest.bottom);
|
|
1696
|
-
return {
|
|
1697
|
-
rect: {
|
|
1698
|
-
x: Math.min(tl.x, br.x),
|
|
1699
|
-
y: Math.min(tl.y, br.y),
|
|
1700
|
-
width: Math.abs(br.x - tl.x),
|
|
1701
|
-
height: Math.abs(br.y - tl.y)
|
|
1702
|
-
},
|
|
1703
|
-
zoom: "fit"
|
|
1704
|
-
};
|
|
1705
|
-
}
|
|
1706
|
-
case "fitB": return {
|
|
1707
|
-
rect: box,
|
|
1708
|
-
zoom: "fit"
|
|
1709
|
-
};
|
|
1710
|
-
case "fitBH": {
|
|
1711
|
-
const hasTop = dest.top != null;
|
|
1712
|
-
const y = hasTop ? toContent(crop.left, dest.top).y : box.y;
|
|
1713
|
-
return {
|
|
1714
|
-
rect: {
|
|
1715
|
-
x: box.x,
|
|
1716
|
-
y,
|
|
1717
|
-
width: box.width,
|
|
1718
|
-
height: 0
|
|
1719
|
-
},
|
|
1720
|
-
zoom: "fit-width",
|
|
1721
|
-
anchor: { y: hasTop ? "start" : "keep" }
|
|
1664
|
+
const { pageIndex, options: reveal } = require_destination.destinationToReveal(node.destination, layout);
|
|
1665
|
+
stage.reveal(pageIndex, {
|
|
1666
|
+
...reveal,
|
|
1667
|
+
behavior: "smooth"
|
|
1668
|
+
});
|
|
1669
|
+
return { status: "executed" };
|
|
1670
|
+
}));
|
|
1671
|
+
ctx.cleanup(actions.registerExecutor("named", (node) => {
|
|
1672
|
+
if (node.type !== "named") return {
|
|
1673
|
+
status: "inert",
|
|
1674
|
+
reason: "not a named node"
|
|
1722
1675
|
};
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
rect: {
|
|
1728
|
-
x: hasLeft ? toContent(dest.left, crop.top).x : box.x,
|
|
1729
|
-
y: box.y,
|
|
1730
|
-
width: 0,
|
|
1731
|
-
height: box.height
|
|
1732
|
-
},
|
|
1733
|
-
zoom: "fit-height",
|
|
1734
|
-
anchor: { x: hasLeft ? "start" : "keep" }
|
|
1676
|
+
const stage = ctx.tryGet(token);
|
|
1677
|
+
if (!stage) return {
|
|
1678
|
+
status: "failed",
|
|
1679
|
+
error: "no stage available"
|
|
1735
1680
|
};
|
|
1736
|
-
|
|
1681
|
+
switch (node.name) {
|
|
1682
|
+
case "NextPage":
|
|
1683
|
+
stage.next({ behavior: "smooth" });
|
|
1684
|
+
return { status: "executed" };
|
|
1685
|
+
case "PrevPage":
|
|
1686
|
+
stage.prev({ behavior: "smooth" });
|
|
1687
|
+
return { status: "executed" };
|
|
1688
|
+
case "FirstPage":
|
|
1689
|
+
stage.goToPage(0, { behavior: "smooth" });
|
|
1690
|
+
return { status: "executed" };
|
|
1691
|
+
case "LastPage":
|
|
1692
|
+
stage.goToPage(Math.max(0, stage.pageCount() - 1), { behavior: "smooth" });
|
|
1693
|
+
return { status: "executed" };
|
|
1694
|
+
default: return {
|
|
1695
|
+
status: "inert",
|
|
1696
|
+
reason: `unknown named action '${node.name}'`
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
}));
|
|
1737
1700
|
}
|
|
1738
|
-
})
|
|
1739
|
-
|
|
1740
|
-
pageIndex: layout.index,
|
|
1741
|
-
options
|
|
1742
|
-
};
|
|
1743
|
-
}
|
|
1701
|
+
});
|
|
1702
|
+
};
|
|
1744
1703
|
//#endregion
|
|
1745
1704
|
//#region src/scroll-handler.ts
|
|
1746
1705
|
/**
|
|
@@ -1784,7 +1743,7 @@ function createScrollHandler(stage, interaction, options = {}) {
|
|
|
1784
1743
|
//#endregion
|
|
1785
1744
|
exports.DEFAULT_RESPONSIVE = DEFAULT_RESPONSIVE;
|
|
1786
1745
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
|
1787
|
-
exports.StageToken = StageToken;
|
|
1746
|
+
exports.StageToken = require_contract.StageToken;
|
|
1788
1747
|
Object.defineProperty(exports, "ZoomMode", {
|
|
1789
1748
|
enumerable: true,
|
|
1790
1749
|
get: function() {
|
|
@@ -1793,7 +1752,7 @@ Object.defineProperty(exports, "ZoomMode", {
|
|
|
1793
1752
|
});
|
|
1794
1753
|
exports.boxOf = boxOf;
|
|
1795
1754
|
exports.createScrollHandler = createScrollHandler;
|
|
1796
|
-
exports.destinationToReveal = destinationToReveal;
|
|
1755
|
+
exports.destinationToReveal = require_destination.destinationToReveal;
|
|
1797
1756
|
exports.matchesQuery = matchesQuery;
|
|
1798
1757
|
exports.resolveResponsive = resolveResponsive;
|
|
1799
1758
|
exports.settingsEqual = settingsEqual;
|