react-native-readium 4.0.1 → 5.0.0-rc.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.
Files changed (118) hide show
  1. package/README.md +93 -9
  2. package/android/build.gradle +32 -29
  3. package/android/gradle.properties +3 -3
  4. package/android/src/main/java/com/reactnativereadium/ReadiumView.kt +88 -28
  5. package/android/src/main/java/com/reactnativereadium/ReadiumViewManager.kt +20 -19
  6. package/android/src/main/java/com/reactnativereadium/reader/BaseReaderFragment.kt +27 -6
  7. package/android/src/main/java/com/reactnativereadium/reader/EpubReaderFragment.kt +53 -69
  8. package/android/src/main/java/com/reactnativereadium/reader/PositionLabelManager.kt +132 -0
  9. package/android/src/main/java/com/reactnativereadium/reader/ReaderService.kt +64 -65
  10. package/android/src/main/java/com/reactnativereadium/reader/ReaderViewModel.kt +6 -85
  11. package/android/src/main/java/com/reactnativereadium/reader/VisualReaderFragment.kt +32 -2
  12. package/android/src/main/java/com/reactnativereadium/utils/FragmentFactory.kt +2 -3
  13. package/android/src/main/java/com/reactnativereadium/utils/JsonExtensions.kt +61 -0
  14. package/android/src/main/java/com/reactnativereadium/utils/MetadataNormalizer.kt +183 -0
  15. package/android/src/main/java/com/reactnativereadium/utils/NormalizedMetadata.kt +179 -0
  16. package/android/src/main/java/com/reactnativereadium/utils/extensions/InputStream.kt +0 -9
  17. package/ios/App/AppModule.swift +3 -9
  18. package/ios/Common/Toolkit/Extensions/Locator.swift +1 -1
  19. package/ios/Data/Bookmark.swift +1 -1
  20. package/ios/Reader/Common/ReaderViewController.swift +118 -21
  21. package/ios/Reader/EPUB/AssociatedColors.swift +1 -1
  22. package/ios/Reader/EPUB/EPUBHTTPServer.swift +13 -0
  23. package/ios/Reader/EPUB/EPUBModule.swift +1 -1
  24. package/ios/Reader/EPUB/EPUBViewController.swift +3 -4
  25. package/ios/Reader/ReaderFormatModule.swift +1 -1
  26. package/ios/Reader/ReaderModule.swift +1 -1
  27. package/ios/Reader/ReaderService.swift +70 -35
  28. package/ios/ReadiumView.swift +62 -25
  29. package/ios/ReadiumViewManager.m +1 -1
  30. package/lib/src/ReadiumViewNativeComponent.d.ts +19 -0
  31. package/lib/src/ReadiumViewNativeComponent.js +10 -0
  32. package/lib/src/components/BaseReadiumView.d.ts +1 -2
  33. package/lib/src/components/BaseReadiumView.js +3 -7
  34. package/lib/src/components/ReadiumView.js +15 -15
  35. package/lib/src/components/ReadiumView.web.js +100 -21
  36. package/lib/src/interfaces/BaseReadiumViewProps.d.ts +2 -1
  37. package/lib/src/interfaces/Preferences.d.ts +3 -2
  38. package/lib/src/interfaces/PublicationMetadata.d.ts +114 -0
  39. package/lib/src/interfaces/PublicationMetadata.js +1 -0
  40. package/lib/src/interfaces/PublicationReady.d.ts +15 -0
  41. package/lib/src/interfaces/PublicationReady.js +1 -0
  42. package/lib/src/interfaces/index.d.ts +2 -0
  43. package/lib/src/interfaces/index.js +2 -0
  44. package/lib/src/utils/index.d.ts +0 -1
  45. package/lib/src/utils/index.js +0 -1
  46. package/lib/web/hooks/index.d.ts +3 -2
  47. package/lib/web/hooks/index.js +3 -2
  48. package/lib/web/hooks/useLocationObserver.d.ts +2 -1
  49. package/lib/web/hooks/useLocationObserver.js +18 -11
  50. package/lib/web/hooks/useNavigator.d.ts +12 -0
  51. package/lib/web/hooks/useNavigator.js +87 -0
  52. package/lib/web/hooks/usePositionLabel.d.ts +9 -0
  53. package/lib/web/hooks/usePositionLabel.js +33 -0
  54. package/lib/web/hooks/usePreferencesObserver.d.ts +2 -0
  55. package/lib/web/hooks/usePreferencesObserver.js +54 -0
  56. package/lib/web/utils/manifestFetcher.d.ts +8 -0
  57. package/lib/web/utils/manifestFetcher.js +28 -0
  58. package/lib/web/utils/manifestNormalizer.d.ts +8 -0
  59. package/lib/web/utils/manifestNormalizer.js +70 -0
  60. package/lib/web/utils/metadataNormalizer.d.ts +53 -0
  61. package/lib/web/utils/metadataNormalizer.js +220 -0
  62. package/lib/web/utils/navigatorListeners.d.ts +6 -0
  63. package/lib/web/utils/navigatorListeners.js +50 -0
  64. package/lib/web/utils/publicationUtils.d.ts +15 -0
  65. package/lib/web/utils/publicationUtils.js +39 -0
  66. package/package.json +24 -14
  67. package/react-native-readium.podspec +7 -5
  68. package/src/ReadiumViewNativeComponent.ts +35 -0
  69. package/src/components/BaseReadiumView.tsx +3 -10
  70. package/src/components/ReadiumView.tsx +15 -15
  71. package/src/components/ReadiumView.web.tsx +120 -27
  72. package/src/interfaces/BaseReadiumViewProps.ts +2 -1
  73. package/src/interfaces/Preferences.ts +3 -2
  74. package/src/interfaces/PublicationMetadata.ts +141 -0
  75. package/src/interfaces/PublicationReady.ts +18 -0
  76. package/src/interfaces/index.ts +2 -0
  77. package/src/utils/index.ts +0 -1
  78. package/web/hooks/index.ts +3 -2
  79. package/web/hooks/useLocationObserver.ts +24 -11
  80. package/web/hooks/useNavigator.ts +146 -0
  81. package/web/hooks/usePositionLabel.ts +51 -0
  82. package/web/hooks/usePreferencesObserver.ts +69 -0
  83. package/web/utils/manifestFetcher.ts +38 -0
  84. package/web/utils/manifestNormalizer.ts +74 -0
  85. package/web/utils/metadataNormalizer.ts +238 -0
  86. package/web/utils/navigatorListeners.ts +60 -0
  87. package/web/utils/publicationUtils.ts +47 -0
  88. package/android/src/main/java/com/reactnativereadium/search/SearchFragment.kt +0 -100
  89. package/android/src/main/java/com/reactnativereadium/search/SearchPagingSource.kt +0 -44
  90. package/android/src/main/java/com/reactnativereadium/search/SearchResultAdapter.kt +0 -68
  91. package/android/src/main/java/com/reactnativereadium/utils/R2DispatcherActivity.kt +0 -45
  92. package/android/src/main/java/com/reactnativereadium/utils/SectionDecoration.kt +0 -98
  93. package/android/src/main/java/com/reactnativereadium/utils/SingleClickListener.kt +0 -32
  94. package/android/src/main/java/com/reactnativereadium/utils/extensions/Bitmap.kt +0 -23
  95. package/android/src/main/java/com/reactnativereadium/utils/extensions/Context.kt +0 -16
  96. package/android/src/main/java/com/reactnativereadium/utils/extensions/File.kt +0 -22
  97. package/android/src/main/java/com/reactnativereadium/utils/extensions/Link.kt +0 -6
  98. package/android/src/main/java/com/reactnativereadium/utils/extensions/Metadata.kt +0 -6
  99. package/android/src/main/java/com/reactnativereadium/utils/extensions/URL.kt +0 -29
  100. package/android/src/main/java/com/reactnativereadium/utils/extensions/Uri.kt +0 -17
  101. package/android/src/main/res/layout/fragment_search.xml +0 -39
  102. package/android/src/main/res/layout/item_recycle_search.xml +0 -14
  103. package/ios/Common/EPUBPreferences.swift +0 -8
  104. package/ios/Common/Paths.swift +0 -52
  105. package/ios/Common/Publication.swift +0 -15
  106. package/ios/Common/Toolkit/Extensions/HTTPClient.swift +0 -65
  107. package/ios/Common/Toolkit/Extensions/UIImage.swift +0 -12
  108. package/ios/Common/Toolkit/Extensions/UIViewController.swift +0 -19
  109. package/ios/Common/Toolkit/ScreenOrientation.swift +0 -13
  110. package/lib/src/utils/createFragment.d.ts +0 -1
  111. package/lib/src/utils/createFragment.js +0 -10
  112. package/lib/web/hooks/useReaderRef.d.ts +0 -3
  113. package/lib/web/hooks/useReaderRef.js +0 -85
  114. package/lib/web/hooks/useSettingsObserver.d.ts +0 -2
  115. package/lib/web/hooks/useSettingsObserver.js +0 -44
  116. package/src/utils/createFragment.ts +0 -15
  117. package/web/hooks/useReaderRef.ts +0 -109
  118. package/web/hooks/useSettingsObserver.ts +0 -61
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Normalizes a Readium manifest object to ensure compatibility with the navigator.
3
+ * Handles various inconsistencies in manifest formats:
4
+ * - Converts string properties to arrays where required
5
+ * - Normalizes date formats to ISO 8601
6
+ * - Ensures required properties exist
7
+ */
8
+ export declare function normalizeManifest(manifest: any): any;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Normalizes a Readium manifest object to ensure compatibility with the navigator.
3
+ * Handles various inconsistencies in manifest formats:
4
+ * - Converts string properties to arrays where required
5
+ * - Normalizes date formats to ISO 8601
6
+ * - Ensures required properties exist
7
+ */
8
+ export function normalizeManifest(manifest) {
9
+ const responseObj = manifest;
10
+ const metadata = responseObj.metadata;
11
+ // Normalize root-level properties
12
+ if (typeof responseObj.conformsTo === 'string') {
13
+ responseObj.conformsTo = [responseObj.conformsTo];
14
+ }
15
+ if (typeof metadata?.conformsTo === 'string') {
16
+ metadata.conformsTo = [metadata.conformsTo];
17
+ }
18
+ if (typeof metadata?.accessMode === 'string') {
19
+ metadata.accessMode = [metadata.accessMode];
20
+ }
21
+ if (typeof metadata?.accessibilityFeature === 'string') {
22
+ metadata.accessibilityFeature = [metadata.accessibilityFeature];
23
+ }
24
+ if (typeof metadata?.accessibilityHazard === 'string') {
25
+ metadata.accessibilityHazard = [metadata.accessibilityHazard];
26
+ }
27
+ // Normalize nested accessibility properties
28
+ const accessibility = metadata?.accessibility;
29
+ if (accessibility) {
30
+ if (typeof accessibility.conformsTo === 'string') {
31
+ accessibility.conformsTo = [accessibility.conformsTo];
32
+ }
33
+ if (typeof accessibility.accessMode === 'string') {
34
+ accessibility.accessMode = [accessibility.accessMode];
35
+ }
36
+ if (typeof accessibility.feature === 'string') {
37
+ accessibility.feature = [accessibility.feature];
38
+ }
39
+ if (typeof accessibility.hazard === 'string') {
40
+ accessibility.hazard = [accessibility.hazard];
41
+ }
42
+ }
43
+ // Normalize date formats
44
+ // Some manifests use JavaScript Date.toString() format instead of ISO 8601
45
+ if (metadata?.modified && typeof metadata.modified === 'string') {
46
+ const date = new Date(metadata.modified);
47
+ if (!isNaN(date.getTime())) {
48
+ metadata.modified = date.toISOString();
49
+ }
50
+ }
51
+ if (metadata?.published && typeof metadata.published === 'string') {
52
+ const date = new Date(metadata.published);
53
+ if (!isNaN(date.getTime())) {
54
+ metadata.published = date.toISOString();
55
+ }
56
+ }
57
+ // Ensure links property exists (required by RWPM spec)
58
+ // Some manifests may have landmarks instead of links
59
+ if (!responseObj.links) {
60
+ // If landmarks exist, convert them to links
61
+ if (responseObj.landmarks && Array.isArray(responseObj.landmarks)) {
62
+ responseObj.links = responseObj.landmarks;
63
+ }
64
+ else {
65
+ // Otherwise create an empty links array
66
+ responseObj.links = [];
67
+ }
68
+ }
69
+ return responseObj;
70
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Normalizes metadata to ensure consistent structure per RWPM spec.
3
+ *
4
+ * This normalizer is library-agnostic and based on the stable RWPM specification,
5
+ * ensuring it works regardless of how the underlying Readium library serializes data.
6
+ *
7
+ * https://readium.org/webpub-manifest/
8
+ */
9
+ /**
10
+ * Normalizes a localized string per RWPM spec.
11
+ *
12
+ * Per RWPM spec, a localized string can be:
13
+ * 1. Plain string: "Moby-Dick"
14
+ * 2. Language map: {"en": "Moby-Dick", "fr": "Moby Dick"}
15
+ *
16
+ * Priority for language selection:
17
+ * 1. "undefined" or "und" (default/undetermined language)
18
+ * 2. "en" (English fallback)
19
+ * 3. First available language
20
+ *
21
+ * https://readium.org/webpub-manifest/contexts/default/
22
+ */
23
+ export declare function normalizeLocalizedString(value: any): string;
24
+ /**
25
+ * Normalizes contributors per RWPM spec.
26
+ *
27
+ * Per RWPM spec, a contributor can be:
28
+ * 1. Plain string: "Herman Melville"
29
+ * 2. Object: {"name": "Herman Melville", "sortAs": "Melville, Herman"}
30
+ *
31
+ * The Web library uses a Contributors class with an "items" property.
32
+ *
33
+ * https://readium.org/webpub-manifest/schema/contributor-object.schema.json
34
+ */
35
+ export declare function normalizeContributors(value: any): any[] | undefined;
36
+ /**
37
+ * Normalizes subjects per RWPM spec.
38
+ *
39
+ * Subject names can be LocalizedStrings.
40
+ * The Web library uses a Subjects class with an "items" property.
41
+ *
42
+ * https://readium.org/webpub-manifest/schema/subject.schema.json
43
+ */
44
+ export declare function normalizeSubjects(value: any): any[] | undefined;
45
+ /**
46
+ * Normalizes the entire metadata object per RWPM spec.
47
+ *
48
+ * This function is library-agnostic and based on the stable RWPM specification,
49
+ * ensuring it works regardless of how the underlying Readium library serializes data.
50
+ *
51
+ * https://readium.org/webpub-manifest/
52
+ */
53
+ export declare function normalizeMetadata(metadata: any): any;
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Normalizes metadata to ensure consistent structure per RWPM spec.
3
+ *
4
+ * This normalizer is library-agnostic and based on the stable RWPM specification,
5
+ * ensuring it works regardless of how the underlying Readium library serializes data.
6
+ *
7
+ * https://readium.org/webpub-manifest/
8
+ */
9
+ /**
10
+ * Normalizes a localized string per RWPM spec.
11
+ *
12
+ * Per RWPM spec, a localized string can be:
13
+ * 1. Plain string: "Moby-Dick"
14
+ * 2. Language map: {"en": "Moby-Dick", "fr": "Moby Dick"}
15
+ *
16
+ * Priority for language selection:
17
+ * 1. "undefined" or "und" (default/undetermined language)
18
+ * 2. "en" (English fallback)
19
+ * 3. First available language
20
+ *
21
+ * https://readium.org/webpub-manifest/contexts/default/
22
+ */
23
+ export function normalizeLocalizedString(value) {
24
+ if (!value)
25
+ return '';
26
+ // Format 1: Plain string (spec-compliant shorthand)
27
+ if (typeof value === 'string')
28
+ return value;
29
+ // Format 2: Language map (spec-compliant full form)
30
+ if (typeof value === 'object') {
31
+ // Check if it's a LocalizedString instance with translations property
32
+ if (value.translations) {
33
+ const translations = value.translations;
34
+ return (translations['undefined'] ||
35
+ translations['und'] ||
36
+ translations['en'] ||
37
+ Object.values(translations)[0] ||
38
+ '');
39
+ }
40
+ // Check if it's already a plain language map object
41
+ return (value['undefined'] ||
42
+ value['und'] ||
43
+ value['en'] ||
44
+ Object.values(value)[0] ||
45
+ '');
46
+ }
47
+ return '';
48
+ }
49
+ /**
50
+ * Normalizes contributors per RWPM spec.
51
+ *
52
+ * Per RWPM spec, a contributor can be:
53
+ * 1. Plain string: "Herman Melville"
54
+ * 2. Object: {"name": "Herman Melville", "sortAs": "Melville, Herman"}
55
+ *
56
+ * The Web library uses a Contributors class with an "items" property.
57
+ *
58
+ * https://readium.org/webpub-manifest/schema/contributor-object.schema.json
59
+ */
60
+ export function normalizeContributors(value) {
61
+ if (!value)
62
+ return undefined;
63
+ // Handle TypeScript library's Contributors class format (has .items property)
64
+ const items = value.items || value;
65
+ if (!Array.isArray(items))
66
+ return undefined;
67
+ return items
68
+ .map((contributor) => {
69
+ // Format 1: Plain string
70
+ if (typeof contributor === 'string') {
71
+ return { name: contributor };
72
+ }
73
+ // Format 2: Object with potentially localized fields
74
+ const normalized = {
75
+ name: normalizeLocalizedString(contributor.name),
76
+ };
77
+ if (contributor.sortAs) {
78
+ normalized.sortAs = normalizeLocalizedString(contributor.sortAs);
79
+ }
80
+ if (contributor.identifier) {
81
+ normalized.identifier = contributor.identifier;
82
+ }
83
+ if (contributor.role) {
84
+ normalized.role = contributor.role;
85
+ }
86
+ if (contributor.position !== undefined) {
87
+ normalized.position = contributor.position;
88
+ }
89
+ return normalized;
90
+ })
91
+ .filter((c) => c.name); // Remove contributors without names
92
+ }
93
+ /**
94
+ * Normalizes subjects per RWPM spec.
95
+ *
96
+ * Subject names can be LocalizedStrings.
97
+ * The Web library uses a Subjects class with an "items" property.
98
+ *
99
+ * https://readium.org/webpub-manifest/schema/subject.schema.json
100
+ */
101
+ export function normalizeSubjects(value) {
102
+ if (!value)
103
+ return undefined;
104
+ // Handle Subjects class format (has .items property)
105
+ const items = value.items || value;
106
+ if (!Array.isArray(items))
107
+ return undefined;
108
+ return items
109
+ .map((subject) => {
110
+ // Format 1: Plain string
111
+ if (typeof subject === 'string') {
112
+ return { name: subject };
113
+ }
114
+ // Format 2: Object
115
+ const normalized = {
116
+ name: normalizeLocalizedString(subject.name),
117
+ };
118
+ if (subject.sortAs) {
119
+ normalized.sortAs = normalizeLocalizedString(subject.sortAs);
120
+ }
121
+ if (subject.code) {
122
+ normalized.code = subject.code;
123
+ }
124
+ if (subject.scheme) {
125
+ normalized.scheme = subject.scheme;
126
+ }
127
+ return normalized;
128
+ })
129
+ .filter((s) => s.name);
130
+ }
131
+ /**
132
+ * Normalizes the entire metadata object per RWPM spec.
133
+ *
134
+ * This function is library-agnostic and based on the stable RWPM specification,
135
+ * ensuring it works regardless of how the underlying Readium library serializes data.
136
+ *
137
+ * https://readium.org/webpub-manifest/
138
+ */
139
+ export function normalizeMetadata(metadata) {
140
+ const normalized = {
141
+ // Title is required
142
+ title: normalizeLocalizedString(metadata.title),
143
+ };
144
+ // Optional localized string fields
145
+ if (metadata.subtitle) {
146
+ normalized.subtitle = normalizeLocalizedString(metadata.subtitle);
147
+ }
148
+ if (metadata.sortAs) {
149
+ normalized.sortAs = normalizeLocalizedString(metadata.sortAs);
150
+ }
151
+ // Direct copy fields
152
+ if (metadata.identifier)
153
+ normalized.identifier = metadata.identifier;
154
+ if (metadata.conformsTo)
155
+ normalized.conformsTo = metadata.conformsTo;
156
+ if (metadata.description)
157
+ normalized.description = metadata.description;
158
+ if (metadata.readingProgression)
159
+ normalized.readingProgression = metadata.readingProgression;
160
+ if (metadata.layout)
161
+ normalized.layout = metadata.layout;
162
+ if (metadata.duration)
163
+ normalized.duration = metadata.duration;
164
+ if (metadata.numberOfPages)
165
+ normalized.numberOfPages = metadata.numberOfPages;
166
+ // Date fields - convert to ISO strings
167
+ if (metadata.modified) {
168
+ normalized.modified =
169
+ metadata.modified instanceof Date
170
+ ? metadata.modified.toISOString()
171
+ : metadata.modified;
172
+ }
173
+ if (metadata.published) {
174
+ normalized.published =
175
+ metadata.published instanceof Date
176
+ ? metadata.published.toISOString()
177
+ : metadata.published;
178
+ }
179
+ // Languages (Web uses plural 'languages', our interface uses singular 'language')
180
+ if (metadata.languages) {
181
+ normalized.language = metadata.languages;
182
+ }
183
+ // Normalize all contributor types (Web uses plural names, our interface uses singular)
184
+ if (metadata.authors)
185
+ normalized.author = normalizeContributors(metadata.authors);
186
+ if (metadata.translators)
187
+ normalized.translator = normalizeContributors(metadata.translators);
188
+ if (metadata.editors)
189
+ normalized.editor = normalizeContributors(metadata.editors);
190
+ if (metadata.artists)
191
+ normalized.artist = normalizeContributors(metadata.artists);
192
+ if (metadata.illustrators)
193
+ normalized.illustrator = normalizeContributors(metadata.illustrators);
194
+ if (metadata.letterers)
195
+ normalized.letterer = normalizeContributors(metadata.letterers);
196
+ if (metadata.pencilers)
197
+ normalized.penciler = normalizeContributors(metadata.pencilers);
198
+ if (metadata.colorists)
199
+ normalized.colorist = normalizeContributors(metadata.colorists);
200
+ if (metadata.inkers)
201
+ normalized.inker = normalizeContributors(metadata.inkers);
202
+ if (metadata.narrators)
203
+ normalized.narrator = normalizeContributors(metadata.narrators);
204
+ if (metadata.contributors)
205
+ normalized.contributor = normalizeContributors(metadata.contributors);
206
+ if (metadata.publishers)
207
+ normalized.publisher = normalizeContributors(metadata.publishers);
208
+ if (metadata.imprints)
209
+ normalized.imprint = normalizeContributors(metadata.imprints);
210
+ // Normalize subjects
211
+ if (metadata.subjects) {
212
+ normalized.subject = normalizeSubjects(metadata.subjects);
213
+ }
214
+ // Copy complex objects as-is
215
+ if (metadata.belongsTo)
216
+ normalized.belongsTo = metadata.belongsTo;
217
+ if (metadata.accessibility)
218
+ normalized.accessibility = metadata.accessibility;
219
+ return normalized;
220
+ }
@@ -0,0 +1,6 @@
1
+ import { EpubNavigatorListeners } from '@readium/navigator';
2
+ import { Locator } from '@readium/shared';
3
+ /**
4
+ * Creates navigator listeners for handling navigation events
5
+ */
6
+ export declare function createNavigatorListeners(onLocationChangeWithTotalProgression: (locator: Locator) => void, onPositionChange?: (position: number | null) => void): EpubNavigatorListeners;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Creates navigator listeners for handling navigation events
3
+ */
4
+ export function createNavigatorListeners(onLocationChangeWithTotalProgression, onPositionChange) {
5
+ return {
6
+ frameLoaded: function (_wnd) {
7
+ // noop
8
+ },
9
+ positionChanged: function (_locator) {
10
+ onLocationChangeWithTotalProgression(_locator);
11
+ if (onPositionChange) {
12
+ onPositionChange(_locator.locations?.position || null);
13
+ }
14
+ window.focus();
15
+ },
16
+ tap: function (_e) {
17
+ return false;
18
+ },
19
+ click: function (_e) {
20
+ return false;
21
+ },
22
+ zoom: function (_scale) {
23
+ // noop
24
+ },
25
+ miscPointer: function (_amount) {
26
+ // noop
27
+ },
28
+ scroll: function (_amount) {
29
+ // noop
30
+ },
31
+ customEvent: function (_key, _data) { },
32
+ handleLocator: function (locator) {
33
+ const href = locator.href;
34
+ if (href.startsWith('http://') ||
35
+ href.startsWith('https://') ||
36
+ href.startsWith('mailto:') ||
37
+ href.startsWith('tel:')) {
38
+ if (confirm(`Open "${href}" ?`))
39
+ window.open(href, '_blank');
40
+ }
41
+ else {
42
+ console.warn('Unhandled locator', locator);
43
+ }
44
+ return false;
45
+ },
46
+ textSelected: function (_selection) {
47
+ // noop
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,15 @@
1
+ import { Locator, Manifest, Publication } from '@readium/shared';
2
+ /**
3
+ * Normalizes a publication URL to ensure it ends with /
4
+ * If URL ends with manifest.json, extracts the base directory
5
+ */
6
+ export declare function normalizePublicationURL(url: string): string;
7
+ /**
8
+ * Creates positions array from publication reading order
9
+ * NOTE: The published npm packages (v2.2.5) require positions to be passed explicitly
10
+ */
11
+ export declare function createPositions(publication: Publication): Locator[];
12
+ /**
13
+ * Extracts table of contents items from manifest
14
+ */
15
+ export declare function extractTableOfContents(manifest: Manifest): any[];
@@ -0,0 +1,39 @@
1
+ import { Locator, LocatorLocations, } from '@readium/shared';
2
+ /**
3
+ * Normalizes a publication URL to ensure it ends with /
4
+ * If URL ends with manifest.json, extracts the base directory
5
+ */
6
+ export function normalizePublicationURL(url) {
7
+ if (url.endsWith('manifest.json')) {
8
+ return url.substring(0, url.lastIndexOf('/') + 1);
9
+ }
10
+ return url.endsWith('/') ? url : `${url}/`;
11
+ }
12
+ /**
13
+ * Creates positions array from publication reading order
14
+ * NOTE: The published npm packages (v2.2.5) require positions to be passed explicitly
15
+ */
16
+ export function createPositions(publication) {
17
+ return publication.readingOrder.items.map((link, idx) => {
18
+ const position = idx + 1;
19
+ return new Locator({
20
+ href: link.href,
21
+ type: link.type,
22
+ title: link.title,
23
+ locations: new LocatorLocations({
24
+ position: position,
25
+ progression: 0,
26
+ totalProgression: idx / publication.readingOrder.items.length,
27
+ }),
28
+ });
29
+ });
30
+ }
31
+ /**
32
+ * Extracts table of contents items from manifest
33
+ */
34
+ export function extractTableOfContents(manifest) {
35
+ return Array.isArray(manifest.toc)
36
+ ? manifest.toc
37
+ : // @ts-ignore
38
+ manifest.toc.items || [];
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-readium",
3
- "version": "4.0.1",
3
+ "version": "5.0.0-rc.0",
4
4
  "description": "A react-native wrapper for https://readium.org/",
5
5
  "main": "lib/src/index",
6
6
  "types": "lib/src/index.d.ts",
@@ -21,6 +21,9 @@
21
21
  "!**/__fixtures__",
22
22
  "!**/__mocks__"
23
23
  ],
24
+ "workspaces": [
25
+ "apps/*"
26
+ ],
24
27
  "scripts": {
25
28
  "test": "jest",
26
29
  "typescript": "tsc --noEmit",
@@ -28,8 +31,9 @@
28
31
  "lint:fix": "eslint ./src --fix",
29
32
  "prepare": "rimraf lib && tsc",
30
33
  "release": "release-it",
31
- "example": "yarn --cwd example",
32
- "pods": "cd example && pod-install --quiet",
34
+ "example": "yarn workspace example-native",
35
+ "example:nextjs": "yarn workspace example-nextjs",
36
+ "pods": "cd apps/example-native && pod-install --quiet",
33
37
  "bootstrap": "yarn example && yarn && yarn pods",
34
38
  "version": "yarn changelog && git add CHANGELOG.md",
35
39
  "postversion": "npm run publish:git && npm run publish:npm",
@@ -61,27 +65,27 @@
61
65
  "devDependencies": {
62
66
  "@commitlint/config-conventional": "^17.0.2",
63
67
  "@evilmartians/lefthook": "^1.5.0",
64
- "@react-native/eslint-config": "^0.73.1",
68
+ "@react-native/eslint-config": "0.83.0",
65
69
  "@release-it/conventional-changelog": "^5.0.0",
66
- "@types/jest": "^29.5.5",
67
- "@types/react": "^18.2.44",
70
+ "@types/jest": "^29.5.13",
71
+ "@types/react": "^19.2.0",
68
72
  "commitlint": "^17.0.2",
69
73
  "conventional-changelog-cli": "^2.2.2",
70
74
  "del-cli": "^5.1.0",
71
- "eslint": "^8.51.0",
75
+ "eslint": "^8.19.0",
72
76
  "eslint-config-prettier": "^9.0.0",
73
77
  "eslint-plugin-prettier": "^5.0.1",
74
78
  "husky": "^6.0.0",
75
- "jest": "^29.7.0",
79
+ "jest": "^29.6.3",
76
80
  "pod-install": "^0.1.0",
77
- "prettier": "^3.0.3",
78
- "react": "18.2.0",
79
- "react-native": "0.74.1",
81
+ "prettier": "2.8.8",
82
+ "react": "19.0.0",
83
+ "react-native": "0.83.1",
80
84
  "react-native-builder-bob": "^0.23.2",
81
85
  "release-it": "^15.0.0",
82
86
  "rimraf": "^5.0.7",
83
87
  "turbo": "^1.10.7",
84
- "typescript": "^5.2.2"
88
+ "typescript": "^5.8.3"
85
89
  },
86
90
  "peerDependencies": {
87
91
  "react": "*",
@@ -122,6 +126,9 @@
122
126
  "@react-native",
123
127
  "prettier"
124
128
  ],
129
+ "plugins": [
130
+ "prettier"
131
+ ],
125
132
  "rules": {
126
133
  "prettier/prettier": [
127
134
  "error",
@@ -147,11 +154,14 @@
147
154
  "useTabs": false
148
155
  },
149
156
  "dependencies": {
150
- "@d-i-t-a/reader": "^2.1.4",
157
+ "@readium/css": "^2.0.0-beta.24",
158
+ "@readium/navigator": "^2.2.5",
159
+ "@readium/navigator-html-injectables": "^2.2.2",
160
+ "@readium/shared": "^2.1.2",
151
161
  "use-deep-compare": "^1.1.0"
152
162
  },
153
163
  "engines": {
154
- "node": ">=18"
164
+ "node": ">=20"
155
165
  },
156
166
  "packageManager": "yarn@3.6.4",
157
167
  "stableVersion": "1.2.1"
@@ -18,10 +18,12 @@ Pod::Spec.new do |s|
18
18
 
19
19
  s.swift_version = "5.0"
20
20
 
21
+ s.dependency 'ReadiumShared', '~> 3.5.0'
22
+ s.dependency 'ReadiumStreamer', '~> 3.5.0'
23
+ s.dependency 'ReadiumNavigator','~> 3.5.0'
24
+ s.dependency 'ReadiumAdapterGCDWebServer', '~> 3.5.0'
25
+ s.dependency 'ReadiumInternal'
26
+
21
27
  s.dependency "React-Core"
22
- s.dependency "R2Shared"
23
- s.dependency "R2Streamer"
24
- s.dependency "R2Navigator"
25
- s.dependency "GCDWebServer"
26
- s.dependency "ReadiumAdapterGCDWebServer"
28
+
27
29
  end
@@ -0,0 +1,35 @@
1
+ import type { HostComponent, ViewProps } from 'react-native';
2
+ import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
3
+ // eslint-disable-next-line @react-native/no-deep-imports
4
+ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
5
+ // eslint-disable-next-line @react-native/no-deep-imports
6
+ import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
7
+ import type { File } from './interfaces/File';
8
+ import type { Locator } from './interfaces/Locator';
9
+ import type { PublicationReadyEvent } from './interfaces/PublicationReady';
10
+
11
+ // Event types for native events
12
+ type OnLocationChangeEvent = Readonly<Locator>;
13
+ type OnPublicationReadyEvent = Readonly<PublicationReadyEvent>;
14
+
15
+ // Native component props interface
16
+ export interface NativeProps extends ViewProps {
17
+ file: File;
18
+ preferences?: string;
19
+ onLocationChange?: DirectEventHandler<OnLocationChangeEvent>;
20
+ onPublicationReady?: DirectEventHandler<OnPublicationReadyEvent>;
21
+ }
22
+
23
+ // Native commands interface
24
+ export interface NativeCommands {
25
+ create: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
26
+ }
27
+
28
+ // Generate the native component
29
+ export const ReadiumViewNativeComponent =
30
+ codegenNativeComponent<NativeProps>('ReadiumView');
31
+
32
+ // Generate the commands
33
+ export const Commands = codegenNativeCommands<NativeCommands>({
34
+ supportedCommands: ['create'],
35
+ });
@@ -1,11 +1,4 @@
1
- import { requireNativeComponent, UIManager } from 'react-native';
1
+ import { ReadiumViewNativeComponent } from '../ReadiumViewNativeComponent';
2
2
 
3
- import type { BaseReadiumViewProps } from '../interfaces';
4
- import { COMPONENT_NAME, LINKING_ERROR } from '../utils';
5
-
6
- export const BaseReadiumView =
7
- UIManager.getViewManagerConfig(COMPONENT_NAME) != null
8
- ? requireNativeComponent<BaseReadiumViewProps>(COMPONENT_NAME)
9
- : () => {
10
- throw new Error(LINKING_ERROR);
11
- };
3
+ // Re-export the native component for backwards compatibility
4
+ export const BaseReadiumView = ReadiumViewNativeComponent;