@youversion/platform-react-hooks 1.22.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 +10 -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.cjs ADDED
@@ -0,0 +1,946 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/context/YouVersionAuthContext.tsx
24
+ function useYouVersionAuthContext() {
25
+ const context = (0, import_react2.useContext)(YouVersionAuthContext);
26
+ if (!context) {
27
+ throw new Error(
28
+ "useYouVersionAuthContext must be used within an auth provider. Make sure your app is wrapped with <YouVersionAuthProvider> from @youversion/platform-react-hooks or create your own provider using YouVersionAuthContext from @youversion/platform-react-hooks."
29
+ );
30
+ }
31
+ return context;
32
+ }
33
+ var import_react2, YouVersionAuthContext;
34
+ var init_YouVersionAuthContext = __esm({
35
+ "src/context/YouVersionAuthContext.tsx"() {
36
+ "use strict";
37
+ "use client";
38
+ import_react2 = require("react");
39
+ YouVersionAuthContext = (0, import_react2.createContext)(null);
40
+ }
41
+ });
42
+
43
+ // src/context/YouVersionAuthProvider.tsx
44
+ var YouVersionAuthProvider_exports = {};
45
+ __export(YouVersionAuthProvider_exports, {
46
+ default: () => YouVersionAuthProvider
47
+ });
48
+ function YouVersionAuthProvider({
49
+ config,
50
+ children
51
+ }) {
52
+ const [userInfo, setUserInfo] = (0, import_react3.useState)(null);
53
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
54
+ const [error, setError] = (0, import_react3.useState)(null);
55
+ (0, import_react3.useEffect)(() => {
56
+ let mounted = true;
57
+ const initAuth = async () => {
58
+ import_platform_core.YouVersionPlatformConfiguration.appKey = config.appKey;
59
+ import_platform_core.YouVersionPlatformConfiguration.apiHost = config.apiHost ?? "api.youversion.com";
60
+ if (typeof window !== "undefined") {
61
+ const urlParams = new URLSearchParams(window.location.search);
62
+ const isOAuthCallback = urlParams.has("state") || urlParams.has("error");
63
+ if (isOAuthCallback) {
64
+ try {
65
+ const result = await import_platform_core.YouVersionAPIUsers.handleAuthCallback();
66
+ if (result && import_platform_core.YouVersionPlatformConfiguration.idToken) {
67
+ const info = import_platform_core.YouVersionAPIUsers.userInfo(import_platform_core.YouVersionPlatformConfiguration.idToken);
68
+ if (!mounted) return;
69
+ setUserInfo(info);
70
+ }
71
+ } catch (err) {
72
+ if (!mounted) return;
73
+ setError(err);
74
+ }
75
+ } else {
76
+ const refreshToken = import_platform_core.YouVersionPlatformConfiguration.refreshToken;
77
+ if (refreshToken) {
78
+ try {
79
+ await import_platform_core.YouVersionAPIUsers.refreshTokenIfNeeded();
80
+ const idToken = import_platform_core.YouVersionPlatformConfiguration.idToken;
81
+ if (idToken) {
82
+ const info = import_platform_core.YouVersionAPIUsers.userInfo(idToken);
83
+ if (!mounted) return;
84
+ setUserInfo(info);
85
+ } else {
86
+ if (!mounted) return;
87
+ setUserInfo(null);
88
+ }
89
+ } catch {
90
+ if (!mounted) return;
91
+ setUserInfo(null);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ if (!mounted) return;
97
+ setIsLoading(false);
98
+ };
99
+ void initAuth();
100
+ return () => {
101
+ mounted = false;
102
+ };
103
+ }, []);
104
+ const value = {
105
+ userInfo,
106
+ setUserInfo,
107
+ isLoading,
108
+ error,
109
+ redirectUri: config.redirectUri
110
+ };
111
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YouVersionAuthContext.Provider, { value, children });
112
+ }
113
+ var import_react3, import_platform_core, import_jsx_runtime;
114
+ var init_YouVersionAuthProvider = __esm({
115
+ "src/context/YouVersionAuthProvider.tsx"() {
116
+ "use strict";
117
+ "use client";
118
+ import_react3 = require("react");
119
+ import_platform_core = require("@youversion/platform-core");
120
+ init_YouVersionAuthContext();
121
+ import_jsx_runtime = require("react/jsx-runtime");
122
+ }
123
+ });
124
+
125
+ // src/index.ts
126
+ var index_exports = {};
127
+ __export(index_exports, {
128
+ DEFAULT: () => DEFAULT,
129
+ ReaderContext: () => ReaderContext,
130
+ ReaderProvider: () => ReaderProvider,
131
+ VerseSelectionContext: () => VerseSelectionContext,
132
+ VerseSelectionProvider: () => VerseSelectionProvider,
133
+ YouVersionContext: () => YouVersionContext,
134
+ YouVersionProvider: () => YouVersionProvider,
135
+ extractTextFromHtml: () => extractTextFromHtml,
136
+ extractVersesFromHTML: () => extractVersesFromHTML,
137
+ getDayOfYear: () => getDayOfYear,
138
+ getISOFromVersion: () => getISOFromVersion,
139
+ useBibleClient: () => useBibleClient,
140
+ useBook: () => useBook,
141
+ useBooks: () => useBooks,
142
+ useChapter: () => useChapter,
143
+ useChapterNavigation: () => useChapterNavigation,
144
+ useChapters: () => useChapters,
145
+ useDebounce: () => useDebounce,
146
+ useFilteredVersions: () => useFilteredVersions,
147
+ useHighlights: () => useHighlights,
148
+ useInitData: () => useInitData,
149
+ useLanguage: () => useLanguage,
150
+ useLanguages: () => useLanguages,
151
+ usePassage: () => usePassage,
152
+ useReaderContext: () => useReaderContext,
153
+ useTheme: () => useTheme,
154
+ useVerse: () => useVerse,
155
+ useVerseOfTheDay: () => useVerseOfTheDay,
156
+ useVerseSelection: () => useVerseSelection,
157
+ useVerses: () => useVerses,
158
+ useVersion: () => useVersion,
159
+ useVersions: () => useVersions,
160
+ useYVAuth: () => useYVAuth
161
+ });
162
+ module.exports = __toCommonJS(index_exports);
163
+
164
+ // src/useBibleClient.ts
165
+ var import_react9 = require("react");
166
+
167
+ // src/context/YouVersionContext.tsx
168
+ var import_react = require("react");
169
+ var YouVersionContext = (0, import_react.createContext)(null);
170
+
171
+ // src/context/YouVersionProvider.tsx
172
+ var import_react4 = require("react");
173
+ var import_platform_core2 = require("@youversion/platform-core");
174
+ var import_jsx_runtime2 = require("react/jsx-runtime");
175
+ var AuthProvider = (0, import_react4.lazy)(() => Promise.resolve().then(() => (init_YouVersionAuthProvider(), YouVersionAuthProvider_exports)));
176
+ function useResolvedTheme(theme) {
177
+ const [resolved, setResolved] = (0, import_react4.useState)(() => {
178
+ if (theme !== "system") return theme;
179
+ if (typeof window === "undefined") return "light";
180
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
181
+ });
182
+ (0, import_react4.useEffect)(() => {
183
+ if (theme !== "system") {
184
+ setResolved(theme);
185
+ return;
186
+ }
187
+ if (typeof window === "undefined") return;
188
+ const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
189
+ setResolved(mediaQueryList.matches ? "dark" : "light");
190
+ const handler = (e) => {
191
+ setResolved(e.matches ? "dark" : "light");
192
+ };
193
+ mediaQueryList.addEventListener("change", handler);
194
+ return () => mediaQueryList.removeEventListener("change", handler);
195
+ }, [theme]);
196
+ return resolved;
197
+ }
198
+ function YouVersionProvider(props) {
199
+ const { appKey, apiHost = "api.youversion.com", includeAuth, theme = "light", children } = props;
200
+ const resolvedTheme = useResolvedTheme(theme);
201
+ (0, import_react4.useEffect)(() => {
202
+ import_platform_core2.YouVersionPlatformConfiguration.appKey = appKey;
203
+ import_platform_core2.YouVersionPlatformConfiguration.apiHost = apiHost;
204
+ }, [appKey, apiHost]);
205
+ if (includeAuth) {
206
+ const { authRedirectUrl } = props;
207
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
208
+ YouVersionContext.Provider,
209
+ {
210
+ value: {
211
+ appKey,
212
+ apiHost,
213
+ installationId: import_platform_core2.YouVersionPlatformConfiguration.installationId,
214
+ theme: resolvedTheme,
215
+ authEnabled: !!includeAuth
216
+ },
217
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Suspense, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AuthProvider, { config: { appKey, apiHost, redirectUri: authRedirectUrl }, children }) })
218
+ }
219
+ );
220
+ }
221
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
222
+ YouVersionContext.Provider,
223
+ {
224
+ value: {
225
+ appKey,
226
+ apiHost,
227
+ installationId: import_platform_core2.YouVersionPlatformConfiguration.installationId,
228
+ theme: resolvedTheme,
229
+ authEnabled: !!includeAuth
230
+ },
231
+ children
232
+ }
233
+ );
234
+ }
235
+
236
+ // src/context/ReaderContext.tsx
237
+ var import_react5 = require("react");
238
+ var ReaderContext = (0, import_react5.createContext)(null);
239
+ function useReaderContext() {
240
+ const context = (0, import_react5.useContext)(ReaderContext);
241
+ if (!context) {
242
+ throw new Error("useReaderContext() must be used within a ReaderProvider");
243
+ }
244
+ return context;
245
+ }
246
+
247
+ // src/context/ReaderProvider.tsx
248
+ var import_react6 = require("react");
249
+ var import_jsx_runtime3 = require("react/jsx-runtime");
250
+ function ReaderProvider(props) {
251
+ const [currentVersion, setCurrentVersion] = (0, import_react6.useState)(props.currentVersion);
252
+ const [currentBook, setCurrentBook] = (0, import_react6.useState)(props.currentBook);
253
+ const [currentChapter, setCurrentChapter] = (0, import_react6.useState)(props.currentChapter);
254
+ const [currentVerse, setCurrentVerse] = (0, import_react6.useState)(props.currentVerse);
255
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
256
+ ReaderContext.Provider,
257
+ {
258
+ value: {
259
+ currentVersion,
260
+ currentBook,
261
+ currentChapter,
262
+ currentVerse,
263
+ setVersion: setCurrentVersion,
264
+ setChapter: setCurrentChapter,
265
+ setBook: setCurrentBook,
266
+ setVerse: setCurrentVerse
267
+ },
268
+ children: props.children
269
+ }
270
+ );
271
+ }
272
+
273
+ // src/context/VerseSelectionProvider.tsx
274
+ var import_react8 = require("react");
275
+
276
+ // src/context/VerseSelectionContext.tsx
277
+ var import_react7 = require("react");
278
+ var VerseSelectionContext = (0, import_react7.createContext)(null);
279
+
280
+ // src/context/VerseSelectionProvider.tsx
281
+ var import_jsx_runtime4 = require("react/jsx-runtime");
282
+ function VerseSelectionProvider({ children }) {
283
+ const [selectedVerseUsfms, setSelectedVerseUsfms] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
284
+ const toggleVerse = (0, import_react8.useCallback)((usfm) => {
285
+ setSelectedVerseUsfms((prev) => {
286
+ const newSet = new Set(prev);
287
+ if (newSet.has(usfm)) {
288
+ newSet.delete(usfm);
289
+ } else {
290
+ newSet.add(usfm);
291
+ }
292
+ return newSet;
293
+ });
294
+ }, []);
295
+ const isSelected = (0, import_react8.useCallback)(
296
+ (usfm) => {
297
+ return selectedVerseUsfms.has(usfm);
298
+ },
299
+ [selectedVerseUsfms]
300
+ );
301
+ const clearSelection = (0, import_react8.useCallback)(() => {
302
+ setSelectedVerseUsfms(/* @__PURE__ */ new Set());
303
+ }, []);
304
+ const value = {
305
+ selectedVerseUsfms,
306
+ toggleVerse,
307
+ isSelected,
308
+ clearSelection,
309
+ selectedCount: selectedVerseUsfms.size
310
+ };
311
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VerseSelectionContext.Provider, { value, children });
312
+ }
313
+
314
+ // src/useBibleClient.ts
315
+ var import_platform_core3 = require("@youversion/platform-core");
316
+ function useBibleClient() {
317
+ const context = (0, import_react9.useContext)(YouVersionContext);
318
+ return (0, import_react9.useMemo)(() => {
319
+ if (!context?.appKey) {
320
+ throw new Error(
321
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
322
+ );
323
+ }
324
+ return new import_platform_core3.BibleClient(
325
+ new import_platform_core3.ApiClient({
326
+ appKey: context.appKey,
327
+ apiHost: context.apiHost,
328
+ installationId: context.installationId
329
+ })
330
+ );
331
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
332
+ }
333
+
334
+ // src/useApiData.ts
335
+ var import_react10 = require("react");
336
+ function useApiData(fetchFn, deps, options = {}) {
337
+ const { enabled = true } = options;
338
+ const [data, setData] = (0, import_react10.useState)(null);
339
+ const [loading, setLoading] = (0, import_react10.useState)(true);
340
+ const [error, setError] = (0, import_react10.useState)(null);
341
+ const fetchData = (0, import_react10.useCallback)(() => {
342
+ if (!enabled) {
343
+ setLoading(false);
344
+ return;
345
+ }
346
+ let canceled = false;
347
+ setLoading(true);
348
+ setError(null);
349
+ fetchFn().then((result) => {
350
+ if (!canceled) {
351
+ setData(result);
352
+ }
353
+ }).catch((err) => {
354
+ if (!canceled) {
355
+ setError(err);
356
+ }
357
+ }).finally(() => {
358
+ if (!canceled) {
359
+ setLoading(false);
360
+ }
361
+ });
362
+ return () => {
363
+ canceled = true;
364
+ };
365
+ }, [fetchFn, enabled]);
366
+ const refetch = (0, import_react10.useCallback)(() => {
367
+ fetchData();
368
+ }, [fetchData]);
369
+ (0, import_react10.useEffect)(() => {
370
+ const cleanup = fetchData();
371
+ return cleanup;
372
+ }, deps);
373
+ return { data, loading, error, refetch };
374
+ }
375
+
376
+ // src/useBook.ts
377
+ function useBook(versionId, book, options) {
378
+ const bibleClient = useBibleClient();
379
+ const { data, loading, error, refetch } = useApiData(
380
+ () => bibleClient.getBook(versionId, book),
381
+ [bibleClient, versionId, book],
382
+ {
383
+ enabled: options?.enabled !== false
384
+ }
385
+ );
386
+ return { book: data, loading, error, refetch };
387
+ }
388
+
389
+ // src/useBooks.ts
390
+ function useBooks(versionId, options) {
391
+ const bibleClient = useBibleClient();
392
+ const {
393
+ data: books,
394
+ loading,
395
+ error,
396
+ refetch
397
+ } = useApiData(
398
+ () => bibleClient.getBooks(versionId),
399
+ [bibleClient, versionId],
400
+ {
401
+ enabled: options?.enabled !== false
402
+ }
403
+ );
404
+ return { books, loading, error, refetch };
405
+ }
406
+
407
+ // src/useChapter.ts
408
+ function useChapter(versionId, book, chapter, options) {
409
+ const bibleClient = useBibleClient();
410
+ const {
411
+ data: chapterData,
412
+ loading,
413
+ error,
414
+ refetch
415
+ } = useApiData(
416
+ () => bibleClient.getChapter(versionId, book, chapter),
417
+ [bibleClient, versionId, book, chapter],
418
+ {
419
+ enabled: options?.enabled !== false
420
+ }
421
+ );
422
+ return { chapter: chapterData, loading, error, refetch };
423
+ }
424
+
425
+ // src/useChapters.ts
426
+ function useChapters(versionId, book, options) {
427
+ const bibleClient = useBibleClient();
428
+ const isValidBook = Boolean(book) && book !== "undefined" && book !== "null";
429
+ const {
430
+ data: chapters,
431
+ loading,
432
+ error,
433
+ refetch
434
+ } = useApiData(
435
+ () => bibleClient.getChapters(versionId, book),
436
+ [bibleClient, versionId, book],
437
+ {
438
+ enabled: options?.enabled !== false && isValidBook
439
+ }
440
+ );
441
+ return { chapters, loading, error, refetch };
442
+ }
443
+
444
+ // src/useVerse.ts
445
+ function useVerse(versionId, book, chapter, verse, options) {
446
+ const bibleClient = useBibleClient();
447
+ const {
448
+ data: verseData,
449
+ loading,
450
+ error,
451
+ refetch
452
+ } = useApiData(
453
+ () => bibleClient.getVerse(versionId, book, chapter, verse),
454
+ [bibleClient, versionId, book, chapter, verse],
455
+ {
456
+ enabled: options?.enabled !== false
457
+ }
458
+ );
459
+ return { verse: verseData, loading, error, refetch };
460
+ }
461
+
462
+ // src/useVerses.ts
463
+ function useVerses(versionId, book, chapter, options) {
464
+ const bibleClient = useBibleClient();
465
+ const {
466
+ data: verses,
467
+ loading,
468
+ error,
469
+ refetch
470
+ } = useApiData(
471
+ () => bibleClient.getVerses(versionId, book, chapter),
472
+ [bibleClient, versionId, book, chapter],
473
+ {
474
+ enabled: options?.enabled !== false
475
+ }
476
+ );
477
+ return { verses, loading, error, refetch };
478
+ }
479
+
480
+ // src/useVersion.ts
481
+ function useVersion(versionId, options) {
482
+ const bibleClient = useBibleClient();
483
+ const {
484
+ data: version,
485
+ loading,
486
+ error,
487
+ refetch
488
+ } = useApiData(() => bibleClient.getVersion(versionId), [bibleClient, versionId], {
489
+ enabled: options?.enabled !== false
490
+ });
491
+ return { version, loading, error, refetch };
492
+ }
493
+
494
+ // src/utility/useDebounce.ts
495
+ var import_react11 = require("react");
496
+ function useDebounce(value, delay) {
497
+ const [debouncedValue, setDebouncedValue] = (0, import_react11.useState)(value);
498
+ (0, import_react11.useEffect)(() => {
499
+ const handler = setTimeout(() => {
500
+ setDebouncedValue(value);
501
+ }, delay);
502
+ return () => clearTimeout(handler);
503
+ }, [value, delay]);
504
+ return debouncedValue;
505
+ }
506
+
507
+ // src/useVersions.ts
508
+ function useVersions(languageRanges = "en", licenseId, options) {
509
+ const bibleClient = useBibleClient();
510
+ const getVersionsOptions = options?.page_size !== void 0 || options?.page_token !== void 0 || options?.fields !== void 0 || options?.all_available !== void 0 ? {
511
+ page_size: options?.page_size,
512
+ page_token: options?.page_token,
513
+ fields: options?.fields,
514
+ all_available: options?.all_available
515
+ } : void 0;
516
+ const languageRangesKey = Array.isArray(languageRanges) ? languageRanges.join(",") : languageRanges;
517
+ const fieldsKey = options?.fields?.join(",");
518
+ const {
519
+ data: versions,
520
+ loading,
521
+ error,
522
+ refetch
523
+ } = useApiData(
524
+ () => bibleClient.getVersions(languageRanges, licenseId, getVersionsOptions),
525
+ [
526
+ bibleClient,
527
+ languageRangesKey,
528
+ licenseId,
529
+ options?.page_size,
530
+ options?.page_token,
531
+ fieldsKey,
532
+ options?.all_available
533
+ ],
534
+ {
535
+ enabled: options?.enabled !== false
536
+ }
537
+ );
538
+ return { versions, loading, error, refetch };
539
+ }
540
+
541
+ // src/useFilteredVersions.ts
542
+ var import_react12 = require("react");
543
+
544
+ // src/utility/version.ts
545
+ function getISOFromVersion(version) {
546
+ return version?.language_tag || "unknown";
547
+ }
548
+
549
+ // src/useFilteredVersions.ts
550
+ function useFilteredVersions(versions, searchTerm, selectedLanguage, recentVersions) {
551
+ return (0, import_react12.useMemo)(() => {
552
+ let result = [...versions];
553
+ if (selectedLanguage && selectedLanguage !== "*") {
554
+ result = result.filter(
555
+ (version) => getISOFromVersion(version).toLowerCase() === selectedLanguage.toLowerCase()
556
+ );
557
+ }
558
+ if (searchTerm.trim()) {
559
+ const searchLower = searchTerm.toLowerCase();
560
+ result = result.filter(
561
+ (version) => version.title.toLowerCase().includes(searchLower) || version.abbreviation.toLowerCase().includes(searchLower) || getISOFromVersion(version).toLowerCase().includes(searchLower)
562
+ );
563
+ }
564
+ if (recentVersions) {
565
+ const recentVersionIds = recentVersions.map((version) => version.id);
566
+ result = result.filter((version) => !recentVersionIds.includes(version.id));
567
+ }
568
+ return result;
569
+ }, [versions, recentVersions, searchTerm, selectedLanguage]);
570
+ }
571
+
572
+ // src/utility/extractTextFromHTML.ts
573
+ function extractTextFromHtml(html) {
574
+ if (!html) return "";
575
+ const container = document.createElement("div");
576
+ container.innerHTML = html;
577
+ const contentText = Array.from(container.querySelectorAll("span.content")).map((el) => (el.textContent || "").trim()).filter(Boolean).join(" ");
578
+ return contentText.replace(/\s+/g, " ").trim();
579
+ }
580
+
581
+ // src/utility/extractVersesFromHTML.ts
582
+ function extractVersesFromHTML(html) {
583
+ if (!html) return [];
584
+ const results = [];
585
+ const pattern = /<span class="yv-v" v="(\d+)"><\/span><span class="yv-vlbl">\d+<\/span>/g;
586
+ let execResult;
587
+ const indices = [];
588
+ while ((execResult = pattern.exec(html)) !== null) {
589
+ const verseNumString = execResult[1];
590
+ indices.push({ verse: parseInt(verseNumString, 10), index: execResult.index });
591
+ }
592
+ for (let i = 0; i < indices.length; i++) {
593
+ const current = indices[i];
594
+ const next = indices[i + 1];
595
+ const start = current.index;
596
+ const end = next ? next.index : html.length;
597
+ const slice = html.slice(start, end).trim();
598
+ results.push({ verse: current.verse, html: slice });
599
+ }
600
+ return results;
601
+ }
602
+
603
+ // src/utility/getDayOfYear.ts
604
+ function getDayOfYear(date) {
605
+ const dayOfYear = Math.floor(
606
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5
607
+ );
608
+ return dayOfYear;
609
+ }
610
+
611
+ // src/useVerseSelection.ts
612
+ var import_react13 = require("react");
613
+ function useVerseSelection() {
614
+ const context = (0, import_react13.useContext)(VerseSelectionContext);
615
+ if (!context) {
616
+ throw new Error("useVerseSelection must be used within a VerseSelectionProvider");
617
+ }
618
+ return context;
619
+ }
620
+
621
+ // src/useChapterNavigation.ts
622
+ var import_platform_core4 = require("@youversion/platform-core");
623
+ function useChapterNavigation() {
624
+ const { currentChapter, currentVersion, currentBook, setChapter, setBook } = useReaderContext();
625
+ const { books, loading: booksLoading } = useBooks(currentVersion?.id ?? 0, {
626
+ enabled: Boolean(currentVersion?.id)
627
+ });
628
+ const booksData = books?.data ?? [];
629
+ const bookId = currentBook?.id ?? "";
630
+ const chapterId = currentChapter?.id ?? "";
631
+ const nextResult = (0, import_platform_core4.getAdjacentChapter)(booksData, bookId, chapterId, "next");
632
+ const prevResult = (0, import_platform_core4.getAdjacentChapter)(booksData, bookId, chapterId, "previous");
633
+ const canNavigateNext = !booksLoading && nextResult !== null;
634
+ const canNavigatePrevious = !booksLoading && prevResult !== null;
635
+ const currentChapterIndex = currentBook?.chapters?.findIndex((c) => c.id === currentChapter?.id) ?? -1;
636
+ const navigate = (result) => {
637
+ if (!result || !booksData.length) return;
638
+ const targetBook = booksData.find((b) => b.id === result.bookId);
639
+ if (!targetBook) return;
640
+ const targetChapter = targetBook.chapters?.find((c) => c.id === result.chapterId) ?? (targetBook.intro?.id === result.chapterId ? {
641
+ id: targetBook.intro.id,
642
+ passage_id: targetBook.intro.passage_id,
643
+ title: targetBook.intro.title
644
+ } : void 0);
645
+ if (!targetChapter) return;
646
+ if (targetBook.id !== currentBook?.id) {
647
+ setBook(targetBook);
648
+ }
649
+ setChapter(targetChapter);
650
+ };
651
+ const navigateToNext = () => navigate(nextResult);
652
+ const navigateToPrevious = () => navigate(prevResult);
653
+ return {
654
+ canNavigatePrevious,
655
+ canNavigateNext,
656
+ navigateToPrevious,
657
+ navigateToNext,
658
+ currentChapterIndex,
659
+ isLoading: booksLoading
660
+ };
661
+ }
662
+
663
+ // src/useInitData.ts
664
+ var import_platform_core5 = require("@youversion/platform-core");
665
+ var DEFAULT = {
666
+ VERSION: import_platform_core5.DEFAULT_LICENSE_FREE_BIBLE_VERSION,
667
+ BOOK: "GEN",
668
+ CHAPTER: 1
669
+ };
670
+ function useInitData({ version, book, chapter } = {
671
+ version: DEFAULT.VERSION,
672
+ book: DEFAULT.BOOK,
673
+ chapter: DEFAULT.CHAPTER
674
+ }) {
675
+ const {
676
+ version: versionData,
677
+ loading: versionLoading,
678
+ error: versionError
679
+ } = useVersion(version);
680
+ const { book: bookData, loading: bookLoading, error: bookError } = useBook(version, book);
681
+ const {
682
+ chapter: chapterData,
683
+ loading: chapterLoading,
684
+ error: chapterError
685
+ } = useChapter(version, book, chapter);
686
+ const allDataAvailable = versionData && bookData && chapterData;
687
+ return {
688
+ loading: versionLoading || bookLoading || chapterLoading,
689
+ error: [versionError, bookError, chapterError].filter(Boolean).join(" "),
690
+ data: allDataAvailable ? { version: versionData, book: bookData, chapter: chapterData } : null
691
+ };
692
+ }
693
+
694
+ // src/usePassage.ts
695
+ function usePassage({
696
+ versionId,
697
+ usfm,
698
+ format = "html",
699
+ include_headings = false,
700
+ include_notes = false,
701
+ options
702
+ }) {
703
+ const bibleClient = useBibleClient();
704
+ const isValidUsfm = Boolean(usfm) && usfm !== "undefined" && usfm !== "null";
705
+ const { data, loading, error, refetch } = useApiData(
706
+ () => bibleClient.getPassage(versionId, usfm, format, include_headings, include_notes),
707
+ [bibleClient, versionId, usfm, format, include_headings, include_notes],
708
+ { enabled: options?.enabled !== false && isValidUsfm }
709
+ );
710
+ return { passage: data, loading, error, refetch };
711
+ }
712
+
713
+ // src/useVOTD.ts
714
+ function useVerseOfTheDay(day, options) {
715
+ const bibleClient = useBibleClient();
716
+ const { data, loading, error, refetch } = useApiData(
717
+ () => bibleClient.getVOTD(day),
718
+ [bibleClient, day],
719
+ { enabled: options?.enabled !== false }
720
+ );
721
+ return { data, loading, error, refetch };
722
+ }
723
+
724
+ // src/useHighlights.ts
725
+ var import_react14 = require("react");
726
+ var import_react15 = require("react");
727
+ var import_platform_core6 = require("@youversion/platform-core");
728
+ var import_platform_core7 = require("@youversion/platform-core");
729
+ function useHighlights(options, apiOptions) {
730
+ const context = (0, import_react15.useContext)(YouVersionContext);
731
+ const highlightsClient = (0, import_react14.useMemo)(() => {
732
+ if (!context?.appKey) {
733
+ throw new Error(
734
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
735
+ );
736
+ }
737
+ return new import_platform_core6.HighlightsClient(
738
+ new import_platform_core6.ApiClient({
739
+ appKey: context.appKey,
740
+ apiHost: context.apiHost,
741
+ installationId: context.installationId
742
+ })
743
+ );
744
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
745
+ const { data, loading, error, refetch } = useApiData(
746
+ () => highlightsClient.getHighlights(options),
747
+ [highlightsClient, options?.version_id, options?.passage_id],
748
+ {
749
+ enabled: apiOptions?.enabled !== false
750
+ }
751
+ );
752
+ const createHighlight = (0, import_react14.useCallback)(
753
+ async (data2) => {
754
+ const result = await highlightsClient.createHighlight(data2);
755
+ refetch();
756
+ return result;
757
+ },
758
+ [highlightsClient, refetch]
759
+ );
760
+ const deleteHighlight = (0, import_react14.useCallback)(
761
+ async (passageId, deleteOptions) => {
762
+ await highlightsClient.deleteHighlight(passageId, deleteOptions);
763
+ refetch();
764
+ },
765
+ [highlightsClient, refetch]
766
+ );
767
+ return {
768
+ highlights: data,
769
+ loading,
770
+ error,
771
+ refetch,
772
+ createHighlight,
773
+ deleteHighlight
774
+ };
775
+ }
776
+
777
+ // src/useLanguages.ts
778
+ var import_platform_core9 = require("@youversion/platform-core");
779
+
780
+ // src/useLanguageClient.ts
781
+ var import_react16 = require("react");
782
+ var import_platform_core8 = require("@youversion/platform-core");
783
+ function useLanguagesClient() {
784
+ const context = (0, import_react16.useContext)(YouVersionContext);
785
+ return (0, import_react16.useMemo)(() => {
786
+ if (!context?.appKey) {
787
+ throw new Error(
788
+ "YouVersion context not found. Make sure your component is wrapped with YouVersionProvider and an API key is provided."
789
+ );
790
+ }
791
+ return new import_platform_core8.LanguagesClient(
792
+ new import_platform_core8.ApiClient({
793
+ appKey: context.appKey,
794
+ apiHost: context.apiHost,
795
+ installationId: context.installationId
796
+ })
797
+ );
798
+ }, [context?.apiHost, context?.appKey, context?.installationId]);
799
+ }
800
+
801
+ // src/useLanguages.ts
802
+ function useLanguages(options = {}, apiOptions) {
803
+ const languagesClient = useLanguagesClient();
804
+ const { data, loading, error, refetch } = useApiData(
805
+ () => languagesClient.getLanguages(options),
806
+ [
807
+ languagesClient,
808
+ JSON.stringify(options.fields),
809
+ options?.country,
810
+ options?.page_size,
811
+ options?.page_token
812
+ ],
813
+ {
814
+ enabled: apiOptions?.enabled !== false
815
+ }
816
+ );
817
+ return {
818
+ languages: data,
819
+ loading,
820
+ error,
821
+ refetch
822
+ };
823
+ }
824
+
825
+ // src/useLanguage.ts
826
+ var import_platform_core10 = require("@youversion/platform-core");
827
+ function useLanguage(languageId, apiOptions) {
828
+ const languagesClient = useLanguagesClient();
829
+ const { data, loading, error, refetch } = useApiData(
830
+ () => languagesClient.getLanguage(languageId),
831
+ [languagesClient, languageId],
832
+ {
833
+ enabled: apiOptions?.enabled !== false
834
+ }
835
+ );
836
+ return {
837
+ language: data,
838
+ loading,
839
+ error,
840
+ refetch
841
+ };
842
+ }
843
+
844
+ // src/useTheme.ts
845
+ var import_react17 = require("react");
846
+ function useTheme() {
847
+ const context = (0, import_react17.useContext)(YouVersionContext);
848
+ return context?.theme || "light";
849
+ }
850
+
851
+ // src/useYVAuth.ts
852
+ var import_react18 = require("react");
853
+ var import_platform_core11 = require("@youversion/platform-core");
854
+ init_YouVersionAuthContext();
855
+ function useYVAuth() {
856
+ const { userInfo, setUserInfo, isLoading, error, redirectUri } = useYouVersionAuthContext();
857
+ const isAuthenticated = !!userInfo;
858
+ const authTokens = (0, import_react18.useMemo)(() => {
859
+ if (typeof window !== "undefined") {
860
+ return {
861
+ accessToken: import_platform_core11.YouVersionPlatformConfiguration.accessToken,
862
+ idToken: import_platform_core11.YouVersionPlatformConfiguration.idToken
863
+ };
864
+ }
865
+ return { accessToken: null, idToken: null };
866
+ }, []);
867
+ const signIn = (0, import_react18.useCallback)(
868
+ async (params) => {
869
+ const url = params?.redirectUrl ?? redirectUri;
870
+ if (!url) {
871
+ throw new Error(
872
+ "redirectUrl is required. Provide it via signIn params or configure redirectUri in the auth provider."
873
+ );
874
+ }
875
+ if (params?.scopes) {
876
+ await import_platform_core11.YouVersionAPIUsers.signIn(url, params.scopes);
877
+ } else {
878
+ await import_platform_core11.YouVersionAPIUsers.signIn(url);
879
+ }
880
+ },
881
+ [redirectUri]
882
+ );
883
+ const processCallback = (0, import_react18.useCallback)(async () => {
884
+ const result = await import_platform_core11.YouVersionAPIUsers.handleAuthCallback();
885
+ return result;
886
+ }, []);
887
+ const auth = (0, import_react18.useMemo)(
888
+ () => ({
889
+ isAuthenticated,
890
+ isLoading,
891
+ accessToken: authTokens.accessToken,
892
+ idToken: authTokens.idToken,
893
+ result: null,
894
+ error
895
+ }),
896
+ [isAuthenticated, isLoading, authTokens.accessToken, authTokens.idToken, error]
897
+ );
898
+ const signOut = (0, import_react18.useCallback)(() => {
899
+ import_platform_core11.YouVersionPlatformConfiguration.clearAuthTokens();
900
+ setUserInfo(null);
901
+ }, []);
902
+ return {
903
+ auth,
904
+ signIn,
905
+ signOut,
906
+ processCallback,
907
+ userInfo,
908
+ redirectUri
909
+ };
910
+ }
911
+ // Annotate the CommonJS export names for ESM import in node:
912
+ 0 && (module.exports = {
913
+ DEFAULT,
914
+ ReaderContext,
915
+ ReaderProvider,
916
+ VerseSelectionContext,
917
+ VerseSelectionProvider,
918
+ YouVersionContext,
919
+ YouVersionProvider,
920
+ extractTextFromHtml,
921
+ extractVersesFromHTML,
922
+ getDayOfYear,
923
+ getISOFromVersion,
924
+ useBibleClient,
925
+ useBook,
926
+ useBooks,
927
+ useChapter,
928
+ useChapterNavigation,
929
+ useChapters,
930
+ useDebounce,
931
+ useFilteredVersions,
932
+ useHighlights,
933
+ useInitData,
934
+ useLanguage,
935
+ useLanguages,
936
+ usePassage,
937
+ useReaderContext,
938
+ useTheme,
939
+ useVerse,
940
+ useVerseOfTheDay,
941
+ useVerseSelection,
942
+ useVerses,
943
+ useVersion,
944
+ useVersions,
945
+ useYVAuth
946
+ });