@nypl/web-reader 1.0.0 → 1.1.0-2

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.
@@ -0,0 +1,112 @@
1
+ import { Injectable } from '../Readium/Injectable';
2
+ import { Locator } from '../Readium/Locator';
3
+ import { WebpubManifest, ColorMode, FontFamily } from '../types';
4
+ import { ReadiumLink } from '../WebpubManifestTypes/ReadiumLink';
5
+ import { ActiveState } from './types';
6
+ /**
7
+ * Constants
8
+ */
9
+ export declare const FONT_SIZE_STEP = 4;
10
+ /**
11
+ * If we provide injectables that are not found, the app won't load at all.
12
+ * Therefore we will not provide any default injectables.
13
+ * @todo - this is not true in our custom renderer. We should provide default injectables.
14
+ */
15
+ export declare const defaultInjectables: Injectable[];
16
+ export declare const defaultInjectablesFixed: Injectable[];
17
+ /**
18
+ * Creates an element for an injectable so it can be injected into the iframe.
19
+ */
20
+ export declare function makeInjectableElement(document: Document, injectable: Injectable): HTMLElement | undefined;
21
+ /**
22
+ * gets the index of the current location href
23
+ */
24
+ export declare function getCurrentIndex(manifest: WebpubManifest, state: ActiveState, baseUrl: string): number;
25
+ /**
26
+ * Find a link in the reading order from a passed in href.
27
+ */
28
+ export declare function getFromReadingOrder(href: string, manifest: WebpubManifest, baseUrl: string): {
29
+ link: ReadiumLink;
30
+ index: number;
31
+ } | undefined;
32
+ /**
33
+ * Check if two hrefs share the same pathname. They can be absolute
34
+ * or relative. This will ignore hash and query params.
35
+ */
36
+ export declare function isSameResource(href1: string, href2: string, baseUrl: string): boolean;
37
+ /**
38
+ * Converts a ReadiumLink to a Locator
39
+ */
40
+ export declare function linkToLocator(link: ReadiumLink, baseUrl: string, locations?: Locator['locations']): Locator;
41
+ declare type CalculatedPosition = {
42
+ isHorizontalPaginated: boolean;
43
+ containerSize: number;
44
+ containerWidth: number;
45
+ containerHeight: number;
46
+ pageSize: number;
47
+ resourceSize: number;
48
+ scrollPosition: number;
49
+ totalPages: number;
50
+ progression: number;
51
+ currentPage: number;
52
+ currentPageFloor: number;
53
+ isAtEnd: boolean;
54
+ isAtStart: boolean;
55
+ };
56
+ /**
57
+ * Calculate current position information
58
+ */
59
+ export declare function calcPosition(iframe: HTMLIFrameElement, isScrolling: boolean): CalculatedPosition;
60
+ /**
61
+ * Gets scroll position of an element
62
+ */
63
+ export declare function getScrollPosition(element: HTMLElement | undefined | null): {
64
+ x: number;
65
+ y: number;
66
+ };
67
+ /**
68
+ * Fetches a resource as text
69
+ */
70
+ export declare function fetchAsTxt(url: string): Promise<string>;
71
+ /**
72
+ * Inject some raw JS into the iframe document
73
+ */
74
+ export declare function injectJS(document: Document): void;
75
+ export declare function getMaybeIframeHtml(iframe: HTMLIFrameElement): HTMLElement | undefined;
76
+ /**
77
+ * Get the HTML element of the iframe
78
+ */
79
+ export declare function getIframeHTML(iframe: HTMLIFrameElement): HTMLElement;
80
+ /**
81
+ * Sets a CSS var on the html element in the iframe. Used to set
82
+ * ReadiumCSS settings like scrolling and color mode and font
83
+ * size.
84
+ */
85
+ export declare function setCSSProperty(html: HTMLElement, name: string, val: string): void;
86
+ /**
87
+ * Translates the readium scroll css var into a boolean
88
+ */
89
+ export declare function getPagination(isPaginated: boolean): 'readium-scroll-on' | 'readium-scroll-off';
90
+ /**
91
+ * Translates the internal color mode value into a Readium
92
+ * color mode value.
93
+ */
94
+ export declare function getColorModeValue(mode: ColorMode): 'readium-default-on' | 'readium-night-on' | 'readium-sepia-on';
95
+ /**
96
+ * Translates the readium color mode value into an internal
97
+ * color mode value
98
+ */
99
+ export declare function getColorMode(d2Mode: string): ColorMode;
100
+ /**
101
+ * Gets the Readium font-override setting based on the given font family.
102
+ */
103
+ export declare function getFontOverride(fontFamily: FontFamily): 'readium-font-off' | 'readium-font-on';
104
+ /**
105
+ * Translates the internal font family to a readium css font family value.
106
+ */
107
+ export declare const familyToReadiumFamily: Record<FontFamily, string>;
108
+ /**
109
+ * Translates a readium css font family to an internal font family.
110
+ */
111
+ export declare const r2FamilyToFamily: Record<string, FontFamily | undefined>;
112
+ export {};
@@ -0,0 +1,8 @@
1
+ import { ReaderArguments } from '../types';
2
+ import { HtmlAction, HtmlState, InactiveState } from './types';
3
+ /**
4
+ * A higher order function that makes it easy to access arguments in the reducer
5
+ * without passing them in to every `dispatch` call.
6
+ */
7
+ export default function makeHtmlReducer(args: ReaderArguments): (state: HtmlState, action: HtmlAction) => HtmlState;
8
+ export declare const inactiveState: InactiveState;
@@ -0,0 +1,109 @@
1
+ import { Locator } from '../Readium/Locator';
2
+ import { ColorMode, FontFamily, HtmlReaderState, ReaderArguments, ReaderState } from '../types';
3
+ /**
4
+ * Html Reader States
5
+ * - Can be broken into distinct states that we create a union from.
6
+ * This helps us avoid invalid states.
7
+ * - We include a `state` property so that it is easy to narrow the type
8
+ * of a given HtmlState to a specific state in the union.
9
+ */
10
+ export declare type HtmlState = InactiveState | ActiveState;
11
+ export declare type ActiveState = FetchingResourceState | ResourceFetchErrorState | RenderingIframeState | LoadingIframeState | NavigatingState | ReadyState;
12
+ export declare type InactiveState = ReaderState & {
13
+ state: 'INACTIVE';
14
+ location: undefined;
15
+ iframe: null;
16
+ resource: undefined;
17
+ resourceFetchError: undefined;
18
+ };
19
+ export declare type FetchingResourceState = HtmlReaderState & {
20
+ state: 'FETCHING_RESOURCE';
21
+ location: Locator;
22
+ iframe: null;
23
+ resource: undefined;
24
+ resourceFetchError: undefined;
25
+ };
26
+ export declare type ResourceFetchErrorState = HtmlReaderState & {
27
+ state: 'RESOURCE_FETCH_ERROR';
28
+ location: Locator;
29
+ iframe: null;
30
+ resource: undefined;
31
+ resourceFetchError: Error;
32
+ };
33
+ export declare type RenderingIframeState = HtmlReaderState & {
34
+ state: 'RENDERING_IFRAME';
35
+ location: Locator;
36
+ iframe: null;
37
+ resource: string;
38
+ resourceFetchError: undefined;
39
+ };
40
+ export declare type LoadingIframeState = HtmlReaderState & {
41
+ state: 'LOADING_IFRAME';
42
+ location: Locator;
43
+ iframe: HTMLIFrameElement;
44
+ resource: string;
45
+ resourceFetchError: undefined;
46
+ };
47
+ export declare type NavigatingState = HtmlReaderState & {
48
+ state: 'NAVIGATING';
49
+ location: Locator;
50
+ iframe: HTMLIFrameElement;
51
+ resource: string;
52
+ resourceFetchError: undefined;
53
+ };
54
+ export declare type ReadyState = HtmlReaderState & {
55
+ state: 'READY';
56
+ location: Locator;
57
+ iframe: HTMLIFrameElement;
58
+ resource: string;
59
+ resourceFetchError: undefined;
60
+ };
61
+ export declare type CSSState = Pick<HtmlState, 'isScrolling' | 'colorMode' | 'fontFamily' | 'fontSize'>;
62
+ export declare type HtmlAction = {
63
+ type: 'ARGS_CHANGED';
64
+ args: ReaderArguments;
65
+ } | {
66
+ type: 'IFRAME_LOADED';
67
+ } | {
68
+ type: 'NAV_PREVIOUS_RESOURCE';
69
+ } | {
70
+ type: 'NAV_NEXT_RESOURCE';
71
+ } | {
72
+ type: 'GO_TO_HREF';
73
+ href: string;
74
+ } | {
75
+ type: 'GO_TO_LOCATION';
76
+ location: Locator;
77
+ } | {
78
+ type: 'GO_FORWARD';
79
+ } | {
80
+ type: 'GO_BACKWARD';
81
+ } | {
82
+ type: 'WINDOW_RESIZED';
83
+ } | {
84
+ type: 'NAV_COMPLETE';
85
+ } | {
86
+ type: 'SET_COLOR_MODE';
87
+ mode: ColorMode;
88
+ } | {
89
+ type: 'SET_SCROLL';
90
+ isScrolling: boolean;
91
+ } | {
92
+ type: 'INCREASE_FONT_SIZE';
93
+ } | {
94
+ type: 'DECREASE_FONT_SIZE';
95
+ } | {
96
+ type: 'SET_FONT_FAMILY';
97
+ family: FontFamily;
98
+ } | {
99
+ type: 'USER_SCROLLED';
100
+ } | {
101
+ type: 'SET_IFRAME';
102
+ iframe: HTMLIFrameElement | null;
103
+ } | {
104
+ type: 'RESOURCE_FETCH_SUCCESS';
105
+ resource: string;
106
+ } | {
107
+ type: 'RESOURCE_FETCH_ERROR';
108
+ error: Error;
109
+ };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { HtmlAction } from './types';
3
+ export default function useIframeLinkClick(dispatch: React.Dispatch<HtmlAction>): void;
@@ -0,0 +1,8 @@
1
+ import { Locator } from '../Readium/Locator';
2
+ import { HtmlState } from './types';
3
+ /**
4
+ * Keep the Location state in the browser's url bar.
5
+ * Dispatch location changed when the url changes.
6
+ */
7
+ export default function useLocationQuery(state: HtmlState): void;
8
+ export declare function getLocationQuery(): Locator | undefined;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Injectable } from '../Readium/Injectable';
3
+ import { HtmlState, HtmlAction } from './types';
4
+ /**
5
+ * Fetches a resource whenever the url changes and dispatches
6
+ * actions to keep the reducer up to date. Works similar to
7
+ * useSWR, but storing the resource in the reducer state, not
8
+ * separately.
9
+ *
10
+ * Also performs some modifications on the resource to add initial
11
+ * css variables and injectables.
12
+ */
13
+ export default function useResource(state: HtmlState, getContent: (url: string) => Promise<string>, injectables: Injectable[], dispatch: React.Dispatch<HtmlAction>): void;
@@ -0,0 +1,7 @@
1
+ import { WebpubManifest } from '../types';
2
+ import { HtmlState } from './types';
3
+ /**
4
+ * Set CSS variables when user state changes.
5
+ * @todo - narrow down the dependencies so this doesn't run on _every_ state change.
6
+ */
7
+ export default function useUpdateCSS(state: HtmlState, manifest: WebpubManifest | undefined): void;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import { HtmlAction, HtmlState } from './types';
3
+ /**
4
+ * Dispatch a USER_SCROLLED event after some delay
5
+ */
6
+ export declare function useUpdateScroll(state: HtmlState, dispatch: React.Dispatch<HtmlAction>): void;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { HtmlAction } from './types';
3
+ /**
4
+ * Simply dispatches an action when the window is resized.
5
+ */
6
+ export default function useWindowResize(dispatch: React.Dispatch<HtmlAction>): void;
@@ -0,0 +1,11 @@
1
+ export interface Injectable {
2
+ type: string;
3
+ url?: string;
4
+ r2after?: boolean;
5
+ r2before?: boolean;
6
+ r2default?: boolean;
7
+ fontFamily?: string;
8
+ systemFont?: boolean;
9
+ appearance?: string;
10
+ async?: boolean;
11
+ }
@@ -0,0 +1,20 @@
1
+ export interface Locator {
2
+ href: string;
3
+ type?: string;
4
+ title?: string;
5
+ locations: Locations;
6
+ text?: LocatorText;
7
+ }
8
+ export interface LocatorText {
9
+ after?: string;
10
+ before?: string;
11
+ highlight?: string;
12
+ }
13
+ export interface Locations {
14
+ fragment?: string;
15
+ progression?: number;
16
+ position?: number;
17
+ totalProgression?: number;
18
+ remainingPositions?: number;
19
+ totalRemainingPositions?: number;
20
+ }
@@ -1,5 +1,6 @@
1
1
  export declare const ReadiumWebpubContext = "http://readium.org/webpub/default.jsonld";
2
2
  export declare const IS_DEV: boolean;
3
+ export declare const IS_SERVER: boolean;
3
4
  export declare const HEADER_HEIGHT = 48;
4
5
  export declare const FOOTER_HEIGHT = 48;
5
6
  export declare const CHROME_HEIGHT: number;
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
- import { Injectable } from '@d-i-t-a/reader/dist/types/navigator/IFrameNavigator';
2
+ import { Injectable } from './Readium/Injectable';
3
+ import { Locator } from './Readium/Locator';
3
4
  import { WebpubManifest } from './WebpubManifestTypes/WebpubManifest';
4
5
  export { WebpubManifest };
5
6
  export declare const EpubMimeType = "application/epub";
@@ -33,6 +34,7 @@ export declare type ReaderState = {
33
34
  currentTocUrl: string | null;
34
35
  atStart: boolean;
35
36
  atEnd: boolean;
37
+ location?: Locator;
36
38
  };
37
39
  export declare type PdfReaderState = ReaderState;
38
40
  export declare type HtmlReaderState = ReaderState;
@@ -73,8 +75,26 @@ export declare type UseWebReaderArguments = {
73
75
  pdfWorkerSrc?: string;
74
76
  injectables?: Injectable[];
75
77
  injectablesFixed?: Injectable[];
78
+ /**
79
+ * CSS string to set the height of the reader in paginated mode, and also
80
+ * in scrolling mode if `growWhenScrolling` is `false`.
81
+ *
82
+ * eg: "800px" or `calc(100vh-${CHROME_HEIGHT})`
83
+ *
84
+ * Default: `calc(100vh-${CHROME_HEIGHT})`
85
+ */
76
86
  height?: string;
87
+ /**
88
+ * Tells the renderer if it should grow to fit content in scrolling mode, or if should
89
+ * remain the same height and instead show an internal scroll bar. Set to `true` by
90
+ * default, as this should be used in a full-page reader, the most common use case.
91
+ *
92
+ * Default: `true`
93
+ */
77
94
  growWhenScrolling?: boolean;
95
+ /**
96
+ * Initial user settings for the reader
97
+ */
78
98
  readerSettings?: ReaderSettings;
79
99
  };
80
100
  export declare type ActiveReaderArguments = UseWebReaderArguments & {
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ export default function LoadingSkeleton({ height, }: {
3
+ height: string;
4
+ }): JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nypl/web-reader",
3
- "version": "1.0.0",
3
+ "version": "1.1.0-2",
4
4
  "license": "MIT",
5
5
  "repository": "https://github.com/NYPL-Simplified/web-reader",
6
6
  "homepage": "https://github.com/NYPL-Simplified/web-reader",
@@ -87,7 +87,7 @@
87
87
  "@storybook/addon-storyshots": "^6.3.1",
88
88
  "@storybook/addons": "^6.3.1",
89
89
  "@storybook/react": "^6.3.1",
90
- "@testing-library/cypress": "^8.0.1",
90
+ "@testing-library/cypress": "^8.0.2",
91
91
  "@testing-library/jest-dom": "^5.14.1",
92
92
  "@testing-library/react": "^12.0.0",
93
93
  "@testing-library/react-hooks": "^7.0.1",
@@ -104,7 +104,7 @@
104
104
  "@typescript-eslint/parser": "^4.29.2",
105
105
  "babel-jest": "^27.0.5",
106
106
  "babel-loader": "^8.2.2",
107
- "cypress": "^8.6.0",
107
+ "cypress": "^9.5.1",
108
108
  "debounce": "^1.2.1",
109
109
  "esbuild": "^0.14.13",
110
110
  "esbuild-jest": "^0.5.0",
@@ -122,7 +122,7 @@
122
122
  "jest-axe": "^5.0.1",
123
123
  "jest-watch-typeahead": "^0.5.0",
124
124
  "lint-staged": "^11.1.2",
125
- "parcel": "^2.0.0-rc.0",
125
+ "parcel": "^2.0.1",
126
126
  "parcel-config-precache-manifest": "^0.0.4",
127
127
  "parcel-plugin-static-files-copy": "^2.6.0",
128
128
  "parcel-reporter-static-files-copy": "^1.3.0",
@@ -145,7 +145,6 @@
145
145
  },
146
146
  "dependencies": {
147
147
  "@chakra-ui/react": "1.6.9",
148
- "@d-i-t-a/reader": "2.0.0-beta.6",
149
148
  "@emotion/react": "^11.4.0",
150
149
  "@emotion/styled": "^11.3.0",
151
150
  "comlink": "^4.3.1",
@@ -154,6 +153,8 @@
154
153
  "react-icons": "^4.3.1",
155
154
  "react-intersection-observer": "^8.32.2",
156
155
  "react-pdf": "^5.3.2",
156
+ "react-resize-observer": "^1.1.1",
157
+ "swr": "^1.0.1",
157
158
  "workbox-expiration": "^6.2.4",
158
159
  "workbox-precaching": "^6.2.4",
159
160
  "workbox-routing": "^6.3.0",
@@ -1,7 +0,0 @@
1
- import * as React from 'react';
2
- declare const HtmlReaderContent: React.FC<{
3
- height: string;
4
- isScrolling: boolean;
5
- growsWhenScrolling: boolean;
6
- }>;
7
- export default HtmlReaderContent;