@nypl/web-reader 5.0.0-alpha.0 → 5.0.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/README.md +12 -0
- package/dist/index.js +143 -159
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +143 -159
- package/dist/index.mjs.map +1 -1
- package/dist/injectable-html-styles/ReadiumCSS-after.css.map +1 -1
- package/dist/injectable-html-styles/ReadiumCSS-before.css.map +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -123,6 +123,18 @@ There are two different injectables props you can pass to the web reader.
|
|
|
123
123
|
|
|
124
124
|
Your app can provide both props or only one. The reader will decide which one to load into the iframe based on the book format defined in the webpub manifest.
|
|
125
125
|
|
|
126
|
+
## Required CSS for the PDF Reader (Text & Annotation Layers)
|
|
127
|
+
|
|
128
|
+
When rendering PDFs the library relies on `react-pdf`'s text and annotation layer styles.
|
|
129
|
+
|
|
130
|
+
To avoid importing global CSS from inside distributed JS in Next.js applications, you must import global CSS only from the app root (`pages/_app.js` / `pages/_app.tsx` or `app/layout.tsx`). After installing `@nypl/web-reader`, import the following CSS from your application root:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
// pages/_app.tsx or app/layout.tsx
|
|
134
|
+
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
|
135
|
+
import 'react-pdf/dist/esm/Page/TextLayer.css';
|
|
136
|
+
```
|
|
137
|
+
|
|
126
138
|
## Other Injectables
|
|
127
139
|
|
|
128
140
|
You can import and inject other files into the `<WebReader />` to customize behavior. For example, in Open eBooks, we import some [custom JavaScript](https://github.com/NYPL/ereading-clients/blob/staging/apps/oew/src/components/theme-ui/WebReader.tsx#L65) to disable right clicking & copying copywritten content.
|
package/dist/index.js
CHANGED
|
@@ -3515,10 +3515,7 @@ function createMultiStyleConfigHelpers(parts) {
|
|
|
3515
3515
|
}
|
|
3516
3516
|
|
|
3517
3517
|
// src/ui/theme/components/tabs.ts
|
|
3518
|
-
var {
|
|
3519
|
-
defineMultiStyleConfig,
|
|
3520
|
-
definePartsStyle
|
|
3521
|
-
} = createMultiStyleConfigHelpers(["root", "tab", "tablist"]);
|
|
3518
|
+
var { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(["root", "tab", "tablist"]);
|
|
3522
3519
|
var getTabsStyle = (getColor2) => defineMultiStyleConfig({
|
|
3523
3520
|
variants: {
|
|
3524
3521
|
custom: definePartsStyle({
|
|
@@ -6129,14 +6126,7 @@ function Header(props) {
|
|
|
6129
6126
|
var _a, _b, _c, _d;
|
|
6130
6127
|
const [, toggleFullscreenHook] = useFullscreen();
|
|
6131
6128
|
const [isFullscreen, setIsFullScreen] = (0, import_react84.useState)(false);
|
|
6132
|
-
const {
|
|
6133
|
-
navigator,
|
|
6134
|
-
manifest,
|
|
6135
|
-
type,
|
|
6136
|
-
containerRef,
|
|
6137
|
-
currentPage,
|
|
6138
|
-
totalPages
|
|
6139
|
-
} = props;
|
|
6129
|
+
const { navigator, manifest, type, containerRef, currentPage, totalPages } = props;
|
|
6140
6130
|
const isAtStart = (_a = props.state) == null ? void 0 : _a.atStart;
|
|
6141
6131
|
const isAtEnd = (_b = props.state) == null ? void 0 : _b.atEnd;
|
|
6142
6132
|
const iconFill = useColorModeValue_default(
|
|
@@ -6756,12 +6746,8 @@ function setReflowableCss(iframeHtml, settings) {
|
|
|
6756
6746
|
}
|
|
6757
6747
|
function setFixedCss(iframeDocument, iframeContainer) {
|
|
6758
6748
|
if (!iframeContainer) return;
|
|
6759
|
-
let { contentWidth, contentHeight } = extractContentViewportSize(
|
|
6760
|
-
|
|
6761
|
-
);
|
|
6762
|
-
const { containerWidth, containerHeight } = extractContentContainerSize(
|
|
6763
|
-
iframeContainer
|
|
6764
|
-
);
|
|
6749
|
+
let { contentWidth, contentHeight } = extractContentViewportSize(iframeDocument);
|
|
6750
|
+
const { containerWidth, containerHeight } = extractContentContainerSize(iframeContainer);
|
|
6765
6751
|
contentWidth = contentWidth != null ? contentWidth : containerWidth;
|
|
6766
6752
|
contentHeight = contentHeight != null ? contentHeight : containerHeight;
|
|
6767
6753
|
const scale = Math.min(
|
|
@@ -7328,9 +7314,7 @@ function useResource(manifest, state2, getContent, injectables, dispatch) {
|
|
|
7328
7314
|
if (element) document2 == null ? void 0 : document2.head.appendChild(element);
|
|
7329
7315
|
}
|
|
7330
7316
|
injectJS(document2.body);
|
|
7331
|
-
const iframeContainer = window.document.querySelector(
|
|
7332
|
-
'main [role="progressbar"]'
|
|
7333
|
-
);
|
|
7317
|
+
const iframeContainer = window.document.querySelector('main [role="progressbar"]');
|
|
7334
7318
|
const readerSettings = {
|
|
7335
7319
|
colorMode: state2.settings.colorMode,
|
|
7336
7320
|
fontSize: state2.settings.fontSize,
|
|
@@ -7695,129 +7679,6 @@ var ChakraPage = (0, import_react96.chakra)(
|
|
|
7695
7679
|
);
|
|
7696
7680
|
var ChakraPage_default = ChakraPage;
|
|
7697
7681
|
|
|
7698
|
-
// src/PdfReader/ScrollPage.tsx
|
|
7699
|
-
var import_react98 = __toESM(require("react"));
|
|
7700
|
-
var import_react_intersection_observer = require("react-intersection-observer");
|
|
7701
|
-
var Placeholder = ({ width, height, pageNumber }) => {
|
|
7702
|
-
return /* @__PURE__ */ import_react98.default.createElement(
|
|
7703
|
-
"div",
|
|
7704
|
-
{
|
|
7705
|
-
"data-page-number": pageNumber,
|
|
7706
|
-
style: { width, height }
|
|
7707
|
-
}
|
|
7708
|
-
);
|
|
7709
|
-
};
|
|
7710
|
-
var ScrollPage = ({
|
|
7711
|
-
scale,
|
|
7712
|
-
pageNumber,
|
|
7713
|
-
width,
|
|
7714
|
-
height,
|
|
7715
|
-
onLoadSuccess,
|
|
7716
|
-
placeholderHeight,
|
|
7717
|
-
placeholderWidth,
|
|
7718
|
-
allowInView,
|
|
7719
|
-
onInView,
|
|
7720
|
-
fitMode,
|
|
7721
|
-
rotate
|
|
7722
|
-
}) => {
|
|
7723
|
-
const { ref: loadRef, inView: loadInView } = (0, import_react_intersection_observer.useInView)({
|
|
7724
|
-
threshold: 0,
|
|
7725
|
-
triggerOnce: true
|
|
7726
|
-
});
|
|
7727
|
-
const { ref: visibilityRef, entry } = (0, import_react_intersection_observer.useInView)({
|
|
7728
|
-
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),
|
|
7729
|
-
triggerOnce: false
|
|
7730
|
-
});
|
|
7731
|
-
const setRefs = import_react98.default.useCallback(
|
|
7732
|
-
(el) => {
|
|
7733
|
-
if (typeof loadRef === "function") loadRef(el);
|
|
7734
|
-
if (typeof visibilityRef === "function") visibilityRef(el);
|
|
7735
|
-
},
|
|
7736
|
-
[loadRef, visibilityRef]
|
|
7737
|
-
);
|
|
7738
|
-
const handleLoadSuccess = import_react98.default.useCallback(
|
|
7739
|
-
(page) => {
|
|
7740
|
-
onLoadSuccess(page);
|
|
7741
|
-
},
|
|
7742
|
-
[onLoadSuccess]
|
|
7743
|
-
);
|
|
7744
|
-
import_react98.default.useEffect(() => {
|
|
7745
|
-
if (onInView && entry) {
|
|
7746
|
-
onInView(pageNumber, entry.intersectionRatio || 0);
|
|
7747
|
-
}
|
|
7748
|
-
}, [entry, onInView, pageNumber]);
|
|
7749
|
-
return /* @__PURE__ */ import_react98.default.createElement("div", { ref: setRefs }, loadInView ? /* @__PURE__ */ import_react98.default.createElement(
|
|
7750
|
-
ChakraPage_default,
|
|
7751
|
-
{
|
|
7752
|
-
"data-page-number": pageNumber,
|
|
7753
|
-
pageNumber,
|
|
7754
|
-
scale,
|
|
7755
|
-
width,
|
|
7756
|
-
height,
|
|
7757
|
-
onLoadSuccess: handleLoadSuccess,
|
|
7758
|
-
fitMode,
|
|
7759
|
-
rotate
|
|
7760
|
-
}
|
|
7761
|
-
) : /* @__PURE__ */ import_react98.default.createElement(
|
|
7762
|
-
Placeholder,
|
|
7763
|
-
{
|
|
7764
|
-
width: placeholderWidth,
|
|
7765
|
-
height: placeholderHeight,
|
|
7766
|
-
pageNumber
|
|
7767
|
-
}
|
|
7768
|
-
));
|
|
7769
|
-
};
|
|
7770
|
-
var ScrollPage_default = ScrollPage;
|
|
7771
|
-
|
|
7772
|
-
// src/PdfReader/useMeasure.tsx
|
|
7773
|
-
var React49 = __toESM(require("react"));
|
|
7774
|
-
var DEFAULT_DIMENSION = {
|
|
7775
|
-
x: 0,
|
|
7776
|
-
y: 0,
|
|
7777
|
-
width: 0,
|
|
7778
|
-
height: 0,
|
|
7779
|
-
top: 0,
|
|
7780
|
-
left: 0,
|
|
7781
|
-
bottom: 0,
|
|
7782
|
-
right: 0
|
|
7783
|
-
};
|
|
7784
|
-
function useMeasure() {
|
|
7785
|
-
const [element, ref] = React49.useState(null);
|
|
7786
|
-
const [rect, setRect] = React49.useState(DEFAULT_DIMENSION);
|
|
7787
|
-
const observer = React49.useMemo(
|
|
7788
|
-
() => new window.ResizeObserver(
|
|
7789
|
-
(entries) => {
|
|
7790
|
-
if (entries[0]) {
|
|
7791
|
-
const {
|
|
7792
|
-
x,
|
|
7793
|
-
y,
|
|
7794
|
-
width,
|
|
7795
|
-
height,
|
|
7796
|
-
top,
|
|
7797
|
-
left,
|
|
7798
|
-
bottom,
|
|
7799
|
-
right
|
|
7800
|
-
} = entries[0].contentRect;
|
|
7801
|
-
setRect({ x, y, width, height, top, left, bottom, right });
|
|
7802
|
-
}
|
|
7803
|
-
}
|
|
7804
|
-
),
|
|
7805
|
-
[]
|
|
7806
|
-
);
|
|
7807
|
-
React49.useLayoutEffect(() => {
|
|
7808
|
-
if (!element) return;
|
|
7809
|
-
observer.observe(element);
|
|
7810
|
-
return () => {
|
|
7811
|
-
observer.disconnect();
|
|
7812
|
-
};
|
|
7813
|
-
}, [element, observer]);
|
|
7814
|
-
return [ref, rect];
|
|
7815
|
-
}
|
|
7816
|
-
|
|
7817
|
-
// src/PdfReader/index.tsx
|
|
7818
|
-
var import_AnnotationLayer = require("react-pdf/dist/Page/AnnotationLayer.css");
|
|
7819
|
-
var import_TextLayer = require("react-pdf/dist/Page/TextLayer.css");
|
|
7820
|
-
|
|
7821
7682
|
// src/PdfReader/lib.ts
|
|
7822
7683
|
var SCALE_STEP = 0.1;
|
|
7823
7684
|
var START_QUERY = "start";
|
|
@@ -8049,6 +7910,116 @@ function isStartOfResource(pageNumber, resourceHref) {
|
|
|
8049
7910
|
return pageNumber === (startPage != null ? startPage : 1);
|
|
8050
7911
|
}
|
|
8051
7912
|
|
|
7913
|
+
// src/PdfReader/ScrollPage.tsx
|
|
7914
|
+
var import_react98 = __toESM(require("react"));
|
|
7915
|
+
var import_react_intersection_observer = require("react-intersection-observer");
|
|
7916
|
+
var Placeholder = ({ width, height, pageNumber }) => {
|
|
7917
|
+
return /* @__PURE__ */ import_react98.default.createElement(
|
|
7918
|
+
"div",
|
|
7919
|
+
{
|
|
7920
|
+
"data-page-number": pageNumber,
|
|
7921
|
+
style: { width, height }
|
|
7922
|
+
}
|
|
7923
|
+
);
|
|
7924
|
+
};
|
|
7925
|
+
var ScrollPage = ({
|
|
7926
|
+
scale,
|
|
7927
|
+
pageNumber,
|
|
7928
|
+
width,
|
|
7929
|
+
height,
|
|
7930
|
+
onLoadSuccess,
|
|
7931
|
+
placeholderHeight,
|
|
7932
|
+
placeholderWidth,
|
|
7933
|
+
allowInView,
|
|
7934
|
+
onInView,
|
|
7935
|
+
fitMode,
|
|
7936
|
+
rotate
|
|
7937
|
+
}) => {
|
|
7938
|
+
const { ref: loadRef, inView: loadInView } = (0, import_react_intersection_observer.useInView)({
|
|
7939
|
+
threshold: 0,
|
|
7940
|
+
triggerOnce: true
|
|
7941
|
+
});
|
|
7942
|
+
const { ref: visibilityRef, entry } = (0, import_react_intersection_observer.useInView)({
|
|
7943
|
+
threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),
|
|
7944
|
+
triggerOnce: false
|
|
7945
|
+
});
|
|
7946
|
+
const setRefs = import_react98.default.useCallback(
|
|
7947
|
+
(el) => {
|
|
7948
|
+
if (typeof loadRef === "function") loadRef(el);
|
|
7949
|
+
if (typeof visibilityRef === "function") visibilityRef(el);
|
|
7950
|
+
},
|
|
7951
|
+
[loadRef, visibilityRef]
|
|
7952
|
+
);
|
|
7953
|
+
const handleLoadSuccess = import_react98.default.useCallback(
|
|
7954
|
+
(page) => {
|
|
7955
|
+
onLoadSuccess(page);
|
|
7956
|
+
},
|
|
7957
|
+
[onLoadSuccess]
|
|
7958
|
+
);
|
|
7959
|
+
import_react98.default.useEffect(() => {
|
|
7960
|
+
if (allowInView && onInView && entry) {
|
|
7961
|
+
onInView(pageNumber, entry.intersectionRatio || 0);
|
|
7962
|
+
}
|
|
7963
|
+
}, [allowInView, entry, onInView, pageNumber]);
|
|
7964
|
+
return /* @__PURE__ */ import_react98.default.createElement("div", { ref: setRefs }, loadInView ? /* @__PURE__ */ import_react98.default.createElement(
|
|
7965
|
+
ChakraPage_default,
|
|
7966
|
+
{
|
|
7967
|
+
"data-page-number": pageNumber,
|
|
7968
|
+
pageNumber,
|
|
7969
|
+
scale,
|
|
7970
|
+
width,
|
|
7971
|
+
height,
|
|
7972
|
+
onLoadSuccess: handleLoadSuccess,
|
|
7973
|
+
fitMode,
|
|
7974
|
+
rotate
|
|
7975
|
+
}
|
|
7976
|
+
) : /* @__PURE__ */ import_react98.default.createElement(
|
|
7977
|
+
Placeholder,
|
|
7978
|
+
{
|
|
7979
|
+
width: placeholderWidth,
|
|
7980
|
+
height: placeholderHeight,
|
|
7981
|
+
pageNumber
|
|
7982
|
+
}
|
|
7983
|
+
));
|
|
7984
|
+
};
|
|
7985
|
+
var ScrollPage_default = ScrollPage;
|
|
7986
|
+
|
|
7987
|
+
// src/PdfReader/useMeasure.tsx
|
|
7988
|
+
var React49 = __toESM(require("react"));
|
|
7989
|
+
var DEFAULT_DIMENSION = {
|
|
7990
|
+
x: 0,
|
|
7991
|
+
y: 0,
|
|
7992
|
+
width: 0,
|
|
7993
|
+
height: 0,
|
|
7994
|
+
top: 0,
|
|
7995
|
+
left: 0,
|
|
7996
|
+
bottom: 0,
|
|
7997
|
+
right: 0
|
|
7998
|
+
};
|
|
7999
|
+
function useMeasure() {
|
|
8000
|
+
const [element, ref] = React49.useState(null);
|
|
8001
|
+
const [rect, setRect] = React49.useState(DEFAULT_DIMENSION);
|
|
8002
|
+
const observer = React49.useMemo(
|
|
8003
|
+
() => new window.ResizeObserver(
|
|
8004
|
+
(entries) => {
|
|
8005
|
+
if (entries[0]) {
|
|
8006
|
+
const { x, y, width, height, top, left, bottom, right } = entries[0].contentRect;
|
|
8007
|
+
setRect({ x, y, width, height, top, left, bottom, right });
|
|
8008
|
+
}
|
|
8009
|
+
}
|
|
8010
|
+
),
|
|
8011
|
+
[]
|
|
8012
|
+
);
|
|
8013
|
+
React49.useLayoutEffect(() => {
|
|
8014
|
+
if (!element) return;
|
|
8015
|
+
observer.observe(element);
|
|
8016
|
+
return () => {
|
|
8017
|
+
observer.disconnect();
|
|
8018
|
+
};
|
|
8019
|
+
}, [element, observer]);
|
|
8020
|
+
return [ref, rect];
|
|
8021
|
+
}
|
|
8022
|
+
|
|
8052
8023
|
// src/PdfReader/index.tsx
|
|
8053
8024
|
function usePdfReader(args) {
|
|
8054
8025
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -8190,6 +8161,10 @@ function usePdfReader(args) {
|
|
|
8190
8161
|
var _a2;
|
|
8191
8162
|
if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling)) return;
|
|
8192
8163
|
if (!state2.rendered) return;
|
|
8164
|
+
if (scrollState.current.isInViewUpdate) {
|
|
8165
|
+
scrollState.current.isInViewUpdate = false;
|
|
8166
|
+
return;
|
|
8167
|
+
}
|
|
8193
8168
|
process.nextTick(() => {
|
|
8194
8169
|
const page = document.querySelector(
|
|
8195
8170
|
`[data-page-number="${state2.pageNumber}"]`
|
|
@@ -8234,29 +8209,38 @@ function usePdfReader(args) {
|
|
|
8234
8209
|
const setFitMode = React50.useCallback((mode) => {
|
|
8235
8210
|
dispatch({ type: "SET_FIT_MODE", fitMode: mode });
|
|
8236
8211
|
}, []);
|
|
8237
|
-
const
|
|
8238
|
-
|
|
8212
|
+
const scrollState = React50.useRef({
|
|
8213
|
+
ratios: /* @__PURE__ */ new Map(),
|
|
8214
|
+
lastVisiblepage: state2.pageNumber,
|
|
8215
|
+
hasScrolled: false,
|
|
8216
|
+
isInViewUpdate: false
|
|
8217
|
+
});
|
|
8239
8218
|
const onInView = React50.useCallback(
|
|
8240
8219
|
(pageNum, ratio) => {
|
|
8241
8220
|
var _a2;
|
|
8221
|
+
const currentScrollState = scrollState.current;
|
|
8242
8222
|
if (!((_a2 = state2.settings) == null ? void 0 : _a2.isScrolling)) return;
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8223
|
+
currentScrollState.ratios.set(pageNum, ratio);
|
|
8224
|
+
if (!currentScrollState.hasScrolled && state2.pageNumber === 1) {
|
|
8225
|
+
const container = document.querySelector(
|
|
8226
|
+
`#${MAIN_CONTENT_ID} .react-pdf__Document`
|
|
8227
|
+
);
|
|
8228
|
+
if (container && container.scrollTop > 0)
|
|
8229
|
+
currentScrollState.hasScrolled = true;
|
|
8230
|
+
else return;
|
|
8231
|
+
}
|
|
8232
|
+
let mostVisiblePage = currentScrollState.lastVisiblepage;
|
|
8249
8233
|
let maxRatio = -1;
|
|
8250
|
-
|
|
8251
|
-
for (const [page, r] of Object.entries(intersectionRatios.current)) {
|
|
8234
|
+
currentScrollState.ratios.forEach((r, p) => {
|
|
8252
8235
|
if (r > maxRatio) {
|
|
8253
8236
|
maxRatio = r;
|
|
8254
|
-
mostVisiblePage =
|
|
8237
|
+
mostVisiblePage = p;
|
|
8255
8238
|
}
|
|
8256
|
-
}
|
|
8257
|
-
if (mostVisiblePage !==
|
|
8258
|
-
|
|
8239
|
+
});
|
|
8240
|
+
if (mostVisiblePage !== currentScrollState.lastVisiblepage) {
|
|
8241
|
+
currentScrollState.lastVisiblepage = mostVisiblePage;
|
|
8259
8242
|
if (state2.pageNumber !== mostVisiblePage) {
|
|
8243
|
+
currentScrollState.isInViewUpdate = true;
|
|
8260
8244
|
dispatch({ type: "PAGE_IN_VIEW", page: mostVisiblePage });
|
|
8261
8245
|
}
|
|
8262
8246
|
}
|
|
@@ -8355,7 +8339,7 @@ function usePdfReader(args) {
|
|
|
8355
8339
|
scale: state2.scale,
|
|
8356
8340
|
pageNumber: index + 1,
|
|
8357
8341
|
onLoadSuccess: onRenderSuccess,
|
|
8358
|
-
allowInView:
|
|
8342
|
+
allowInView: state2.rendered,
|
|
8359
8343
|
onInView,
|
|
8360
8344
|
fitMode: state2.fitMode,
|
|
8361
8345
|
rotate: (_a2 = state2.rotation) != null ? _a2 : 0
|