@youversion/platform-react-hooks 1.21.0 → 1.22.1

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 (97) hide show
  1. package/.turbo/turbo-build.log +21 -1
  2. package/CHANGELOG.md +21 -0
  3. package/dist/YouVersionAuthProvider-VORD6KDZ.js +80 -0
  4. package/dist/chunk-ITHJF2FD.js +17 -0
  5. package/dist/index.cjs +946 -0
  6. package/dist/index.js +788 -26
  7. package/package.json +11 -6
  8. package/tsconfig.build.json +4 -1
  9. package/dist/__tests__/mocks/auth.js +0 -43
  10. package/dist/__tests__/mocks/auth.js.map +0 -1
  11. package/dist/__tests__/mocks/bibles.js +0 -23
  12. package/dist/__tests__/mocks/bibles.js.map +0 -1
  13. package/dist/__tests__/mocks/core-mock-factory.js +0 -138
  14. package/dist/__tests__/mocks/core-mock-factory.js.map +0 -1
  15. package/dist/__tests__/utils/test-utils.js +0 -11
  16. package/dist/__tests__/utils/test-utils.js.map +0 -1
  17. package/dist/context/ReaderContext.js +0 -17
  18. package/dist/context/ReaderContext.js.map +0 -1
  19. package/dist/context/ReaderProvider.js +0 -24
  20. package/dist/context/ReaderProvider.js.map +0 -1
  21. package/dist/context/VerseSelectionContext.js +0 -6
  22. package/dist/context/VerseSelectionContext.js.map +0 -1
  23. package/dist/context/VerseSelectionProvider.js +0 -36
  24. package/dist/context/VerseSelectionProvider.js.map +0 -1
  25. package/dist/context/YouVersionAuthContext.js +0 -13
  26. package/dist/context/YouVersionAuthContext.js.map +0 -1
  27. package/dist/context/YouVersionAuthProvider.js +0 -81
  28. package/dist/context/YouVersionAuthProvider.js.map +0 -1
  29. package/dist/context/YouVersionContext.js +0 -4
  30. package/dist/context/YouVersionContext.js.map +0 -1
  31. package/dist/context/YouVersionProvider.js +0 -63
  32. package/dist/context/YouVersionProvider.js.map +0 -1
  33. package/dist/context/index.js +0 -7
  34. package/dist/context/index.js.map +0 -1
  35. package/dist/index.js.map +0 -1
  36. package/dist/test/setup.js +0 -9
  37. package/dist/test/setup.js.map +0 -1
  38. package/dist/test/utils.js +0 -7
  39. package/dist/test/utils.js.map +0 -1
  40. package/dist/types/auth.js +0 -2
  41. package/dist/types/auth.js.map +0 -1
  42. package/dist/useApiData.js +0 -46
  43. package/dist/useApiData.js.map +0 -1
  44. package/dist/useBibleClient.js +0 -18
  45. package/dist/useBibleClient.js.map +0 -1
  46. package/dist/useBook.js +0 -11
  47. package/dist/useBook.js.map +0 -1
  48. package/dist/useBooks.js +0 -11
  49. package/dist/useBooks.js.map +0 -1
  50. package/dist/useChapter.js +0 -11
  51. package/dist/useChapter.js.map +0 -1
  52. package/dist/useChapterNavigation.js +0 -57
  53. package/dist/useChapterNavigation.js.map +0 -1
  54. package/dist/useChapters.js +0 -13
  55. package/dist/useChapters.js.map +0 -1
  56. package/dist/useFilteredVersions.js +0 -29
  57. package/dist/useFilteredVersions.js.map +0 -1
  58. package/dist/useHighlights.js +0 -41
  59. package/dist/useHighlights.js.map +0 -1
  60. package/dist/useInitData.js +0 -29
  61. package/dist/useInitData.js.map +0 -1
  62. package/dist/useLanguage.js +0 -17
  63. package/dist/useLanguage.js.map +0 -1
  64. package/dist/useLanguageClient.js +0 -18
  65. package/dist/useLanguageClient.js.map +0 -1
  66. package/dist/useLanguages.js +0 -23
  67. package/dist/useLanguages.js.map +0 -1
  68. package/dist/usePassage.js +0 -11
  69. package/dist/usePassage.js.map +0 -1
  70. package/dist/useTheme.js +0 -21
  71. package/dist/useTheme.js.map +0 -1
  72. package/dist/useVOTD.js +0 -9
  73. package/dist/useVOTD.js.map +0 -1
  74. package/dist/useVerse.js +0 -11
  75. package/dist/useVerse.js.map +0 -1
  76. package/dist/useVerseSelection.js +0 -13
  77. package/dist/useVerseSelection.js.map +0 -1
  78. package/dist/useVerses.js +0 -11
  79. package/dist/useVerses.js.map +0 -1
  80. package/dist/useVersion.js +0 -11
  81. package/dist/useVersion.js.map +0 -1
  82. package/dist/useVersions.js +0 -35
  83. package/dist/useVersions.js.map +0 -1
  84. package/dist/useYVAuth.js +0 -144
  85. package/dist/useYVAuth.js.map +0 -1
  86. package/dist/utility/extractTextFromHTML.js +0 -21
  87. package/dist/utility/extractTextFromHTML.js.map +0 -1
  88. package/dist/utility/extractVersesFromHTML.js +0 -26
  89. package/dist/utility/extractVersesFromHTML.js.map +0 -1
  90. package/dist/utility/getDayOfYear.js +0 -5
  91. package/dist/utility/getDayOfYear.js.map +0 -1
  92. package/dist/utility/index.js +0 -6
  93. package/dist/utility/index.js.map +0 -1
  94. package/dist/utility/useDebounce.js +0 -24
  95. package/dist/utility/useDebounce.js.map +0 -1
  96. package/dist/utility/version.js +0 -4
  97. package/dist/utility/version.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,26 +1,788 @@
1
- export * from './useBook';
2
- export * from './useBooks';
3
- export * from './useChapter';
4
- export * from './useChapters';
5
- export * from './useVerse';
6
- export * from './useVerses';
7
- export * from './useVersion';
8
- export * from './utility/useDebounce';
9
- export * from './useVersions';
10
- export * from './useFilteredVersions';
11
- export * from './context';
12
- export * from './utility';
13
- export * from './useBibleClient';
14
- export * from './useVerseSelection';
15
- export * from './useChapterNavigation';
16
- export * from './useInitData';
17
- export * from './usePassage';
18
- export * from './useVOTD';
19
- export * from './useHighlights';
20
- export * from './useLanguages';
21
- export * from './useLanguage';
22
- export * from './useTheme';
23
- // Auth hooks
24
- export * from './useYVAuth';
25
- export * from './types/auth';
26
- //# sourceMappingURL=index.js.map
1
+ import {
2
+ useYouVersionAuthContext
3
+ } from "./chunk-ITHJF2FD.js";
4
+
5
+ // src/useBibleClient.ts
6
+ import { useContext as useContext2, useMemo } from "react";
7
+
8
+ // src/context/YouVersionContext.tsx
9
+ import { createContext } from "react";
10
+ var YouVersionContext = createContext(null);
11
+
12
+ // src/context/YouVersionProvider.tsx
13
+ import { lazy, Suspense, useEffect, useState } from "react";
14
+ import { YouVersionPlatformConfiguration } from "@youversion/platform-core";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var AuthProvider = lazy(() => import("./YouVersionAuthProvider-VORD6KDZ.js"));
17
+ function useResolvedTheme(theme) {
18
+ const [resolved, setResolved] = useState(() => {
19
+ if (theme !== "system") return theme;
20
+ if (typeof window === "undefined") return "light";
21
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
22
+ });
23
+ useEffect(() => {
24
+ if (theme !== "system") {
25
+ setResolved(theme);
26
+ return;
27
+ }
28
+ if (typeof window === "undefined") return;
29
+ const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
30
+ setResolved(mediaQueryList.matches ? "dark" : "light");
31
+ const handler = (e) => {
32
+ setResolved(e.matches ? "dark" : "light");
33
+ };
34
+ mediaQueryList.addEventListener("change", handler);
35
+ return () => mediaQueryList.removeEventListener("change", handler);
36
+ }, [theme]);
37
+ return resolved;
38
+ }
39
+ function YouVersionProvider(props) {
40
+ const { appKey, apiHost = "api.youversion.com", includeAuth, theme = "light", children } = props;
41
+ const resolvedTheme = useResolvedTheme(theme);
42
+ useEffect(() => {
43
+ YouVersionPlatformConfiguration.appKey = appKey;
44
+ YouVersionPlatformConfiguration.apiHost = apiHost;
45
+ }, [appKey, apiHost]);
46
+ if (includeAuth) {
47
+ const { authRedirectUrl } = props;
48
+ return /* @__PURE__ */ jsx(
49
+ YouVersionContext.Provider,
50
+ {
51
+ value: {
52
+ appKey,
53
+ apiHost,
54
+ installationId: YouVersionPlatformConfiguration.installationId,
55
+ theme: resolvedTheme,
56
+ authEnabled: !!includeAuth
57
+ },
58
+ children: /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(AuthProvider, { config: { appKey, apiHost, redirectUri: authRedirectUrl }, children }) })
59
+ }
60
+ );
61
+ }
62
+ return /* @__PURE__ */ jsx(
63
+ YouVersionContext.Provider,
64
+ {
65
+ value: {
66
+ appKey,
67
+ apiHost,
68
+ installationId: YouVersionPlatformConfiguration.installationId,
69
+ theme: resolvedTheme,
70
+ authEnabled: !!includeAuth
71
+ },
72
+ children
73
+ }
74
+ );
75
+ }
76
+
77
+ // src/context/ReaderContext.tsx
78
+ import { createContext as createContext2, useContext } from "react";
79
+ var ReaderContext = createContext2(null);
80
+ function useReaderContext() {
81
+ const context = useContext(ReaderContext);
82
+ if (!context) {
83
+ throw new Error("useReaderContext() must be used within a ReaderProvider");
84
+ }
85
+ return context;
86
+ }
87
+
88
+ // src/context/ReaderProvider.tsx
89
+ import { useState as useState2 } from "react";
90
+ import { jsx as jsx2 } from "react/jsx-runtime";
91
+ function ReaderProvider(props) {
92
+ const [currentVersion, setCurrentVersion] = useState2(props.currentVersion);
93
+ const [currentBook, setCurrentBook] = useState2(props.currentBook);
94
+ const [currentChapter, setCurrentChapter] = useState2(props.currentChapter);
95
+ const [currentVerse, setCurrentVerse] = useState2(props.currentVerse);
96
+ return /* @__PURE__ */ jsx2(
97
+ ReaderContext.Provider,
98
+ {
99
+ value: {
100
+ currentVersion,
101
+ currentBook,
102
+ currentChapter,
103
+ currentVerse,
104
+ setVersion: setCurrentVersion,
105
+ setChapter: setCurrentChapter,
106
+ setBook: setCurrentBook,
107
+ setVerse: setCurrentVerse
108
+ },
109
+ children: props.children
110
+ }
111
+ );
112
+ }
113
+
114
+ // src/context/VerseSelectionProvider.tsx
115
+ import { useCallback, useState as useState3 } from "react";
116
+
117
+ // src/context/VerseSelectionContext.tsx
118
+ import { createContext as createContext3 } from "react";
119
+ var VerseSelectionContext = createContext3(null);
120
+
121
+ // src/context/VerseSelectionProvider.tsx
122
+ import { jsx as jsx3 } from "react/jsx-runtime";
123
+ function VerseSelectionProvider({ children }) {
124
+ const [selectedVerseUsfms, setSelectedVerseUsfms] = useState3(/* @__PURE__ */ new Set());
125
+ const toggleVerse = useCallback((usfm) => {
126
+ setSelectedVerseUsfms((prev) => {
127
+ const newSet = new Set(prev);
128
+ if (newSet.has(usfm)) {
129
+ newSet.delete(usfm);
130
+ } else {
131
+ newSet.add(usfm);
132
+ }
133
+ return newSet;
134
+ });
135
+ }, []);
136
+ const isSelected = useCallback(
137
+ (usfm) => {
138
+ return selectedVerseUsfms.has(usfm);
139
+ },
140
+ [selectedVerseUsfms]
141
+ );
142
+ const clearSelection = useCallback(() => {
143
+ setSelectedVerseUsfms(/* @__PURE__ */ new Set());
144
+ }, []);
145
+ const value = {
146
+ selectedVerseUsfms,
147
+ toggleVerse,
148
+ isSelected,
149
+ clearSelection,
150
+ selectedCount: selectedVerseUsfms.size
151
+ };
152
+ return /* @__PURE__ */ jsx3(VerseSelectionContext.Provider, { value, children });
153
+ }
154
+
155
+ // src/useBibleClient.ts
156
+ import { BibleClient, ApiClient } from "@youversion/platform-core";
157
+ function useBibleClient() {
158
+ const context = useContext2(YouVersionContext);
159
+ return useMemo(() => {
160
+ if (!context?.appKey) {
161
+ throw new Error(
162
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
163
+ );
164
+ }
165
+ return new BibleClient(
166
+ new ApiClient({
167
+ appKey: context.appKey,
168
+ apiHost: context.apiHost,
169
+ installationId: context.installationId
170
+ })
171
+ );
172
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
173
+ }
174
+
175
+ // src/useApiData.ts
176
+ import { useState as useState4, useEffect as useEffect2, useCallback as useCallback2 } from "react";
177
+ function useApiData(fetchFn, deps, options = {}) {
178
+ const { enabled = true } = options;
179
+ const [data, setData] = useState4(null);
180
+ const [loading, setLoading] = useState4(true);
181
+ const [error, setError] = useState4(null);
182
+ const fetchData = useCallback2(() => {
183
+ if (!enabled) {
184
+ setLoading(false);
185
+ return;
186
+ }
187
+ let canceled = false;
188
+ setLoading(true);
189
+ setError(null);
190
+ fetchFn().then((result) => {
191
+ if (!canceled) {
192
+ setData(result);
193
+ }
194
+ }).catch((err) => {
195
+ if (!canceled) {
196
+ setError(err);
197
+ }
198
+ }).finally(() => {
199
+ if (!canceled) {
200
+ setLoading(false);
201
+ }
202
+ });
203
+ return () => {
204
+ canceled = true;
205
+ };
206
+ }, [fetchFn, enabled]);
207
+ const refetch = useCallback2(() => {
208
+ fetchData();
209
+ }, [fetchData]);
210
+ useEffect2(() => {
211
+ const cleanup = fetchData();
212
+ return cleanup;
213
+ }, deps);
214
+ return { data, loading, error, refetch };
215
+ }
216
+
217
+ // src/useBook.ts
218
+ function useBook(versionId, book, options) {
219
+ const bibleClient = useBibleClient();
220
+ const { data, loading, error, refetch } = useApiData(
221
+ () => bibleClient.getBook(versionId, book),
222
+ [bibleClient, versionId, book],
223
+ {
224
+ enabled: options?.enabled !== false
225
+ }
226
+ );
227
+ return { book: data, loading, error, refetch };
228
+ }
229
+
230
+ // src/useBooks.ts
231
+ function useBooks(versionId, options) {
232
+ const bibleClient = useBibleClient();
233
+ const {
234
+ data: books,
235
+ loading,
236
+ error,
237
+ refetch
238
+ } = useApiData(
239
+ () => bibleClient.getBooks(versionId),
240
+ [bibleClient, versionId],
241
+ {
242
+ enabled: options?.enabled !== false
243
+ }
244
+ );
245
+ return { books, loading, error, refetch };
246
+ }
247
+
248
+ // src/useChapter.ts
249
+ function useChapter(versionId, book, chapter, options) {
250
+ const bibleClient = useBibleClient();
251
+ const {
252
+ data: chapterData,
253
+ loading,
254
+ error,
255
+ refetch
256
+ } = useApiData(
257
+ () => bibleClient.getChapter(versionId, book, chapter),
258
+ [bibleClient, versionId, book, chapter],
259
+ {
260
+ enabled: options?.enabled !== false
261
+ }
262
+ );
263
+ return { chapter: chapterData, loading, error, refetch };
264
+ }
265
+
266
+ // src/useChapters.ts
267
+ function useChapters(versionId, book, options) {
268
+ const bibleClient = useBibleClient();
269
+ const isValidBook = Boolean(book) && book !== "undefined" && book !== "null";
270
+ const {
271
+ data: chapters,
272
+ loading,
273
+ error,
274
+ refetch
275
+ } = useApiData(
276
+ () => bibleClient.getChapters(versionId, book),
277
+ [bibleClient, versionId, book],
278
+ {
279
+ enabled: options?.enabled !== false && isValidBook
280
+ }
281
+ );
282
+ return { chapters, loading, error, refetch };
283
+ }
284
+
285
+ // src/useVerse.ts
286
+ function useVerse(versionId, book, chapter, verse, options) {
287
+ const bibleClient = useBibleClient();
288
+ const {
289
+ data: verseData,
290
+ loading,
291
+ error,
292
+ refetch
293
+ } = useApiData(
294
+ () => bibleClient.getVerse(versionId, book, chapter, verse),
295
+ [bibleClient, versionId, book, chapter, verse],
296
+ {
297
+ enabled: options?.enabled !== false
298
+ }
299
+ );
300
+ return { verse: verseData, loading, error, refetch };
301
+ }
302
+
303
+ // src/useVerses.ts
304
+ function useVerses(versionId, book, chapter, options) {
305
+ const bibleClient = useBibleClient();
306
+ const {
307
+ data: verses,
308
+ loading,
309
+ error,
310
+ refetch
311
+ } = useApiData(
312
+ () => bibleClient.getVerses(versionId, book, chapter),
313
+ [bibleClient, versionId, book, chapter],
314
+ {
315
+ enabled: options?.enabled !== false
316
+ }
317
+ );
318
+ return { verses, loading, error, refetch };
319
+ }
320
+
321
+ // src/useVersion.ts
322
+ function useVersion(versionId, options) {
323
+ const bibleClient = useBibleClient();
324
+ const {
325
+ data: version,
326
+ loading,
327
+ error,
328
+ refetch
329
+ } = useApiData(() => bibleClient.getVersion(versionId), [bibleClient, versionId], {
330
+ enabled: options?.enabled !== false
331
+ });
332
+ return { version, loading, error, refetch };
333
+ }
334
+
335
+ // src/utility/useDebounce.ts
336
+ import { useEffect as useEffect3, useState as useState5 } from "react";
337
+ function useDebounce(value, delay) {
338
+ const [debouncedValue, setDebouncedValue] = useState5(value);
339
+ useEffect3(() => {
340
+ const handler = setTimeout(() => {
341
+ setDebouncedValue(value);
342
+ }, delay);
343
+ return () => clearTimeout(handler);
344
+ }, [value, delay]);
345
+ return debouncedValue;
346
+ }
347
+
348
+ // src/useVersions.ts
349
+ function useVersions(languageRanges = "en", licenseId, options) {
350
+ const bibleClient = useBibleClient();
351
+ const getVersionsOptions = options?.page_size !== void 0 || options?.page_token !== void 0 || options?.fields !== void 0 || options?.all_available !== void 0 ? {
352
+ page_size: options?.page_size,
353
+ page_token: options?.page_token,
354
+ fields: options?.fields,
355
+ all_available: options?.all_available
356
+ } : void 0;
357
+ const languageRangesKey = Array.isArray(languageRanges) ? languageRanges.join(",") : languageRanges;
358
+ const fieldsKey = options?.fields?.join(",");
359
+ const {
360
+ data: versions,
361
+ loading,
362
+ error,
363
+ refetch
364
+ } = useApiData(
365
+ () => bibleClient.getVersions(languageRanges, licenseId, getVersionsOptions),
366
+ [
367
+ bibleClient,
368
+ languageRangesKey,
369
+ licenseId,
370
+ options?.page_size,
371
+ options?.page_token,
372
+ fieldsKey,
373
+ options?.all_available
374
+ ],
375
+ {
376
+ enabled: options?.enabled !== false
377
+ }
378
+ );
379
+ return { versions, loading, error, refetch };
380
+ }
381
+
382
+ // src/useFilteredVersions.ts
383
+ import { useMemo as useMemo2 } from "react";
384
+
385
+ // src/utility/version.ts
386
+ function getISOFromVersion(version) {
387
+ return version?.language_tag || "unknown";
388
+ }
389
+
390
+ // src/useFilteredVersions.ts
391
+ function useFilteredVersions(versions, searchTerm, selectedLanguage, recentVersions) {
392
+ return useMemo2(() => {
393
+ let result = [...versions];
394
+ if (selectedLanguage && selectedLanguage !== "*") {
395
+ result = result.filter(
396
+ (version) => getISOFromVersion(version).toLowerCase() === selectedLanguage.toLowerCase()
397
+ );
398
+ }
399
+ if (searchTerm.trim()) {
400
+ const searchLower = searchTerm.toLowerCase();
401
+ result = result.filter(
402
+ (version) => version.title.toLowerCase().includes(searchLower) || version.abbreviation.toLowerCase().includes(searchLower) || getISOFromVersion(version).toLowerCase().includes(searchLower)
403
+ );
404
+ }
405
+ if (recentVersions) {
406
+ const recentVersionIds = recentVersions.map((version) => version.id);
407
+ result = result.filter((version) => !recentVersionIds.includes(version.id));
408
+ }
409
+ return result;
410
+ }, [versions, recentVersions, searchTerm, selectedLanguage]);
411
+ }
412
+
413
+ // src/utility/extractTextFromHTML.ts
414
+ function extractTextFromHtml(html) {
415
+ if (!html) return "";
416
+ const container = document.createElement("div");
417
+ container.innerHTML = html;
418
+ const contentText = Array.from(container.querySelectorAll("span.content")).map((el) => (el.textContent || "").trim()).filter(Boolean).join(" ");
419
+ return contentText.replace(/\s+/g, " ").trim();
420
+ }
421
+
422
+ // src/utility/extractVersesFromHTML.ts
423
+ function extractVersesFromHTML(html) {
424
+ if (!html) return [];
425
+ const results = [];
426
+ const pattern = /<span class="yv-v" v="(\d+)"><\/span><span class="yv-vlbl">\d+<\/span>/g;
427
+ let execResult;
428
+ const indices = [];
429
+ while ((execResult = pattern.exec(html)) !== null) {
430
+ const verseNumString = execResult[1];
431
+ indices.push({ verse: parseInt(verseNumString, 10), index: execResult.index });
432
+ }
433
+ for (let i = 0; i < indices.length; i++) {
434
+ const current = indices[i];
435
+ const next = indices[i + 1];
436
+ const start = current.index;
437
+ const end = next ? next.index : html.length;
438
+ const slice = html.slice(start, end).trim();
439
+ results.push({ verse: current.verse, html: slice });
440
+ }
441
+ return results;
442
+ }
443
+
444
+ // src/utility/getDayOfYear.ts
445
+ function getDayOfYear(date) {
446
+ const dayOfYear = Math.floor(
447
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5
448
+ );
449
+ return dayOfYear;
450
+ }
451
+
452
+ // src/useVerseSelection.ts
453
+ import { useContext as useContext3 } from "react";
454
+ function useVerseSelection() {
455
+ const context = useContext3(VerseSelectionContext);
456
+ if (!context) {
457
+ throw new Error("useVerseSelection must be used within a VerseSelectionProvider");
458
+ }
459
+ return context;
460
+ }
461
+
462
+ // src/useChapterNavigation.ts
463
+ import { getAdjacentChapter } from "@youversion/platform-core";
464
+ function useChapterNavigation() {
465
+ const { currentChapter, currentVersion, currentBook, setChapter, setBook } = useReaderContext();
466
+ const { books, loading: booksLoading } = useBooks(currentVersion?.id ?? 0, {
467
+ enabled: Boolean(currentVersion?.id)
468
+ });
469
+ const booksData = books?.data ?? [];
470
+ const bookId = currentBook?.id ?? "";
471
+ const chapterId = currentChapter?.id ?? "";
472
+ const nextResult = getAdjacentChapter(booksData, bookId, chapterId, "next");
473
+ const prevResult = getAdjacentChapter(booksData, bookId, chapterId, "previous");
474
+ const canNavigateNext = !booksLoading && nextResult !== null;
475
+ const canNavigatePrevious = !booksLoading && prevResult !== null;
476
+ const currentChapterIndex = currentBook?.chapters?.findIndex((c) => c.id === currentChapter?.id) ?? -1;
477
+ const navigate = (result) => {
478
+ if (!result || !booksData.length) return;
479
+ const targetBook = booksData.find((b) => b.id === result.bookId);
480
+ if (!targetBook) return;
481
+ const targetChapter = targetBook.chapters?.find((c) => c.id === result.chapterId) ?? (targetBook.intro?.id === result.chapterId ? {
482
+ id: targetBook.intro.id,
483
+ passage_id: targetBook.intro.passage_id,
484
+ title: targetBook.intro.title
485
+ } : void 0);
486
+ if (!targetChapter) return;
487
+ if (targetBook.id !== currentBook?.id) {
488
+ setBook(targetBook);
489
+ }
490
+ setChapter(targetChapter);
491
+ };
492
+ const navigateToNext = () => navigate(nextResult);
493
+ const navigateToPrevious = () => navigate(prevResult);
494
+ return {
495
+ canNavigatePrevious,
496
+ canNavigateNext,
497
+ navigateToPrevious,
498
+ navigateToNext,
499
+ currentChapterIndex,
500
+ isLoading: booksLoading
501
+ };
502
+ }
503
+
504
+ // src/useInitData.ts
505
+ import { DEFAULT_LICENSE_FREE_BIBLE_VERSION } from "@youversion/platform-core";
506
+ var DEFAULT = {
507
+ VERSION: DEFAULT_LICENSE_FREE_BIBLE_VERSION,
508
+ BOOK: "GEN",
509
+ CHAPTER: 1
510
+ };
511
+ function useInitData({ version, book, chapter } = {
512
+ version: DEFAULT.VERSION,
513
+ book: DEFAULT.BOOK,
514
+ chapter: DEFAULT.CHAPTER
515
+ }) {
516
+ const {
517
+ version: versionData,
518
+ loading: versionLoading,
519
+ error: versionError
520
+ } = useVersion(version);
521
+ const { book: bookData, loading: bookLoading, error: bookError } = useBook(version, book);
522
+ const {
523
+ chapter: chapterData,
524
+ loading: chapterLoading,
525
+ error: chapterError
526
+ } = useChapter(version, book, chapter);
527
+ const allDataAvailable = versionData && bookData && chapterData;
528
+ return {
529
+ loading: versionLoading || bookLoading || chapterLoading,
530
+ error: [versionError, bookError, chapterError].filter(Boolean).join(" "),
531
+ data: allDataAvailable ? { version: versionData, book: bookData, chapter: chapterData } : null
532
+ };
533
+ }
534
+
535
+ // src/usePassage.ts
536
+ function usePassage({
537
+ versionId,
538
+ usfm,
539
+ format = "html",
540
+ include_headings = false,
541
+ include_notes = false,
542
+ options
543
+ }) {
544
+ const bibleClient = useBibleClient();
545
+ const isValidUsfm = Boolean(usfm) && usfm !== "undefined" && usfm !== "null";
546
+ const { data, loading, error, refetch } = useApiData(
547
+ () => bibleClient.getPassage(versionId, usfm, format, include_headings, include_notes),
548
+ [bibleClient, versionId, usfm, format, include_headings, include_notes],
549
+ { enabled: options?.enabled !== false && isValidUsfm }
550
+ );
551
+ return { passage: data, loading, error, refetch };
552
+ }
553
+
554
+ // src/useVOTD.ts
555
+ function useVerseOfTheDay(day, options) {
556
+ const bibleClient = useBibleClient();
557
+ const { data, loading, error, refetch } = useApiData(
558
+ () => bibleClient.getVOTD(day),
559
+ [bibleClient, day],
560
+ { enabled: options?.enabled !== false }
561
+ );
562
+ return { data, loading, error, refetch };
563
+ }
564
+
565
+ // src/useHighlights.ts
566
+ import { useMemo as useMemo3, useCallback as useCallback3 } from "react";
567
+ import { useContext as useContext4 } from "react";
568
+ import { HighlightsClient, ApiClient as ApiClient2 } from "@youversion/platform-core";
569
+ import "@youversion/platform-core";
570
+ function useHighlights(options, apiOptions) {
571
+ const context = useContext4(YouVersionContext);
572
+ const highlightsClient = useMemo3(() => {
573
+ if (!context?.appKey) {
574
+ throw new Error(
575
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
576
+ );
577
+ }
578
+ return new HighlightsClient(
579
+ new ApiClient2({
580
+ appKey: context.appKey,
581
+ apiHost: context.apiHost,
582
+ installationId: context.installationId
583
+ })
584
+ );
585
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
586
+ const { data, loading, error, refetch } = useApiData(
587
+ () => highlightsClient.getHighlights(options),
588
+ [highlightsClient, options?.version_id, options?.passage_id],
589
+ {
590
+ enabled: apiOptions?.enabled !== false
591
+ }
592
+ );
593
+ const createHighlight = useCallback3(
594
+ async (data2) => {
595
+ const result = await highlightsClient.createHighlight(data2);
596
+ refetch();
597
+ return result;
598
+ },
599
+ [highlightsClient, refetch]
600
+ );
601
+ const deleteHighlight = useCallback3(
602
+ async (passageId, deleteOptions) => {
603
+ await highlightsClient.deleteHighlight(passageId, deleteOptions);
604
+ refetch();
605
+ },
606
+ [highlightsClient, refetch]
607
+ );
608
+ return {
609
+ highlights: data,
610
+ loading,
611
+ error,
612
+ refetch,
613
+ createHighlight,
614
+ deleteHighlight
615
+ };
616
+ }
617
+
618
+ // src/useLanguages.ts
619
+ import "@youversion/platform-core";
620
+
621
+ // src/useLanguageClient.ts
622
+ import { useContext as useContext5, useMemo as useMemo4 } from "react";
623
+ import { ApiClient as ApiClient3, LanguagesClient } from "@youversion/platform-core";
624
+ function useLanguagesClient() {
625
+ const context = useContext5(YouVersionContext);
626
+ return useMemo4(() => {
627
+ if (!context?.appKey) {
628
+ throw new Error(
629
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
630
+ );
631
+ }
632
+ return new LanguagesClient(
633
+ new ApiClient3({
634
+ appKey: context.appKey,
635
+ apiHost: context.apiHost,
636
+ installationId: context.installationId
637
+ })
638
+ );
639
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
640
+ }
641
+
642
+ // src/useLanguages.ts
643
+ function useLanguages(options = {}, apiOptions) {
644
+ const languagesClient = useLanguagesClient();
645
+ const { data, loading, error, refetch } = useApiData(
646
+ () => languagesClient.getLanguages(options),
647
+ [
648
+ languagesClient,
649
+ JSON.stringify(options.fields),
650
+ options?.country,
651
+ options?.page_size,
652
+ options?.page_token
653
+ ],
654
+ {
655
+ enabled: apiOptions?.enabled !== false
656
+ }
657
+ );
658
+ return {
659
+ languages: data,
660
+ loading,
661
+ error,
662
+ refetch
663
+ };
664
+ }
665
+
666
+ // src/useLanguage.ts
667
+ import "@youversion/platform-core";
668
+ function useLanguage(languageId, apiOptions) {
669
+ const languagesClient = useLanguagesClient();
670
+ const { data, loading, error, refetch } = useApiData(
671
+ () => languagesClient.getLanguage(languageId),
672
+ [languagesClient, languageId],
673
+ {
674
+ enabled: apiOptions?.enabled !== false
675
+ }
676
+ );
677
+ return {
678
+ language: data,
679
+ loading,
680
+ error,
681
+ refetch
682
+ };
683
+ }
684
+
685
+ // src/useTheme.ts
686
+ import { useContext as useContext6 } from "react";
687
+ function useTheme() {
688
+ const context = useContext6(YouVersionContext);
689
+ return context?.theme || "light";
690
+ }
691
+
692
+ // src/useYVAuth.ts
693
+ import { useMemo as useMemo5, useCallback as useCallback4 } from "react";
694
+ import {
695
+ YouVersionAPIUsers,
696
+ YouVersionPlatformConfiguration as YouVersionPlatformConfiguration2
697
+ } from "@youversion/platform-core";
698
+ function useYVAuth() {
699
+ const { userInfo, setUserInfo, isLoading, error, redirectUri } = useYouVersionAuthContext();
700
+ const isAuthenticated = !!userInfo;
701
+ const authTokens = useMemo5(() => {
702
+ if (typeof window !== "undefined") {
703
+ return {
704
+ accessToken: YouVersionPlatformConfiguration2.accessToken,
705
+ idToken: YouVersionPlatformConfiguration2.idToken
706
+ };
707
+ }
708
+ return { accessToken: null, idToken: null };
709
+ }, []);
710
+ const signIn = useCallback4(
711
+ async (params) => {
712
+ const url = params?.redirectUrl ?? redirectUri;
713
+ if (!url) {
714
+ throw new Error(
715
+ "redirectUrl is required. Provide it via signIn params or configure redirectUri in the auth provider."
716
+ );
717
+ }
718
+ if (params?.scopes) {
719
+ await YouVersionAPIUsers.signIn(url, params.scopes);
720
+ } else {
721
+ await YouVersionAPIUsers.signIn(url);
722
+ }
723
+ },
724
+ [redirectUri]
725
+ );
726
+ const processCallback = useCallback4(async () => {
727
+ const result = await YouVersionAPIUsers.handleAuthCallback();
728
+ return result;
729
+ }, []);
730
+ const auth = useMemo5(
731
+ () => ({
732
+ isAuthenticated,
733
+ isLoading,
734
+ accessToken: authTokens.accessToken,
735
+ idToken: authTokens.idToken,
736
+ result: null,
737
+ error
738
+ }),
739
+ [isAuthenticated, isLoading, authTokens.accessToken, authTokens.idToken, error]
740
+ );
741
+ const signOut = useCallback4(() => {
742
+ YouVersionPlatformConfiguration2.clearAuthTokens();
743
+ setUserInfo(null);
744
+ }, []);
745
+ return {
746
+ auth,
747
+ signIn,
748
+ signOut,
749
+ processCallback,
750
+ userInfo,
751
+ redirectUri
752
+ };
753
+ }
754
+ export {
755
+ DEFAULT,
756
+ ReaderContext,
757
+ ReaderProvider,
758
+ VerseSelectionContext,
759
+ VerseSelectionProvider,
760
+ YouVersionContext,
761
+ YouVersionProvider,
762
+ extractTextFromHtml,
763
+ extractVersesFromHTML,
764
+ getDayOfYear,
765
+ getISOFromVersion,
766
+ useBibleClient,
767
+ useBook,
768
+ useBooks,
769
+ useChapter,
770
+ useChapterNavigation,
771
+ useChapters,
772
+ useDebounce,
773
+ useFilteredVersions,
774
+ useHighlights,
775
+ useInitData,
776
+ useLanguage,
777
+ useLanguages,
778
+ usePassage,
779
+ useReaderContext,
780
+ useTheme,
781
+ useVerse,
782
+ useVerseOfTheDay,
783
+ useVerseSelection,
784
+ useVerses,
785
+ useVersion,
786
+ useVersions,
787
+ useYVAuth
788
+ };