mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Smart PDF pan/select + reactive spread toggle
- In select mode, only defer to the text/annotation layer when the pointer is actually on text or a link; otherwise start panning. Lets PDF pages be dragged on blank space while keeping text selection. Shift and explicit 'pan' mode still force-pan. - Make the 'spread' attribute reactive: extract #computeSpreads(), add #setSpread() which re-groups while preserving the current page.
This commit is contained in:
+32
-7
@@ -23,7 +23,7 @@ const getViewport = (doc, viewport) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class FixedLayout extends HTMLElement {
|
export class FixedLayout extends HTMLElement {
|
||||||
static observedAttributes = ["zoom", "interaction-mode"];
|
static observedAttributes = ["zoom", "interaction-mode", "spread"];
|
||||||
#root = this.attachShadow({ mode: "closed" });
|
#root = this.attachShadow({ mode: "closed" });
|
||||||
#observer = new ResizeObserver(() => this.#onResize());
|
#observer = new ResizeObserver(() => this.#onResize());
|
||||||
#spreads;
|
#spreads;
|
||||||
@@ -121,6 +121,10 @@ export class FixedLayout extends HTMLElement {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "spread": {
|
||||||
|
this.#setSpread(value == null ? undefined : value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,8 +496,14 @@ export class FixedLayout extends HTMLElement {
|
|||||||
|
|
||||||
#handleMouseDown(event) {
|
#handleMouseDown(event) {
|
||||||
if (event.button !== 0) return;
|
if (event.button !== 0) return;
|
||||||
if (this.#isPDF && this.#interactionMode === "select" && !event.shiftKey)
|
if (this.#isPDF && this.#interactionMode === "select" && !event.shiftKey) {
|
||||||
return false;
|
const t = event.realTarget;
|
||||||
|
if (
|
||||||
|
t?.closest?.(".textLayer span") ||
|
||||||
|
t?.closest?.(".annotationLayer a")
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.#dragState.startX = event.clientX;
|
this.#dragState.startX = event.clientX;
|
||||||
this.#dragState.startY = event.clientY;
|
this.#dragState.startY = event.clientY;
|
||||||
@@ -643,6 +653,7 @@ export class FixedLayout extends HTMLElement {
|
|||||||
});
|
});
|
||||||
mouseEvent.sourceIframe = frameId;
|
mouseEvent.sourceIframe = frameId;
|
||||||
mouseEvent.sourceFrame = frame;
|
mouseEvent.sourceFrame = frame;
|
||||||
|
mouseEvent.realTarget = event.target;
|
||||||
const dragStarted = this.#handleMouseDown(mouseEvent);
|
const dragStarted = this.#handleMouseDown(mouseEvent);
|
||||||
if (dragStarted) event.preventDefault();
|
if (dragStarted) event.preventDefault();
|
||||||
});
|
});
|
||||||
@@ -831,11 +842,15 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.spread = rendition?.spread;
|
this.spread = rendition?.spread;
|
||||||
this.defaultViewport = rendition?.viewport;
|
this.defaultViewport = rendition?.viewport;
|
||||||
|
|
||||||
const rtl = book.dir === "rtl";
|
this.rtl = book.dir === "rtl";
|
||||||
const ltr = !rtl;
|
this.#computeSpreads();
|
||||||
this.rtl = rtl;
|
}
|
||||||
|
|
||||||
if (rendition?.spread === "none")
|
#computeSpreads() {
|
||||||
|
const { book } = this;
|
||||||
|
const rtl = this.rtl;
|
||||||
|
const ltr = !rtl;
|
||||||
|
if (this.spread === "none")
|
||||||
this.#spreads = book.sections.map((section) => ({ center: section }));
|
this.#spreads = book.sections.map((section) => ({ center: section }));
|
||||||
else
|
else
|
||||||
this.#spreads = book.sections.reduce(
|
this.#spreads = book.sections.reduce(
|
||||||
@@ -873,6 +888,16 @@ export class FixedLayout extends HTMLElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#setSpread(value) {
|
||||||
|
this.spread = value;
|
||||||
|
const currentSection =
|
||||||
|
this.book?.sections[this.index] ?? this.book?.sections[0];
|
||||||
|
this.#computeSpreads();
|
||||||
|
const resolved = currentSection ? this.getSpreadOf(currentSection) : null;
|
||||||
|
if (resolved) this.goToSpread(resolved.index, resolved.side, "page");
|
||||||
|
else this.#render();
|
||||||
|
}
|
||||||
|
|
||||||
get index() {
|
get index() {
|
||||||
const spread = this.#spreads[this.#index];
|
const spread = this.#spreads[this.#index];
|
||||||
const section =
|
const section =
|
||||||
|
|||||||
Reference in New Issue
Block a user