@nypl/web-reader 0.1.4 → 0.2.0-alpha.3

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.
Files changed (144) hide show
  1. package/dist/cjs/ServiceWorker/sw.js +2 -0
  2. package/dist/cjs/ServiceWorker/sw.js.map +7 -0
  3. package/dist/cjs/index.js +683 -0
  4. package/dist/cjs/index.js.map +7 -0
  5. package/dist/esm/ServiceWorker/sw.js +1263 -0
  6. package/dist/esm/ServiceWorker/sw.js.map +7 -0
  7. package/dist/esm/index.js +88803 -0
  8. package/dist/esm/index.js.map +7 -0
  9. package/dist/html-styles.css +2 -0
  10. package/dist/html-styles.css.map +7 -0
  11. package/dist/pdf-styles.css +2 -0
  12. package/dist/pdf-styles.css.map +7 -0
  13. package/dist/{HtmlReader → types/HtmlReader}/HtmlReaderContent.d.ts +3 -3
  14. package/dist/{HtmlReader → types/HtmlReader}/index.d.ts +22 -22
  15. package/dist/{HtmlReader → types/HtmlReader}/injectables.d.ts +30 -30
  16. package/dist/{PdfReader → types/PdfReader}/index.d.ts +11 -12
  17. package/dist/{PdfReader → types/PdfReader}/useMeasure.d.ts +7 -4
  18. package/dist/{ServiceWorker → types/ServiceWorker}/client.d.ts +9 -9
  19. package/dist/{ServiceWorker → types/ServiceWorker}/constants.d.ts +3 -3
  20. package/{src/ServiceWorker/index.ts → dist/types/ServiceWorker/index.d.ts} +0 -0
  21. package/dist/{ServiceWorker → types/ServiceWorker}/sw.d.ts +7 -7
  22. package/dist/{ServiceWorker → types/ServiceWorker}/types.d.ts +3 -3
  23. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/ConformsTo.d.ts +3 -3
  24. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/Contributor.d.ts +17 -17
  25. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/EpubExtension.d.ts +47 -47
  26. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/LanguageMap.d.ts +3 -3
  27. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/Metadata.d.ts +46 -46
  28. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/OPDSLink.d.ts +63 -63
  29. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/PresentationHints.d.ts +53 -53
  30. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/ReadiumLink.d.ts +58 -58
  31. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/Subject.d.ts +16 -16
  32. package/dist/{WebpubManifestTypes → types/WebpubManifestTypes}/WebpubManifest.d.ts +14 -14
  33. package/dist/{constants.d.ts → types/constants.d.ts} +2 -2
  34. package/dist/{index.d.ts → types/index.d.ts} +7 -7
  35. package/dist/{types.d.ts → types/types.d.ts} +66 -66
  36. package/dist/{ui → types/ui}/Button.d.ts +9 -7
  37. package/dist/{ui → types/ui}/Header.d.ts +6 -6
  38. package/dist/{ui → types/ui}/HtmlSettings.d.ts +9 -9
  39. package/dist/{ui → types/ui}/PageButton.d.ts +7 -7
  40. package/dist/{ui → types/ui}/PdfSettings.d.ts +9 -9
  41. package/dist/{ui → types/ui}/SettingsButton.d.ts +5 -5
  42. package/dist/{ui → types/ui}/TableOfContent.d.ts +7 -7
  43. package/dist/{ui → types/ui}/ToggleButton.d.ts +10 -10
  44. package/dist/{ui → types/ui}/ToggleGroup.d.ts +8 -8
  45. package/dist/{ui → types/ui}/constants.d.ts +1 -1
  46. package/dist/{ui → types/ui}/hooks/useColorModeValue.d.ts +7 -7
  47. package/dist/{ui → types/ui}/hooks/useContainerWidth.d.ts +6 -6
  48. package/dist/{ui → types/ui}/hooks/useEventListener.d.ts +8 -8
  49. package/dist/{ui → types/ui}/manager.d.ts +9 -9
  50. package/dist/{ui → types/ui}/nypl-base-theme/components/button.d.ts +94 -94
  51. package/dist/{ui → types/ui}/nypl-base-theme/components/checkbox.d.ts +41 -41
  52. package/dist/{ui → types/ui}/nypl-base-theme/components/form-error.d.ts +14 -14
  53. package/dist/{ui → types/ui}/nypl-base-theme/components/form-label.d.ts +14 -14
  54. package/dist/{ui → types/ui}/nypl-base-theme/components/form.d.ts +15 -15
  55. package/dist/{ui → types/ui}/nypl-base-theme/components/input.d.ts +107 -107
  56. package/dist/{ui → types/ui}/nypl-base-theme/components/text-area.d.ts +34 -34
  57. package/dist/{ui → types/ui}/nypl-base-theme/foundations/breakpoints.d.ts +8 -8
  58. package/dist/{ui → types/ui}/nypl-base-theme/foundations/colors.d.ts +3 -3
  59. package/dist/{ui → types/ui}/nypl-base-theme/foundations/global.d.ts +13 -13
  60. package/dist/{ui → types/ui}/nypl-base-theme/foundations/radii.d.ts +12 -12
  61. package/dist/{ui → types/ui}/nypl-base-theme/foundations/spacing.d.ts +49 -49
  62. package/dist/{ui → types/ui}/nypl-base-theme/foundations/typography.d.ts +10 -10
  63. package/dist/{ui → types/ui}/nypl-base-theme/index.d.ts +6 -6
  64. package/dist/{ui → types/ui}/nypl-base-theme/types.d.ts +1 -1
  65. package/dist/{ui → types/ui}/theme/components/button.d.ts +78 -78
  66. package/dist/{ui → types/ui}/theme/components/text.d.ts +20 -20
  67. package/dist/{ui → types/ui}/theme/foundations/colors.d.ts +3 -3
  68. package/dist/{ui → types/ui}/theme/index.d.ts +11 -11
  69. package/dist/{ui → types/ui}/theme/types.d.ts +1 -1
  70. package/dist/{useWebReader.d.ts → types/useWebReader.d.ts} +7 -7
  71. package/dist/{utils → types/utils}/decryptAxisNow.d.ts +0 -0
  72. package/dist/{utils → types/utils}/fetch.d.ts +4 -4
  73. package/dist/{utils → types/utils}/getColor.d.ts +2 -2
  74. package/dist/{utils → types/utils}/toggleFullScreen.d.ts +5 -5
  75. package/package.json +21 -33
  76. package/dist/ServiceWorker/index.d.ts +0 -1
  77. package/dist/index.js +0 -8
  78. package/dist/web-reader.cjs.development.js +0 -3363
  79. package/dist/web-reader.cjs.development.js.map +0 -1
  80. package/dist/web-reader.cjs.production.min.js +0 -2
  81. package/dist/web-reader.cjs.production.min.js.map +0 -1
  82. package/dist/web-reader.esm.js +0 -3356
  83. package/dist/web-reader.esm.js.map +0 -1
  84. package/src/HtmlReader/HtmlReaderContent.tsx +0 -19
  85. package/src/HtmlReader/index.tsx +0 -262
  86. package/src/HtmlReader/injectables.ts +0 -26
  87. package/src/PdfReader/index.tsx +0 -492
  88. package/src/PdfReader/useMeasure.tsx +0 -68
  89. package/src/ServiceWorker/client.ts +0 -106
  90. package/src/ServiceWorker/constants.ts +0 -4
  91. package/src/ServiceWorker/sw.ts +0 -84
  92. package/src/ServiceWorker/types.ts +0 -3
  93. package/src/WebpubManifestTypes/ConformsTo.ts +0 -9
  94. package/src/WebpubManifestTypes/Contributor.ts +0 -24
  95. package/src/WebpubManifestTypes/EpubExtension.ts +0 -48
  96. package/src/WebpubManifestTypes/LanguageMap.ts +0 -5
  97. package/src/WebpubManifestTypes/Metadata.ts +0 -48
  98. package/src/WebpubManifestTypes/OPDSLink.ts +0 -251
  99. package/src/WebpubManifestTypes/PresentationHints.ts +0 -54
  100. package/src/WebpubManifestTypes/ReadiumLink.ts +0 -61
  101. package/src/WebpubManifestTypes/Subject.ts +0 -20
  102. package/src/WebpubManifestTypes/WebpubManifest.ts +0 -15
  103. package/src/constants.ts +0 -3
  104. package/src/index.tsx +0 -25
  105. package/src/types.ts +0 -94
  106. package/src/ui/Button.tsx +0 -12
  107. package/src/ui/Header.tsx +0 -89
  108. package/src/ui/HtmlSettings.tsx +0 -97
  109. package/src/ui/PageButton.tsx +0 -39
  110. package/src/ui/PdfSettings.tsx +0 -85
  111. package/src/ui/SettingsButton.tsx +0 -71
  112. package/src/ui/TableOfContent.tsx +0 -144
  113. package/src/ui/ToggleButton.tsx +0 -60
  114. package/src/ui/ToggleGroup.tsx +0 -41
  115. package/src/ui/constants.ts +0 -2
  116. package/src/ui/hooks/useColorModeValue.tsx +0 -19
  117. package/src/ui/hooks/useContainerWidth.ts +0 -24
  118. package/src/ui/hooks/useEventListener.ts +0 -26
  119. package/src/ui/manager.tsx +0 -73
  120. package/src/ui/nypl-base-theme/components/button.ts +0 -117
  121. package/src/ui/nypl-base-theme/components/checkbox.ts +0 -45
  122. package/src/ui/nypl-base-theme/components/form-error.ts +0 -15
  123. package/src/ui/nypl-base-theme/components/form-label.ts +0 -15
  124. package/src/ui/nypl-base-theme/components/form.ts +0 -16
  125. package/src/ui/nypl-base-theme/components/input.ts +0 -101
  126. package/src/ui/nypl-base-theme/components/text-area.ts +0 -17
  127. package/src/ui/nypl-base-theme/foundations/breakpoints.ts +0 -10
  128. package/src/ui/nypl-base-theme/foundations/colors.ts +0 -136
  129. package/src/ui/nypl-base-theme/foundations/global.ts +0 -16
  130. package/src/ui/nypl-base-theme/foundations/radii.ts +0 -13
  131. package/src/ui/nypl-base-theme/foundations/spacing.ts +0 -58
  132. package/src/ui/nypl-base-theme/foundations/typography.ts +0 -43
  133. package/src/ui/nypl-base-theme/index.ts +0 -42
  134. package/src/ui/nypl-base-theme/types.ts +0 -1
  135. package/src/ui/theme/components/button.ts +0 -85
  136. package/src/ui/theme/components/text.ts +0 -24
  137. package/src/ui/theme/foundations/colors.ts +0 -10
  138. package/src/ui/theme/index.ts +0 -34
  139. package/src/ui/theme/types.ts +0 -1
  140. package/src/useWebReader.tsx +0 -105
  141. package/src/utils/decryptAxisNow.ts +0 -45
  142. package/src/utils/fetch.ts +0 -13
  143. package/src/utils/getColor.ts +0 -14
  144. package/src/utils/toggleFullScreen.ts +0 -71
@@ -1,492 +0,0 @@
1
- import { Document, Page, PageProps, pdfjs } from 'react-pdf';
2
- import * as React from 'react';
3
- import {
4
- ColorMode,
5
- ReaderArguments,
6
- ReaderReturn,
7
- WebpubManifest,
8
- PdfReaderState,
9
- } from '../types';
10
- import { chakra, Flex, shouldForwardProp } from '@chakra-ui/react';
11
- import useMeasure from './useMeasure';
12
- import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
13
- import { ReadiumLink } from '../WebpubManifestTypes/ReadiumLink';
14
-
15
- type PdfState = PdfReaderState & {
16
- resourceIndex: number;
17
- resource: { data: Uint8Array } | null;
18
- // we only know the numPages once the resource has been parsed
19
- numPages: number | null;
20
- // if pageNumber is -1, we will navigate to the end of the
21
- // resource once it is parsed
22
- pageNumber: number;
23
- scale: number;
24
- pdfHeight: number;
25
- pdfWidth: number;
26
- pageHeight: number | undefined;
27
- pageWidth: number | undefined;
28
- };
29
-
30
- pdfjs.GlobalWorkerOptions.workerSrc = `pdf.worker.min.js`;
31
-
32
- type PdfReaderAction =
33
- | {
34
- type: 'SET_CURRENT_RESOURCE';
35
- index: number;
36
- shouldNavigateToEnd: boolean;
37
- }
38
- | { type: 'RESOURCE_FETCH_SUCCESS'; resource: { data: Uint8Array } }
39
- | { type: 'PDF_PARSED'; numPages: number }
40
- | { type: 'NAVIGATE_PAGE'; pageNum: number }
41
- | { type: 'SET_COLOR_MODE'; mode: ColorMode }
42
- | { type: 'SET_SCALE'; scale: number }
43
- | { type: 'SET_SCROLL'; isScrolling: boolean }
44
- | { type: 'PAGE_LOAD_SUCCESS'; height: number; width: number }
45
- | {
46
- type: 'RESIZE_PAGE';
47
- height: number | undefined;
48
- width: number | undefined;
49
- };
50
- const IFRAME_WRAPPER_ID = 'iframe-wrapper';
51
-
52
- function pdfReducer(state: PdfState, action: PdfReaderAction): PdfState {
53
- switch (action.type) {
54
- /**
55
- * Cleares the current resource and sets the current index, which will cause
56
- * the useEffect hook to load a new resource.
57
- */
58
- case 'SET_CURRENT_RESOURCE':
59
- return {
60
- ...state,
61
- resource: null,
62
- resourceIndex: action.index,
63
- pageNumber: action.shouldNavigateToEnd ? -1 : 1,
64
- numPages: null,
65
- };
66
-
67
- case 'RESOURCE_FETCH_SUCCESS':
68
- return {
69
- ...state,
70
- resource: action.resource,
71
- };
72
-
73
- // called when the resource has been parsed by react-pdf
74
- // and we know the number of pages
75
- case 'PDF_PARSED':
76
- return {
77
- ...state,
78
- numPages: action.numPages,
79
- // if the state.pageNumber is -1, we know to navigate to the
80
- // end of the PDF that was just parsed
81
- pageNumber:
82
- state.pageNumber === -1 ? action.numPages : state.pageNumber,
83
- };
84
-
85
- // Navigates to page in resource
86
- case 'NAVIGATE_PAGE':
87
- return {
88
- ...state,
89
- pageNumber: action.pageNum,
90
- };
91
-
92
- case 'SET_COLOR_MODE':
93
- return {
94
- ...state,
95
- colorMode: action.mode,
96
- };
97
-
98
- case 'SET_SCROLL':
99
- return {
100
- ...state,
101
- isScrolling: action.isScrolling,
102
- };
103
-
104
- case 'SET_SCALE':
105
- return {
106
- ...state,
107
- scale: action.scale,
108
- };
109
-
110
- case 'PAGE_LOAD_SUCCESS':
111
- return {
112
- ...state,
113
- pdfWidth: action.width,
114
- pdfHeight: action.height,
115
- pageWidth: action.width,
116
- pageHeight: action.height,
117
- };
118
-
119
- case 'RESIZE_PAGE':
120
- return {
121
- ...state,
122
- pageWidth: action.width,
123
- pageHeight: action.height,
124
- };
125
- }
126
- }
127
-
128
- const getResourceUrl = (
129
- index: number,
130
- readingOrder: ReadiumLink[] | undefined
131
- ): string => {
132
- if (!readingOrder || !readingOrder.length) {
133
- throw new Error('A manifest has been returned, but has no reading order');
134
- }
135
-
136
- // If it has no children, return the link href
137
- return readingOrder[index].href;
138
- };
139
-
140
- const loadResource = async (resourceUrl: string, proxyUrl?: string) => {
141
- // Generate the resource URL using the proxy
142
- const resource: string = proxyUrl + encodeURI(resourceUrl);
143
- const response = await fetch(resource, { mode: 'cors' });
144
- const array = new Uint8Array(await response.arrayBuffer());
145
-
146
- if (!response.ok) {
147
- throw new Error('Response not Ok for URL: ' + resource);
148
- }
149
- return array;
150
- };
151
-
152
- /**
153
- * The PDF reader
154
- *
155
- * The PDF reader loads resources in two stages: First, it fetches the PDF resource as an Uint8Array
156
- * Then, it passes this array into the <Document> object, which loads the PDF inside an iframe
157
- *
158
- * @param args T
159
- * @returns
160
- */
161
- export default function usePdfReader(args: ReaderArguments): ReaderReturn {
162
- const { webpubManifestUrl, manifest, proxyUrl } = args ?? {};
163
- const [state, dispatch] = React.useReducer(pdfReducer, {
164
- colorMode: 'day',
165
- isScrolling: false,
166
- fontSize: 16,
167
- fontFamily: 'sans-serif',
168
- resourceIndex: 0,
169
- resource: null,
170
- pageNumber: 1,
171
- numPages: null,
172
- currentTocUrl: null,
173
- scale: 1,
174
- pdfWidth: 0,
175
- pdfHeight: 0,
176
- pageHeight: undefined,
177
- pageWidth: undefined,
178
- });
179
-
180
- // state we can derive from the state above
181
- const isFetching = !state.resource;
182
- const isParsed = typeof state.numPages === 'number';
183
- const [containerRef, containerSize] = useMeasure<HTMLDivElement>();
184
-
185
- // Wrap Page component so that we can pass it styles
186
- const ChakraPage = chakra(Page, {
187
- shouldForwardProp: (prop) => {
188
- // Definitely forward width and height
189
- if (['width', 'height', 'scale'].includes(prop)) return true;
190
- // don't forward the rest of Chakra's props
191
- const isChakraProp = !shouldForwardProp(prop);
192
- if (isChakraProp) return false;
193
- // else, only forward `sample` prop
194
- return true;
195
- },
196
- baseStyle: {
197
- outline: '1px',
198
- outlineColor: 'ui.gray.light-cool',
199
- },
200
- });
201
-
202
- /**
203
- * Load the current resource and set it in state,
204
- * and reload whenever it changes (via navigation)
205
- */
206
- React.useEffect(() => {
207
- // bail out if there is not manifest passed in,
208
- // that indicates that this format is inactive
209
- if (!manifest) return;
210
- // throw an error on a badly formed manifest
211
- if (!manifest.readingOrder || !manifest.readingOrder.length) {
212
- throw new Error('Manifest has no Reading Order');
213
- }
214
-
215
- const resourceUrl = getResourceUrl(
216
- state.resourceIndex,
217
- manifest.readingOrder
218
- );
219
- loadResource(resourceUrl, proxyUrl).then((data) => {
220
- dispatch({
221
- type: 'RESOURCE_FETCH_SUCCESS',
222
- resource: { data },
223
- });
224
- });
225
- }, [state.resourceIndex, manifest, proxyUrl]);
226
-
227
- /**
228
- * calculate the height or width of the pdf page in paginated mode.
229
- * - if the page's aspect ratio is taller than the container's, we will constrain
230
- * the page to the height of the container.
231
- * - if the page's aspect ratio is wider than the container's, we will constrain
232
- * the page to the width of the container
233
- */
234
-
235
- const resizePage = React.useCallback(
236
- (
237
- pdfWidth: number,
238
- pdfHeight: number,
239
- containerSize: { width: number; height: number }
240
- ) => {
241
- const wRatio = pdfWidth / containerSize.width;
242
- const hRatio = pdfHeight / containerSize.height;
243
-
244
- const fitHorizontal = wRatio > hRatio;
245
- const width = fitHorizontal ? Math.round(containerSize.width) : undefined;
246
- const height = !fitHorizontal
247
- ? Math.round(containerSize.height)
248
- : undefined;
249
-
250
- dispatch({ type: 'RESIZE_PAGE', width, height });
251
- },
252
- []
253
- );
254
-
255
- //TODO: Somehow, this window size updates when height
256
- React.useEffect(() => {
257
- if (containerSize) {
258
- resizePage(state.pdfWidth, state.pdfHeight, containerSize);
259
- }
260
- }, [containerSize, state.pdfWidth, state.pdfHeight, resizePage]);
261
-
262
- // prev and next page functions
263
- const goForward = React.useCallback(async () => {
264
- // do nothing if we haven't parsed the number of pages yet
265
- if (!state.numPages) return;
266
-
267
- if (state.pageNumber < state.numPages && !state.isScrolling) {
268
- dispatch({
269
- type: 'NAVIGATE_PAGE',
270
- pageNum: state.pageNumber + 1,
271
- });
272
- } else if (
273
- manifest &&
274
- manifest.readingOrder &&
275
- state.resourceIndex < manifest?.readingOrder?.length - 1
276
- ) {
277
- const nextIndex = state.resourceIndex + 1;
278
- dispatch({
279
- type: 'SET_CURRENT_RESOURCE',
280
- index: nextIndex,
281
- shouldNavigateToEnd: false,
282
- });
283
- }
284
- // Do nothing if it's at the last page of the last resource
285
- }, [
286
- manifest,
287
- state.isScrolling,
288
- state.numPages,
289
- state.pageNumber,
290
- state.resourceIndex,
291
- ]);
292
-
293
- const goBackward = React.useCallback(async () => {
294
- // do nothing if we haven't parsed the PDF yet
295
- if (!isParsed) return;
296
-
297
- if (state.pageNumber > 1) {
298
- dispatch({
299
- type: 'NAVIGATE_PAGE',
300
- pageNum: state.pageNumber - 1,
301
- });
302
- } else if (manifest?.readingOrder && state.resourceIndex > 0) {
303
- const nextIndex = state.resourceIndex - 1;
304
- dispatch({
305
- type: 'SET_CURRENT_RESOURCE',
306
- index: nextIndex,
307
- shouldNavigateToEnd: !state.isScrolling,
308
- });
309
- }
310
- }, [
311
- manifest,
312
- isParsed,
313
- state.isScrolling,
314
- state.pageNumber,
315
- state.resourceIndex,
316
- ]);
317
-
318
- /**
319
- * These ones don't make sense in the PDF case I dont think. I'm still
320
- * deciding how we will separate the types of Navigators and States, so
321
- * for now just pass dummies through.
322
- */
323
- const setColorMode = React.useCallback(async () => {
324
- console.log('unimplemented');
325
- }, []);
326
-
327
- const setScroll = React.useCallback(
328
- async (val: 'scrolling' | 'paginated') => {
329
- const isScrolling = val === 'scrolling';
330
- dispatch({ type: 'SET_SCROLL', isScrolling });
331
- },
332
- []
333
- );
334
-
335
- /**
336
- * TODO: Change this button into a different "scale" button
337
- */
338
- const increaseFontSize = React.useCallback(async () => {
339
- dispatch({
340
- type: 'SET_SCALE',
341
- scale: state.scale + 0.1,
342
- });
343
- }, [state.scale]);
344
-
345
- const decreaseFontSize = React.useCallback(async () => {
346
- dispatch({
347
- type: 'SET_SCALE',
348
- scale: state.scale - 0.1,
349
- });
350
- }, [state.scale]);
351
-
352
- const setFontFamily = React.useCallback(async () => {
353
- console.log('unimplemented');
354
- }, []);
355
-
356
- const goToPage = React.useCallback(
357
- async (href) => {
358
- const getIndexFromHref = (href: string): number => {
359
- const index = manifest?.readingOrder?.findIndex((link) => {
360
- return link.href === href;
361
- });
362
- if (!index) {
363
- throw new Error('Cannot find resource in readingOrder');
364
- }
365
- return index;
366
- };
367
-
368
- dispatch({
369
- type: 'SET_CURRENT_RESOURCE',
370
- index: getIndexFromHref(href),
371
- shouldNavigateToEnd: false,
372
- });
373
- },
374
- [manifest?.readingOrder]
375
- );
376
-
377
- // this format is inactive, return null
378
- if (!webpubManifestUrl || !manifest) return null;
379
-
380
- if (isFetching) {
381
- // The Reader is fetching a PDF resource
382
- return {
383
- type: 'PDF',
384
- isLoading: false,
385
- content: (
386
- <Flex
387
- as="main"
388
- tabIndex={-1}
389
- id="iframe-wrapper"
390
- zIndex="base"
391
- alignItems="center"
392
- justifyContent="center"
393
- flex="1 0 auto"
394
- >
395
- PDF is loading
396
- </Flex>
397
- ),
398
- state,
399
- manifest,
400
- navigator: {
401
- goForward,
402
- goBackward,
403
- increaseFontSize,
404
- decreaseFontSize,
405
- setFontFamily,
406
- setColorMode,
407
- setScroll,
408
- goToPage,
409
- },
410
- };
411
- }
412
-
413
- function onDocumentLoadSuccess({ numPages }: { numPages: number }) {
414
- dispatch({
415
- type: 'PDF_PARSED',
416
- numPages: numPages,
417
- });
418
- }
419
-
420
- function onRenderSuccess(page: PageProps) {
421
- if (!page.height || !page.width || !containerSize)
422
- throw new Error('Error rendering page from Reader');
423
- if (
424
- Math.round(page.height) !== state.pdfHeight ||
425
- Math.round(page.width) !== state.pdfWidth
426
- ) {
427
- dispatch({
428
- type: 'PAGE_LOAD_SUCCESS',
429
- height: Math.round(page.height),
430
- width: Math.round(page.width),
431
- });
432
-
433
- resizePage(page.width, page.height, containerSize);
434
- }
435
- }
436
-
437
- // the reader is active but loading a page
438
- return {
439
- type: 'PDF',
440
- isLoading: false,
441
- content: (
442
- <Flex
443
- as="main"
444
- zIndex="base"
445
- flex="1 0 auto"
446
- justifyContent="center"
447
- alignItems="center"
448
- tabIndex={-1}
449
- id={IFRAME_WRAPPER_ID}
450
- ref={containerRef}
451
- >
452
- <Document file={state.resource} onLoadSuccess={onDocumentLoadSuccess}>
453
- {isParsed && state.numPages && (
454
- <>
455
- {state.isScrolling &&
456
- Array.from(new Array(state.numPages), (_, index) => (
457
- <ChakraPage
458
- key={`page_${index + 1}`}
459
- width={containerSize?.width}
460
- scale={state.scale}
461
- pageNumber={index + 1}
462
- />
463
- ))}
464
- {!state.isScrolling && (
465
- <ChakraPage
466
- pageNumber={state.pageNumber}
467
- onLoadSuccess={onRenderSuccess}
468
- width={state.pageWidth}
469
- height={state.pageHeight}
470
- scale={state.scale}
471
- loading={<></>}
472
- />
473
- )}
474
- </>
475
- )}
476
- </Document>
477
- </Flex>
478
- ),
479
- state,
480
- manifest,
481
- navigator: {
482
- goForward,
483
- goBackward,
484
- setColorMode,
485
- setScroll,
486
- increaseFontSize,
487
- decreaseFontSize,
488
- setFontFamily,
489
- goToPage,
490
- },
491
- };
492
- }
@@ -1,68 +0,0 @@
1
- import * as React from 'react';
2
-
3
- declare const window: Window &
4
- typeof globalThis & {
5
- ResizeObserver: any;
6
- };
7
- export type Dimensions = Pick<
8
- DOMRectReadOnly,
9
- 'x' | 'y' | 'top' | 'left' | 'right' | 'bottom' | 'height' | 'width'
10
- >;
11
- export type UseMeasureRef<E extends Element = Element> = (element: E) => void;
12
- export type UseMeasureResult<E extends Element = Element> = [
13
- UseMeasureRef<E> | null,
14
- Dimensions | null
15
- ];
16
-
17
- export default function useMeasure<
18
- E extends Element = Element
19
- >(): UseMeasureResult<E> {
20
- // this is a little trick to get a reference to an HTML element. Using useRef wouldn't
21
- // work because we actually need rerenders when it changes, to update the useLayoutEffect
22
- const [element, ref] = React.useState<E | null>(null);
23
- const [rect, setRect] = React.useState<Dimensions | null>(null);
24
- const observer = React.useMemo(
25
- () =>
26
- new window.ResizeObserver(
27
- (
28
- entries: {
29
- contentRect: {
30
- x: any;
31
- y: any;
32
- width: any;
33
- height: any;
34
- top: any;
35
- left: any;
36
- bottom: any;
37
- right: any;
38
- };
39
- }[]
40
- ) => {
41
- if (entries[0]) {
42
- const {
43
- x,
44
- y,
45
- width,
46
- height,
47
- top,
48
- left,
49
- bottom,
50
- right,
51
- } = entries[0].contentRect;
52
- setRect({ x, y, width, height, top, left, bottom, right });
53
- }
54
- }
55
- ),
56
- []
57
- );
58
-
59
- React.useLayoutEffect(() => {
60
- if (!element) return;
61
- observer.observe(element);
62
- return () => {
63
- observer.disconnect();
64
- };
65
- }, [element, observer]);
66
-
67
- return [ref, rect];
68
- }
@@ -1,106 +0,0 @@
1
- import React from 'react';
2
- import { WebpubManifest } from '../WebpubManifestTypes/WebpubManifest';
3
- import { ReadiumLink } from '../WebpubManifestTypes/ReadiumLink';
4
- import { WEBPUB_CACHE_NAME } from './constants';
5
-
6
- export type PublicationConfig = {
7
- manifestUrl: string;
8
- proxyUrl?: string;
9
- };
10
-
11
- /**
12
- * Will add all publication resources to the cache so they
13
- * can be picked up by the SW.
14
- */
15
- export default function usePublicationSW(
16
- publications: PublicationConfig[]
17
- ): void {
18
- // add each manifest and its resources to the cache directly
19
- React.useEffect(() => {
20
- async function cachePublications() {
21
- const cache = await caches.open(WEBPUB_CACHE_NAME);
22
-
23
- const promises = publications.map(async (pub) => {
24
- const finalManifestUrl = getProxiedUrl(pub.manifestUrl, pub.proxyUrl);
25
- const manifestResponse = await fetch(finalManifestUrl);
26
- handleBadResponse(finalManifestUrl, manifestResponse);
27
- // add the manifest response to the cache
28
- await cache.put(finalManifestUrl, manifestResponse.clone());
29
-
30
- const manifest: WebpubManifest = await manifestResponse.json();
31
-
32
- // make a list of resources with proxy included
33
- const resourceHrefs = extractHrefs(
34
- manifest.resources ?? [],
35
- pub.manifestUrl,
36
- pub.proxyUrl
37
- );
38
-
39
- const readingOrderHrefs = extractHrefs(
40
- manifest.readingOrder ?? [],
41
- pub.manifestUrl,
42
- pub.proxyUrl
43
- );
44
-
45
- // make sure array is deduped using set or we may get a cache error
46
- const allResourcesToCache = Array.from(
47
- new Set([...resourceHrefs, ...readingOrderHrefs])
48
- );
49
- // add them all to the cache
50
- await Promise.all(
51
- allResourcesToCache.map(async (url) => {
52
- const response = await fetch(url);
53
- handleBadResponse(url, response);
54
- return await cache.put(url, response);
55
- })
56
- );
57
- });
58
- // wait for this to finish for all of the manifests, but don't reject if one fails
59
- return await Promise.allSettled(promises);
60
- }
61
-
62
- cachePublications();
63
- }, [publications]);
64
- }
65
-
66
- function handleBadResponse(url: string, response: Response) {
67
- if (!response.ok) {
68
- const message = `Bad response status for: ${url}. Status: ${response.status}`;
69
- console.warn(message);
70
- throw new Error(message);
71
- }
72
- }
73
-
74
- /**
75
- * Prepends the proxy url if there is one
76
- */
77
- function getProxiedUrl(url: string, proxyUrl: string | undefined) {
78
- return proxyUrl ? `${proxyUrl}${encodeURIComponent(url)}` : url;
79
- }
80
-
81
- /**
82
- * If the passed in url is relative, it will resolve it relative to the
83
- * manifest url. Otherwise it should stay the same. Finally, the proxy is
84
- * conditionally added
85
- */
86
- function getAbsoluteUrl(
87
- maybeRelative: string,
88
- manifestUrl: string,
89
- proxyUrl?: string
90
- ) {
91
- return getProxiedUrl(
92
- new URL(maybeRelative, manifestUrl).toString(),
93
- proxyUrl
94
- );
95
- }
96
-
97
- /**
98
- * Gets an array of raw href values from an array of readium links
99
- */
100
- function extractHrefs(
101
- links: ReadiumLink[],
102
- manifestUrl: string,
103
- proxyUrl: string | undefined
104
- ): string[] {
105
- return links.map((res) => getAbsoluteUrl(res.href, manifestUrl, proxyUrl));
106
- }
@@ -1,4 +0,0 @@
1
- export const WEBPUB_CACHE_NAME = 'webpub-cache';
2
- export const AGE_HEADER = 'sw-fetched-on';
3
- // one week worth of seconds
4
- export const CACHE_EXPIRATION_SECONDS = 7 * 24 * 60 * 60;